Skip to content

STYLE use absolute imports #39561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 3, 2021
Merged

Conversation

MarcoGorelli
Copy link
Member

@MarcoGorelli MarcoGorelli commented Feb 2, 2021

  • Ensure all linting tests pass, see here for how to run them

The code style guide reads

Imports (aim for absolute)

In Python 3, absolute imports are recommended. Using absolute imports, doing something
like import string will import the string module rather than string.py
in the same directory. As much as possible, you should try to write out
absolute imports that show the whole import chain from top-level pandas.

Explicit relative imports are also supported in Python 3 but it is not
recommended to use them. Implicit relative imports should never be used
and are removed in Python 3.

For example:

::

# preferred
import pandas.core.common as com

# not preferred
from .common import test_base

# wrong
from common import test_base

yet this isn't checked (nor followed).

So I've made a little package which does this - it's pretty simple and light (link to source), just standard Python libraries (ast.parse). Timing on my laptop:

$ time pre-commit run abs-imports --all-files
abs-imports..............................................................Passed

real    0m1.102s
user    0m10.050s
sys     0m0.373s

I asked about doing this on the gitter channel and got the response

in general we go for absolute imports, the exception being in places where that creates circular imports (generally init files)

I didn't find that this created any circular imports (at least, running ./test_fast.sh worked fine), but __init__ files can always be excluded if necessary (exclude: __init__\.py$)

@MarcoGorelli MarcoGorelli marked this pull request as ready for review February 2, 2021 18:43
@jbrockmendel
Copy link
Member

I didn't find that this created any circular imports

i think this has been an issue in some of the cython code

Does this affect import speed?

@MarcoGorelli
Copy link
Member Author

MarcoGorelli commented Feb 2, 2021

I didn't find that this created any circular imports

i think this has been an issue in some of the cython code

So if this is just run on Python files, it should be OK?

Does this affect import speed?

I didn't notice any difference from several runs of python -X importtime -c "import pandas"

@@ -180,7 +180,7 @@
import pandas.arrays

# use the closest tagged version if possible
from ._version import get_versions
from pandas._version import get_versions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this added automatically by versioneer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, thanks for spotting this - I've updated versioneer.py to use an absolute import

Copy link
Member

@jbrockmendel jbrockmendel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lithomas1 lithomas1 added the Code Style Code style, linting, code_checks label Feb 2, 2021
@jreback jreback added this to the 1.3 milestone Feb 3, 2021
@jreback jreback merged commit 9a52a81 into pandas-dev:master Feb 3, 2021
@jreback
Copy link
Contributor

jreback commented Feb 3, 2021

thanks @MarcoGorelli very nice.

@MarcoGorelli MarcoGorelli deleted the absolute-imports branch February 3, 2021 13:49
from .missing import BaseMissingTests # noqa
from .ops import ( # noqa
from pandas.tests.extension.base.casting import BaseCastingTests # noqa
from pandas.tests.extension.base.constructors import BaseConstructorsTests # noqa
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I am -1 on general linting check for this. For example, this specific example where I am commenting on, I find the relative imports actually more readable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Joris on this (more generally, i like relative imports for same-directory as it clarified dependency structure)

Copy link
Member Author

@MarcoGorelli MarcoGorelli Feb 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no strong opinion here, I was just following the (existing) pandas style guide - should the style guide be changed so an exception is made for same-level imports?

Or this can be reverted if you wish, it was a really good learning exercise anyway.

My personal preference would be to have some kind of rule agreed on, but again, not a strong opinion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we had easily automatic check able for relative imports that would be ok for a limited purpose

we cannot expreess 'more readable' in this way and have it enforced

this is why i am currently -1 on relative imports and why we cannot use them in the code base

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just following the (existing) pandas style guide - should the style guide be changed so an exception is made for same-level imports?

The part of the style guide about general relative imports, of course fully agreed that we never want implicit relative imports. But personally I think we should reconsider explicit ones, yes.

more generally, i like relative imports for same-directory as it clarified dependency structure

+1, I also find this helpful. I think it should certainly be doable to have a check that relative imports are never outside the local directory

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just don't (yet) see why you'd make an exception for same-directory imports. Doesn't from ..foo import bar also clarify the dependency structure?

there are a bunch of places where we have dependency structure rules (imperfectly enforced, so maybe better thought of as aspirations) of the form "this file doesnt depend on anything else in pandas except other files in this directory or things explicitly higher up in the dependency structure":

pandas._config
pandas._libs.tslibs (depends only on _config)
pandas._libs (depends almost-only on tslibs)
pandas.tseries (depends only on tslibs)
pandas.core.dtypes (depends almost-only on _libs)
pandas.core.arrays (depends almost^2-only on dtypes)
pandas.core.indexes (doesnt depend in groupby or internals)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining, I hadn't appreciated that - I'll look into this and see how to adapt imports

Copy link
Member Author

@MarcoGorelli MarcoGorelli Feb 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pandas.core.arrays (depends almost^2-only on dtypes)

@jbrockmendel just to make sure I've understood, are you suggesting that every file inside pandas/core/arrays should import from pandas/core/arrays in a relative manner? For example, in pandas/core/arrays/sparse/array.py there is

from pandas.core.arrays import ExtensionArray

, would you want that to be from .. import ExtensionArray instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you want that to be from .. import ExtensionArray instead?

No, I would essentially never use from .. import, only from . import

Note that isort has a LOCALFOLDER section, so from . imports get put below everything else, which is consistent with the pattern of laying out imports in rough order of dependency structure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so you'd always use a relative import when importing from the same directory (even outside of the folders you listed above), and use absolute elsewhere? If so, this seems easily enforceable, I can make a PR later this week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code Style Code style, linting, code_checks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants