|
88 | 88 |
|
89 | 89 | __version__ = "git"
|
90 | 90 |
|
91 |
| -from typing import List, Optional, Sequence, TYPE_CHECKING, Tuple, Union |
| 91 | +from typing import Any, List, Optional, Sequence, TYPE_CHECKING, Tuple, Union |
| 92 | + |
| 93 | +if TYPE_CHECKING: |
| 94 | + from types import ModuleType |
92 | 95 |
|
93 | 96 | from gitdb.util import to_hex_sha
|
94 | 97 |
|
|
144 | 147 | SymbolicReference,
|
145 | 148 | Tag,
|
146 | 149 | TagReference,
|
147 |
| - head, # noqa: F401 # Nonpublic. May disappear! Use git.refs.head. |
148 |
| - log, # noqa: F401 # Nonpublic. May disappear! Use git.refs.log. |
149 |
| - reference, # noqa: F401 # Nonpublic. May disappear! Use git.refs.reference. |
150 |
| - symbolic, # noqa: F401 # Nonpublic. May disappear! Use git.refs.symbolic. |
151 |
| - tag, # noqa: F401 # Nonpublic. May disappear! Use git.refs.tag. |
152 | 150 | )
|
153 | 151 | from git.diff import ( # @NoMove
|
154 | 152 | INDEX,
|
|
169 | 167 | IndexEntry,
|
170 | 168 | IndexFile,
|
171 | 169 | StageType,
|
172 |
| - base, # noqa: F401 # Nonpublic. May disappear! Use git.index.base. |
173 |
| - fun, # noqa: F401 # Nonpublic. May disappear! Use git.index.fun. |
174 |
| - typ, # noqa: F401 # Nonpublic. May disappear! Use git.index.typ. |
175 |
| - # |
176 |
| - # NOTE: The expression `git.util` evaluates to git.index.util, and the import |
177 |
| - # `from git import util` imports git.index.util, NOT git.util. It may not be |
178 |
| - # feasible to change this until the next major version, to avoid breaking code |
179 |
| - # inadvertently relying on it. If git.index.util really is what you want, use or |
180 |
| - # import from that name, to avoid confusion. To use the "real" git.util module, |
181 |
| - # write `from git.util import ...`, or access it as `sys.modules["git.util"]`. |
182 |
| - # (This differs from other historical indirect-submodule imports that are |
183 |
| - # unambiguously nonpublic and are subject to immediate removal. Here, the public |
184 |
| - # git.util module, even though different, makes it less discoverable that the |
185 |
| - # expression `git.util` refers to a non-public attribute of the git module.) |
186 |
| - util, # noqa: F401 |
187 | 170 | )
|
188 | 171 | from git.util import ( # @NoMove
|
189 | 172 | Actor,
|
|
196 | 179 | except GitError as _exc:
|
197 | 180 | raise ImportError("%s: %s" % (_exc.__class__.__name__, _exc)) from _exc
|
198 | 181 |
|
| 182 | + |
| 183 | +# NOTE: The expression `git.util` evaluates to git.index.util and `from git import util` |
| 184 | +# imports git.index.util, NOT git.util. It may not be feasible to change this until the |
| 185 | +# next major version, to avoid breaking code inadvertently relying on it. |
| 186 | +# |
| 187 | +# - If git.index.util *is* what you want, use or import from that, to avoid confusion. |
| 188 | +# |
| 189 | +# - To use the "real" git.util module, write `from git.util import ...`, or if necessary |
| 190 | +# access it as `sys.modules["git.util"]`. |
| 191 | +# |
| 192 | +# (This differs from other indirect-submodule imports that are unambiguously non-public |
| 193 | +# and subject to immediate removal. Here, the public git.util module, though different, |
| 194 | +# makes less discoverable that the expression `git.util` refers to a non-public |
| 195 | +# attribute of the git module.) |
| 196 | +# |
| 197 | +# This had come about by a wildcard import. Now that all intended imports are explicit, |
| 198 | +# the intuitive but potentially incompatible binding occurs due to the usual rules for |
| 199 | +# Python submodule bindings. So for now we delete that and let __getattr__ handle it. |
| 200 | +# |
| 201 | +del util # type: ignore[name-defined] # noqa: F821 |
| 202 | + |
| 203 | + |
| 204 | +def _warned_import(message: str, fullname: str) -> "ModuleType": |
| 205 | + import importlib |
| 206 | + import warnings |
| 207 | + |
| 208 | + warnings.warn(message, DeprecationWarning, stacklevel=3) |
| 209 | + return importlib.import_module(fullname) |
| 210 | + |
| 211 | + |
| 212 | +def _getattr(name: str) -> Any: |
| 213 | + # TODO: If __version__ is made dynamic and lazily fetched, put that case right here. |
| 214 | + |
| 215 | + if name == "util": |
| 216 | + return _warned_import( |
| 217 | + "The expression `git.util` and the import `from git import util` actually " |
| 218 | + "reference git.index.util, and not the git.util module accessed in " |
| 219 | + '`from git.util import XYZ` or `sys.modules["git.util"]`. This potentially ' |
| 220 | + "confusing behavior is currently preserved for compatibility, but may be " |
| 221 | + "changed in the future and should not be relied on.", |
| 222 | + fullname="git.index.util", |
| 223 | + ) |
| 224 | + |
| 225 | + for names, prefix in ( |
| 226 | + ({"head", "log", "reference", "symbolic", "tag"}, "git.refs"), |
| 227 | + ({"base", "fun", "typ"}, "git.index"), |
| 228 | + ): |
| 229 | + if name not in names: |
| 230 | + continue |
| 231 | + |
| 232 | + fullname = f"{prefix}.{name}" |
| 233 | + |
| 234 | + return _warned_import( |
| 235 | + f"{__name__}.{name} is a private alias of {fullname} and subject to " |
| 236 | + f"immediate removal. Use {fullname} instead.", |
| 237 | + fullname=fullname, |
| 238 | + ) |
| 239 | + |
| 240 | + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") |
| 241 | + |
| 242 | + |
| 243 | +if not TYPE_CHECKING: # Preserve static checking for undefined/misspelled attributes. |
| 244 | + __getattr__ = _getattr |
| 245 | + |
199 | 246 | # { Initialize git executable path
|
| 247 | + |
200 | 248 | GIT_OK = None
|
201 | 249 |
|
202 | 250 |
|
@@ -232,12 +280,9 @@ def refresh(path: Optional[PathLike] = None) -> None:
|
232 | 280 | GIT_OK = True
|
233 | 281 |
|
234 | 282 |
|
235 |
| -# } END initialize git executable path |
236 |
| - |
237 |
| - |
238 |
| -################# |
239 | 283 | try:
|
240 | 284 | refresh()
|
241 | 285 | except Exception as _exc:
|
242 | 286 | raise ImportError("Failed to initialize: {0}".format(_exc)) from _exc
|
243 |
| -################# |
| 287 | + |
| 288 | +# } END initialize git executable path |
0 commit comments