-
Notifications
You must be signed in to change notification settings - Fork 123
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
Fix circular imports and introduce isort #594
Conversation
Codecov Report
@@ Coverage Diff @@
## main #594 +/- ##
==========================================
- Coverage 94.69% 94.64% -0.05%
==========================================
Files 75 73 -2
Lines 10776 10725 -51
Branches 1053 1053
==========================================
- Hits 10204 10151 -53
- Misses 396 397 +1
- Partials 176 177 +1
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm broadly 👍🏽 on this change. I don't like having to think about import order, so this takes care of that for me; I'm also 👍🏽 on namespacing free functions, etc. Future-proofing against import hell is also a good thing. The big core.py
file isn't ideal but sometimes that's what has to happen.
CHANGELOG.md
Outdated
- Moved contents of `item`, `catalog`, and `collection` modules into `core` module | ||
(top-level package exports remain unchanged) ([#594](https://github.com/stac-utils/pystac/pull/594)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This I think is for sure a breaking change, and if there's a way to keep these imports working (with a deprecation notice) I'd be in favor. I find, for example, that some IDE's auto-import from the deeper path, so folks could be relying on the original import locations without even knowing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got things back to using separate item
, catalog
, and collection
modules in the latest push. I was able to resolve most of the import issues by being more careful about using the TYPE_CHECKING
gate on imports that were only used for type checking, and by using the new module import style.
There was 1 circular dependency that couldn't be cleanly resolved using these strategies, which was between any of item
, catalog
, and collection
and stac_io
. The root cause is that each of those modules uses stac_io
to call stac_io.StacIO.default()
in some methods that have an optional stac_io
argument, and the stac_io
module itself depends on item
, catalog
, and collection
as part of the logic in stac_object_from_dict
. I think there's probably a more elegant solution to be had here, but to work around this, I simply added a default_stac_io
method to pystac/__init__.py
that those other modules can use to break the circular dependency.
Yeah, this was by far my least favorite part of this change. I'll take another pass at making the imports work with the old |
The new import style feels very verbose and foreign. There's a lot of aliasing going on (e.g. from pystac import stac_object as stac_object_mod
x = stac_object_mod.STACObjectType.COLLECTION and there will be a lot of PR churn on getting import statements correct in second or third passes. I understand the desire to reduce the import burden in That said, and as I mentioned in the last isort PR, if it seems like generally contributors are positive to this change, I'm willing to go along with it. |
I agree, this seems a bit awkward, and we end up having to use it in a number of places due to naming conflicts.
I don't know of any tooling that would enforce this, and I agree this puts a lot of pressure on both developers and reviewers to get this right.
I agree here as well. When I embarked on this I was hoping I would be able to simplify the way our imports worked, but I think in the end we're just trading one kind of pain for another. I'll leave this PR open for a bit in case other contributors and maintainers have other opinions, but having gone through the work now of fleshing this out I'm not sure the change is worth it either. Maybe someone else can come up with a better approach for resolving the circular import issues that doesn't also introduce some of the problems here. |
Related Issue(s):
Description:
isort
for sorting importsTYPE_CHECKING
gate for imports that are only used in type checkingItem
,Catalog
, andCollection
classes intocore
module to avoid circular importsbump2version
for managing package version changes instead of reading from package dynamically.I do not have a strong opinion on sorting of imports or the style of import that we use throughout the code, but introducing these changes uncovered and fixed a number of circular import issues. Those circular imports have worked up until now only by keeping a certain order to the imports in the
pystac/__init__.py
. This has caused problems on a few occasions where I have added or moved modules and had to figure out where to insert them into thepystac/__init__.py
import order by trial and error. Introducingisort
doesn't solve this problem, but it does make sure we don't paper over it with a specific import order in that__init__
file.Using the Google style of imports does seem to help with some of the circular imports since it avoids import partially initialized modules in most case. I also moved the Item, Catalog, and Collection code into a single
core
module because there were legitimate circular imports between those modules that could not be resolved by theTYPE_CHECKING
gating.This PR could represent a breaking change to anyone who has been importing things directly from(UPDATE: This change was reverted based on feedback on this PR).pystac.item
,pystac.collection
, orpystac.catalog
instead of from the the top-level package. If we think this is a big enough concern I can re-introduce those modules and explicitly re-export the classes with a deprecation warning for now, but given that all of our docs and examples demonstrate importing these classes from the top-level module, it didn't seem worth that extra complexity.UPDATE: This also introduces
bump2version
for managing changes to this package's version. Previouslysetup.cfg
was reading this dynamically frompystac.version.__version__
, but sincepystac
and its dependencies are not necessarily installed by the timesetuptools
read this information this could cause problems. Usingbump2version
allows us to manage this as a static string, but still update it everywhere it needs updating when we change versions.PR Checklist:
pre-commit run --all-files
)scripts/test
)cc: @l0b0