-
Notifications
You must be signed in to change notification settings - Fork 275
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
import-style prevents vendoring #1165
Comments
Example you can run or have a look at: |
The issue is any "submodule import" really, not just internal submodule imports: |
This reads like in order to support vendoring TUF (and securesystemslib) we need to change the way we do imports to either
All things being equal, I prefer absolute imports – I believe they make the code easier to read and follow. Indeed, I recently rejected a securesystemslib PR which added explicit relative imports (secure-systems-lab/securesystemslib#254), but now I'm wondering if that's the direction we should take? I certainly prefer explicit relative imports to importing functions from a dependent module into our own namespace. |
If the important bit is the complete code namespacing, I suppose that would still be possible if package initialization imported the submodules? As in you could do
if |
Two reasons not to do that today would be clients importing all of the repository logic and everyone who imported tuf would have log handlers modified #1148 If we had a clearer distinction between the client and repository logic, it might make more sense to have the package initialisation import submodules. |
If we have to choose between relative imports and importing names (functions, globals, etc) directly, I too vote for the former. At least this requirement will make it easy to choose an import style convention. :) @jku, have you checked if we'd need to patch any of TUF's dependencies or transitive dependencies, except for securesystemslib? |
All of TUF dependencies are already pip dependencies (so succesfully vendored) except SSL and iso8601 (which is a single file library).
I'm researching more clever alternatives as both of these options mean a massive PR: ~700 actual code lines would need to change and the possibility of a namespace mistake is real. I'll try to have a possible solution for discussion by tomorrow. |
There's a possible fix in a PR -- it might look like a large change but 70% of it is test changes that are completely optional: I just did those to make them the same style as the actual source. I'm also speaking to the vendoring maintainer to make sure this is not a misunderstanding (I don't think it is -- it's just impossible for vendoring to handle the current imports) |
other points that should maybe be bug reports?
|
I've been looking at and testing the Draft PR and it works: the patch is reasonable size (most changes are in tests and completely optional), all current methods of importing keep working, and vendoring now works (apart from the securesystemslib imports that would also have to be fixed) ... but I'm not entirely happy:
|
Documenting the core issue and main options for those who are not familiar with it: Core issue Options I see available
class Tuf:
def __init__(self):
from tuf import exceptions
self.exceptions = exceptions
tuf=Tuf() # voila, tuf.exceptions now works as expected. Also ewww
|
Related findings:
|
We've talked elsewhere about adopting, with minimal modifications, the Google Python coding style. That style guide recommends either: import foo.bar
badger = foo.bar.BADGER or from foo import bar
badger = bar.BADGER and explicitly recommends against using relative imports. I think the second pattern above ( |
Yes, that seems correct to me. Bringing the example to TUF context: Current style import tuf.download
tuf.download.safe_download(...) would become from tuf import download
download.safe_download(...) That is a big change and cannot be completely automated. I don't think we have name clashes where a tuf module could be mistaken for another imported package or module... But the change is likely to lead to some local name clashes (in the sense that
|
Thanks for all the digging, @jku! Based on the If that is not the case, and constructs like I would only go with any of your proposed trickery, if it makes the refactor substantially easier and we make it very clear that it is only a temporary hack that won't survive the upcoming refactor. |
Regarding the other pain points you mentioned ...
Agreed but probably not worth to change before the planned refactor? Definitely something to consider together with #1136 and #881. Maybe this warrants a separate over-arching module architecture design issue? Also #1134 (comment) seems related.
Agreed but IMO low-prio.
Agreed but see both comments above and #1135.
I know. :/ I've been meaning to at least submit an issue for this for a long time (I will do this right now). FWIW, I've fixed this a long time ago in in-toto and have created a ticket in securesystemslib, which both adopted their linter config from tuf (see secure-systems-lab/securesystemslib#243).
I know. :/ I think a sensible linter config would catch this (see above). |
right I can see how that was ambiguous. vendoring can cope with any form of |
--> #1178 |
well this one's done already |
I just tried to vendor TUF into pip (in other words embed the tuf sources inside pip sources) and it fails (even with #1160 fixed) because of the import style used in TUF source code itself:
import tuf.download
Using this (instead of relative imports) means tuf needs to be installed to python path for the imports to work.
I've looked at the dozen other projects pip vendors and the system seems to cope with two styles:
The second style works because vendoring (the tool) modifies
import NAME
tofrom vendored.path import NAME
andfrom NAME.module import something
tofrom vendored.path.NAME.module import something
. I assume this is mostly done so vendored dependencies of vendored projects work (so e.g. vendored tuf can "import securesystemslib"). In any case the TUF style cannot be automatically modified as far as I can tell.I'll try to add reproduction instructions that don't require my pip branch...
The text was updated successfully, but these errors were encountered: