diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/AUTHORS b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/AUTHORS deleted file mode 100644 index 55d6818..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/AUTHORS +++ /dev/null @@ -1,48 +0,0 @@ -GitPython was originally written by Michael Trier. -GitPython 0.2 was partially (re)written by Sebastian Thiel, based on 0.1.6 and git-dulwich. - -Contributors are: - --Michael Trier --Alan Briolat --Florian Apolloner --David Aguilar --Jelmer Vernooij --Steve Frécinaux --Kai Lautaportti --Paul Sowden --Sebastian Thiel --Jonathan Chu --Vincent Driessen --Phil Elson --Bernard `Guyzmo` Pratz --Timothy B. Hartman --Konstantin Popov --Peter Jones --Anson Mansfield --Ken Odegard --Alexis Horgix Chotard --Piotr Babij --Mikuláš Poul --Charles Bouchard-Légaré --Yaroslav Halchenko --Tim Swast --William Luc Ritchie --David Host --A. Jesse Jiryu Davis --Steven Whitman --Stefan Stancu --César Izurieta --Arthur Milchior --Anil Khatri --JJ Graham --Ben Thayer --Dries Kennes --Pratik Anurag --Harmon --Liam Beguin --Ram Rachum --Alba Mendez --Robert Westman --Hugo van Kemenade -Portions derived from other open source works and are clearly marked. diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/INSTALLER b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/LICENSE b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/LICENSE deleted file mode 100644 index 5a9a6f8..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (C) 2008, 2009 Michael Trier and contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -* Neither the name of the GitPython project nor the names of -its contributors may be used to endorse or promote products derived -from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/METADATA b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/METADATA deleted file mode 100644 index 8a04eba..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/METADATA +++ /dev/null @@ -1,33 +0,0 @@ -Metadata-Version: 2.1 -Name: GitPython -Version: 3.1.27 -Summary: GitPython is a python library used to interact with Git repositories -Home-page: https://github.com/gitpython-developers/GitPython -Author: Sebastian Thiel, Michael Trier -Author-email: byronimo@gmail.com, mtrier@gmail.com -License: BSD -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Operating System :: POSIX -Classifier: Operating System :: Microsoft :: Windows -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Typing :: Typed -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -License-File: LICENSE -License-File: AUTHORS -Requires-Dist: gitdb (<5,>=4.0.1) -Requires-Dist: typing-extensions (>=3.7.4.3) ; python_version < "3.8" - -GitPython is a python library used to interact with Git repositories - diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/RECORD b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/RECORD deleted file mode 100644 index e588b40..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/RECORD +++ /dev/null @@ -1,83 +0,0 @@ -GitPython-3.1.27.dist-info/AUTHORS,sha256=vjnd09wZL3p1v8gB5lsk4nj-2nDyHcZEzY_MKrZQyco,1936 -GitPython-3.1.27.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -GitPython-3.1.27.dist-info/LICENSE,sha256=_WV__CzvY9JceMq3gI1BTdA6KC5jiTSR_RHDL5i-Z_s,1521 -GitPython-3.1.27.dist-info/METADATA,sha256=h9Z-ZVEP5r7UES4v0wOH-dyhekIRG0qBBg_7VX5zAFc,1289 -GitPython-3.1.27.dist-info/RECORD,, -GitPython-3.1.27.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -GitPython-3.1.27.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 -GitPython-3.1.27.dist-info/top_level.txt,sha256=0hzDuIp8obv624V3GmbqsagBWkk8ohtGU-Bc1PmTT0o,4 -git/__init__.py,sha256=LIqmpO0UYXoia_6ymWif0fdDpVN1apyh-yuzD1Qmkog,2500 -git/__pycache__/__init__.cpython-310.pyc,, -git/__pycache__/cmd.cpython-310.pyc,, -git/__pycache__/compat.cpython-310.pyc,, -git/__pycache__/config.cpython-310.pyc,, -git/__pycache__/db.cpython-310.pyc,, -git/__pycache__/diff.cpython-310.pyc,, -git/__pycache__/exc.cpython-310.pyc,, -git/__pycache__/remote.cpython-310.pyc,, -git/__pycache__/types.cpython-310.pyc,, -git/__pycache__/util.cpython-310.pyc,, -git/cmd.py,sha256=8QI5KptzHzAEGzfMg2FtQrPaggMAzv_YKwF4-rGhJRI,51897 -git/compat.py,sha256=A__j0NDexK9vm-IP59CveY7V_Epef9Km4wH94nykvGs,2244 -git/config.py,sha256=ABfTzzFy82NkwTKHreMbJF78JC43dAR385LbrUhnc84,34506 -git/db.py,sha256=Ji8Zrdq5Gvo3Hm54gBB7DXFYJE0SgPmoHyAp_5RI3s0,2255 -git/diff.py,sha256=nzQ2ZtSFrvcpgTvKBKlheLLZGdLgmW3xbwjaZQtaJBQ,22587 -git/exc.py,sha256=rtiF2l2ZONIih_yF3DZ_WuDXAocdq0inhjQzGJq5T7o,6079 -git/index/__init__.py,sha256=43ovvVNocVRNiQd4fLqvUMuGGmwhBQ9SsiQ46vkvk1E,89 -git/index/__pycache__/__init__.cpython-310.pyc,, -git/index/__pycache__/base.cpython-310.pyc,, -git/index/__pycache__/fun.cpython-310.pyc,, -git/index/__pycache__/typ.cpython-310.pyc,, -git/index/__pycache__/util.cpython-310.pyc,, -git/index/base.py,sha256=-MV0W-PyJwCYxFb-Klbooaay3uDm-sr8xHAiK_4lXaU,57001 -git/index/fun.py,sha256=Ac9zLk2JAnayb4Gl9QpJ8S2CzNqWDfxFhZT2S9bhWX8,16431 -git/index/typ.py,sha256=8-yL3QhdHXkVaDHfUuk4Kmks1Comrq547Kg48m6H2gA,5516 -git/index/util.py,sha256=t3llCo90s1L_OgPYIqah5AuVU6043XKTaQrmJtUeYjU,3454 -git/objects/__init__.py,sha256=1uMoWicK_mgiQIaikCMsX7uiRWc9US4XUXCouSmH4Dk,703 -git/objects/__pycache__/__init__.cpython-310.pyc,, -git/objects/__pycache__/base.cpython-310.pyc,, -git/objects/__pycache__/blob.cpython-310.pyc,, -git/objects/__pycache__/commit.cpython-310.pyc,, -git/objects/__pycache__/fun.cpython-310.pyc,, -git/objects/__pycache__/tag.cpython-310.pyc,, -git/objects/__pycache__/tree.cpython-310.pyc,, -git/objects/__pycache__/util.cpython-310.pyc,, -git/objects/base.py,sha256=qLgh-OStkOke3yKgwq2ZNFTC45Qsl1UTSI1-fdjR8-w,7759 -git/objects/blob.py,sha256=nXCRt885vuNjI6VRw_fXOZSgQfD9PjXPg3XZIRZkIfM,987 -git/objects/commit.py,sha256=-dXHQvop5HXIqQjuMYIFMNLL2AY9y0a7Gw3ayG8OAHY,25869 -git/objects/fun.py,sha256=vSmm8p4_6ZMOh3Vtwbi65gP1vIFczXF2hXtgHclP-EY,8542 -git/objects/submodule/__init__.py,sha256=OsMeiex7cG6ev2f35IaJ5csH-eXchSoNKCt4HXUG5Ws,93 -git/objects/submodule/__pycache__/__init__.cpython-310.pyc,, -git/objects/submodule/__pycache__/base.cpython-310.pyc,, -git/objects/submodule/__pycache__/root.cpython-310.pyc,, -git/objects/submodule/__pycache__/util.cpython-310.pyc,, -git/objects/submodule/base.py,sha256=QOZfeU4mQVyGFLKGWS8YTRD8DtN_lVjhtPsw6N9Upqs,58774 -git/objects/submodule/root.py,sha256=cy7wRBLJwqNXGm6bK0tgEucYX7lx-KNQS-WTTlEXvig,18288 -git/objects/submodule/util.py,sha256=iX1EYGDhVrr1PG8729zQPm2GL47FkE9MPqPYC8C_h-o,3358 -git/objects/tag.py,sha256=mqlDG5UyScqHEnwDXRBPwbMcPrTZnhMiezpDM7DkEss,3764 -git/objects/tree.py,sha256=ly7fgePvItjB-B69AvdlFXrekH8MixOMauO31sCpg7E,14292 -git/objects/util.py,sha256=gx1jzp1oiqdlADrWu6oorIF3FwXJZtaprzxPlyY9u8I,22466 -git/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -git/refs/__init__.py,sha256=PMF97jMUcivbCCEJnl2zTs-YtECNFp8rL8GHK8AitXU,203 -git/refs/__pycache__/__init__.cpython-310.pyc,, -git/refs/__pycache__/head.cpython-310.pyc,, -git/refs/__pycache__/log.cpython-310.pyc,, -git/refs/__pycache__/reference.cpython-310.pyc,, -git/refs/__pycache__/remote.cpython-310.pyc,, -git/refs/__pycache__/symbolic.cpython-310.pyc,, -git/refs/__pycache__/tag.cpython-310.pyc,, -git/refs/head.py,sha256=UbIuWCb9WI87DZY6puX92YaHLDnh-D6DkONwDjyxcvM,9626 -git/refs/log.py,sha256=8ZTiE7KV4SVAlx14xR7xVG1uh_jFgsSNZ_6QSMh4vpA,12061 -git/refs/reference.py,sha256=28aB_lnYLKIXx2wvy_y87P0EDIuNiCsGLgBmV-29qP0,5405 -git/refs/remote.py,sha256=3iSjMHPlQCUA3QacJ-CHK60yihCmGeyVnuTh-zTq7qo,2556 -git/refs/symbolic.py,sha256=nBmwXAK48w-vmFq-tAl40XlemKsPxiu7aDnyctlWA5o,29739 -git/refs/tag.py,sha256=xboM_oFCFXakpZvvb-bn4GgLcsddPvNIuEK9E3gNuNs,4273 -git/remote.py,sha256=VohJ7s27AC0RCP8EgG-_oMjTE1nxOqnQTHSulhqglnY,41704 -git/repo/__init__.py,sha256=XMpdeowJRtTEd80jAcrKSQfMu2JZGMfPlpuIYHG2ZCk,80 -git/repo/__pycache__/__init__.cpython-310.pyc,, -git/repo/__pycache__/base.cpython-310.pyc,, -git/repo/__pycache__/fun.cpython-310.pyc,, -git/repo/base.py,sha256=mF3lmjtg81KQfst2RZad290fp-bwsEG28dEh7NYkmf0,51847 -git/repo/fun.py,sha256=yjsY_sna6XaUzB0ZANiIMwu97QMxWAWpWtoj4pynqg4,12713 -git/types.py,sha256=L9yBmFn6XUdV9BJgnKSwXPcYEPj9mACl7VuIi7FcNQ8,3072 -git/util.py,sha256=AAebYTIADbA46Iu5rsUqCvCPAM2w-PlbMp2-sm6Wdok,39531 diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/REQUESTED b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/WHEEL b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/WHEEL deleted file mode 100644 index becc9a6..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.37.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/top_level.txt b/venv/Lib/site-packages/GitPython-3.1.27.dist-info/top_level.txt deleted file mode 100644 index 5664e30..0000000 --- a/venv/Lib/site-packages/GitPython-3.1.27.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -git diff --git a/venv/Lib/site-packages/_distutils_hack/__init__.py b/venv/Lib/site-packages/_distutils_hack/__init__.py deleted file mode 100644 index f987a53..0000000 --- a/venv/Lib/site-packages/_distutils_hack/__init__.py +++ /dev/null @@ -1,222 +0,0 @@ -# don't import any costly modules -import sys -import os - - -is_pypy = '__pypy__' in sys.builtin_module_names - - -def warn_distutils_present(): - if 'distutils' not in sys.modules: - return - if is_pypy and sys.version_info < (3, 7): - # PyPy for 3.6 unconditionally imports distutils, so bypass the warning - # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 - return - import warnings - - warnings.warn( - "Distutils was imported before Setuptools, but importing Setuptools " - "also replaces the `distutils` module in `sys.modules`. This may lead " - "to undesirable behaviors or errors. To avoid these issues, avoid " - "using distutils directly, ensure that setuptools is installed in the " - "traditional way (e.g. not an editable install), and/or make sure " - "that setuptools is always imported before distutils." - ) - - -def clear_distutils(): - if 'distutils' not in sys.modules: - return - import warnings - - warnings.warn("Setuptools is replacing distutils.") - mods = [ - name - for name in sys.modules - if name == "distutils" or name.startswith("distutils.") - ] - for name in mods: - del sys.modules[name] - - -def enabled(): - """ - Allow selection of distutils by environment variable. - """ - which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local') - return which == 'local' - - -def ensure_local_distutils(): - import importlib - - clear_distutils() - - # With the DistutilsMetaFinder in place, - # perform an import to cause distutils to be - # loaded from setuptools._distutils. Ref #2906. - with shim(): - importlib.import_module('distutils') - - # check that submodules load as expected - core = importlib.import_module('distutils.core') - assert '_distutils' in core.__file__, core.__file__ - assert 'setuptools._distutils.log' not in sys.modules - - -def do_override(): - """ - Ensure that the local copy of distutils is preferred over stdlib. - - See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 - for more motivation. - """ - if enabled(): - warn_distutils_present() - ensure_local_distutils() - - -class _TrivialRe: - def __init__(self, *patterns): - self._patterns = patterns - - def match(self, string): - return all(pat in string for pat in self._patterns) - - -class DistutilsMetaFinder: - def find_spec(self, fullname, path, target=None): - # optimization: only consider top level modules and those - # found in the CPython test suite. - if path is not None and not fullname.startswith('test.'): - return - - method_name = 'spec_for_{fullname}'.format(**locals()) - method = getattr(self, method_name, lambda: None) - return method() - - def spec_for_distutils(self): - if self.is_cpython(): - return - - import importlib - import importlib.abc - import importlib.util - - try: - mod = importlib.import_module('setuptools._distutils') - except Exception: - # There are a couple of cases where setuptools._distutils - # may not be present: - # - An older Setuptools without a local distutils is - # taking precedence. Ref #2957. - # - Path manipulation during sitecustomize removes - # setuptools from the path but only after the hook - # has been loaded. Ref #2980. - # In either case, fall back to stdlib behavior. - return - - class DistutilsLoader(importlib.abc.Loader): - def create_module(self, spec): - mod.__name__ = 'distutils' - return mod - - def exec_module(self, module): - pass - - return importlib.util.spec_from_loader( - 'distutils', DistutilsLoader(), origin=mod.__file__ - ) - - @staticmethod - def is_cpython(): - """ - Suppress supplying distutils for CPython (build and tests). - Ref #2965 and #3007. - """ - return os.path.isfile('pybuilddir.txt') - - def spec_for_pip(self): - """ - Ensure stdlib distutils when running under pip. - See pypa/pip#8761 for rationale. - """ - if self.pip_imported_during_build(): - return - clear_distutils() - self.spec_for_distutils = lambda: None - - @classmethod - def pip_imported_during_build(cls): - """ - Detect if pip is being imported in a build script. Ref #2355. - """ - import traceback - - return any( - cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None) - ) - - @staticmethod - def frame_file_is_setup(frame): - """ - Return True if the indicated frame suggests a setup.py file. - """ - # some frames may not have __file__ (#2940) - return frame.f_globals.get('__file__', '').endswith('setup.py') - - def spec_for_sensitive_tests(self): - """ - Ensure stdlib distutils when running select tests under CPython. - - python/cpython#91169 - """ - clear_distutils() - self.spec_for_distutils = lambda: None - - sensitive_tests = ( - [ - 'test.test_distutils', - 'test.test_peg_generator', - 'test.test_importlib', - ] - if sys.version_info < (3, 10) - else [ - 'test.test_distutils', - ] - ) - - -for name in DistutilsMetaFinder.sensitive_tests: - setattr( - DistutilsMetaFinder, - f'spec_for_{name}', - DistutilsMetaFinder.spec_for_sensitive_tests, - ) - - -DISTUTILS_FINDER = DistutilsMetaFinder() - - -def add_shim(): - DISTUTILS_FINDER in sys.meta_path or insert_shim() - - -class shim: - def __enter__(self): - insert_shim() - - def __exit__(self, exc, value, tb): - remove_shim() - - -def insert_shim(): - sys.meta_path.insert(0, DISTUTILS_FINDER) - - -def remove_shim(): - try: - sys.meta_path.remove(DISTUTILS_FINDER) - except ValueError: - pass diff --git a/venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 1945fd5..0000000 Binary files a/venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc b/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc deleted file mode 100644 index e7f802f..0000000 Binary files a/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/_distutils_hack/override.py b/venv/Lib/site-packages/_distutils_hack/override.py deleted file mode 100644 index 2cc433a..0000000 --- a/venv/Lib/site-packages/_distutils_hack/override.py +++ /dev/null @@ -1 +0,0 @@ -__import__('_distutils_hack').do_override() diff --git a/venv/Lib/site-packages/distutils-precedence.pth b/venv/Lib/site-packages/distutils-precedence.pth deleted file mode 100644 index 7f009fe..0000000 --- a/venv/Lib/site-packages/distutils-precedence.pth +++ /dev/null @@ -1 +0,0 @@ -import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/venv/Lib/site-packages/git/__init__.py b/venv/Lib/site-packages/git/__init__.py deleted file mode 100644 index 3229b59..0000000 --- a/venv/Lib/site-packages/git/__init__.py +++ /dev/null @@ -1,90 +0,0 @@ -# __init__.py -# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors -# -# This module is part of GitPython and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php -# flake8: noqa -#@PydevCodeAnalysisIgnore -from git.exc import * # @NoMove @IgnorePep8 -import inspect -import os -import sys -import os.path as osp - -from typing import Optional -from git.types import PathLike - -__version__ = '3.1.27' - - -#{ Initialization -def _init_externals() -> None: - """Initialize external projects by putting them into the path""" - if __version__ == '3.1.27' and 'PYOXIDIZER' not in os.environ: - sys.path.insert(1, osp.join(osp.dirname(__file__), 'ext', 'gitdb')) - - try: - import gitdb - except ImportError as e: - raise ImportError("'gitdb' could not be found in your PYTHONPATH") from e - # END verify import - -#} END initialization - - -################# -_init_externals() -################# - -#{ Imports - -try: - from git.config import GitConfigParser # @NoMove @IgnorePep8 - from git.objects import * # @NoMove @IgnorePep8 - from git.refs import * # @NoMove @IgnorePep8 - from git.diff import * # @NoMove @IgnorePep8 - from git.db import * # @NoMove @IgnorePep8 - from git.cmd import Git # @NoMove @IgnorePep8 - from git.repo import Repo # @NoMove @IgnorePep8 - from git.remote import * # @NoMove @IgnorePep8 - from git.index import * # @NoMove @IgnorePep8 - from git.util import ( # @NoMove @IgnorePep8 - LockFile, - BlockingLockFile, - Stats, - Actor, - rmtree, - ) -except GitError as exc: - raise ImportError('%s: %s' % (exc.__class__.__name__, exc)) from exc - -#} END imports - -__all__ = [name for name, obj in locals().items() - if not (name.startswith('_') or inspect.ismodule(obj))] - - -#{ Initialize git executable path -GIT_OK = None - - -def refresh(path: Optional[PathLike] = None) -> None: - """Convenience method for setting the git executable path.""" - global GIT_OK - GIT_OK = False - - if not Git.refresh(path=path): - return - if not FetchInfo.refresh(): - return - - GIT_OK = True -#} END initialize git executable path - - -################# -try: - refresh() -except Exception as exc: - raise ImportError('Failed to initialize: {0}'.format(exc)) from exc -################# diff --git a/venv/Lib/site-packages/git/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 0793eb0..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/cmd.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/cmd.cpython-310.pyc deleted file mode 100644 index 6608548..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/cmd.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/compat.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/compat.cpython-310.pyc deleted file mode 100644 index a5fbdb4..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/compat.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/config.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/config.cpython-310.pyc deleted file mode 100644 index 3e7c44a..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/config.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/db.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/db.cpython-310.pyc deleted file mode 100644 index c8c2a4b..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/db.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/diff.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/diff.cpython-310.pyc deleted file mode 100644 index e16ca65..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/diff.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/exc.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/exc.cpython-310.pyc deleted file mode 100644 index 926439e..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/exc.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/remote.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/remote.cpython-310.pyc deleted file mode 100644 index 2135be1..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/remote.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/types.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/types.cpython-310.pyc deleted file mode 100644 index 9fb7dc5..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/types.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/__pycache__/util.cpython-310.pyc b/venv/Lib/site-packages/git/__pycache__/util.cpython-310.pyc deleted file mode 100644 index d8645f6..0000000 Binary files a/venv/Lib/site-packages/git/__pycache__/util.cpython-310.pyc and /dev/null differ diff --git a/venv/Lib/site-packages/git/cmd.py b/venv/Lib/site-packages/git/cmd.py deleted file mode 100644 index 4f05698..0000000 --- a/venv/Lib/site-packages/git/cmd.py +++ /dev/null @@ -1,1286 +0,0 @@ -# cmd.py -# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors -# -# This module is part of GitPython and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php -from __future__ import annotations -from contextlib import contextmanager -import io -import logging -import os -import signal -from subprocess import ( - call, - Popen, - PIPE, - DEVNULL -) -import subprocess -import threading -from textwrap import dedent - -from git.compat import ( - defenc, - force_bytes, - safe_decode, - is_posix, - is_win, -) -from git.exc import CommandError -from git.util import is_cygwin_git, cygpath, expand_path, remove_password_if_present - -from .exc import ( - GitCommandError, - GitCommandNotFound -) -from .util import ( - LazyMixin, - stream_copy, -) - -# typing --------------------------------------------------------------------------- - -from typing import (Any, AnyStr, BinaryIO, Callable, Dict, IO, Iterator, List, Mapping, - Sequence, TYPE_CHECKING, TextIO, Tuple, Union, cast, overload) - -from git.types import PathLike, Literal, TBD - -if TYPE_CHECKING: - from git.repo.base import Repo - from git.diff import DiffIndex - - -# --------------------------------------------------------------------------------- - -execute_kwargs = {'istream', 'with_extended_output', - 'with_exceptions', 'as_process', 'stdout_as_string', - 'output_stream', 'with_stdout', 'kill_after_timeout', - 'universal_newlines', 'shell', 'env', 'max_chunk_size'} - -log = logging.getLogger(__name__) -log.addHandler(logging.NullHandler()) - -__all__ = ('Git',) - - -# ============================================================================== -## @name Utilities -# ------------------------------------------------------------------------------ -# Documentation -## @{ - -def handle_process_output(process: 'Git.AutoInterrupt' | Popen, - stdout_handler: Union[None, - Callable[[AnyStr], None], - Callable[[List[AnyStr]], None], - Callable[[bytes, 'Repo', 'DiffIndex'], None]], - stderr_handler: Union[None, - Callable[[AnyStr], None], - Callable[[List[AnyStr]], None]], - finalizer: Union[None, - Callable[[Union[subprocess.Popen, 'Git.AutoInterrupt']], None]] = None, - decode_streams: bool = True, - kill_after_timeout: Union[None, float] = None) -> None: - """Registers for notifications to learn that process output is ready to read, and dispatches lines to - the respective line handlers. - This function returns once the finalizer returns - - :return: result of finalizer - :param process: subprocess.Popen instance - :param stdout_handler: f(stdout_line_string), or None - :param stderr_handler: f(stderr_line_string), or None - :param finalizer: f(proc) - wait for proc to finish - :param decode_streams: - Assume stdout/stderr streams are binary and decode them before pushing \ - their contents to handlers. - Set it to False if `universal_newline == True` (then streams are in text-mode) - or if decoding must happen later (i.e. for Diffs). - :param kill_after_timeout: - float or None, Default = None - To specify a timeout in seconds for the git command, after which the process - should be killed. - """ - # Use 2 "pump" threads and wait for both to finish. - def pump_stream(cmdline: List[str], name: str, stream: Union[BinaryIO, TextIO], is_decode: bool, - handler: Union[None, Callable[[Union[bytes, str]], None]]) -> None: - try: - for line in stream: - if handler: - if is_decode: - assert isinstance(line, bytes) - line_str = line.decode(defenc) - handler(line_str) - else: - handler(line) - - except Exception as ex: - log.error(f"Pumping {name!r} of cmd({remove_password_if_present(cmdline)}) failed due to: {ex!r}") - if "I/O operation on closed file" not in str(ex): - # Only reraise if the error was not due to the stream closing - raise CommandError([f'<{name}-pump>'] + remove_password_if_present(cmdline), ex) from ex - finally: - stream.close() - - if hasattr(process, 'proc'): - process = cast('Git.AutoInterrupt', process) - cmdline: str | Tuple[str, ...] | List[str] = getattr(process.proc, 'args', '') - p_stdout = process.proc.stdout if process.proc else None - p_stderr = process.proc.stderr if process.proc else None - else: - process = cast(Popen, process) - cmdline = getattr(process, 'args', '') - p_stdout = process.stdout - p_stderr = process.stderr - - if not isinstance(cmdline, (tuple, list)): - cmdline = cmdline.split() - - pumps: List[Tuple[str, IO, Callable[..., None] | None]] = [] - if p_stdout: - pumps.append(('stdout', p_stdout, stdout_handler)) - if p_stderr: - pumps.append(('stderr', p_stderr, stderr_handler)) - - threads: List[threading.Thread] = [] - - for name, stream, handler in pumps: - t = threading.Thread(target=pump_stream, - args=(cmdline, name, stream, decode_streams, handler)) - t.daemon = True - t.start() - threads.append(t) - - ## FIXME: Why Join?? Will block if `stdin` needs feeding... - # - for t in threads: - t.join(timeout=kill_after_timeout) - if t.is_alive(): - if isinstance(process, Git.AutoInterrupt): - process._terminate() - else: # Don't want to deal with the other case - raise RuntimeError("Thread join() timed out in cmd.handle_process_output()." - f" kill_after_timeout={kill_after_timeout} seconds") - if stderr_handler: - error_str: Union[str, bytes] = ( - "error: process killed because it timed out." - f" kill_after_timeout={kill_after_timeout} seconds") - if not decode_streams and isinstance(p_stderr, BinaryIO): - # Assume stderr_handler needs binary input - error_str = cast(str, error_str) - error_str = error_str.encode() - # We ignore typing on the next line because mypy does not like - # the way we inferred that stderr takes str or bytes - stderr_handler(error_str) # type: ignore - - if finalizer: - return finalizer(process) - else: - return None - - -def dashify(string: str) -> str: - return string.replace('_', '-') - - -def slots_to_dict(self: object, exclude: Sequence[str] = ()) -> Dict[str, Any]: - return {s: getattr(self, s) for s in self.__slots__ if s not in exclude} - - -def dict_to_slots_and__excluded_are_none(self: object, d: Mapping[str, Any], excluded: Sequence[str] = ()) -> None: - for k, v in d.items(): - setattr(self, k, v) - for k in excluded: - setattr(self, k, None) - -## -- End Utilities -- @} - - -# value of Windows process creation flag taken from MSDN -CREATE_NO_WINDOW = 0x08000000 - -## CREATE_NEW_PROCESS_GROUP is needed to allow killing it afterwards, -# see https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal -PROC_CREATIONFLAGS = (CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore[attr-defined] - if is_win else 0) # mypy error if not windows - - -class Git(LazyMixin): - - """ - The Git class manages communication with the Git binary. - - It provides a convenient interface to calling the Git binary, such as in:: - - g = Git( git_dir ) - g.init() # calls 'git init' program - rval = g.ls_files() # calls 'git ls-files' program - - ``Debugging`` - Set the GIT_PYTHON_TRACE environment variable print each invocation - of the command to stdout. - Set its value to 'full' to see details about the returned values. - """ - __slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info", - "_git_options", "_persistent_git_options", "_environment") - - _excluded_ = ('cat_file_all', 'cat_file_header', '_version_info') - - def __getstate__(self) -> Dict[str, Any]: - return slots_to_dict(self, exclude=self._excluded_) - - def __setstate__(self, d: Dict[str, Any]) -> None: - dict_to_slots_and__excluded_are_none(self, d, excluded=self._excluded_) - - # CONFIGURATION - - git_exec_name = "git" # default that should work on linux and windows - - # Enables debugging of GitPython's git commands - GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False) - - # If True, a shell will be used when executing git commands. - # This should only be desirable on Windows, see https://github.com/gitpython-developers/GitPython/pull/126 - # and check `git/test_repo.py:TestRepo.test_untracked_files()` TC for an example where it is required. - # Override this value using `Git.USE_SHELL = True` - USE_SHELL = False - - # Provide the full path to the git executable. Otherwise it assumes git is in the path - _git_exec_env_var = "GIT_PYTHON_GIT_EXECUTABLE" - _refresh_env_var = "GIT_PYTHON_REFRESH" - GIT_PYTHON_GIT_EXECUTABLE = None - # note that the git executable is actually found during the refresh step in - # the top level __init__ - - @classmethod - def refresh(cls, path: Union[None, PathLike] = None) -> bool: - """This gets called by the refresh function (see the top level - __init__). - """ - # discern which path to refresh with - if path is not None: - new_git = os.path.expanduser(path) - new_git = os.path.abspath(new_git) - else: - new_git = os.environ.get(cls._git_exec_env_var, cls.git_exec_name) - - # keep track of the old and new git executable path - old_git = cls.GIT_PYTHON_GIT_EXECUTABLE - cls.GIT_PYTHON_GIT_EXECUTABLE = new_git - - # test if the new git executable path is valid - - # - a GitCommandNotFound error is spawned by ourselves - # - a PermissionError is spawned if the git executable provided - # cannot be executed for whatever reason - - has_git = False - try: - cls().version() - has_git = True - except (GitCommandNotFound, PermissionError): - pass - - # warn or raise exception if test failed - if not has_git: - err = dedent("""\ - Bad git executable. - The git executable must be specified in one of the following ways: - - be included in your $PATH - - be set via $%s - - explicitly set via git.refresh() - """) % cls._git_exec_env_var - - # revert to whatever the old_git was - cls.GIT_PYTHON_GIT_EXECUTABLE = old_git - - if old_git is None: - # on the first refresh (when GIT_PYTHON_GIT_EXECUTABLE is - # None) we only are quiet, warn, or error depending on the - # GIT_PYTHON_REFRESH value - - # determine what the user wants to happen during the initial - # refresh we expect GIT_PYTHON_REFRESH to either be unset or - # be one of the following values: - # 0|q|quiet|s|silence - # 1|w|warn|warning - # 2|r|raise|e|error - - mode = os.environ.get(cls._refresh_env_var, "raise").lower() - - quiet = ["quiet", "q", "silence", "s", "none", "n", "0"] - warn = ["warn", "w", "warning", "1"] - error = ["error", "e", "raise", "r", "2"] - - if mode in quiet: - pass - elif mode in warn or mode in error: - err = dedent("""\ - %s - All git commands will error until this is rectified. - - This initial warning can be silenced or aggravated in the future by setting the - $%s environment variable. Use one of the following values: - - %s: for no warning or exception - - %s: for a printed warning - - %s: for a raised exception - - Example: - export %s=%s - """) % ( - err, - cls._refresh_env_var, - "|".join(quiet), - "|".join(warn), - "|".join(error), - cls._refresh_env_var, - quiet[0]) - - if mode in warn: - print("WARNING: %s" % err) - else: - raise ImportError(err) - else: - err = dedent("""\ - %s environment variable has been set but it has been set with an invalid value. - - Use only the following values: - - %s: for no warning or exception - - %s: for a printed warning - - %s: for a raised exception - """) % ( - cls._refresh_env_var, - "|".join(quiet), - "|".join(warn), - "|".join(error)) - raise ImportError(err) - - # we get here if this was the init refresh and the refresh mode - # was not error, go ahead and set the GIT_PYTHON_GIT_EXECUTABLE - # such that we discern the difference between a first import - # and a second import - cls.GIT_PYTHON_GIT_EXECUTABLE = cls.git_exec_name - else: - # after the first refresh (when GIT_PYTHON_GIT_EXECUTABLE - # is no longer None) we raise an exception - raise GitCommandNotFound("git", err) - - return has_git - - @classmethod - def is_cygwin(cls) -> bool: - return is_cygwin_git(cls.GIT_PYTHON_GIT_EXECUTABLE) - - @overload - @classmethod - def polish_url(cls, url: str, is_cygwin: Literal[False] = ...) -> str: - ... - - @overload - @classmethod - def polish_url(cls, url: str, is_cygwin: Union[None, bool] = None) -> str: - ... - - @classmethod - def polish_url(cls, url: str, is_cygwin: Union[None, bool] = None) -> PathLike: - if is_cygwin is None: - is_cygwin = cls.is_cygwin() - - if is_cygwin: - url = cygpath(url) - else: - """Remove any backslahes from urls to be written in config files. - - Windows might create config-files containing paths with backslashed, - but git stops liking them as it will escape the backslashes. - Hence we undo the escaping just to be sure. - """ - url = os.path.expandvars(url) - if url.startswith('~'): - url = os.path.expanduser(url) - url = url.replace("\\\\", "\\").replace("\\", "/") - return url - - class AutoInterrupt(object): - """Kill/Interrupt the stored process instance once this instance goes out of scope. It is - used to prevent processes piling up in case iterators stop reading. - Besides all attributes are wired through to the contained process object. - - The wait method was overridden to perform automatic status code checking - and possibly raise.""" - - __slots__ = ("proc", "args", "status") - - # If this is non-zero it will override any status code during - # _terminate, used to prevent race conditions in testing - _status_code_if_terminate: int = 0 - - def __init__(self, proc: Union[None, subprocess.Popen], args: Any) -> None: - self.proc = proc - self.args = args - self.status: Union[int, None] = None - - def _terminate(self) -> None: - """Terminate the underlying process""" - if self.proc is None: - return - - proc = self.proc - self.proc = None - if proc.stdin: - proc.stdin.close() - if proc.stdout: - proc.stdout.close() - if proc.stderr: - proc.stderr.close() - # did the process finish already so we have a return code ? - try: - if proc.poll() is not None: - self.status = self._status_code_if_terminate or proc.poll() - return None - except OSError as ex: - log.info("Ignored error after process had died: %r", ex) - - # can be that nothing really exists anymore ... - if os is None or getattr(os, 'kill', None) is None: - return None - - # try to kill it - try: - proc.terminate() - status = proc.wait() # ensure process goes away - - self.status = self._status_code_if_terminate or status - except OSError as ex: - log.info("Ignored error after process had died: %r", ex) - except AttributeError: - # try windows - # for some reason, providing None for stdout/stderr still prints something. This is why - # we simply use the shell and redirect to nul. Its slower than CreateProcess, question - # is whether we really want to see all these messages. Its annoying no matter what. - if is_win: - call(("TASKKILL /F /T /PID %s 2>nul 1>nul" % str(proc.pid)), shell=True) - # END exception handling - - def __del__(self) -> None: - self._terminate() - - def __getattr__(self, attr: str) -> Any: - return getattr(self.proc, attr) - - # TODO: Bad choice to mimic `proc.wait()` but with different args. - def wait(self, stderr: Union[None, str, bytes] = b'') -> int: - """Wait for the process and return its status code. - - :param stderr: Previously read value of stderr, in case stderr is already closed. - :warn: may deadlock if output or error pipes are used and not handled separately. - :raise GitCommandError: if the return status is not 0""" - if stderr is None: - stderr_b = b'' - stderr_b = force_bytes(data=stderr, encoding='utf-8') - status: Union[int, None] - if self.proc is not None: - status = self.proc.wait() - p_stderr = self.proc.stderr - else: # Assume the underlying proc was killed earlier or never existed - status = self.status - p_stderr = None - - def read_all_from_possibly_closed_stream(stream: Union[IO[bytes], None]) -> bytes: - if stream: - try: - return stderr_b + force_bytes(stream.read()) - except ValueError: - return stderr_b or b'' - else: - return stderr_b or b'' - - # END status handling - - if status != 0: - errstr = read_all_from_possibly_closed_stream(p_stderr) - log.debug('AutoInterrupt wait stderr: %r' % (errstr,)) - raise GitCommandError(remove_password_if_present(self.args), status, errstr) - return status - - # END auto interrupt - - class CatFileContentStream(object): - - """Object representing a sized read-only stream returning the contents of - an object. - It behaves like a stream, but counts the data read and simulates an empty - stream once our sized content region is empty. - If not all data is read to the end of the objects's lifetime, we read the - rest to assure the underlying stream continues to work""" - - __slots__: Tuple[str, ...] = ('_stream', '_nbr', '_size') - - def __init__(self, size: int, stream: IO[bytes]) -> None: - self._stream = stream - self._size = size - self._nbr = 0 # num bytes read - - # special case: if the object is empty, has null bytes, get the - # final newline right away. - if size == 0: - stream.read(1) - # END handle empty streams - - def read(self, size: int = -1) -> bytes: - bytes_left = self._size - self._nbr - if bytes_left == 0: - return b'' - if size > -1: - # assure we don't try to read past our limit - size = min(bytes_left, size) - else: - # they try to read all, make sure its not more than what remains - size = bytes_left - # END check early depletion - data = self._stream.read(size) - self._nbr += len(data) - - # check for depletion, read our final byte to make the stream usable by others - if self._size - self._nbr == 0: - self._stream.read(1) # final newline - # END finish reading - return data - - def readline(self, size: int = -1) -> bytes: - if self._nbr == self._size: - return b'' - - # clamp size to lowest allowed value - bytes_left = self._size - self._nbr - if size > -1: - size = min(bytes_left, size) - else: - size = bytes_left - # END handle size - - data = self._stream.readline(size) - self._nbr += len(data) - - # handle final byte - if self._size - self._nbr == 0: - self._stream.read(1) - # END finish reading - - return data - - def readlines(self, size: int = -1) -> List[bytes]: - if self._nbr == self._size: - return [] - - # leave all additional logic to our readline method, we just check the size - out = [] - nbr = 0 - while True: - line = self.readline() - if not line: - break - out.append(line) - if size > -1: - nbr += len(line) - if nbr > size: - break - # END handle size constraint - # END readline loop - return out - - # skipcq: PYL-E0301 - def __iter__(self) -> 'Git.CatFileContentStream': - return self - - def __next__(self) -> bytes: - return next(self) - - def next(self) -> bytes: - line = self.readline() - if not line: - raise StopIteration - - return line - - def __del__(self) -> None: - bytes_left = self._size - self._nbr - if bytes_left: - # read and discard - seeking is impossible within a stream - # includes terminating newline - self._stream.read(bytes_left + 1) - # END handle incomplete read - - def __init__(self, working_dir: Union[None, PathLike] = None): - """Initialize this instance with: - - :param working_dir: - Git directory we should work in. If None, we always work in the current - directory as returned by os.getcwd(). - It is meant to be the working tree directory if available, or the - .git directory in case of bare repositories.""" - super(Git, self).__init__() - self._working_dir = expand_path(working_dir) - self._git_options: Union[List[str], Tuple[str, ...]] = () - self._persistent_git_options: List[str] = [] - - # Extra environment variables to pass to git commands - self._environment: Dict[str, str] = {} - - # cached command slots - self.cat_file_header: Union[None, TBD] = None - self.cat_file_all: Union[None, TBD] = None - - def __getattr__(self, name: str) -> Any: - """A convenience method as it allows to call the command as if it was - an object. - :return: Callable object that will execute call _call_process with your arguments.""" - if name[0] == '_': - return LazyMixin.__getattr__(self, name) - return lambda *args, **kwargs: self._call_process(name, *args, **kwargs) - - def set_persistent_git_options(self, **kwargs: Any) -> None: - """Specify command line options to the git executable - for subsequent subcommand calls - - :param kwargs: - is a dict of keyword arguments. - these arguments are passed as in _call_process - but will be passed to the git command rather than - the subcommand. - """ - - self._persistent_git_options = self.transform_kwargs( - split_single_char_options=True, **kwargs) - - def _set_cache_(self, attr: str) -> None: - if attr == '_version_info': - # We only use the first 4 numbers, as everything else could be strings in fact (on windows) - process_version = self._call_process('version') # should be as default *args and **kwargs used - version_numbers = process_version.split(' ')[2] - - self._version_info = cast(Tuple[int, int, int, int], - tuple(int(n) for n in version_numbers.split('.')[:4] if n.isdigit()) - ) - else: - super(Git, self)._set_cache_(attr) - # END handle version info - - @ property - def working_dir(self) -> Union[None, PathLike]: - """:return: Git directory we are working on""" - return self._working_dir - - @ property - def version_info(self) -> Tuple[int, int, int, int]: - """ - :return: tuple(int, int, int, int) tuple with integers representing the major, minor - and additional version numbers as parsed from git version. - This value is generated on demand and is cached""" - return self._version_info - - @ overload - def execute(self, - command: Union[str, Sequence[Any]], - *, - as_process: Literal[True] - ) -> 'AutoInterrupt': - ... - - @ overload - def execute(self, - command: Union[str, Sequence[Any]], - *, - as_process: Literal[False] = False, - stdout_as_string: Literal[True] - ) -> Union[str, Tuple[int, str, str]]: - ... - - @ overload - def execute(self, - command: Union[str, Sequence[Any]], - *, - as_process: Literal[False] = False, - stdout_as_string: Literal[False] = False - ) -> Union[bytes, Tuple[int, bytes, str]]: - ... - - @ overload - def execute(self, - command: Union[str, Sequence[Any]], - *, - with_extended_output: Literal[False], - as_process: Literal[False], - stdout_as_string: Literal[True] - ) -> str: - ... - - @ overload - def execute(self, - command: Union[str, Sequence[Any]], - *, - with_extended_output: Literal[False], - as_process: Literal[False], - stdout_as_string: Literal[False] - ) -> bytes: - ... - - def execute(self, - command: Union[str, Sequence[Any]], - istream: Union[None, BinaryIO] = None, - with_extended_output: bool = False, - with_exceptions: bool = True, - as_process: bool = False, - output_stream: Union[None, BinaryIO] = None, - stdout_as_string: bool = True, - kill_after_timeout: Union[None, float] = None, - with_stdout: bool = True, - universal_newlines: bool = False, - shell: Union[None, bool] = None, - env: Union[None, Mapping[str, str]] = None, - max_chunk_size: int = io.DEFAULT_BUFFER_SIZE, - **subprocess_kwargs: Any - ) -> Union[str, bytes, Tuple[int, Union[str, bytes], str], AutoInterrupt]: - """Handles executing the command on the shell and consumes and returns - the returned information (stdout) - - :param command: - The command argument list to execute. - It should be a string, or a sequence of program arguments. The - program to execute is the first item in the args sequence or string. - - :param istream: - Standard input filehandle passed to subprocess.Popen. - - :param with_extended_output: - Whether to return a (status, stdout, stderr) tuple. - - :param with_exceptions: - Whether to raise an exception when git returns a non-zero status. - - :param as_process: - Whether to return the created process instance directly from which - streams can be read on demand. This will render with_extended_output and - with_exceptions ineffective - the caller will have - to deal with the details himself. - It is important to note that the process will be placed into an AutoInterrupt - wrapper that will interrupt the process once it goes out of scope. If you - use the command in iterators, you should pass the whole process instance - instead of a single stream. - - :param output_stream: - If set to a file-like object, data produced by the git command will be - output to the given stream directly. - This feature only has any effect if as_process is False. Processes will - always be created with a pipe due to issues with subprocess. - This merely is a workaround as data will be copied from the - output pipe to the given output stream directly. - Judging from the implementation, you shouldn't use this flag ! - - :param stdout_as_string: - if False, the commands standard output will be bytes. Otherwise, it will be - decoded into a string using the default encoding (usually utf-8). - The latter can fail, if the output contains binary data. - - :param env: - A dictionary of environment variables to be passed to `subprocess.Popen`. - - :param max_chunk_size: - Maximum number of bytes in one chunk of data passed to the output_stream in - one invocation of write() method. If the given number is not positive then - the default value is used. - - :param subprocess_kwargs: - Keyword arguments to be passed to subprocess.Popen. Please note that - some of the valid kwargs are already set by this method, the ones you - specify may not be the same ones. - - :param with_stdout: If True, default True, we open stdout on the created process - :param universal_newlines: - if True, pipes will be opened as text, and lines are split at - all known line endings. - :param shell: - Whether to invoke commands through a shell (see `Popen(..., shell=True)`). - It overrides :attr:`USE_SHELL` if it is not `None`. - :param kill_after_timeout: - To specify a timeout in seconds for the git command, after which the process - should be killed. This will have no effect if as_process is set to True. It is - set to None by default and will let the process run until the timeout is - explicitly specified. This feature is not supported on Windows. It's also worth - noting that kill_after_timeout uses SIGKILL, which can have negative side - effects on a repository. For example, stale locks in case of git gc could - render the repository incapable of accepting changes until the lock is manually - removed. - - :return: - * str(output) if extended_output = False (Default) - * tuple(int(status), str(stdout), str(stderr)) if extended_output = True - - if output_stream is True, the stdout value will be your output stream: - * output_stream if extended_output = False - * tuple(int(status), output_stream, str(stderr)) if extended_output = True - - Note git is executed with LC_MESSAGES="C" to ensure consistent - output regardless of system language. - - :raise GitCommandError: - - :note: - If you add additional keyword arguments to the signature of this method, - you must update the execute_kwargs tuple housed in this module.""" - # Remove password for the command if present - redacted_command = remove_password_if_present(command) - if self.GIT_PYTHON_TRACE and (self.GIT_PYTHON_TRACE != 'full' or as_process): - log.info(' '.join(redacted_command)) - - # Allow the user to have the command executed in their working dir. - try: - cwd = self._working_dir or os.getcwd() # type: Union[None, str] - if not os.access(str(cwd), os.X_OK): - cwd = None - except FileNotFoundError: - cwd = None - - # Start the process - inline_env = env - env = os.environ.copy() - # Attempt to force all output to plain ascii english, which is what some parsing code - # may expect. - # According to stackoverflow (http://goo.gl/l74GC8), we are setting LANGUAGE as well - # just to be sure. - env["LANGUAGE"] = "C" - env["LC_ALL"] = "C" - env.update(self._environment) - if inline_env is not None: - env.update(inline_env) - - if is_win: - cmd_not_found_exception = OSError - if kill_after_timeout is not None: - raise GitCommandError(redacted_command, '"kill_after_timeout" feature is not supported on Windows.') - else: - cmd_not_found_exception = FileNotFoundError # NOQA # exists, flake8 unknown @UndefinedVariable - # end handle - - stdout_sink = (PIPE - if with_stdout - else getattr(subprocess, 'DEVNULL', None) or open(os.devnull, 'wb')) - istream_ok = "None" - if istream: - istream_ok = "" - log.debug("Popen(%s, cwd=%s, universal_newlines=%s, shell=%s, istream=%s)", - redacted_command, cwd, universal_newlines, shell, istream_ok) - try: - proc = Popen(command, - env=env, - cwd=cwd, - bufsize=-1, - stdin=istream or DEVNULL, - stderr=PIPE, - stdout=stdout_sink, - shell=shell is not None and shell or self.USE_SHELL, - close_fds=is_posix, # unsupported on windows - universal_newlines=universal_newlines, - creationflags=PROC_CREATIONFLAGS, - **subprocess_kwargs - ) - - except cmd_not_found_exception as err: - raise GitCommandNotFound(redacted_command, err) from err - else: - # replace with a typeguard for Popen[bytes]? - proc.stdout = cast(BinaryIO, proc.stdout) - proc.stderr = cast(BinaryIO, proc.stderr) - - if as_process: - return self.AutoInterrupt(proc, command) - - def _kill_process(pid: int) -> None: - """ Callback method to kill a process. """ - p = Popen(['ps', '--ppid', str(pid)], stdout=PIPE, - creationflags=PROC_CREATIONFLAGS) - child_pids = [] - if p.stdout is not None: - for line in p.stdout: - if len(line.split()) > 0: - local_pid = (line.split())[0] - if local_pid.isdigit(): - child_pids.append(int(local_pid)) - try: - # Windows does not have SIGKILL, so use SIGTERM instead - sig = getattr(signal, 'SIGKILL', signal.SIGTERM) - os.kill(pid, sig) - for child_pid in child_pids: - try: - os.kill(child_pid, sig) - except OSError: - pass - kill_check.set() # tell the main routine that the process was killed - except OSError: - # It is possible that the process gets completed in the duration after timeout - # happens and before we try to kill the process. - pass - return - # end - - if kill_after_timeout is not None: - kill_check = threading.Event() - watchdog = threading.Timer(kill_after_timeout, _kill_process, args=(proc.pid,)) - - # Wait for the process to return - status = 0 - stdout_value: Union[str, bytes] = b'' - stderr_value: Union[str, bytes] = b'' - newline = "\n" if universal_newlines else b"\n" - try: - if output_stream is None: - if kill_after_timeout is not None: - watchdog.start() - stdout_value, stderr_value = proc.communicate() - if kill_after_timeout is not None: - watchdog.cancel() - if kill_check.is_set(): - stderr_value = ('Timeout: the command "%s" did not complete in %d ' - 'secs.' % (" ".join(redacted_command), kill_after_timeout)) - if not universal_newlines: - stderr_value = stderr_value.encode(defenc) - # strip trailing "\n" - if stdout_value.endswith(newline): # type: ignore - stdout_value = stdout_value[:-1] - if stderr_value.endswith(newline): # type: ignore - stderr_value = stderr_value[:-1] - - status = proc.returncode - else: - max_chunk_size = max_chunk_size if max_chunk_size and max_chunk_size > 0 else io.DEFAULT_BUFFER_SIZE - stream_copy(proc.stdout, output_stream, max_chunk_size) - stdout_value = proc.stdout.read() - stderr_value = proc.stderr.read() - # strip trailing "\n" - if stderr_value.endswith(newline): # type: ignore - stderr_value = stderr_value[:-1] - status = proc.wait() - # END stdout handling - finally: - proc.stdout.close() - proc.stderr.close() - - if self.GIT_PYTHON_TRACE == 'full': - cmdstr = " ".join(redacted_command) - - def as_text(stdout_value: Union[bytes, str]) -> str: - return not output_stream and safe_decode(stdout_value) or '' - # end - - if stderr_value: - log.info("%s -> %d; stdout: '%s'; stderr: '%s'", - cmdstr, status, as_text(stdout_value), safe_decode(stderr_value)) - elif stdout_value: - log.info("%s -> %d; stdout: '%s'", cmdstr, status, as_text(stdout_value)) - else: - log.info("%s -> %d", cmdstr, status) - # END handle debug printing - - if with_exceptions and status != 0: - raise GitCommandError(redacted_command, status, stderr_value, stdout_value) - - if isinstance(stdout_value, bytes) and stdout_as_string: # could also be output_stream - stdout_value = safe_decode(stdout_value) - - # Allow access to the command's status code - if with_extended_output: - return (status, stdout_value, safe_decode(stderr_value)) - else: - return stdout_value - - def environment(self) -> Dict[str, str]: - return self._environment - - def update_environment(self, **kwargs: Any) -> Dict[str, Union[str, None]]: - """ - Set environment variables for future git invocations. Return all changed - values in a format that can be passed back into this function to revert - the changes: - - ``Examples``:: - - old_env = self.update_environment(PWD='/tmp') - self.update_environment(**old_env) - - :param kwargs: environment variables to use for git processes - :return: dict that maps environment variables to their old values - """ - old_env = {} - for key, value in kwargs.items(): - # set value if it is None - if value is not None: - old_env[key] = self._environment.get(key) - self._environment[key] = value - # remove key from environment if its value is None - elif key in self._environment: - old_env[key] = self._environment[key] - del self._environment[key] - return old_env - - @contextmanager - def custom_environment(self, **kwargs: Any) -> Iterator[None]: - """ - A context manager around the above ``update_environment`` method to restore the - environment back to its previous state after operation. - - ``Examples``:: - - with self.custom_environment(GIT_SSH='/bin/ssh_wrapper'): - repo.remotes.origin.fetch() - - :param kwargs: see update_environment - """ - old_env = self.update_environment(**kwargs) - try: - yield - finally: - self.update_environment(**old_env) - - def transform_kwarg(self, name: str, value: Any, split_single_char_options: bool) -> List[str]: - if len(name) == 1: - if value is True: - return ["-%s" % name] - elif value not in (False, None): - if split_single_char_options: - return ["-%s" % name, "%s" % value] - else: - return ["-%s%s" % (name, value)] - else: - if value is True: - return ["--%s" % dashify(name)] - elif value is not False and value is not None: - return ["--%s=%s" % (dashify(name), value)] - return [] - - def transform_kwargs(self, split_single_char_options: bool = True, **kwargs: Any) -> List[str]: - """Transforms Python style kwargs into git command line options.""" - args = [] - for k, v in kwargs.items(): - if isinstance(v, (list, tuple)): - for value in v: - args += self.transform_kwarg(k, value, split_single_char_options) - else: - args += self.transform_kwarg(k, v, split_single_char_options) - return args - - @classmethod - def __unpack_args(cls, arg_list: Sequence[str]) -> List[str]: - - outlist = [] - if isinstance(arg_list, (list, tuple)): - for arg in arg_list: - outlist.extend(cls.__unpack_args(arg)) - else: - outlist.append(str(arg_list)) - - return outlist - - def __call__(self, **kwargs: Any) -> 'Git': - """Specify command line options to the git executable - for a subcommand call - - :param kwargs: - is a dict of keyword arguments. - these arguments are passed as in _call_process - but will be passed to the git command rather than - the subcommand. - - ``Examples``:: - git(work_tree='/tmp').difftool()""" - self._git_options = self.transform_kwargs( - split_single_char_options=True, **kwargs) - return self - - @overload - def _call_process(self, method: str, *args: None, **kwargs: None - ) -> str: - ... # if no args given, execute called with all defaults - - @overload - def _call_process(self, method: str, - istream: int, - as_process: Literal[True], - *args: Any, **kwargs: Any - ) -> 'Git.AutoInterrupt': ... - - @overload - def _call_process(self, method: str, *args: Any, **kwargs: Any - ) -> Union[str, bytes, Tuple[int, Union[str, bytes], str], 'Git.AutoInterrupt']: - ... - - def _call_process(self, method: str, *args: Any, **kwargs: Any - ) -> Union[str, bytes, Tuple[int, Union[str, bytes], str], 'Git.AutoInterrupt']: - """Run the given git command with the specified arguments and return - the result as a String - - :param method: - is the command. Contained "_" characters will be converted to dashes, - such as in 'ls_files' to call 'ls-files'. - - :param args: - is the list of arguments. If None is included, it will be pruned. - This allows your commands to call git more conveniently as None - is realized as non-existent - - :param kwargs: - It contains key-values for the following: - - the :meth:`execute()` kwds, as listed in :var:`execute_kwargs`; - - "command options" to be converted by :meth:`transform_kwargs()`; - - the `'insert_kwargs_after'` key which its value must match one of ``*args`` - and any cmd-options will be appended after the matched arg. - - Examples:: - - git.rev_list('master', max_count=10, header=True) - - turns into:: - - git rev-list max-count 10 --header master - - :return: Same as ``execute`` - if no args given used execute default (esp. as_process = False, stdout_as_string = True) - and return str """ - # Handle optional arguments prior to calling transform_kwargs - # otherwise these'll end up in args, which is bad. - exec_kwargs = {k: v for k, v in kwargs.items() if k in execute_kwargs} - opts_kwargs = {k: v for k, v in kwargs.items() if k not in execute_kwargs} - - insert_after_this_arg = opts_kwargs.pop('insert_kwargs_after', None) - - # Prepare the argument list - - opt_args = self.transform_kwargs(**opts_kwargs) - ext_args = self.__unpack_args([a for a in args if a is not None]) - - if insert_after_this_arg is None: - args_list = opt_args + ext_args - else: - try: - index = ext_args.index(insert_after_this_arg) - except ValueError as err: - raise ValueError("Couldn't find argument '%s' in args %s to insert cmd options after" - % (insert_after_this_arg, str(ext_args))) from err - # end handle error - args_list = ext_args[:index + 1] + opt_args + ext_args[index + 1:] - # end handle opts_kwargs - - call = [self.GIT_PYTHON_GIT_EXECUTABLE] - - # add persistent git options - call.extend(self._persistent_git_options) - - # add the git options, then reset to empty - # to avoid side_effects - call.extend(self._git_options) - self._git_options = () - - call.append(dashify(method)) - call.extend(args_list) - - return self.execute(call, **exec_kwargs) - - def _parse_object_header(self, header_line: str) -> Tuple[str, str, int]: - """ - :param header_line: - type_string size_as_int - - :return: (hex_sha, type_string, size_as_int) - - :raise ValueError: if the header contains indication for an error due to - incorrect input sha""" - tokens = header_line.split() - if len(tokens) != 3: - if not tokens: - raise ValueError("SHA could not be resolved, git returned: %r" % (header_line.strip())) - else: - raise ValueError("SHA %s could not be resolved, git returned: %r" % (tokens[0], header_line.strip())) - # END handle actual return value - # END error handling - - if len(tokens[0]) != 40: - raise ValueError("Failed to parse header: %r" % header_line) - return (tokens[0], tokens[1], int(tokens[2])) - - def _prepare_ref(self, ref: AnyStr) -> bytes: - # required for command to separate refs on stdin, as bytes - if isinstance(ref, bytes): - # Assume 40 bytes hexsha - bin-to-ascii for some reason returns bytes, not text - refstr: str = ref.decode('ascii') - elif not isinstance(ref, str): - refstr = str(ref) # could be ref-object - else: - refstr = ref - - if not refstr.endswith("\n"): - refstr += "\n" - return refstr.encode(defenc) - - def _get_persistent_cmd(self, attr_name: str, cmd_name: str, *args: Any, **kwargs: Any - ) -> 'Git.AutoInterrupt': - cur_val = getattr(self, attr_name) - if cur_val is not None: - return cur_val - - options = {"istream": PIPE, "as_process": True} - options.update(kwargs) - - cmd = self._call_process(cmd_name, *args, **options) - setattr(self, attr_name, cmd) - cmd = cast('Git.AutoInterrupt', cmd) - return cmd - - def __get_object_header(self, cmd: 'Git.AutoInterrupt', ref: AnyStr) -> Tuple[str, str, int]: - if cmd.stdin and cmd.stdout: - cmd.stdin.write(self._prepare_ref(ref)) - cmd.stdin.flush() - return self._parse_object_header(cmd.stdout.readline()) - else: - raise ValueError("cmd stdin was empty") - - def get_object_header(self, ref: str) -> Tuple[str, str, int]: - """ Use this method to quickly examine the type and size of the object behind - the given ref. - - :note: The method will only suffer from the costs of command invocation - once and reuses the command in subsequent calls. - - :return: (hexsha, type_string, size_as_int)""" - cmd = self._get_persistent_cmd("cat_file_header", "cat_file", batch_check=True) - return self.__get_object_header(cmd, ref) - - def get_object_data(self, ref: str) -> Tuple[str, str, int, bytes]: - """ As get_object_header, but returns object data as well - :return: (hexsha, type_string, size_as_int,data_string) - :note: not threadsafe""" - hexsha, typename, size, stream = self.stream_object_data(ref) - data = stream.read(size) - del(stream) - return (hexsha, typename, size, data) - - def stream_object_data(self, ref: str) -> Tuple[str, str, int, 'Git.CatFileContentStream']: - """ As get_object_header, but returns the data as a stream - - :return: (hexsha, type_string, size_as_int, stream) - :note: This method is not threadsafe, you need one independent Command instance per thread to be safe !""" - cmd = self._get_persistent_cmd("cat_file_all", "cat_file", batch=True) - hexsha, typename, size = self.__get_object_header(cmd, ref) - cmd_stdout = cmd.stdout if cmd.stdout is not None else io.BytesIO() - return (hexsha, typename, size, self.CatFileContentStream(size, cmd_stdout)) - - def clear_cache(self) -> 'Git': - """Clear all kinds of internal caches to release resources. - - Currently persistent commands will be interrupted. - - :return: self""" - for cmd in (self.cat_file_all, self.cat_file_header): - if cmd: - cmd.__del__() - - self.cat_file_all = None - self.cat_file_header = None - return self diff --git a/venv/Lib/site-packages/git/compat.py b/venv/Lib/site-packages/git/compat.py deleted file mode 100644 index 988c04e..0000000 --- a/venv/Lib/site-packages/git/compat.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# config.py -# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors -# -# This module is part of GitPython and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php -"""utilities to help provide compatibility with python 3""" -# flake8: noqa - -import locale -import os -import sys - -from gitdb.utils.encoding import ( - force_bytes, # @UnusedImport - force_text # @UnusedImport -) - -# typing -------------------------------------------------------------------- - -from typing import ( - Any, - AnyStr, - Dict, - IO, - Optional, - Tuple, - Type, - Union, - overload, -) -# --------------------------------------------------------------------------- - - -is_win: bool = (os.name == 'nt') -is_posix = (os.name == 'posix') -is_darwin = (os.name == 'darwin') -defenc = sys.getfilesystemencoding() - - -@overload -def safe_decode(s: None) -> None: ... - - -@overload -def safe_decode(s: AnyStr) -> str: ... - - -def safe_decode(s: Union[AnyStr, None]) -> Optional[str]: - """Safely decodes a binary string to unicode""" - if isinstance(s, str): - return s - elif isinstance(s, bytes): - return s.decode(defenc, 'surrogateescape') - elif s is None: - return None - else: - raise TypeError('Expected bytes or text, but got %r' % (s,)) - - -@overload -def safe_encode(s: None) -> None: ... - - -@overload -def safe_encode(s: AnyStr) -> bytes: ... - - -def safe_encode(s: Optional[AnyStr]) -> Optional[bytes]: - """Safely encodes a binary string to unicode""" - if isinstance(s, str): - return s.encode(defenc) - elif isinstance(s, bytes): - return s - elif s is None: - return None - else: - raise TypeError('Expected bytes or text, but got %r' % (s,)) - - -@overload -def win_encode(s: None) -> None: ... - - -@overload -def win_encode(s: AnyStr) -> bytes: ... - - -def win_encode(s: Optional[AnyStr]) -> Optional[bytes]: - """Encode unicodes for process arguments on Windows.""" - if isinstance(s, str): - return s.encode(locale.getpreferredencoding(False)) - elif isinstance(s, bytes): - return s - elif s is not None: - raise TypeError('Expected bytes or text, but got %r' % (s,)) - return None diff --git a/venv/Lib/site-packages/git/config.py b/venv/Lib/site-packages/git/config.py deleted file mode 100644 index cbd6602..0000000 --- a/venv/Lib/site-packages/git/config.py +++ /dev/null @@ -1,847 +0,0 @@ -# config.py -# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors -# -# This module is part of GitPython and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php -"""Module containing module parser implementation able to properly read and write -configuration files""" - -import sys -import abc -from functools import wraps -import inspect -from io import BufferedReader, IOBase -import logging -import os -import re -import fnmatch - -from git.compat import ( - defenc, - force_text, - is_win, -) - -from git.util import LockFile - -import os.path as osp - -import configparser as cp - -# typing------------------------------------------------------- - -from typing import (Any, Callable, Generic, IO, List, Dict, Sequence, - TYPE_CHECKING, Tuple, TypeVar, Union, cast) - -from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, assert_never, _T - -if TYPE_CHECKING: - from git.repo.base import Repo - from io import BytesIO - -T_ConfigParser = TypeVar('T_ConfigParser', bound='GitConfigParser') -T_OMD_value = TypeVar('T_OMD_value', str, bytes, int, float, bool) - -if sys.version_info[:3] < (3, 7, 2): - # typing.Ordereddict not added until py 3.7.2 - from collections import OrderedDict - OrderedDict_OMD = OrderedDict -else: - from typing import OrderedDict - OrderedDict_OMD = OrderedDict[str, List[T_OMD_value]] # type: ignore[assignment, misc] - -# ------------------------------------------------------------- - -__all__ = ('GitConfigParser', 'SectionConstraint') - - -log = logging.getLogger('git.config') -log.addHandler(logging.NullHandler()) - -# invariants -# represents the configuration level of a configuration file - - -CONFIG_LEVELS: ConfigLevels_Tup = ("system", "user", "global", "repository") - - -# Section pattern to detect conditional includes. -# https://git-scm.com/docs/git-config#_conditional_includes -CONDITIONAL_INCLUDE_REGEXP = re.compile(r"(?<=includeIf )\"(gitdir|gitdir/i|onbranch):(.+)\"") - - -class MetaParserBuilder(abc.ABCMeta): - """Utlity class wrapping base-class methods into decorators that assure read-only properties""" - def __new__(cls, name: str, bases: Tuple, clsdict: Dict[str, Any]) -> 'MetaParserBuilder': - """ - Equip all base-class methods with a needs_values decorator, and all non-const methods - with a set_dirty_and_flush_changes decorator in addition to that.""" - kmm = '_mutating_methods_' - if kmm in clsdict: - mutating_methods = clsdict[kmm] - for base in bases: - methods = (t for t in inspect.getmembers(base, inspect.isroutine) if not t[0].startswith("_")) - for name, method in methods: - if name in clsdict: - continue - method_with_values = needs_values(method) - if name in mutating_methods: - method_with_values = set_dirty_and_flush_changes(method_with_values) - # END mutating methods handling - - clsdict[name] = method_with_values - # END for each name/method pair - # END for each base - # END if mutating methods configuration is set - - new_type = super(MetaParserBuilder, cls).__new__(cls, name, bases, clsdict) - return new_type - - -def needs_values(func: Callable[..., _T]) -> Callable[..., _T]: - """Returns method assuring we read values (on demand) before we try to access them""" - - @wraps(func) - def assure_data_present(self: 'GitConfigParser', *args: Any, **kwargs: Any) -> _T: - self.read() - return func(self, *args, **kwargs) - # END wrapper method - return assure_data_present - - -def set_dirty_and_flush_changes(non_const_func: Callable[..., _T]) -> Callable[..., _T]: - """Return method that checks whether given non constant function may be called. - If so, the instance will be set dirty. - Additionally, we flush the changes right to disk""" - - def flush_changes(self: 'GitConfigParser', *args: Any, **kwargs: Any) -> _T: - rval = non_const_func(self, *args, **kwargs) - self._dirty = True - self.write() - return rval - # END wrapper method - flush_changes.__name__ = non_const_func.__name__ - return flush_changes - - -class SectionConstraint(Generic[T_ConfigParser]): - - """Constrains a ConfigParser to only option commands which are constrained to - always use the section we have been initialized with. - - It supports all ConfigParser methods that operate on an option. - - :note: - If used as a context manager, will release the wrapped ConfigParser.""" - __slots__ = ("_config", "_section_name") - _valid_attrs_ = ("get_value", "set_value", "get", "set", "getint", "getfloat", "getboolean", "has_option", - "remove_section", "remove_option", "options") - - def __init__(self, config: T_ConfigParser, section: str) -> None: - self._config = config - self._section_name = section - - def __del__(self) -> None: - # Yes, for some reason, we have to call it explicitly for it to work in PY3 ! - # Apparently __del__ doesn't get call anymore if refcount becomes 0 - # Ridiculous ... . - self._config.release() - - def __getattr__(self, attr: str) -> Any: - if attr in self._valid_attrs_: - return lambda *args, **kwargs: self._call_config(attr, *args, **kwargs) - return super(SectionConstraint, self).__getattribute__(attr) - - def _call_config(self, method: str, *args: Any, **kwargs: Any) -> Any: - """Call the configuration at the given method which must take a section name - as first argument""" - return getattr(self._config, method)(self._section_name, *args, **kwargs) - - @property - def config(self) -> T_ConfigParser: - """return: Configparser instance we constrain""" - return self._config - - def release(self) -> None: - """Equivalent to GitConfigParser.release(), which is called on our underlying parser instance""" - return self._config.release() - - def __enter__(self) -> 'SectionConstraint[T_ConfigParser]': - self._config.__enter__() - return self - - def __exit__(self, exception_type: str, exception_value: str, traceback: str) -> None: - self._config.__exit__(exception_type, exception_value, traceback) - - -class _OMD(OrderedDict_OMD): - """Ordered multi-dict.""" - - def __setitem__(self, key: str, value: _T) -> None: - super(_OMD, self).__setitem__(key, [value]) - - def add(self, key: str, value: Any) -> None: - if key not in self: - super(_OMD, self).__setitem__(key, [value]) - return None - super(_OMD, self).__getitem__(key).append(value) - - def setall(self, key: str, values: List[_T]) -> None: - super(_OMD, self).__setitem__(key, values) - - def __getitem__(self, key: str) -> Any: - return super(_OMD, self).__getitem__(key)[-1] - - def getlast(self, key: str) -> Any: - return super(_OMD, self).__getitem__(key)[-1] - - def setlast(self, key: str, value: Any) -> None: - if key not in self: - super(_OMD, self).__setitem__(key, [value]) - return - - prior = super(_OMD, self).__getitem__(key) - prior[-1] = value - - def get(self, key: str, default: Union[_T, None] = None) -> Union[_T, None]: - return super(_OMD, self).get(key, [default])[-1] - - def getall(self, key: str) -> List[_T]: - return super(_OMD, self).__getitem__(key) - - def items(self) -> List[Tuple[str, _T]]: # type: ignore[override] - """List of (key, last value for key).""" - return [(k, self[k]) for k in self] - - def items_all(self) -> List[Tuple[str, List[_T]]]: - """List of (key, list of values for key).""" - return [(k, self.getall(k)) for k in self] - - -def get_config_path(config_level: Lit_config_levels) -> str: - - # we do not support an absolute path of the gitconfig on windows , - # use the global config instead - if is_win and config_level == "system": - config_level = "global" - - if config_level == "system": - return "/etc/gitconfig" - elif config_level == "user": - config_home = os.environ.get("XDG_CONFIG_HOME") or osp.join(os.environ.get("HOME", '~'), ".config") - return osp.normpath(osp.expanduser(osp.join(config_home, "git", "config"))) - elif config_level == "global": - return osp.normpath(osp.expanduser("~/.gitconfig")) - elif config_level == "repository": - raise ValueError("No repo to get repository configuration from. Use Repo._get_config_path") - else: - # Should not reach here. Will raise ValueError if does. Static typing will warn missing elifs - assert_never(config_level, # type: ignore[unreachable] - ValueError(f"Invalid configuration level: {config_level!r}")) - - -class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder): - - """Implements specifics required to read git style configuration files. - - This variation behaves much like the git.config command such that the configuration - will be read on demand based on the filepath given during initialization. - - The changes will automatically be written once the instance goes out of scope, but - can be triggered manually as well. - - The configuration file will be locked if you intend to change values preventing other - instances to write concurrently. - - :note: - The config is case-sensitive even when queried, hence section and option names - must match perfectly. - If used as a context manager, will release the locked file.""" - - #{ Configuration - # The lock type determines the type of lock to use in new configuration readers. - # They must be compatible to the LockFile interface. - # A suitable alternative would be the BlockingLockFile - t_lock = LockFile - re_comment = re.compile(r'^\s*[#;]') - - #} END configuration - - optvalueonly_source = r'\s*(?P