Repository navigation
Conversation
import dropbox used to import every namespace module, including team_log, because base.py and base_team.py import all of them at module level. The generator now emits LazyNamespace proxies that import a namespace on first use, and base_team is generated by the same generator so it gets them too. Closes dropbox#269
Contributor
|
Thanks for submitting this! I'll ask the team to review it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #269
import dropboximports every namespace module, because the generatedbase.pyandbase_team.pystart withfrom dropbox import <namespace>for all 21 namespaces. Most of that isteam_log(about 122k lines), which a typical app never touches.This changes the generator to emit lazy references instead:
LazyNamespaceimports the real module throughimportlib.import_modulethe first time an attribute is read, so route methods (which look upteam_log.get_eventsetc. inside the method body) work unchanged, and concurrent first use is covered by the import lock.from dropbox import team_logstill returns the real module.Changes:
generator/dropbox_python_client.stoneg.py: override_generate_importsgenerate_base_client.py: generatebase_teamwith the same generator asbase(it used stone's built-inpython_client), so it gets lazy imports too. The only other difference inbase_team.pyis that the abstractrequestsignature now includesextra_headers=None, matchingbase.py.dropbox/base.py,dropbox/base_team.py: regenerated withpython generate_base_client.py,ruff format dropbox,ruff check --fix dropbox(same steps as spec_update.yml). Before my change, that pipeline reproduced the committed files exactly, so the diff is only the import block.scripts/benchmark_import.py: measuresimport dropboxin fresh interpreters, with requests and stone imported firstNumbers from
python scripts/benchmark_import.py 21(Apple Silicon arm64, Python 3.12, median of 21 runs; traced memory median of 3):import dropboxtimedropbox.*modules loadedteam,team_log,account,check,contacts,openidandsecondary_emailsare no longer loaded at import.files,sharing,paper,rivieraandfile_requestsstill load at import because some route methods use their types as default argument values. The cost of a namespace isn't removed, just moved to the first call that needs it.Tests (
test/unit/test_lazy_namespace.py): a fresh interpreter doesn't loadteam/team_logonimport dropbox;team_log_get_eventsloads it and passes the real route object and arg type torequest; 16 threads hitting a cold namespace at once get the same module; proxydir/repr/missing attribute/missing module behavior; a user route still builds realfilestypes.Checklist
General Contributing
Is This a Code Change?
Validation
toxpass? (I ran tox's commands directly:ruff check dropbox example test,ruff format --check dropbox example test, and the unit tests)pytest test/unit/: 125 passed)