Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork938
Replace all wildcard imports with explicit imports#1880
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
This script can be removed after imports are refactored and checkedto see that module contents are the same as before or otherwisenon-broken.This script assumes that module contents are the same as thecontents of their dictionaries, and that all modules in the projectget imported as a consequence of importing the top-level module.These are both the case currently for GitPython, but they do nothold for all projects, and may not hold for GitPython at some pointin the future.
Although this situation is not inherently desirable, for backwardcompatibility it cannot change at this time. It may be possible tochange it in the next major version of GitPython, but even then itshould not be changed accidentally, which can easily happen whilerefactoring imports.This tests the highest-risk accidental change (of those that arecurrently known) of the kind that the temporary modattrs.py scriptexists to help safeguard against. That script will be removed whenthe immediately forthcoming import refactoring is complete, whereasthese test cases can be kept.For information about the specific situation this helps ensureisn't changed accidentally, see the new test cases' docstrings, aswell as the next commit (which will test modattrs.py and these testcases by performing an incomplete change that would be a bug untilcompleted).This commit adds three test cases. The first tests the unintuitiveaspect of the current situation:- test_git_util_attribute_is_git_index_utilThe other two test the intuitive aspects of it, i.e., they testthat changes (perhaps in an attempt to preserve the aspect neededfor backward compatibility) do not make `git.util` unusual in new(and themselves incompatible) ways:- test_git_index_util_attribute_is_git_index_util- test_separate_git_util_module_existsThe latter tests should also clarify, for readers of the tests, thelimited nature of the condition the first test asserts.
This also checks if the regression tests in test_imports.py work.This replaces wildcard imports in git.index with explicit imports,and adds git.index.__all__. But this temporarily omits from it thepublic attributes of git.index that name its Python submodules andare thus are present as an indirect effect of importing names*from* them (since doing so also imports them).This partial change, until it is completed in the next commit,represents the kind of bug that modattrs.py seeks to safeguardagainst, and verifies that a diff between old and current output ofmodattrs.py clearly shows it. This diff is temporarily included asab.diff, which will be deleted in the next commit.The key problem that diff reveals is the changed value of the utilattribute of the top-level git module. Due to the way wildcardimports have been used within GitPython for its own modules,expressions like `git.util` (where `git` is the top-level gitmodule) and imports like `from git import util` are actuallyreferring to git.index.util, rather than the util Python submoduleof the git module (conceptually git.util), which can only beaccessed via `from git.util import ...` or in `sys.modules`.Although this is not an inherently good situation, in practice ithas to be maintained at least until the next major version, becausereasonable code that uses GitPython would be broken if thesituation were changed to be more intuitive.But the more intuitive behavior automatically happens if wildcardimports are replaced with explicit imports of the names they hadoriginally intended to import (in this case, in the top-level gitmodule, which has not yet been done but will be), or if __all__ isadded where helpful (in this case, in git.index, which this does).Adding the names explicitly is sufficient to restore the oldbehavior that is needed for backward compatibility, and has thefurther advantage that the unintuitive behavior will be explicitonce all wildcard imports are replaced and __all__ is added to eachmodule where it would be helpful. The modattrs.py script serves toensure incompatible changes are not made; this commit checks it.The tests in test_imports.py also cover this specific anticipatedincompatibility in git.util, but not all breakages that may arisewhen refactoring imports and that diff-ing modattrs.py output wouldhelp catch.
- Add the base, fun, typ, and util Python submodules of git.index to git.index.__all__ to restore the old behavior.- Import them explicitly for clarity, even though they are bound to the same-named attributes of git.index either way. This should help human readers know what the entries in __all__ are referring to, and may also help some automated tools. This is a preliminary decision and not necessarily the one that will ultimately be taken in this import refactoring. It *may* cause some kinds of mistakes, such as those arising from ill-advised use of wildcard imports in production code *outside* GitPython, somewhat worse in their effects.- Remove the ab.diff file that showed the problem this solves.This resolves the problem deliberately introduced in the previousincomplete commit, which modattrs.py output and test_imports testresults confirm.
This uses explicit imports rather than wildcard imports in git.refsfor names from its submodules.A comment suggested that the import order was deliberate. But eachof the modules being imported from defined __all__, and there wasno overlap in the names across any of them.The other main reason to import in a specific order is an orderdependency in the side effects, but that does not appear to apply,at least not at this time.(In addition, at least for now, this adds explicit imports for thePython submodules of git.refs, so it is clear that they can alwaysbe accessed directly in git.refs without further imports, ifdesired. For clarity, those appear first, and that makes the orderof the "from" imports not relevant to such side effects, due to the"from" imports no longer causing modules to be loaded for the firsttime. However, this is a much less important reason to consider theother imports' reordering okay, because these module imports mayend up being removed later during this refactoring; their claritybenefit might not be justified, because if production code outsideGitPython ill-advisedly uses wildcard imports, the bad effect ofdoing so could be increased.)
- No need to import Repo "as Repo". Some tools only recognize this to give the name conceptually public status when it appears in type stub files (.pyi files), and listing it in the newly created __all__ is sufficient to let humans and all tools know it has that status.- As very recently done in git.refs, this explicitly imports the submodules, so it is clear they are available and don't have to be explicitly imported. (Fundamental to the way they are used is that they will end up being imported in order to import Repo.) However, also as in git.refs, it may be that the problems this could cause in some inherently flawed but plausible uses are too greater for it to be justified. So this may be revisited.
But not yet in git.objects.submodule.* modules.
Such patching, which was introduced in9519f18, seems no longer tobe necessary. Since git.objects.submodule.util.__all__ has existedfor a long time without including those names, they are notconceptually public attributes of git.objects.submodule.util, sothey should not be in use by any code outside GitPython either.The modattrs.py script shows the change, as expected, showing thesetwo names as no longer being in the git.objects.submodule.utilmodule dictionary, in output of: python modattrs.py >b git diff --no-index a bHowever, because the removal is intentional, this is okay.
The submodules being made explicit here are of course Pythonsubmodules, not git submodules.The git.objects.submodule Python submodule (which is *about* gitsubmodules) is made explicit here (as are the names imported fromthat Python submodule's own Python submodules) along with the otherPython submodules of git.objects.Unlike some other submodules, but like the top-level git moduleuntilgitpython-developers#1659, git.objects already defined __all__ but it wasdynamically constructed. As with git.__all__ previously (as notedingitpython-developers#1859), I have usedhttps://github.com/EliahKagan/deltall hereto check that it is safe, sufficient, and probably necessary toreplace this dynamically constructed __all__ with a literal list ofstrings in which all of the original elements are included. See:https://gist.github.com/EliahKagan/e627603717ca5f9cafaf8de9d9f27ad7Running the modattrs.py script, and diffing against the output frombefore the current import refactoring began, reveals two changes tomodule contents as a result of the change here:- git.objects no longer contains `inspect`, which it imported just to build the dynamically constructed __all__. Because this was not itself included in that __all__ or otherwise made public or used out of git.objects, that is okay. This is exactly analogous to the situation in8197e90, which removed it from the top-level git module aftergitpython-developers#1659.- The top-level git module now has has new attributes blob, commit, submodule, and tree, aliasing the corresponding modules. This has happened as a result of them being put in git.objects.__all__ along with various names imported from them. (As noted in some prior commits, there are tradeoffs associated with doing this, and it may be that such elements of __all__ should be removed, here and elsewhere.)
So git.objects.util is less likely to be confused with git.util.(The modattrs.py script reveals the change in the value ofgit.objects.util.__doc__, as expected.)
This is the top-level of the git.objects.submodule subpackage, forits own Python submodules.This appears only not to have been done before because of a cyclicimport problem involving imports that are no longer present. Doingit improves consistency, since all the other subpackages under thetop-level git package already do this.The modattrs.py script reveals the four new attributes ofgit.objects.submodule for the four classes obtained by the newimports, as expected. (The explicit module imports do not changethe attribues because they are the same attributes as come intoexistence due to those Python submodules being imported anywhere inany style.)
+ Update the detailed comment about the unused import situation.
These are in the modules that are directly under the top-level gitmodule (and are not themselves subpackages, with their ownsubmodules in the Python sense), except for:- git.util, where this change was very recently made.- git.compat, where no improvements of this kind were needed.- git.types, which currently has no __all__ and will only benefit from it if what should go in it is carefully considered (and where the imports themselves are grouped, sorted, and formatted already).
In git.compat and git.util.This applies them individually to each name that is known to be anunused import, rather than to entire import statements (exceptwhere the entire statement fit on one line and everything itimported is known to be unused).Either Ruff has the ability to accept this more granular style ofsuppression, or I had been unaware of it from flake8 (used before).I have veriifed that the suppressions are not superfluous: with nosuppressions, Ruff does warn. This commit makes no change ingit.types because it looks like no suppression at all may beneeded there anymore; that will be covered in the next commit.This also removes the old `@UnusedImport` comments, which had beenkept before because they were more granular; this specificity isnow achieved by comments the tools being used can recognize.
In git.types.It appears Ruff, unlike flake8, recognizes "import X as X" to meanthat "X" should not be considered unused, even when it appearsoutside a .pyi type stub file where that notation is more commonlyused.Those imports in git.types may benefit from being changed in someway that uses a syntax whose intent is clearer in context, anddepending on how that is done it may even be necessary to bringback suppressions. If so, they can be written more specifically.(For now, changing them would express more than is known about whatnames that are only present in git.types becuase it imports themshould continue to be imported, should be considered conceptuallypublic, or should be condered suitable for use within GitPython.)
- Use explicit imports instead of * imports.- Remove now-unneeded linter suppressions.- Alphabetize inside the try-block, though this will be undone.This currently fails to import due to a cyclic import error, so thethird change, alphabetizing the imports, will have to be undone (atleast in the absence of other changes). It is not merely that theyshould not be reordered in a way that makes them cross into or outof the try-block, but that within the try block not all orders willwork.There will be more to do for backward compatibility, but themodattrs.py script, which imports the top-level git module, cannotbe run until the cyclic import problem is fixed.
This still uses all explicit rather than wildcard imports (andstill omits suppressions that are no longer needed due to wildcardimports not being used). But it brings back the old relative orderof the `from ... import ...` statements inside the try-block.Since this fixes the circular import problem, it is possible to runthe modattrs.py script to check for changes. New changes sincereplacing wildcard imports, which are probably undesirable, are theremoval of these attributes pointing to indirect Python submodulesof the git module: base -> git.index.base fun -> git.index.fun head -> git.refs.head log -> git.refs.log reference -> git.refs.reference symbolic -> git.refs.symbolic tag -> git.refs.tag typ -> git.index.typ
These should definitely never be used by code inside or outside ofGitPython, as they have never been public, having even been omittedby the dynamic (and expansive) technique used to build git.__all__in the past (which omitted modules intentionally).However, to ease compatibility, for now they are back. This is sothat the change of making all imports explicit rather than usingwildcards does not break anything. However, code using these namescould never be relied on to work, and these should be consideredeligible for removal, at least from the perspective of code outsideGitPython.That is for the indirect submodules whose absence as a same-nameddirect submodule or attribute listed in __all__ was readilydiscoverable.The more difficult case is util. git.util is a module, git/util.py,which is how it is treated when it appears immediately after the"from" keyword, or as a key in sys.modules. However, the expression`git.util`, and a `from git import util` import, instead access theseparate git.index.util module, which due to a wildcard import hasbeen an attribute of the top-level git module for a long time.It may not be safe to change this, because although any codeanywhere is better off not relying on this, this situation hasn'tbeen (and isn't) immediately clear. To help with it somewhat, thisalso includes a detailed comment over where util is imported fromgit.index, explaining the situation.
Since they are listed in __all__. (They are imported either waybecause names are imported from them, and this caused them to bepresent with the same effect.)Though they are proably about to be removed along with thecorresponding entries in __all__.
This is for non-toplevel __all__, as git.__all__ already did notdo this.As noted in some of the previous commit messags that added them,omitting them might be a bit safer in terms of the impact of bugsbugs in code using GitPython, in that unexpected modules, some ofwhich have the same name as other modules within GitPython, won'tbe imported due to wildcard imports from intermediate subpackages(those that are below the top-level git package/module but collectnon-subpackage modules). Though it is hard to know, since some ofthese would have been imported before, when an __all__ was notdefined at that level.However, a separate benefit of omitting them is consistency withgit.__all__, which does not list the direct Python submodules ofthe git module.This does not affect the output of the modattrs.py script, becausethe attributes exist with the same objects as their values as aresult of those Python submodules being imported (in "from" importsand otherwise), including when importing the top-level git module.
This makes all __all__ everywhere in the git package lists. Before,roughly half were lists and half were tuples. There are reasonabletheoretical arguments for both, and in practice all tools todaysupport both. Traditionally using a list is far more common, and itremains at least somewhat more common. Furthermore, git/util.pyuses a list and is currently written to append an element to itthat is conditionally defined on Windows (though it would probablybe fine for that to be the only list, since it reflects an actualrelevant difference about it).The goal here is just to remove inconsistency that does not signifyanything and is the result of drift over time. If a reason (evenpreference) arises to make them all tuples in the future, then thatis also probably fine.
This commits the diff of the output of the modattrs.py scriptbetween when the script was introduced in1e5a944, and now (withthe import refactoring finished and no wildcard imports remainingoutside the test suite, and only there in one import statement fortest helpers).Neither this diff nor modattrs.py itself will be retained. Bothwill be removed in the next commit. This is committed here tofacilitate inspection and debugging (especially if turns out thereare thus-far undetected regressions).
Now that it has served its purpose. (Of course, it can also bebrought back from the history at any time if needed.)Changes:- Delete the modattrs.py script that was used to check for unintended changes to what module attributes existed and what objects they referred to, while doing the import refactoring.- Delete the ab.diff file showing the overall diff, which was temporarily introduced in the previous commit.- Remove the "a" and "b" temporary entries in .gitignore that were used to facilitate efficient use of modattrs.py while carrying out the import refactoring.
There is only one __all__ in the test suite, so this is mostly thechange to imports, grouping and sorting them in a fully consistentstyle that is the same as the import style in the code under test.
It looks likehttps://github.com/gitpython-developers/GitPython/actions/runs/8339331003/job/22821123508, in5b2771d, is due to a network error and would go away if run again. In contrast, the subsequent commit,fc86a23, is expected to having a failing status (which should go green again starting in the commit after that). |
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.
Thanks so much for fixing these imports! It sounds like doing so is going to have major benefits, despite being a conceptually simple change.
- I wrote a short script (1e5a944,f705fd6) to verify thatchanges to module contents were minimal and as expected, including verifying what object attributes reference, not just what the attributes' names were.
Incredibly diligent, thanks so much.
I will merge this PR once CI has caught up and is green.
Uh oh!
There was an error while loading.Please reload this page.
[](https://renovatebot.com)This PR contains the following updates:| Package | Change | Age | Adoption | Passing | Confidence ||---|---|---|---|---|---|| [GitPython](https://togithub.com/gitpython-developers/GitPython) |`==3.1.42` -> `==3.1.43` |[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|---### Release Notes<details><summary>gitpython-developers/GitPython (GitPython)</summary>###[`v3.1.43`](https://togithub.com/gitpython-developers/GitPython/releases/tag/3.1.43)[CompareSource](https://togithub.com/gitpython-developers/GitPython/compare/3.1.42...3.1.43)#### Particularly Important ChangesThese are likely to affect you, please do take a careful look.- Issue and test deprecation warnings by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1886](https://togithub.com/gitpython-developers/GitPython/pull/1886)- Fix version_info cache invalidation, typing, parsing, andserialization by [@​EliahKagan](https://togithub.com/EliahKagan)in[https://github.com/gitpython-developers/GitPython/pull/1838](https://togithub.com/gitpython-developers/GitPython/pull/1838)- Document manual refresh path treatment by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1839](https://togithub.com/gitpython-developers/GitPython/pull/1839)- Improve static typing and docstrings related to git object types by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1859](https://togithub.com/gitpython-developers/GitPython/pull/1859)#### Other Changes- Test in Docker with Alpine Linux on CI by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1826](https://togithub.com/gitpython-developers/GitPython/pull/1826)- Build online docs (RTD) with -W and dependencies by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1843](https://togithub.com/gitpython-developers/GitPython/pull/1843)- Suggest full-path refresh() in failure message by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1844](https://togithub.com/gitpython-developers/GitPython/pull/1844)- `repo.blame` and `repo.blame_incremental` now accept `None` as the`rev` parameter. by [@​Gaubbe](https://togithub.com/Gaubbe) in[https://github.com/gitpython-developers/GitPython/pull/1846](https://togithub.com/gitpython-developers/GitPython/pull/1846)- Make sure diff always uses the default diff driver when`create_patch=True` by[@​can-taslicukur](https://togithub.com/can-taslicukur) in[https://github.com/gitpython-developers/GitPython/pull/1832](https://togithub.com/gitpython-developers/GitPython/pull/1832)- Revise docstrings, comments, and a few messages by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1850](https://togithub.com/gitpython-developers/GitPython/pull/1850)- Expand what is included in the API Reference by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1855](https://togithub.com/gitpython-developers/GitPython/pull/1855)- Restore building of documentation downloads by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1856](https://togithub.com/gitpython-developers/GitPython/pull/1856)- Revise type annotations slightly by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1860](https://togithub.com/gitpython-developers/GitPython/pull/1860)- Updating regex pattern to handle unicode whitespaces. by[@​jcole-crowdstrike](https://togithub.com/jcole-crowdstrike) in[https://github.com/gitpython-developers/GitPython/pull/1853](https://togithub.com/gitpython-developers/GitPython/pull/1853)- Use upgraded pip in test fixture virtual environment by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1864](https://togithub.com/gitpython-developers/GitPython/pull/1864)- lint: replace `flake8` with `ruff` check by[@​Borda](https://togithub.com/Borda) in[https://github.com/gitpython-developers/GitPython/pull/1862](https://togithub.com/gitpython-developers/GitPython/pull/1862)- lint: switch Black with `ruff-format` by[@​Borda](https://togithub.com/Borda) in[https://github.com/gitpython-developers/GitPython/pull/1865](https://togithub.com/gitpython-developers/GitPython/pull/1865)- Update readme and tox.ini for recent tooling changes by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1868](https://togithub.com/gitpython-developers/GitPython/pull/1868)- Split tox lint env into three envs, all safe by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1870](https://togithub.com/gitpython-developers/GitPython/pull/1870)- Slightly broaden Ruff, and update and clarify tool configuration by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1871](https://togithub.com/gitpython-developers/GitPython/pull/1871)- Add a "doc" extra for documentation build dependencies by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1872](https://togithub.com/gitpython-developers/GitPython/pull/1872)- Describe `Submodule.__init__` parent_commit parameter by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1877](https://togithub.com/gitpython-developers/GitPython/pull/1877)- Include TagObject in git.types.Tree_ish by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1878](https://togithub.com/gitpython-developers/GitPython/pull/1878)- Improve Sphinx role usage, including linking Git manpages by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1879](https://togithub.com/gitpython-developers/GitPython/pull/1879)- Replace all wildcard imports with explicit imports by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1880](https://togithub.com/gitpython-developers/GitPython/pull/1880)- Clarify how tag objects are usually tree-ish and commit-ish by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1881](https://togithub.com/gitpython-developers/GitPython/pull/1881)#### New Contributors- [@​Gaubbe](https://togithub.com/Gaubbe) made their firstcontribution in[https://github.com/gitpython-developers/GitPython/pull/1846](https://togithub.com/gitpython-developers/GitPython/pull/1846)- [@​can-taslicukur](https://togithub.com/can-taslicukur) madetheir first contribution in[https://github.com/gitpython-developers/GitPython/pull/1832](https://togithub.com/gitpython-developers/GitPython/pull/1832)- [@​jcole-crowdstrike](https://togithub.com/jcole-crowdstrike)made their first contribution in[https://github.com/gitpython-developers/GitPython/pull/1853](https://togithub.com/gitpython-developers/GitPython/pull/1853)- [@​Borda](https://togithub.com/Borda) made their firstcontribution in[https://github.com/gitpython-developers/GitPython/pull/1862](https://togithub.com/gitpython-developers/GitPython/pull/1862)**Full Changelog**:gitpython-developers/GitPython@3.1.42...3.1.43</details>---### Configuration📅 **Schedule**: Branch creation - At any time (no schedule defined),Automerge - At any time (no schedule defined).🚦 **Automerge**: Enabled.♻ **Rebasing**: Whenever PR becomes conflicted, or you tick therebase/retry checkbox.🔕 **Ignore**: Close this PR and you won't be reminded about this updateagain.---- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, checkthis box---This PR has been generated by [MendRenovate](https://www.mend.io/free-developer-tools/renovate/). Viewrepository job log[here](https://developer.mend.io/github/allenporter/flux-local).<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
[](https://renovatebot.com)This PR contains the following updates:| Package | Change | Age | Adoption | Passing | Confidence ||---|---|---|---|---|---|| [GitPython](https://togithub.com/gitpython-developers/GitPython) |`==3.1.42` -> `==3.1.43` |[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|[](https://docs.renovatebot.com/merge-confidence/)|---### Release Notes<details><summary>gitpython-developers/GitPython (GitPython)</summary>###[`v3.1.43`](https://togithub.com/gitpython-developers/GitPython/releases/tag/3.1.43)[CompareSource](https://togithub.com/gitpython-developers/GitPython/compare/3.1.42...3.1.43)#### Particularly Important ChangesThese are likely to affect you, please do take a careful look.- Issue and test deprecation warnings by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1886](https://togithub.com/gitpython-developers/GitPython/pull/1886)- Fix version_info cache invalidation, typing, parsing, andserialization by [@​EliahKagan](https://togithub.com/EliahKagan)in[https://github.com/gitpython-developers/GitPython/pull/1838](https://togithub.com/gitpython-developers/GitPython/pull/1838)- Document manual refresh path treatment by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1839](https://togithub.com/gitpython-developers/GitPython/pull/1839)- Improve static typing and docstrings related to git object types by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1859](https://togithub.com/gitpython-developers/GitPython/pull/1859)#### Other Changes- Test in Docker with Alpine Linux on CI by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1826](https://togithub.com/gitpython-developers/GitPython/pull/1826)- Build online docs (RTD) with -W and dependencies by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1843](https://togithub.com/gitpython-developers/GitPython/pull/1843)- Suggest full-path refresh() in failure message by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1844](https://togithub.com/gitpython-developers/GitPython/pull/1844)- `repo.blame` and `repo.blame_incremental` now accept `None` as the`rev` parameter. by [@​Gaubbe](https://togithub.com/Gaubbe) in[https://github.com/gitpython-developers/GitPython/pull/1846](https://togithub.com/gitpython-developers/GitPython/pull/1846)- Make sure diff always uses the default diff driver when`create_patch=True` by[@​can-taslicukur](https://togithub.com/can-taslicukur) in[https://github.com/gitpython-developers/GitPython/pull/1832](https://togithub.com/gitpython-developers/GitPython/pull/1832)- Revise docstrings, comments, and a few messages by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1850](https://togithub.com/gitpython-developers/GitPython/pull/1850)- Expand what is included in the API Reference by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1855](https://togithub.com/gitpython-developers/GitPython/pull/1855)- Restore building of documentation downloads by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1856](https://togithub.com/gitpython-developers/GitPython/pull/1856)- Revise type annotations slightly by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1860](https://togithub.com/gitpython-developers/GitPython/pull/1860)- Updating regex pattern to handle unicode whitespaces. by[@​jcole-crowdstrike](https://togithub.com/jcole-crowdstrike) in[https://github.com/gitpython-developers/GitPython/pull/1853](https://togithub.com/gitpython-developers/GitPython/pull/1853)- Use upgraded pip in test fixture virtual environment by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1864](https://togithub.com/gitpython-developers/GitPython/pull/1864)- lint: replace `flake8` with `ruff` check by[@​Borda](https://togithub.com/Borda) in[https://github.com/gitpython-developers/GitPython/pull/1862](https://togithub.com/gitpython-developers/GitPython/pull/1862)- lint: switch Black with `ruff-format` by[@​Borda](https://togithub.com/Borda) in[https://github.com/gitpython-developers/GitPython/pull/1865](https://togithub.com/gitpython-developers/GitPython/pull/1865)- Update readme and tox.ini for recent tooling changes by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1868](https://togithub.com/gitpython-developers/GitPython/pull/1868)- Split tox lint env into three envs, all safe by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1870](https://togithub.com/gitpython-developers/GitPython/pull/1870)- Slightly broaden Ruff, and update and clarify tool configuration by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1871](https://togithub.com/gitpython-developers/GitPython/pull/1871)- Add a "doc" extra for documentation build dependencies by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1872](https://togithub.com/gitpython-developers/GitPython/pull/1872)- Describe `Submodule.__init__` parent_commit parameter by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1877](https://togithub.com/gitpython-developers/GitPython/pull/1877)- Include TagObject in git.types.Tree_ish by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1878](https://togithub.com/gitpython-developers/GitPython/pull/1878)- Improve Sphinx role usage, including linking Git manpages by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1879](https://togithub.com/gitpython-developers/GitPython/pull/1879)- Replace all wildcard imports with explicit imports by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1880](https://togithub.com/gitpython-developers/GitPython/pull/1880)- Clarify how tag objects are usually tree-ish and commit-ish by[@​EliahKagan](https://togithub.com/EliahKagan) in[https://github.com/gitpython-developers/GitPython/pull/1881](https://togithub.com/gitpython-developers/GitPython/pull/1881)#### New Contributors- [@​Gaubbe](https://togithub.com/Gaubbe) made their firstcontribution in[https://github.com/gitpython-developers/GitPython/pull/1846](https://togithub.com/gitpython-developers/GitPython/pull/1846)- [@​can-taslicukur](https://togithub.com/can-taslicukur) madetheir first contribution in[https://github.com/gitpython-developers/GitPython/pull/1832](https://togithub.com/gitpython-developers/GitPython/pull/1832)- [@​jcole-crowdstrike](https://togithub.com/jcole-crowdstrike)made their first contribution in[https://github.com/gitpython-developers/GitPython/pull/1853](https://togithub.com/gitpython-developers/GitPython/pull/1853)- [@​Borda](https://togithub.com/Borda) made their firstcontribution in[https://github.com/gitpython-developers/GitPython/pull/1862](https://togithub.com/gitpython-developers/GitPython/pull/1862)**Full Changelog**:gitpython-developers/GitPython@3.1.42...3.1.43</details>---### Configuration📅 **Schedule**: Branch creation - At any time (no schedule defined),Automerge - At any time (no schedule defined).🚦 **Automerge**: Disabled by config. Please merge this manually once youare satisfied.♻ **Rebasing**: Whenever PR becomes conflicted, or you tick therebase/retry checkbox.🔕 **Ignore**: Close this PR and you won't be reminded about theseupdates again.---- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, checkthis box---This PR has been generated by [MendRenovate](https://www.mend.io/free-developer-tools/renovate/). Viewrepository job log[here](https://developer.mend.io/github/lettuce-financial/github-bot-signed-commit).<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->
Uh oh!
There was an error while loading.Please reload this page.
Fixes#1349
This actually makes a number of related changes, several of which the reduction in mypy errors in#1859 helped in validating:
All wildcard imports (
from blah import *
) are replaced with imports of specific names. This is the key change, with everything else done to support it, or directly facilitated by it, or conceptually related to it, or practically easy to do alongside it.Wildcard imports are inherently brittle, discouraged in PEP-8, and have already led tosome difficulties for GitPython (seefc86a23 and the "Another ambiguity, possibly relevant" section of#1802). Even more importantly, this makes things easier for type checkers, especially for code that uses GitPython from the outside where common and useful configurations otherwise report errors due to the wildcards' lack of explicitness about what names they introduce.
Furthermore, the combination of the mypy error reduction in#1859 with the elimination of wildcard imports makes it feasible to verify that newly introduced dynamic behavior is done in a way that avoids breaking static type checking for users of GitPython. This allows deprecation warnings on access to specific module attributes, as may be usefulin
git.compat
, as well asa dynamically generatedgit.__version__
attribute, to be safely approachable. (But such now-doable enhancements are not part of this pull request.)I wrote a short script (1e5a944,f705fd6) to verify thatchanges to module contents were minimal and as expected, including verifying what object attributes reference, not just what the attributes' names were.
Top-level names that are imported only to match what was imported before, but that are nonpublic and inadvisable to use, are commented as such where they are imported. Most of these could possibly be removed very soon.
The test suite has a few new tests, to test a particularly tricky aspect of the observable behavior of imports that is easy to change accidentally but should only ever be changed intentionally (the
git.util
vs.git.objects.util
issue).__all__
is added where absent but clearly useful, which is everywhere undergit
where it was absent exceptgit.types
. This was only a handful of places.git.objects.__all__
, which was dynamically generated as a list comprehension--asgit.__all__
was prior to#1659--is likewise replaced with a literal__all__
. As detailed in thef89d065 commit message, I useddeltall
(see also#1875) to verify that this was the right course.The
__init__
forgit.objects.submodule
no longer patchesIndexObject
andObject
intogit.objects.submodule.util
. This had been done to avoid a circular import error, but at some point ceased to be needed. Becausegit.objects.submodule.util
has defined__all__
for a long time, which omits them (and seems always to have omitted them), and because it also does not use them, I didn't replace that patching with any other way of getting them in there. However, it looks like it would be feasible to import them in a way that would not cause problems, if that is called for.Also related to that situation,
git.objects.submodule
had been the only subpackage whose__init__
didn't make names from its own submodules available directly in it. Because neither the circular import error nor the dynamic patching workaround are being done, there is no impediment to this, which improves consistency across the project and seemed to me to be what users would expect, so I included that.__all__
is now placed at the PEP-8 recommended location near the top of each module, above imports except in rare cases where that is infeasible.A number of linter suppressions are removed, most of which are no longer needed due to wildcard imports no longer being used. Some others are made more specific, including by splitting them into suppressions that apply to specific names in a
from
import. Some of what facilitates this is actually the switch from flake8 to Ruff in#1862.Imports across the project are fully sorted and grouped, in a consistent style that I think reflects the sensibility of the style that has been in place for an extended time. This is something that I had done bits of as part of other pull requests, and it was convenient to "complete" it here. I use scare quotes because it is likely I have missed some things. Ideally this should eventually be checked--or, better, applied--by an automated tool. Ruff can sort imports but I don't think it supports anything like this style, while isort is more configurable but might still be difficult to get to do it. However, the goal here is not this specific style, but instead to have something as consistent and helpful as possible if the style is not changed or before it is changed, while also making it easier to identify the advantages and disadvantages of an automatically applicable style over the best the current style has to offer.
Minor cleanup alongside these changes, including removal of old commented-out code (done in its own commits so it's easy to find in case that code is wanted again) and rewording the
git.objects.util
module docstring to distinguish that module fromgit.util
. The latter is the reason forthat__doc__
attribute change.A few special considerations:
Itwas suggested that#1349 could be fixed by writing
git.__all__
literally rather than dynamically generating it. But that improvement was since made in#1659, and while#1656 was fixed,#1349 remained. I've re-verified that this is the case by creating a repository that uses GitPython in a way that more closely approximates installing it from PyPI than is common during development, and ensures that the non-defaultmypy
configuration inpyproject.toml
is not used, while still allowing arbitrary files to be tested, by doing a non-editable installation into a different directory with a separate virtual environment.More details are in this gist. This confirmed that, as of the main branch at0a609b9,#1349 was reproducible, while at the tip of this feature branch,d524c76, it was resolved.I am not sure what the best choice is for whether intermediate subpackages--Python modules like
git.objects
andgit.refs
that are under the top-levelgit
package but contain their own Python submodules--should include their Python submodules' names in__all__
. In GitPython (though not all projects), everything is imported as a consequence of importing the top-levelgit
module, so these are already available, and they are also already public, in the sense that they are available due to having been imported, with the fully qualified names they are guaranteed to have as a consequence of being imported. In most but not all cases--git.objects
being a major counterexample due to its previously dynamically built__all__
that omitted modules--these were already importable in wildcard imports due to the absence of__all__
.However, that this was the case had caused some problems, including several modules that are not direct children of the top-level
git
module ending up as attributes of it (most of which are simply private attributes that should not be used, but one of which, beinggit.index.util
, is the cause of thegit.util
/git.index.util
ambiguity). Something different could be done ingit.objects
than elsewhere for maximum similarity to the previous state of affairs, but I decided instead to omit them everywhere, based on the top-levelgit
module not listing its own direct Python submodules in its__all__
, and the possibility that omitting them would help mitigate the risks of wildcard imports outside of GitPython.Some modules have unused imports not listed in
__all__
, present intentionally for use in other GitPython modules but not public outside the project. Ascommented on #1854, I'm unsure whether or how that should ultimately be improved, but I definitely consider it beyond the scope of this pull request. As such,implicit_reexport = true
remains set formypy
inpyproject.toml
(mypy
otherwise warns about this situation wherever other modules use such imports).