From 46bc4a982892c050b0d17ab4737332a7f7c6e885 Mon Sep 17 00:00:00 2001 From: SneakyFoxy Date: Tue, 21 Jan 2025 18:25:30 +0300 Subject: [PATCH 1/2] Add Ubuntu 24.04 support [Fixed network plugin for new Wireshark headers, add building LLVM and libosi] --- configure | 4 +- panda/dependencies/ubuntu_24.04_base.txt | 90 ++++ panda/dependencies/ubuntu_24.04_build.txt | 90 ++++ panda/plugins/network/network.cpp | 48 +- panda/python/core/.eggs/README.txt | 6 + .../EGG-INFO/LICENSE | 17 + .../EGG-INFO/PKG-INFO | 166 +++++++ .../EGG-INFO/RECORD | 36 ++ .../EGG-INFO/WHEEL | 5 + .../EGG-INFO/entry_points.txt | 42 ++ .../EGG-INFO/requires.txt | 21 + .../EGG-INFO/top_level.txt | 1 + .../setuptools_scm/.git_archival.txt | 3 + .../setuptools_scm/__init__.py | 30 ++ .../setuptools_scm/__main__.py | 6 + .../setuptools_scm/_cli.py | 186 +++++++ .../setuptools_scm/_config.py | 152 ++++++ .../setuptools_scm/_entrypoints.py | 139 ++++++ .../setuptools_scm/_file_finders/__init__.py | 113 +++++ .../setuptools_scm/_file_finders/git.py | 117 +++++ .../setuptools_scm/_file_finders/hg.py | 72 +++ .../setuptools_scm/_file_finders/pathtools.py | 9 + .../setuptools_scm/_get_version_impl.py | 175 +++++++ .../setuptools_scm/_integration/__init__.py | 0 .../_integration/dump_version.py | 94 ++++ .../_integration/pyproject_reading.py | 85 ++++ .../setuptools_scm/_integration/setuptools.py | 123 +++++ .../setuptools_scm/_integration/toml.py | 59 +++ .../setuptools_scm/_log.py | 87 ++++ .../setuptools_scm/_modify_version.py | 61 +++ .../setuptools_scm/_overrides.py | 55 +++ .../setuptools_scm/_run_cmd.py | 214 +++++++++ .../setuptools_scm/_types.py | 28 ++ .../setuptools_scm/_version_cls.py | 91 ++++ .../setuptools_scm/discover.py | 70 +++ .../setuptools_scm/fallbacks.py | 45 ++ .../setuptools_scm/git.py | 340 +++++++++++++ .../setuptools_scm/hg.py | 192 ++++++++ .../setuptools_scm/hg_git.py | 156 ++++++ .../setuptools_scm/integration.py | 31 ++ .../setuptools_scm/scm_workdir.py | 15 + .../setuptools_scm/version.py | 454 ++++++++++++++++++ panda/scripts/build_libosi.sh | 18 + panda/scripts/build_llvm.sh | 45 ++ panda/scripts/install_ubuntu.sh | 42 +- 45 files changed, 3796 insertions(+), 37 deletions(-) create mode 100644 panda/dependencies/ubuntu_24.04_base.txt create mode 100644 panda/dependencies/ubuntu_24.04_build.txt create mode 100644 panda/python/core/.eggs/README.txt create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py create mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py create mode 100755 panda/scripts/build_libosi.sh create mode 100755 panda/scripts/build_llvm.sh diff --git a/configure b/configure index 67759ef53f5..db7431ce212 100755 --- a/configure +++ b/configure @@ -5412,9 +5412,9 @@ if test "$llvm" != "no"; then llvm_components="" llvm_cxxflags=$($llvm_config $llvm_components --cxxflags 2> /dev/null) - llvm_ldflags=$($llvm_config $llvm_components --ldflags 2> /dev/null) + # Add ltinfo for fixing LLVM linking error [Maybe i just messed up with LLVM compiling] + llvm_ldflags="$($llvm_config $llvm_components --ldflags 2> /dev/null) -ltinfo" llvm_libs=$($llvm_config $llvm_components --libs 2> /dev/null) - if compile_prog_clangxx "$llvm_cxxflags -Wno-unused-variable" "$llvm_libs $llvm_ldflags" ; then : LLVM found elif test "$llvm" = "yes"; then diff --git a/panda/dependencies/ubuntu_24.04_base.txt b/panda/dependencies/ubuntu_24.04_base.txt new file mode 100644 index 00000000000..2c0eaf019e9 --- /dev/null +++ b/panda/dependencies/ubuntu_24.04_base.txt @@ -0,0 +1,90 @@ +# Panda dependencies +# Note that libcapstone >= v4.1 is also required, but that's not available in apt +git +libdwarf1 +libjsoncpp-dev +# libllvm11 +libprotobuf-c-dev +libvte-2.91-0 +libwireshark-dev +libwiretap-dev +# Fixes config.h build error +wireshark-dev +libxen-dev +libz3-dev +python3 +python3-pip +wget + +# pyperipheral (only needed for armel) +libpython3-dev + +# pypanda dependencies +genisoimage +libffi-dev +python3-protobuf +python3-colorama + +# Not sure what this one is needed for +liblzo2-2 + +# apt-rdepends qemu-system-common +acl +libc6 +libcap-ng0 +libcap2 +libgbm1 +libglib2.0-0 +libglib2.0-dev +zlib1g-dev +libgnutls30 +libnettle8 +libpixman-1-0 +libvirglrenderer1 + +# apt-rdepends qemu-block-extra +libcurl3-gnutls +libglib2.0-0 +libiscsi7 +librados2 +librbd1 +libssh-4 + +# apt-rdepends qemu-system-arm, seems most of the system-[arch]es have same dependencies +libaio1t64 +libasound2t64 +libbrlapi-dev +libc6 +libcacard0 +libepoxy0 +libfdt1 +libgbm1 +libgcc-s1 +libglib2.0-0 +libgnutls30 +libibverbs1 +libjpeg8 +libncursesw6 +libnuma1 +libpixman-1-0 +libpmem1 +libpng16-16 +librdmacm1 +libsasl2-2 +libseccomp2 +libslirp0 +libspice-server1 +libstdc++6 +libtinfo6 +libusb-1.0-0 +libusbredirparser1 +libvirglrenderer1 +zlib1g + +# rr2 dependencies +libarchive-dev +libssl-dev + +# libosi build dependecies +pkg-config +libglib2.0-dev diff --git a/panda/dependencies/ubuntu_24.04_build.txt b/panda/dependencies/ubuntu_24.04_build.txt new file mode 100644 index 00000000000..8f8d472e094 --- /dev/null +++ b/panda/dependencies/ubuntu_24.04_build.txt @@ -0,0 +1,90 @@ +libc++-dev +libelf-dev +libtool-bin +libwireshark-dev +libwiretap-dev +# lsb-core +zip + +# panda build deps +# Note libcapstone-dev is required, but we need v4 + which isn't in apt +build-essential +chrpath +# clang-11 +gcc +libdwarf-dev +libprotoc-dev +# llvm-11-dev +protobuf-c-compiler +protobuf-compiler +python3-dev +libpixman-1-dev +zip + +# pypanda dependencies +python3-setuptools +python3-wheel + +# pypanda test dependencies +gcc-multilib +libc6-dev-i386 +nasm + +# Qemu build deps +debhelper +device-tree-compiler +libgnutls28-dev +libaio-dev +libasound2-dev +libattr1-dev +libbrlapi-dev +libcacard-dev +libcap-dev +libcap-ng-dev +libcurl4-gnutls-dev +libdrm-dev +libepoxy-dev +libfdt-dev +libgbm-dev +libibumad-dev +libibverbs-dev +libiscsi-dev +libjpeg-dev +libncursesw5-dev +libnuma-dev +libpmem-dev +libpng-dev +libpulse-dev +librbd-dev +librdmacm-dev +libsasl2-dev +libseccomp-dev +libslirp-dev +libspice-protocol-dev +libspice-server-dev +libssh-dev +libudev-dev +libusb-1.0-0-dev +libusbredirparser-dev +libvirglrenderer-dev +nettle-dev +python3 +python3-sphinx +texinfo +uuid-dev +xfslibs-dev +zlib1g-dev +libc6.1-dev-alpha-cross + +# qemu build deps that conflict with gcc-multilib +#gcc-alpha-linux-gnu +#gcc-powerpc64-linux-gnu +#gcc-s390x-linux-gnu + +# rust install deps +curl + +# libosi install deps +cmake +ninja-build +rapidjson-dev diff --git a/panda/plugins/network/network.cpp b/panda/plugins/network/network.cpp index 16ad8a63353..6518dfa31ce 100644 --- a/panda/plugins/network/network.cpp +++ b/panda/plugins/network/network.cpp @@ -1,15 +1,15 @@ /* PANDABEGINCOMMENT - * + * * Authors: * Tim Leek tleek@ll.mit.edu * Ryan Whelan rwhelan@ll.mit.edu * Joshua Hodosh josh.hodosh@ll.mit.edu * Michael Zhivich mzhivich@ll.mit.edu * Brendan Dolan-Gavitt brendandg@gatech.edu - * - * This work is licensed under the terms of the GNU GPL, version 2. - * See the COPYING file in the top-level directory. - * + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + * PANDAENDCOMMENT */ // This needs to be defined before anything is included in order to get // the PRIx64 macro @@ -21,6 +21,7 @@ #include #include +#include // These need to be extern "C" so that the ABI is compatible with // QEMU/PANDA, which is written in C @@ -56,7 +57,7 @@ bool init_plugin(void *self) { .snaplen = 65535, .shb_hdrs = NULL, .idb_inf = NULL, - .nrb_hdrs = NULL, + .nrbs_growing = NULL, .dsbs_initial = NULL, .dsbs_growing = NULL }; @@ -76,20 +77,19 @@ bool init_plugin(void *self) { fprintf(stderr, "Plugin 'network' needs argument: -panda-arg network:file=\n"); return false; } - + int file_type = wtap_pcapng_file_type_subtype(); #if (VERSION_MAJOR == 2 && VERSION_MINOR >= 6 ) || (VERSION_MAJOR>=3) wtap_init(false); #elif VERSION_MAJOR == 2 && VERSION_MINOR == 2 && VERSION_MICRO >= 4 wtap_init(); #endif - #if (VERSION_MAJOR>=3) #if (VERSION_MAJOR>=4 || VERSION_MINOR>=4) gchar *write_err_info; #endif plugin_log = wtap_dump_open( tblog_filename, - WTAP_FILE_TYPE_SUBTYPE_PCAPNG, + file_type, WTAP_UNCOMPRESSED, // assuming this... &wdparams, // the new structure that wraps all the ng params &err @@ -100,15 +100,15 @@ bool init_plugin(void *self) { #else plugin_log = wtap_dump_open_ng( /*filename*/tblog_filename, - /*file_type_subtype*/WTAP_FILE_TYPE_SUBTYPE_PCAPNG, + /*file_type_subtype*/file_type, /*encap*/WTAP_ENCAP_ETHERNET, /*snaplen*/65535, /*compressed*/1, /*shb_hdrs*/NULL, /*idb_inf*/NULL, - #if VERSION_MAJOR == 2 + #if VERSION_MAJOR == 2 /*nrb_hdrs*/NULL, - #endif + #endif /*err*/&err); #endif @@ -134,7 +134,8 @@ void uninit_plugin(void *self) { #endif #if (VERSION_MAJOR>=4 || (VERSION_MAJOR==3 && VERSION_MINOR>=4)) gchar *write_err_info; - gboolean ret = wtap_dump_close(plugin_log, &err, &write_err_info); + gboolean needs_reload; + gboolean ret = wtap_dump_close(plugin_log, &needs_reload, &err, &write_err_info); #else gboolean ret = wtap_dump_close(plugin_log, &err); #endif @@ -163,8 +164,8 @@ void handle_packet(CPUState *env, uint8_t *buf, size_t size, uint8_t direction, rec.rec_header.packet_header.caplen = size; rec.rec_header.packet_header.len = size; rec.rec_header.packet_header.pkt_encap = WTAP_ENCAP_ETHERNET; - rec.opt_comment = comment_buf; - rec.has_comment_changed = true; + wtap_block_t pkt_block = wtap_block_create(WTAP_BLOCK_PACKET); + wtap_block_add_string_option(pkt_block, OPT_COMMENT, comment_buf, strlen(comment_buf) + 1); ret = wtap_dump( /*wtap_dumper*/ plugin_log, /*wtap_rec*/ &rec, @@ -173,9 +174,9 @@ void handle_packet(CPUState *env, uint8_t *buf, size_t size, uint8_t direction, /*err_info*/ &err_info); #else struct wtap_pkthdr header; - #if VERSION_MAJOR >= 2 - wtap_phdr_init(&header); - #endif + #if VERSION_MAJOR >= 2 + wtap_phdr_init(&header); + #endif header.ts.secs = now_tv.tv_sec; header.ts.nsecs = now_tv.tv_usec * 1000; header.caplen = size; @@ -187,14 +188,14 @@ void handle_packet(CPUState *env, uint8_t *buf, size_t size, uint8_t direction, /*wtap_pkthdr*/ &header, /*buf*/ buf, /*err*/ &err - #if VERSION_MAJOR >= 2 + #if VERSION_MAJOR >= 2 , /*err_info*/ &err_info - #endif + #endif ); - #if VERSION_MAJOR >= 2 - wtap_phdr_cleanup(&header); - #endif + #if VERSION_MAJOR >= 2 + wtap_phdr_cleanup(&header); + #endif #endif if (!ret) { fprintf(stderr, "Plugin 'network': failed wtap_dump() with error %d", err); @@ -206,4 +207,3 @@ void handle_packet(CPUState *env, uint8_t *buf, size_t size, uint8_t direction, return; } #endif - diff --git a/panda/python/core/.eggs/README.txt b/panda/python/core/.eggs/README.txt new file mode 100644 index 00000000000..5d01668824f --- /dev/null +++ b/panda/python/core/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE new file mode 100644 index 00000000000..89de354795e --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO new file mode 100644 index 00000000000..edf8a1d4a17 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO @@ -0,0 +1,166 @@ +Metadata-Version: 2.1 +Name: setuptools-scm +Version: 8.1.0 +Summary: the blessed package to manage your versions by scm tags +Author-email: Ronny Pfannschmidt +License: Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +Project-URL: documentation, https://setuptools-scm.readthedocs.io/ +Project-URL: repository, https://github.com/pypa/setuptools_scm/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Software Development :: Version Control +Classifier: Topic :: System :: Software Distribution +Classifier: Topic :: Utilities +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: packaging >=20 +Requires-Dist: setuptools +Requires-Dist: typing-extensions ; python_version < "3.10" +Requires-Dist: tomli >=1 ; python_version < "3.11" +Provides-Extra: docs +Requires-Dist: entangled-cli ~=2.0 ; extra == 'docs' +Requires-Dist: mkdocs ; extra == 'docs' +Requires-Dist: mkdocs-entangled-plugin ; extra == 'docs' +Requires-Dist: mkdocs-material ; extra == 'docs' +Requires-Dist: mkdocstrings[python] ; extra == 'docs' +Requires-Dist: pygments ; extra == 'docs' +Provides-Extra: rich +Requires-Dist: rich ; extra == 'rich' +Provides-Extra: test +Requires-Dist: build ; extra == 'test' +Requires-Dist: pytest ; extra == 'test' +Requires-Dist: rich ; extra == 'test' +Requires-Dist: wheel ; extra == 'test' +Requires-Dist: typing-extensions ; (python_version < "3.11") and extra == 'test' +Provides-Extra: toml + +# setuptools_scm +[![github ci](https://github.com/pypa/setuptools_scm/workflows/python%20tests+artifacts+release/badge.svg)](https://github.com/pypa/setuptools_scm/actions) +[![Documentation Status](https://readthedocs.org/projects/setuptools-scm/badge/?version=latest)](https://setuptools-scm.readthedocs.io/en/latest/?badge=latest) +[![tidelift](https://tidelift.com/badges/package/pypi/setuptools-scm) ](https://tidelift.com/subscription/pkg/pypi-setuptools-scm?utm_source=pypi-setuptools-scm&utm_medium=readme) + +## about + +[setuptools-scm] extracts Python package versions from `git` or +`hg` metadata instead of declaring them as the version argument +or in an SCM managed file. + +Additionally, [setuptools-scm] provides setuptools +with a list of files that are managed by the SCM
+(i.e. it automatically adds **all of** the SCM-managed files to the sdist).
+Unwanted files must be excluded via `MANIFEST.in`. + + +## `pyproject.toml` usage + +The preferred way to configure [setuptools-scm] is to author +settings in a `tool.setuptools_scm` section of `pyproject.toml`. + +This feature requires setuptools 61 or later. +First, ensure that [setuptools-scm] is present during the project's +build step by specifying it as one of the build requirements. + +```toml title="pyproject.toml" +[build-system] +requires = ["setuptools>=64", "setuptools_scm>=8"] +build-backend = "setuptools.build_meta" +``` + +That will be sufficient to require [setuptools-scm] for projects +that support [PEP 518] like [pip] and [build]. + +[pip]: https://pypi.org/project/pip +[build]: https://pypi.org/project/build +[PEP 518]: https://peps.python.org/pep-0518/ + + +To enable version inference, you need to set the version +dynamically in the `project` section of `pyproject.toml`: + +```toml title="pyproject.toml" +[project] +# version = "0.0.1" # Remove any existing version parameter. +dynamic = ["version"] + +[tool.setuptools_scm] +``` + +Additionally, a version file can be written by specifying: + +```toml title="pyproject.toml" +[tool.setuptools_scm] +version_file = "pkg/_version.py" +``` + +Where `pkg` is the name of your package. + +If you need to confirm which version string is being generated or debug the configuration, +you can install [setuptools-scm] directly in your working environment and run: + +```console +$ python -m setuptools_scm +# To explore other options, try: +$ python -m setuptools_scm --help +``` + +For further configuration see the [documentation]. + +[setuptools-scm]: https://github.com/pypa/setuptools_scm +[documentation]: https://setuptools-scm.readthedocs.io/ + + +## Interaction with Enterprise Distributions + +Some enterprise distributions like RHEL7 +ship rather old setuptools versions. + +In those cases its typically possible to build by using an sdist against `setuptools_scm<2.0`. +As those old setuptools versions lack sensible types for versions, +modern [setuptools-scm] is unable to support them sensibly. + +It's strongly recommended to build a wheel artifact using modern Python and setuptools, +then installing the artifact instead of trying to run against old setuptools versions. + + +## Code of Conduct + + +Everyone interacting in the [setuptools-scm] project's codebases, issue +trackers, chat rooms, and mailing lists is expected to follow the +[PSF Code of Conduct]. + +[PSF Code of Conduct]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + + +## Security Contact + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD new file mode 100644 index 00000000000..161a093c43f --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD @@ -0,0 +1,36 @@ +setuptools_scm/.git_archival.txt,sha256=2_90kdS1POSQMuZfBCUw6qNjObu7Ijp8DmptEAmlGkU,102 +setuptools_scm/__init__.py,sha256=k4jjJK8ejFI95amIoLWNCFECWIQW9NlxF9Had4RqOHM,785 +setuptools_scm/__main__.py,sha256=AhntzdNH3Jhcio_Ohoc6_EW7CuIN02OM-0irpGEXXh0,116 +setuptools_scm/_cli.py,sha256=c1OtDXCGl7IzCdZ8z8yJg9TEBt1eXjh3mgqr16Qc5dQ,5597 +setuptools_scm/_config.py,sha256=Zf9jOxr7BWQ8RN863MPOfzO6x8Os_pwYi7VuA0Bbr4U,4968 +setuptools_scm/_entrypoints.py,sha256=GX3Lqs4YFUbQMa0mKCVYpXsfP8kR8nIuYbXRYkPaz7Y,3843 +setuptools_scm/_get_version_impl.py,sha256=P72m2imnte-J7IXD3nTjYk7gBUoLk6hrZZv5O5r9akY,5940 +setuptools_scm/_log.py,sha256=BFsXD-s2fcLV3zZaSQkQfRKPS-MjcI0tsmthJ3a2HqA,2137 +setuptools_scm/_modify_version.py,sha256=9VU-juFg2IZjrcyz9kLGRfBq4RyZZElhjPMipqjB3Xc,1738 +setuptools_scm/_overrides.py,sha256=2-ld0PSoi8IPVUAS3H2aBWM7yxJneDcyydq9ueQRdsE,1655 +setuptools_scm/_run_cmd.py,sha256=6AB6Kv1kg75Yx6-p7NHMrXSWTCPWDAN5id8cSF8XW6s,6094 +setuptools_scm/_types.py,sha256=QhY9jqXTH8sSxHXNQg2toQduk60s0vXya_Mdfv5rQAg,708 +setuptools_scm/_version_cls.py,sha256=9wEWl4WY_sUvqZhN1PQbVETVq9OAQKu1Y47ZPg9vx-c,2925 +setuptools_scm/discover.py,sha256=Kfm8S5I078vw8Cvbs9qpKOg5dr2TqBp1us-W579Dlts,2027 +setuptools_scm/fallbacks.py,sha256=x3Xv1p89AqJiBX6oxuoo8Di0yR5ijOFOwKBJGAeWTbY,1448 +setuptools_scm/git.py,sha256=-FbDzrVeEYd6jgEEzpWfuaeIfksS2QPktHZINXeSyzA,10526 +setuptools_scm/hg.py,sha256=iY294X0ZOqLEv_KXmPWwXXsPDhgx4wsOVoxFkM9WiPc,6207 +setuptools_scm/hg_git.py,sha256=hx2rq1kwW9Zs23xK9ZCn509emze22iyXvT3zIZh7JFM,4546 +setuptools_scm/integration.py,sha256=0l04N6IhRKW32vD9DPvvJuiZ1HrVCYupmNYDcYXu8lQ,806 +setuptools_scm/scm_workdir.py,sha256=oreoRhJfvhhxVGIhDPWH8-dg9umsmZM0sV2oRIzGXc8,327 +setuptools_scm/version.py,sha256=TzdIjApX5t-aWBwGZoJLykpGWVVStRxH2Fui0RVVXvU,14215 +setuptools_scm/_file_finders/__init__.py,sha256=QBZkrT7FLNfclH7taOohnNAPkVtaLJva3cHpX0sozbc,3751 +setuptools_scm/_file_finders/git.py,sha256=vW_SGVGTXNFyC4dHOhNjh3ER2Aqp0QNe1qc0XLUIZEQ,4156 +setuptools_scm/_file_finders/hg.py,sha256=1I4LPr_k7lIVMTqSl9_h1_csIEYMfRow2ta5FEo0Rjs,2246 +setuptools_scm/_file_finders/pathtools.py,sha256=AgOl5u_WHxCQeiUCwlN8bUE3B4vs5BxSJEK1LJutyus,179 +setuptools_scm/_integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools_scm/_integration/dump_version.py,sha256=2VYFa0Aa1YRcrQQVit-COg7w1QaRjmZFM22LYZWuvEg,2584 +setuptools_scm/_integration/pyproject_reading.py,sha256=Wz-_ncjggrC-YfCsclIsSd2BkH0OYLdQhl9Insobpcg,2604 +setuptools_scm/_integration/setuptools.py,sha256=DcYqpUUMMu_gD2XxdyY3enPFr12pqV9fZa06PuFqBSU,3468 +setuptools_scm/_integration/toml.py,sha256=GYXDZOUC-AfQ_WmOIESP1ARBnc6WKIBQy3oDvsF-bUQ,1467 +setuptools_scm-8.1.0.dist-info/LICENSE,sha256=iYB6zyMJvShfAzQE7nhYFgLzzZuBmhasLw5fYP9KRz4,1023 +setuptools_scm-8.1.0.dist-info/METADATA,sha256=JstkuN1RJAjyijO1FYrd2ZfrphMgbl-j1LyiGmVbzrQ,6614 +setuptools_scm-8.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92 +setuptools_scm-8.1.0.dist-info/entry_points.txt,sha256=7VjBrJmw12qwaWG0yLbRs5fYIf7g4ySdOwHNsJMhy4A,1776 +setuptools_scm-8.1.0.dist-info/top_level.txt,sha256=kiu-91q3_rJLUoc2wl8_lC4cIlpgtgdD_4NaChF4hOA,15 +setuptools_scm-8.1.0.dist-info/RECORD,, diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL new file mode 100644 index 00000000000..bab98d67588 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.43.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt new file mode 100644 index 00000000000..2212baa8d1c --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt @@ -0,0 +1,42 @@ +[distutils.setup_keywords] +use_scm_version = setuptools_scm._integration.setuptools:version_keyword + +[setuptools.file_finders] +setuptools_scm = setuptools_scm._file_finders:find_files + +[setuptools.finalize_distribution_options] +setuptools_scm = setuptools_scm._integration.setuptools:infer_version + +[setuptools_scm.files_command] +.git = setuptools_scm._file_finders.git:git_find_files +.hg = setuptools_scm._file_finders.hg:hg_find_files + +[setuptools_scm.files_command_fallback] +.git_archival.txt = setuptools_scm._file_finders.git:git_archive_find_files +.hg_archival.txt = setuptools_scm._file_finders.hg:hg_archive_find_files + +[setuptools_scm.local_scheme] +dirty-tag = setuptools_scm.version:get_local_dirty_tag +no-local-version = setuptools_scm.version:get_no_local_node +node-and-date = setuptools_scm.version:get_local_node_and_date +node-and-timestamp = setuptools_scm.version:get_local_node_and_timestamp + +[setuptools_scm.parse_scm] +.git = setuptools_scm.git:parse +.hg = setuptools_scm.hg:parse + +[setuptools_scm.parse_scm_fallback] +.git_archival.txt = setuptools_scm.git:parse_archival +.hg_archival.txt = setuptools_scm.hg:parse_archival +PKG-INFO = setuptools_scm.fallbacks:parse_pkginfo +pyproject.toml = setuptools_scm.fallbacks:fallback_version +setup.py = setuptools_scm.fallbacks:fallback_version + +[setuptools_scm.version_scheme] +calver-by-date = setuptools_scm.version:calver_by_date +guess-next-dev = setuptools_scm.version:guess_next_dev_version +no-guess-dev = setuptools_scm.version:no_guess_dev_version +only-version = setuptools_scm.version:only_version +post-release = setuptools_scm.version:postrelease_version +python-simplified-semver = setuptools_scm.version:simplified_semver_version +release-branch-semver = setuptools_scm.version:release_branch_semver_version diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt new file mode 100644 index 00000000000..84a7b7d4911 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt @@ -0,0 +1,21 @@ +packaging>=20 +setuptools + +[docs] +entangled-cli~=2.0 +mkdocs +mkdocs-entangled-plugin +mkdocs-material +mkdocstrings[python] +pygments + +[rich] +rich + +[test] +build +pytest +rich +wheel + +[toml] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt new file mode 100644 index 00000000000..cba8d886074 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt @@ -0,0 +1 @@ +setuptools_scm diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt new file mode 100644 index 00000000000..7c5100942aa --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt @@ -0,0 +1,3 @@ +node: $Format:%H$ +node-date: $Format:%cI$ +describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py new file mode 100644 index 00000000000..e265e859ca1 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py @@ -0,0 +1,30 @@ +""" +:copyright: 2010-2023 by Ronny Pfannschmidt +:license: MIT +""" + +from __future__ import annotations + +from ._config import DEFAULT_LOCAL_SCHEME +from ._config import DEFAULT_VERSION_SCHEME +from ._config import Configuration +from ._get_version_impl import _get_version +from ._get_version_impl import get_version +from ._integration.dump_version import dump_version # soft deprecated +from ._version_cls import NonNormalizedVersion +from ._version_cls import Version +from .version import ScmVersion + +# Public API +__all__ = [ + "DEFAULT_LOCAL_SCHEME", + "DEFAULT_VERSION_SCHEME", + "Configuration", + "NonNormalizedVersion", + "ScmVersion", + "Version", + "_get_version", + "dump_version", + # soft deprecated imports, left for backward compatibility + "get_version", +] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py new file mode 100644 index 00000000000..3f56d42a0c6 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py @@ -0,0 +1,6 @@ +from __future__ import annotations + +from ._cli import main + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py new file mode 100644 index 00000000000..8c815237a0f --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py @@ -0,0 +1,186 @@ +from __future__ import annotations + +import argparse +import json +import os +import sys + +from typing import Any + +from setuptools_scm import Configuration +from setuptools_scm._file_finders import find_files +from setuptools_scm._get_version_impl import _get_version +from setuptools_scm.discover import walk_potential_roots + + +def main(args: list[str] | None = None) -> int: + opts = _get_cli_opts(args) + inferred_root: str = opts.root or "." + + pyproject = opts.config or _find_pyproject(inferred_root) + + try: + config = Configuration.from_file( + pyproject, + root=(os.path.abspath(opts.root) if opts.root is not None else None), + ) + except (LookupError, FileNotFoundError) as ex: + # no pyproject.toml OR no [tool.setuptools_scm] + print( + f"Warning: could not use {os.path.relpath(pyproject)}," + " using default configuration.\n" + f" Reason: {ex}.", + file=sys.stderr, + ) + config = Configuration(root=inferred_root) + + version = _get_version( + config, force_write_version_files=opts.force_write_version_files + ) + if version is None: + raise SystemExit("ERROR: no version found for", opts) + if opts.strip_dev: + version = version.partition(".dev")[0] + + return command(opts, version, config) + + +def _get_cli_opts(args: list[str] | None) -> argparse.Namespace: + prog = "python -m setuptools_scm" + desc = "Print project version according to SCM metadata" + parser = argparse.ArgumentParser(prog, description=desc) + # By default, help for `--help` starts with lower case, so we keep the pattern: + parser.add_argument( + "-r", + "--root", + default=None, + help='directory managed by the SCM, default: inferred from config file, or "."', + ) + parser.add_argument( + "-c", + "--config", + default=None, + metavar="PATH", + help="path to 'pyproject.toml' with setuptools_scm config, " + "default: looked up in the current or parent directories", + ) + parser.add_argument( + "--strip-dev", + action="store_true", + help="remove the dev/local parts of the version before printing the version", + ) + parser.add_argument( + "-N", + "--no-version", + action="store_true", + help="do not include package version in the output", + ) + output_formats = ["json", "plain", "key-value"] + parser.add_argument( + "-f", + "--format", + type=str.casefold, + default="plain", + help="specify output format", + choices=output_formats, + ) + parser.add_argument( + "-q", + "--query", + type=str.casefold, + nargs="*", + help="display setuptools_scm settings according to query, " + "e.g. dist_name, do not supply an argument in order to " + "print a list of valid queries.", + ) + parser.add_argument( + "--force-write-version-files", + action="store_true", + help="trigger to write the content of the version files\n" + "its recommended to use normal/editable installation instead)", + ) + sub = parser.add_subparsers(title="extra commands", dest="command", metavar="") + # We avoid `metavar` to prevent printing repetitive information + desc = "List information about the package, e.g. included files" + sub.add_parser("ls", help=desc[0].lower() + desc[1:], description=desc) + return parser.parse_args(args) + + +# flake8: noqa: C901 +def command(opts: argparse.Namespace, version: str, config: Configuration) -> int: + data: dict[str, Any] = {} + + if opts.command == "ls": + opts.query = ["files"] + + if opts.query == []: + opts.no_version = True + sys.stderr.write("Available queries:\n\n") + opts.query = ["queries"] + data["queries"] = ["files", *config.__dataclass_fields__] + + if opts.query is None: + opts.query = [] + + if not opts.no_version: + data["version"] = version + + if "files" in opts.query: + data["files"] = find_files(config.root) + + for q in opts.query: + if q in ["files", "queries", "version"]: + continue + + try: + if q.startswith("_"): + raise AttributeError() + data[q] = getattr(config, q) + except AttributeError: + sys.stderr.write(f"Error: unknown query: '{q}'\n") + return 1 + + if opts.format == "json": + print(json.dumps(data, indent=2)) + + if opts.format == "plain": + _print_plain(data) + + if opts.format == "key-value": + _print_key_value(data) + + return 0 + + +def _print_plain(data: dict[str, Any]) -> None: + version = data.pop("version", None) + if version: + print(version) + files = data.pop("files", []) + for file_ in files: + print(file_) + queries = data.pop("queries", []) + for query in queries: + print(query) + if data: + print("\n".join(data.values())) + + +def _print_key_value(data: dict[str, Any]) -> None: + for key, value in data.items(): + if isinstance(value, str): + print(f"{key} = {value}") + else: + str_value = "\n ".join(value) + print(f"{key} = {str_value}") + + +def _find_pyproject(parent: str) -> str: + for directory in walk_potential_roots(os.path.abspath(parent)): + pyproject = os.path.join(directory, "pyproject.toml") + if os.path.isfile(pyproject): + return pyproject + + return os.path.abspath( + "pyproject.toml" + ) # use default name to trigger the default errors diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py new file mode 100644 index 00000000000..6ed520f933d --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py @@ -0,0 +1,152 @@ +"""configuration""" + +from __future__ import annotations + +import dataclasses +import os +import re +import warnings + +from pathlib import Path +from typing import Any +from typing import Pattern +from typing import Protocol + +from . import _log +from . import _types as _t +from ._integration.pyproject_reading import ( + get_args_for_pyproject as _get_args_for_pyproject, +) +from ._integration.pyproject_reading import read_pyproject as _read_pyproject +from ._overrides import read_toml_overrides +from ._version_cls import Version as _Version +from ._version_cls import _validate_version_cls +from ._version_cls import _VersionT + +log = _log.log.getChild("config") + +DEFAULT_TAG_REGEX = re.compile( + r"^(?:[\w-]+-)?(?P[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$" +) +"""default tag regex that tries to match PEP440 style versions +with prefix consisting of dashed words""" + +DEFAULT_VERSION_SCHEME = "guess-next-dev" +DEFAULT_LOCAL_SCHEME = "node-and-date" + + +def _check_tag_regex(value: str | Pattern[str] | None) -> Pattern[str]: + if not value: + regex = DEFAULT_TAG_REGEX + else: + regex = re.compile(value) + + group_names = regex.groupindex.keys() + if regex.groups == 0 or (regex.groups > 1 and "version" not in group_names): + warnings.warn( + "Expected tag_regex to contain a single match group or a group named" + " 'version' to identify the version part of any tag." + ) + + return regex + + +class ParseFunction(Protocol): + def __call__( + self, root: _t.PathT, *, config: Configuration + ) -> _t.SCMVERSION | None: ... + + +def _check_absolute_root(root: _t.PathT, relative_to: _t.PathT | None) -> str: + log.debug("check absolute root=%s relative_to=%s", root, relative_to) + if relative_to: + if ( + os.path.isabs(root) + and os.path.isabs(relative_to) + and not os.path.commonpath([root, relative_to]) == root + ): + warnings.warn( + f"absolute root path '{root}' overrides relative_to '{relative_to}'" + ) + if os.path.isdir(relative_to): + warnings.warn( + "relative_to is expected to be a file," + f" its the directory {relative_to}\n" + "assuming the parent directory was passed" + ) + log.debug("dir %s", relative_to) + root = os.path.join(relative_to, root) + else: + log.debug("file %s", relative_to) + root = os.path.join(os.path.dirname(relative_to), root) + return os.path.abspath(root) + + +@dataclasses.dataclass +class Configuration: + """Global configuration model""" + + relative_to: _t.PathT | None = None + root: _t.PathT = "." + version_scheme: _t.VERSION_SCHEME = DEFAULT_VERSION_SCHEME + local_scheme: _t.VERSION_SCHEME = DEFAULT_LOCAL_SCHEME + tag_regex: Pattern[str] = DEFAULT_TAG_REGEX + parentdir_prefix_version: str | None = None + fallback_version: str | None = None + fallback_root: _t.PathT = "." + write_to: _t.PathT | None = None + write_to_template: str | None = None + version_file: _t.PathT | None = None + version_file_template: str | None = None + parse: ParseFunction | None = None + git_describe_command: _t.CMD_TYPE | None = None + dist_name: str | None = None + version_cls: type[_VersionT] = _Version + search_parent_directories: bool = False + + parent: _t.PathT | None = None + + @property + def absolute_root(self) -> str: + return _check_absolute_root(self.root, self.relative_to) + + @classmethod + def from_file( + cls, + name: str | os.PathLike[str] = "pyproject.toml", + dist_name: str | None = None, + _require_section: bool = True, + **kwargs: Any, + ) -> Configuration: + """ + Read Configuration from pyproject.toml (or similar). + Raises exceptions when file is not found or toml is + not installed or the file has invalid format or does + not contain the [tool.setuptools_scm] section. + """ + + pyproject_data = _read_pyproject(Path(name), require_section=_require_section) + args = _get_args_for_pyproject(pyproject_data, dist_name, kwargs) + + args.update(read_toml_overrides(args["dist_name"])) + relative_to = args.pop("relative_to", name) + return cls.from_data(relative_to=relative_to, data=args) + + @classmethod + def from_data( + cls, relative_to: str | os.PathLike[str], data: dict[str, Any] + ) -> Configuration: + """ + given configuration data + create a config instance after validating tag regex/version class + """ + tag_regex = _check_tag_regex(data.pop("tag_regex", None)) + version_cls = _validate_version_cls( + data.pop("version_cls", None), data.pop("normalize", True) + ) + return cls( + relative_to=relative_to, + version_cls=version_cls, + tag_regex=tag_regex, + **data, + ) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py new file mode 100644 index 00000000000..5eab1ed2b9a --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py @@ -0,0 +1,139 @@ +from __future__ import annotations + +import sys + +from typing import TYPE_CHECKING +from typing import Any +from typing import Callable +from typing import Iterator +from typing import cast +from typing import overload + +from . import _log +from . import version + +if TYPE_CHECKING: + from . import _types as _t + from ._config import Configuration + from ._config import ParseFunction + + +from importlib.metadata import EntryPoint as EntryPoint + +if sys.version_info[:2] < (3, 10): + from importlib.metadata import entry_points as legacy_entry_points + + class EntryPoints: + _groupdata: list[EntryPoint] + + def __init__(self, groupdata: list[EntryPoint]) -> None: + self._groupdata = groupdata + + def select(self, name: str) -> EntryPoints: + return EntryPoints([x for x in self._groupdata if x.name == name]) + + def __iter__(self) -> Iterator[EntryPoint]: + return iter(self._groupdata) + + def entry_points(group: str) -> EntryPoints: + return EntryPoints(legacy_entry_points()[group]) + +else: + from importlib.metadata import EntryPoints + from importlib.metadata import entry_points + + +log = _log.log.getChild("entrypoints") + + +def version_from_entrypoint( + config: Configuration, *, entrypoint: str, root: _t.PathT +) -> version.ScmVersion | None: + from .discover import iter_matching_entrypoints + + log.debug("version_from_ep %s in %s", entrypoint, root) + for ep in iter_matching_entrypoints(root, entrypoint, config): + fn: ParseFunction = ep.load() + maybe_version: version.ScmVersion | None = fn(root, config=config) + log.debug("%s found %r", ep, maybe_version) + if maybe_version is not None: + return maybe_version + return None + + +def iter_entry_points(group: str, name: str | None = None) -> Iterator[EntryPoint]: + eps: EntryPoints = entry_points(group=group) + res = eps if name is None else eps.select(name=name) + + return iter(res) + + +def _get_ep(group: str, name: str) -> Any | None: + for ep in iter_entry_points(group, name): + log.debug("ep found: %s", ep.name) + return ep.load() + else: + return None + + +def _get_from_object_reference_str(path: str, group: str) -> Any | None: + # todo: remove for importlib native spelling + ep = EntryPoint(path, path, group) + try: + return ep.load() + except (AttributeError, ModuleNotFoundError): + return None + + +def _iter_version_schemes( + entrypoint: str, + scheme_value: _t.VERSION_SCHEMES, + _memo: set[object] | None = None, +) -> Iterator[Callable[[version.ScmVersion], str]]: + if _memo is None: + _memo = set() + if isinstance(scheme_value, str): + scheme_value = cast( + "_t.VERSION_SCHEMES", + _get_ep(entrypoint, scheme_value) + or _get_from_object_reference_str(scheme_value, entrypoint), + ) + + if isinstance(scheme_value, (list, tuple)): + for variant in scheme_value: + if variant not in _memo: + _memo.add(variant) + yield from _iter_version_schemes(entrypoint, variant, _memo=_memo) + elif callable(scheme_value): + yield scheme_value + + +@overload +def _call_version_scheme( + version: version.ScmVersion, + entrypoint: str, + given_value: _t.VERSION_SCHEMES, + default: str, +) -> str: ... + + +@overload +def _call_version_scheme( + version: version.ScmVersion, + entrypoint: str, + given_value: _t.VERSION_SCHEMES, + default: None, +) -> str | None: ... + + +def _call_version_scheme( + version: version.ScmVersion, + entrypoint: str, + given_value: _t.VERSION_SCHEMES, + default: str | None, +) -> str | None: + for scheme in _iter_version_schemes(entrypoint, given_value): + result = scheme(version) + if result is not None: + return result + return default diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py new file mode 100644 index 00000000000..8201bae1713 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py @@ -0,0 +1,113 @@ +from __future__ import annotations + +import itertools +import os + +from typing import TYPE_CHECKING +from typing import Callable + +from .. import _log +from .. import _types as _t +from .._entrypoints import iter_entry_points +from .pathtools import norm_real + +if TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 10): + from typing import TypeGuard + else: + from typing_extensions import TypeGuard + + +log = _log.log.getChild("file_finder") + + +def scm_find_files( + path: _t.PathT, + scm_files: set[str], + scm_dirs: set[str], + force_all_files: bool = False, +) -> list[str]: + """ setuptools compatible file finder that follows symlinks + + - path: the root directory from which to search + - scm_files: set of scm controlled files and symlinks + (including symlinks to directories) + - scm_dirs: set of scm controlled directories + (including directories containing no scm controlled files) + - force_all_files: ignore ``scm_files`` and ``scm_dirs`` and list everything. + + scm_files and scm_dirs must be absolute with symlinks resolved (realpath), + with normalized case (normcase) + + Spec here: https://setuptools.pypa.io/en/latest/userguide/extension.html#\ + adding-support-for-revision-control-systems + """ + realpath = norm_real(path) + seen: set[str] = set() + res: list[str] = [] + for dirpath, dirnames, filenames in os.walk(realpath, followlinks=True): + # dirpath with symlinks resolved + realdirpath = norm_real(dirpath) + + def _link_not_in_scm(n: str, realdirpath: str = realdirpath) -> bool: + fn = os.path.join(realdirpath, os.path.normcase(n)) + return os.path.islink(fn) and fn not in scm_files + + if not force_all_files and realdirpath not in scm_dirs: + # directory not in scm, don't walk it's content + dirnames[:] = [] + continue + if os.path.islink(dirpath) and not os.path.relpath( + realdirpath, realpath + ).startswith(os.pardir): + # a symlink to a directory not outside path: + # we keep it in the result and don't walk its content + res.append(os.path.join(path, os.path.relpath(dirpath, path))) + dirnames[:] = [] + continue + if realdirpath in seen: + # symlink loop protection + dirnames[:] = [] + continue + dirnames[:] = [ + dn for dn in dirnames if force_all_files or not _link_not_in_scm(dn) + ] + for filename in filenames: + if not force_all_files and _link_not_in_scm(filename): + continue + # dirpath + filename with symlinks preserved + fullfilename = os.path.join(dirpath, filename) + is_tracked = norm_real(fullfilename) in scm_files + if force_all_files or is_tracked: + res.append(os.path.join(path, os.path.relpath(fullfilename, realpath))) + seen.add(realdirpath) + return res + + +def is_toplevel_acceptable(toplevel: str | None) -> TypeGuard[str]: + """ """ + if toplevel is None: + return False + + ignored: list[str] = os.environ.get("SETUPTOOLS_SCM_IGNORE_VCS_ROOTS", "").split( + os.pathsep + ) + ignored = [os.path.normcase(p) for p in ignored] + + log.debug("toplevel: %r\n ignored %s", toplevel, ignored) + + return toplevel not in ignored + + +def find_files(path: _t.PathT = "") -> list[str]: + for ep in itertools.chain( + iter_entry_points("setuptools_scm.files_command"), + iter_entry_points("setuptools_scm.files_command_fallback"), + ): + command: Callable[[_t.PathT], list[str]] = ep.load() + res: list[str] = command(path) + if res: + return res + return [] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py new file mode 100644 index 00000000000..7b23f886420 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +import logging +import os +import subprocess +import tarfile + +from typing import IO + +from .. import _types as _t +from .._run_cmd import run as _run +from ..integration import data_from_mime +from . import is_toplevel_acceptable +from . import scm_find_files +from .pathtools import norm_real + +log = logging.getLogger(__name__) + + +def _git_toplevel(path: str) -> str | None: + try: + cwd = os.path.abspath(path or ".") + res = _run(["git", "rev-parse", "HEAD"], cwd=cwd) + if res.returncode: + # BAIL if there is no commit + log.error("listing git files failed - pretending there aren't any") + return None + res = _run( + ["git", "rev-parse", "--show-prefix"], + cwd=cwd, + ) + if res.returncode: + return None + out = res.stdout[:-1] # remove the trailing pathsep + if not out: + out = cwd + else: + # Here, ``out`` is a relative path to root of git. + # ``cwd`` is absolute path to current working directory. + # the below method removes the length of ``out`` from + # ``cwd``, which gives the git toplevel + assert cwd.replace("\\", "/").endswith(out), f"cwd={cwd!r}\nout={out!r}" + # In windows cwd contains ``\`` which should be replaced by ``/`` + # for this assertion to work. Length of string isn't changed by replace + # ``\\`` is just and escape for `\` + out = cwd[: -len(out)] + log.debug("find files toplevel %s", out) + return norm_real(out) + except subprocess.CalledProcessError: + # git returned error, we are not in a git repo + return None + except OSError: + # git command not found, probably + return None + + +def _git_interpret_archive(fd: IO[bytes], toplevel: str) -> tuple[set[str], set[str]]: + with tarfile.open(fileobj=fd, mode="r|*") as tf: + git_files = set() + git_dirs = {toplevel} + for member in tf.getmembers(): + name = os.path.normcase(member.name).replace("/", os.path.sep) + if member.type == tarfile.DIRTYPE: + git_dirs.add(name) + else: + git_files.add(name) + return git_files, git_dirs + + +def _git_ls_files_and_dirs(toplevel: str) -> tuple[set[str], set[str]]: + # use git archive instead of git ls-file to honor + # export-ignore git attribute + + cmd = ["git", "archive", "--prefix", toplevel + os.path.sep, "HEAD"] + proc = subprocess.Popen( + cmd, stdout=subprocess.PIPE, cwd=toplevel, stderr=subprocess.DEVNULL + ) + assert proc.stdout is not None + try: + try: + return _git_interpret_archive(proc.stdout, toplevel) + finally: + # ensure we avoid resource warnings by cleaning up the process + proc.stdout.close() + proc.terminate() + except Exception: + if proc.wait() != 0: + log.error("listing git files failed - pretending there aren't any") + return set(), set() + + +def git_find_files(path: _t.PathT = "") -> list[str]: + toplevel = _git_toplevel(os.fspath(path)) + if not is_toplevel_acceptable(toplevel): + return [] + fullpath = norm_real(path) + if not fullpath.startswith(toplevel): + log.warning("toplevel mismatch computed %s vs resolved %s ", toplevel, fullpath) + git_files, git_dirs = _git_ls_files_and_dirs(toplevel) + return scm_find_files(path, git_files, git_dirs) + + +def git_archive_find_files(path: _t.PathT = "") -> list[str]: + # This function assumes that ``path`` is obtained from a git archive + # and therefore all the files that should be ignored were already removed. + archival = os.path.join(path, ".git_archival.txt") + if not os.path.exists(archival): + return [] + + data = data_from_mime(archival) + + if "$Format" in data.get("node", ""): + # Substitutions have not been performed, so not a reliable archive + return [] + + log.warning("git archive detected - fallback to listing all files") + return scm_find_files(path, set(), set(), force_all_files=True) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py new file mode 100644 index 00000000000..9115a5fa8ac --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py @@ -0,0 +1,72 @@ +from __future__ import annotations + +import logging +import os +import subprocess + +from .. import _types as _t +from .._file_finders import is_toplevel_acceptable +from .._file_finders import scm_find_files +from .._run_cmd import run as _run +from ..integration import data_from_mime +from .pathtools import norm_real + +log = logging.getLogger(__name__) + + +def _hg_toplevel(path: str) -> str | None: + try: + return _run( + ["hg", "root"], + cwd=(path or "."), + check=True, + ).parse_success(norm_real) + except subprocess.CalledProcessError: + # hg returned error, we are not in a mercurial repo + return None + except OSError: + # hg command not found, probably + return None + + +def _hg_ls_files_and_dirs(toplevel: str) -> tuple[set[str], set[str]]: + hg_files: set[str] = set() + hg_dirs = {toplevel} + res = _run(["hg", "files"], cwd=toplevel) + if res.returncode: + return set(), set() + for name in res.stdout.splitlines(): + name = os.path.normcase(name).replace("/", os.path.sep) + fullname = os.path.join(toplevel, name) + hg_files.add(fullname) + dirname = os.path.dirname(fullname) + while len(dirname) > len(toplevel) and dirname not in hg_dirs: + hg_dirs.add(dirname) + dirname = os.path.dirname(dirname) + return hg_files, hg_dirs + + +def hg_find_files(path: str = "") -> list[str]: + toplevel = _hg_toplevel(path) + if not is_toplevel_acceptable(toplevel): + return [] + assert toplevel is not None + hg_files, hg_dirs = _hg_ls_files_and_dirs(toplevel) + return scm_find_files(path, hg_files, hg_dirs) + + +def hg_archive_find_files(path: _t.PathT = "") -> list[str]: + # This function assumes that ``path`` is obtained from a mercurial archive + # and therefore all the files that should be ignored were already removed. + archival = os.path.join(path, ".hg_archival.txt") + if not os.path.exists(archival): + return [] + + data = data_from_mime(archival) + + if "node" not in data: + # Ensure file is valid + return [] + + log.warning("hg archive detected - fallback to listing all files") + return scm_find_files(path, set(), set(), force_all_files=True) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py new file mode 100644 index 00000000000..6de850897b9 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py @@ -0,0 +1,9 @@ +from __future__ import annotations + +import os + +from setuptools_scm import _types as _t + + +def norm_real(path: _t.PathT) -> str: + return os.path.normcase(os.path.realpath(path)) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py new file mode 100644 index 00000000000..877804c18bf --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py @@ -0,0 +1,175 @@ +from __future__ import annotations + +import logging +import re +import warnings + +from pathlib import Path +from typing import Any +from typing import NoReturn +from typing import Pattern + +from . import _config +from . import _entrypoints +from . import _run_cmd +from . import _types as _t +from ._config import Configuration +from ._overrides import _read_pretended_version_for +from ._version_cls import _validate_version_cls +from .version import ScmVersion +from .version import format_version as _format_version + +EMPTY_TAG_REGEX_DEPRECATION = DeprecationWarning( + "empty regex for tag regex is invalid, using default" +) + +_log = logging.getLogger(__name__) + + +def parse_scm_version(config: Configuration) -> ScmVersion | None: + try: + if config.parse is not None: + parse_result = config.parse(config.absolute_root, config=config) + if parse_result is not None and not isinstance(parse_result, ScmVersion): + raise TypeError( + f"version parse result was {str!r}\n" + "please return a parsed version (ScmVersion)" + ) + return parse_result + else: + return _entrypoints.version_from_entrypoint( + config, + entrypoint="setuptools_scm.parse_scm", + root=config.absolute_root, + ) + except _run_cmd.CommandNotFoundError as e: + _log.exception("command %s not found while parsing the scm, using fallbacks", e) + return None + + +def parse_fallback_version(config: Configuration) -> ScmVersion | None: + return _entrypoints.version_from_entrypoint( + config, + entrypoint="setuptools_scm.parse_scm_fallback", + root=config.fallback_root, + ) + + +def parse_version(config: Configuration) -> ScmVersion | None: + return ( + _read_pretended_version_for(config) + or parse_scm_version(config) + or parse_fallback_version(config) + ) + + +def write_version_files( + config: Configuration, version: str, scm_version: ScmVersion +) -> None: + if config.write_to is not None: + from ._integration.dump_version import dump_version + + dump_version( + root=config.root, + version=version, + scm_version=scm_version, + write_to=config.write_to, + template=config.write_to_template, + ) + if config.version_file: + from ._integration.dump_version import write_version_to_path + + version_file = Path(config.version_file) + assert not version_file.is_absolute(), f"{version_file=}" + # todo: use a better name than fallback root + assert config.relative_to is not None + target = Path(config.relative_to).parent.joinpath(version_file) + write_version_to_path( + target, + template=config.version_file_template, + version=version, + scm_version=scm_version, + ) + + +def _get_version( + config: Configuration, force_write_version_files: bool | None = None +) -> str | None: + parsed_version = parse_version(config) + if parsed_version is None: + return None + version_string = _format_version(parsed_version) + if force_write_version_files is None: + force_write_version_files = True + warnings.warn( + "force_write_version_files ought to be set," + " presuming the legacy True value", + DeprecationWarning, + ) + + if force_write_version_files: + write_version_files(config, version=version_string, scm_version=parsed_version) + + return version_string + + +def _version_missing(config: Configuration) -> NoReturn: + raise LookupError( + f"setuptools-scm was unable to detect version for {config.absolute_root}.\n\n" + "Make sure you're either building from a fully intact git repository " + "or PyPI tarballs. Most other sources (such as GitHub's tarballs, a " + "git checkout without the .git folder) don't contain the necessary " + "metadata and will not work.\n\n" + "For example, if you're using pip, instead of " + "https://github.com/user/proj/archive/master.zip " + "use git+https://github.com/user/proj.git#egg=proj" + ) + + +def get_version( + root: _t.PathT = ".", + version_scheme: _t.VERSION_SCHEME = _config.DEFAULT_VERSION_SCHEME, + local_scheme: _t.VERSION_SCHEME = _config.DEFAULT_LOCAL_SCHEME, + write_to: _t.PathT | None = None, + write_to_template: str | None = None, + version_file: _t.PathT | None = None, + version_file_template: str | None = None, + relative_to: _t.PathT | None = None, + tag_regex: str | Pattern[str] = _config.DEFAULT_TAG_REGEX, + parentdir_prefix_version: str | None = None, + fallback_version: str | None = None, + fallback_root: _t.PathT = ".", + parse: Any | None = None, + git_describe_command: _t.CMD_TYPE | None = None, + dist_name: str | None = None, + version_cls: Any | None = None, + normalize: bool = True, + search_parent_directories: bool = False, +) -> str: + """ + If supplied, relative_to should be a file from which root may + be resolved. Typically called by a script or module that is not + in the root of the repository to direct setuptools_scm to the + root of the repository by supplying ``__file__``. + """ + + version_cls = _validate_version_cls(version_cls, normalize) + del normalize + tag_regex = parse_tag_regex(tag_regex) + config = Configuration(**locals()) + maybe_version = _get_version(config, force_write_version_files=True) + + if maybe_version is None: + _version_missing(config) + return maybe_version + + +def parse_tag_regex(tag_regex: str | Pattern[str]) -> Pattern[str]: + if isinstance(tag_regex, str): + if tag_regex == "": + warnings.warn(EMPTY_TAG_REGEX_DEPRECATION) + return _config.DEFAULT_TAG_REGEX + else: + return re.compile(tag_regex) + else: + return tag_regex diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py new file mode 100644 index 00000000000..1901b1d3ba7 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import warnings + +from pathlib import Path + +from .. import _types as _t +from .._log import log as parent_log +from .._version_cls import _version_as_tuple +from ..version import ScmVersion + +log = parent_log.getChild("dump_version") + +TEMPLATES = { + ".py": """\ +# file generated by setuptools_scm +# don't change, don't track in version control +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple, Union + VERSION_TUPLE = Tuple[Union[int, str], ...] +else: + VERSION_TUPLE = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE + +__version__ = version = {version!r} +__version_tuple__ = version_tuple = {version_tuple!r} +""", + ".txt": "{version}", +} + + +def dump_version( + root: _t.PathT, + version: str, + write_to: _t.PathT, + template: str | None = None, + scm_version: ScmVersion | None = None, +) -> None: + assert isinstance(version, str) + root = Path(root) + write_to = Path(write_to) + if write_to.is_absolute(): + # trigger warning on escape + write_to.relative_to(root) + warnings.warn( + f"{write_to=!s} is a absolute path," + " please switch to using a relative version file", + DeprecationWarning, + ) + target = write_to + else: + target = Path(root).joinpath(write_to) + write_version_to_path( + target, template=template, version=version, scm_version=scm_version + ) + + +def _validate_template(target: Path, template: str | None) -> str: + if template == "": + warnings.warn(f"{template=} looks like a error, using default instead") + template = None + if template is None: + template = TEMPLATES.get(target.suffix) + + if template is None: + raise ValueError( + f"bad file format: {target.suffix!r} (of {target})\n" + "only *.txt and *.py have a default template" + ) + else: + return template + + +def write_version_to_path( + target: Path, template: str | None, version: str, scm_version: ScmVersion | None +) -> None: + final_template = _validate_template(target, template) + log.debug("dump %s into %s", version, target) + version_tuple = _version_as_tuple(version) + if scm_version is not None: + content = final_template.format( + version=version, + version_tuple=version_tuple, + scm_version=scm_version, + ) + else: + content = final_template.format(version=version, version_tuple=version_tuple) + + target.write_text(content, encoding="utf-8") diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py new file mode 100644 index 00000000000..0e4f9aa11b7 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py @@ -0,0 +1,85 @@ +from __future__ import annotations + +import warnings + +from pathlib import Path +from typing import NamedTuple + +from .. import _log +from .setuptools import read_dist_name_from_setup_cfg +from .toml import TOML_RESULT +from .toml import read_toml_content + +log = _log.log.getChild("pyproject_reading") + +_ROOT = "root" + + +class PyProjectData(NamedTuple): + path: Path + tool_name: str + project: TOML_RESULT + section: TOML_RESULT + + @property + def project_name(self) -> str | None: + return self.project.get("name") + + +def read_pyproject( + path: Path = Path("pyproject.toml"), + tool_name: str = "setuptools_scm", + require_section: bool = True, +) -> PyProjectData: + defn = read_toml_content(path, None if require_section else {}) + try: + section = defn.get("tool", {})[tool_name] + except LookupError as e: + error = f"{path} does not contain a tool.{tool_name} section" + if require_section: + raise LookupError(error) from e + else: + log.warning("toml section missing %r", error, exc_info=True) + section = {} + + project = defn.get("project", {}) + return PyProjectData(path, tool_name, project, section) + + +def get_args_for_pyproject( + pyproject: PyProjectData, + dist_name: str | None, + kwargs: TOML_RESULT, +) -> TOML_RESULT: + """drops problematic details and figures the distribution name""" + section = pyproject.section.copy() + kwargs = kwargs.copy() + if "relative_to" in section: + relative = section.pop("relative_to") + warnings.warn( + f"{pyproject.path}: at [tool.{pyproject.tool_name}]\n" + f"ignoring value relative_to={relative!r}" + " as its always relative to the config file" + ) + if "dist_name" in section: + if dist_name is None: + dist_name = section.pop("dist_name") + else: + assert dist_name == section["dist_name"] + section.pop("dist_name") + if dist_name is None: + # minimal pep 621 support for figuring the pretend keys + dist_name = pyproject.project_name + if dist_name is None: + dist_name = read_dist_name_from_setup_cfg() + if _ROOT in kwargs: + if kwargs[_ROOT] is None: + kwargs.pop(_ROOT, None) + elif _ROOT in section: + if section[_ROOT] != kwargs[_ROOT]: + warnings.warn( + f"root {section[_ROOT]} is overridden" + f" by the cli arg {kwargs[_ROOT]}" + ) + section.pop(_ROOT, None) + return {"dist_name": dist_name, **section, **kwargs} diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py new file mode 100644 index 00000000000..dfc5a286430 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py @@ -0,0 +1,123 @@ +from __future__ import annotations + +import logging +import os +import warnings + +from typing import Any +from typing import Callable + +import setuptools + +from .. import _config + +log = logging.getLogger(__name__) + + +def read_dist_name_from_setup_cfg( + input: str | os.PathLike[str] = "setup.cfg", +) -> str | None: + # minimal effort to read dist_name off setup.cfg metadata + import configparser + + parser = configparser.ConfigParser() + parser.read([input], encoding="utf-8") + dist_name = parser.get("metadata", "name", fallback=None) + return dist_name + + +def _warn_on_old_setuptools(_version: str = setuptools.__version__) -> None: + if int(_version.split(".")[0]) < 61: + warnings.warn( + RuntimeWarning( + f""" +ERROR: setuptools=={_version} is used in combination with setuptools_scm>=8.x + +Your build configuration is incomplete and previously worked by accident! +setuptools_scm requires setuptools>=61 + +Suggested workaround if applicable: + - migrating from the deprecated setup_requires mechanism to pep517/518 + and using a pyproject.toml to declare build dependencies + which are reliably pre-installed before running the build tools +""" + ) + ) + + +def _assign_version( + dist: setuptools.Distribution, config: _config.Configuration +) -> None: + from .._get_version_impl import _get_version + from .._get_version_impl import _version_missing + + # todo: build time plugin + maybe_version = _get_version(config, force_write_version_files=True) + + if maybe_version is None: + _version_missing(config) + else: + assert dist.metadata.version is None + dist.metadata.version = maybe_version + + +_warn_on_old_setuptools() + + +def _log_hookstart(hook: str, dist: setuptools.Distribution) -> None: + log.debug("%s %r", hook, vars(dist.metadata)) + + +def version_keyword( + dist: setuptools.Distribution, + keyword: str, + value: bool | dict[str, Any] | Callable[[], dict[str, Any]], +) -> None: + overrides: dict[str, Any] + if value is True: + overrides = {} + elif callable(value): + overrides = value() + else: + assert isinstance(value, dict), "version_keyword expects a dict or True" + overrides = value + + assert ( + "dist_name" not in overrides + ), "dist_name may not be specified in the setup keyword " + dist_name: str | None = dist.metadata.name + _log_hookstart("version_keyword", dist) + + if dist.metadata.version is not None: + warnings.warn(f"version of {dist_name} already set") + return + + if dist_name is None: + dist_name = read_dist_name_from_setup_cfg() + + config = _config.Configuration.from_file( + dist_name=dist_name, + _require_section=False, + **overrides, + ) + _assign_version(dist, config) + + +def infer_version(dist: setuptools.Distribution) -> None: + _log_hookstart("infer_version", dist) + log.debug("dist %s %s", id(dist), id(dist.metadata)) + if dist.metadata.version is not None: + return # metadata already added by hook + dist_name = dist.metadata.name + if dist_name is None: + dist_name = read_dist_name_from_setup_cfg() + if not os.path.isfile("pyproject.toml"): + return + if dist_name == "setuptools_scm": + return + try: + config = _config.Configuration.from_file(dist_name=dist_name) + except LookupError as e: + log.info(e, exc_info=True) + else: + _assign_version(dist, config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py new file mode 100644 index 00000000000..8ca38d975ab --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +import sys + +from pathlib import Path +from typing import TYPE_CHECKING +from typing import Any +from typing import Callable +from typing import Dict +from typing import TypedDict +from typing import cast + +if sys.version_info >= (3, 11): + from tomllib import loads as load_toml +else: + from tomli import loads as load_toml + +if TYPE_CHECKING: + if sys.version_info >= (3, 10): + from typing import TypeAlias + else: + from typing_extensions import TypeAlias + +from .. import _log + +log = _log.log.getChild("toml") + +TOML_RESULT: TypeAlias = Dict[str, Any] +TOML_LOADER: TypeAlias = Callable[[str], TOML_RESULT] + + +def read_toml_content(path: Path, default: TOML_RESULT | None = None) -> TOML_RESULT: + try: + data = path.read_text(encoding="utf-8") + except FileNotFoundError: + if default is None: + raise + else: + log.debug("%s missing, presuming default %r", path, default) + return default + else: + return load_toml(data) + + +class _CheatTomlData(TypedDict): + cheat: dict[str, Any] + + +def load_toml_or_inline_map(data: str | None) -> dict[str, Any]: + """ + load toml data - with a special hack if only a inline map is given + """ + if not data: + return {} + elif data[0] == "{": + data = "cheat=" + data + loaded: _CheatTomlData = cast(_CheatTomlData, load_toml(data)) + return loaded["cheat"] + return load_toml(data) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py new file mode 100644 index 00000000000..7e4b7db7da1 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py @@ -0,0 +1,87 @@ +""" +logging helpers, supports vendoring +""" + +from __future__ import annotations + +import contextlib +import logging +import os +import sys + +from typing import IO +from typing import Iterator +from typing import Mapping + +log = logging.getLogger(__name__.rsplit(".", 1)[0]) +log.propagate = False + + +class AlwaysStdErrHandler(logging.StreamHandler): # type: ignore[type-arg] + def __init___(self) -> None: + super().__init__(sys.stderr) + + @property # type: ignore [override] + def stream(self) -> IO[str]: + return sys.stderr + + @stream.setter + def stream(self, value: IO[str]) -> None: + assert value is sys.stderr + + +def make_default_handler() -> logging.Handler: + try: + from rich.console import Console + + console = Console(stderr=True) + from rich.logging import RichHandler + + return RichHandler(console=console) + except ImportError: + handler = AlwaysStdErrHandler() + handler.setFormatter(logging.Formatter("%(levelname)s %(name)s %(message)s")) + return handler + + +_default_handler = make_default_handler() + +log.addHandler(_default_handler) + + +def _default_log_level(_env: Mapping[str, str] = os.environ) -> int: + val: str | None = _env.get("SETUPTOOLS_SCM_DEBUG") + return logging.WARN if val is None else logging.DEBUG + + +log.setLevel(_default_log_level()) + + +@contextlib.contextmanager +def defer_to_pytest() -> Iterator[None]: + log.propagate = True + old_level = log.level + log.setLevel(logging.NOTSET) + log.removeHandler(_default_handler) + try: + yield + finally: + log.addHandler(_default_handler) + log.propagate = False + log.setLevel(old_level) + + +@contextlib.contextmanager +def enable_debug(handler: logging.Handler = _default_handler) -> Iterator[None]: + log.addHandler(handler) + old_level = log.level + log.setLevel(logging.DEBUG) + old_handler_level = handler.level + handler.setLevel(logging.DEBUG) + try: + yield + finally: + log.setLevel(old_level) + handler.setLevel(old_handler_level) + if handler is not _default_handler: + log.removeHandler(handler) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py new file mode 100644 index 00000000000..aae41a632fc --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import re + +from . import _types as _t + + +def strip_local(version_string: str) -> str: + public = version_string.partition("+")[0] + return public + + +def _add_post(version: str) -> str: + if "post" in version: + raise ValueError( + f"{version} already is a post release, refusing to guess the update" + ) + return f"{version}.post1" + + +def _bump_dev(version: str) -> str | None: + if ".dev" not in version: + return None + + prefix, tail = version.rsplit(".dev", 1) + if tail != "0": + raise ValueError( + "choosing custom numbers for the `.devX` distance " + "is not supported.\n " + f"The {version} can't be bumped\n" + "Please drop the tag or create a new supported one ending in .dev0" + ) + return prefix + + +def _bump_regex(version: str) -> str: + match = re.match(r"(.*?)(\d+)$", version) + if match is None: + raise ValueError( + f"{version} does not end with a number to bump, " + "please correct or use a custom version scheme" + ) + else: + prefix, tail = match.groups() + return f"{prefix}{int(tail) + 1}" + + +def _format_local_with_time(version: _t.SCMVERSION, time_format: str) -> str: + if version.exact or version.node is None: + return version.format_choice( + "", "+d{time:{time_format}}", time_format=time_format + ) + else: + return version.format_choice( + "+{node}", "+{node}.d{time:{time_format}}", time_format=time_format + ) + + +def _dont_guess_next_version(tag_version: _t.SCMVERSION) -> str: + version = strip_local(str(tag_version.tag)) + return _bump_dev(version) or _add_post(version) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py new file mode 100644 index 00000000000..ee9269a719f --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import os +import re + +from typing import Any + +from . import _config +from . import _log +from . import version +from ._integration.toml import load_toml_or_inline_map + +log = _log.log.getChild("overrides") + +PRETEND_KEY = "SETUPTOOLS_SCM_PRETEND_VERSION" +PRETEND_KEY_NAMED = PRETEND_KEY + "_FOR_{name}" + + +def read_named_env( + *, tool: str = "SETUPTOOLS_SCM", name: str, dist_name: str | None +) -> str | None: + """ """ + if dist_name is not None: + # Normalize the dist name as per PEP 503. + normalized_dist_name = re.sub(r"[-_.]+", "-", dist_name) + env_var_dist_name = normalized_dist_name.replace("-", "_").upper() + val = os.environ.get(f"{tool}_{name}_FOR_{env_var_dist_name}") + if val is not None: + return val + return os.environ.get(f"{tool}_{name}") + + +def _read_pretended_version_for( + config: _config.Configuration, +) -> version.ScmVersion | None: + """read a a overridden version from the environment + + tries ``SETUPTOOLS_SCM_PRETEND_VERSION`` + and ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_$UPPERCASE_DIST_NAME`` + """ + log.debug("dist name: %s", config.dist_name) + + pretended = read_named_env(name="PRETEND_VERSION", dist_name=config.dist_name) + + if pretended: + # we use meta here since the pretended version + # must adhere to the pep to begin with + return version.meta(tag=pretended, preformatted=True, config=config) + else: + return None + + +def read_toml_overrides(dist_name: str | None) -> dict[str, Any]: + data = read_named_env(name="OVERRIDES", dist_name=dist_name) + return load_toml_or_inline_map(data) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py new file mode 100644 index 00000000000..f2a82852c31 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py @@ -0,0 +1,214 @@ +from __future__ import annotations + +import os +import shlex +import subprocess +import textwrap +import warnings + +from typing import TYPE_CHECKING +from typing import Callable +from typing import Final +from typing import Mapping +from typing import Sequence +from typing import TypeVar +from typing import overload + +from . import _log +from . import _types as _t + +if TYPE_CHECKING: + BaseCompletedProcess = subprocess.CompletedProcess[str] +else: + BaseCompletedProcess = subprocess.CompletedProcess + +# pick 40 seconds +# unfortunately github CI for windows sometimes needs +# up to 30 seconds to start a command + + +def _get_timeout(env: Mapping[str, str]) -> int: + return int(env.get("SETUPTOOLS_SCM_SUBPROCESS_TIMEOUT") or 40) + + +BROKEN_TIMEOUT: Final[int] = _get_timeout(os.environ) + +log = _log.log.getChild("run_cmd") + +PARSE_RESULT = TypeVar("PARSE_RESULT") +T = TypeVar("T") + + +class CompletedProcess(BaseCompletedProcess): + @classmethod + def from_raw( + cls, input: BaseCompletedProcess, strip: bool = True + ) -> CompletedProcess: + return cls( + args=input.args, + returncode=input.returncode, + stdout=input.stdout.strip() if strip and input.stdout else input.stdout, + stderr=input.stderr.strip() if strip and input.stderr else input.stderr, + ) + + @overload + def parse_success( + self, + parse: Callable[[str], PARSE_RESULT], + default: None = None, + error_msg: str | None = None, + ) -> PARSE_RESULT | None: ... + + @overload + def parse_success( + self, + parse: Callable[[str], PARSE_RESULT], + default: T, + error_msg: str | None = None, + ) -> PARSE_RESULT | T: ... + + def parse_success( + self, + parse: Callable[[str], PARSE_RESULT], + default: T | None = None, + error_msg: str | None = None, + ) -> PARSE_RESULT | T | None: + if self.returncode: + if error_msg: + log.warning("%s %s", error_msg, self) + return default + else: + return parse(self.stdout) + + +def no_git_env(env: Mapping[str, str]) -> dict[str, str]: + # adapted from pre-commit + # Too many bugs dealing with environment variables and GIT: + # https://github.com/pre-commit/pre-commit/issues/300 + # In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running + # pre-commit hooks + # In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE + # while running pre-commit hooks in submodules. + # GIT_DIR: Causes git clone to clone wrong thing + # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit + for k, v in env.items(): + if k.startswith("GIT_"): + log.debug("%s: %s", k, v) + return { + k: v + for k, v in env.items() + if not k.startswith("GIT_") + or k in ("GIT_EXEC_PATH", "GIT_SSH", "GIT_SSH_COMMAND") + } + + +def avoid_pip_isolation(env: Mapping[str, str]) -> dict[str, str]: + """ + pip build isolation can break Mercurial + (see https://github.com/pypa/pip/issues/10635) + + pip uses PYTHONNOUSERSITE and a path in PYTHONPATH containing "pip-build-env-". + """ + new_env = {k: v for k, v in env.items() if k != "PYTHONNOUSERSITE"} + if "PYTHONPATH" not in new_env: + return new_env + + new_env["PYTHONPATH"] = os.pathsep.join( + [ + path + for path in new_env["PYTHONPATH"].split(os.pathsep) + if "pip-build-env-" not in path + ] + ) + return new_env + + +def ensure_stripped_str(str_or_bytes: str | bytes) -> str: + if isinstance(str_or_bytes, str): + return str_or_bytes.strip() + else: + return str_or_bytes.decode("utf-8", "surrogateescape").strip() + + +def run( + cmd: _t.CMD_TYPE, + cwd: _t.PathT, + *, + strip: bool = True, + trace: bool = True, + timeout: int | None = None, + check: bool = False, +) -> CompletedProcess: + if isinstance(cmd, str): + cmd = shlex.split(cmd) + else: + cmd = [os.fspath(x) for x in cmd] + cmd_4_trace = " ".join(map(_unsafe_quote_for_display, cmd)) + log.debug("at %s\n $ %s ", cwd, cmd_4_trace) + if timeout is None: + timeout = BROKEN_TIMEOUT + res = subprocess.run( + cmd, + capture_output=True, + cwd=os.fspath(cwd), + env=dict( + avoid_pip_isolation(no_git_env(os.environ)), + # os.environ, + # try to disable i18n, but still allow UTF-8 encoded text. + LC_ALL="C.UTF-8", + LANGUAGE="", + HGPLAIN="1", + ), + text=True, + encoding="utf-8", + timeout=timeout, + ) + + res = CompletedProcess.from_raw(res, strip=strip) + if trace: + if res.stdout: + log.debug("out:\n%s", textwrap.indent(res.stdout, " ")) + if res.stderr: + log.debug("err:\n%s", textwrap.indent(res.stderr, " ")) + if res.returncode: + log.debug("ret: %s", res.returncode) + if check: + res.check_returncode() + return res + + +def _unsafe_quote_for_display(item: _t.PathT) -> str: + # give better results than shlex.join in our cases + text = os.fspath(item) + return text if all(c not in text for c in " {[:") else f'"{text}"' + + +def has_command( + name: str, args: Sequence[str] = ["version"], warn: bool = True +) -> bool: + try: + p = run([name, *args], cwd=".") + if p.returncode != 0: + log.error(f"Command '{name}' returned non-zero. This is stderr:") + log.error(p.stderr) + except OSError as e: + log.warning("command %s missing: %s", name, e) + res = False + except subprocess.TimeoutExpired as e: + log.warning("command %s timed out %s", name, e) + res = False + + else: + res = not p.returncode + if not res and warn: + warnings.warn("%r was not found" % name, category=RuntimeWarning) + return res + + +class CommandNotFoundError(LookupError, FileNotFoundError): + pass + + +def require_command(name: str) -> None: + if not has_command(name, warn=False): + raise CommandNotFoundError(name) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py new file mode 100644 index 00000000000..b655c76f290 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +import os + +from typing import TYPE_CHECKING +from typing import Callable +from typing import List +from typing import Sequence +from typing import Tuple +from typing import Union + +if TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 10): + from typing import TypeAlias + else: + from typing_extensions import TypeAlias + + from . import version + +PathT: TypeAlias = Union["os.PathLike[str]", str] + +CMD_TYPE: TypeAlias = Union[Sequence[PathT], str] + +VERSION_SCHEME: TypeAlias = Union[str, Callable[["version.ScmVersion"], str]] +VERSION_SCHEMES: TypeAlias = Union[List[str], Tuple[str, ...], VERSION_SCHEME] +SCMVERSION: TypeAlias = "version.ScmVersion" diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py new file mode 100644 index 00000000000..bb89bbb1250 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +from typing import Type +from typing import Union +from typing import cast + +try: + from packaging.version import InvalidVersion + from packaging.version import Version as Version +except ImportError: + from setuptools.extern.packaging.version import InvalidVersion # type: ignore + from setuptools.extern.packaging.version import Version as Version # type: ignore +from . import _log + +log = _log.log.getChild("version_cls") + + +class NonNormalizedVersion(Version): + """A non-normalizing version handler. + + You can use this class to preserve version verification but skip normalization. + For example you can use this to avoid git release candidate version tags + ("1.0.0-rc1") to be normalized to "1.0.0rc1". Only use this if you fully + trust the version tags. + """ + + def __init__(self, version: str) -> None: + # parse and validate using parent + super().__init__(version) + + # store raw for str + self._raw_version = version + + def __str__(self) -> str: + # return the non-normalized version (parent returns the normalized) + return self._raw_version + + def __repr__(self) -> str: + # same pattern as parent + return f"" + + +def _version_as_tuple(version_str: str) -> tuple[int | str, ...]: + try: + parsed_version = Version(version_str) + except InvalidVersion as e: + log.error("failed to parse version %s: %s", e, version_str) + return (version_str,) + else: + version_fields: tuple[int | str, ...] = parsed_version.release + if parsed_version.dev is not None: + version_fields += (f"dev{parsed_version.dev}",) + if parsed_version.local is not None: + version_fields += (parsed_version.local,) + return version_fields + + +_VersionT = Union[Version, NonNormalizedVersion] + + +def import_name(name: str) -> object: + import importlib + + pkg_name, cls_name = name.rsplit(".", 1) + pkg = importlib.import_module(pkg_name) + return getattr(pkg, cls_name) + + +def _validate_version_cls( + version_cls: type[_VersionT] | str | None, normalize: bool +) -> type[_VersionT]: + if not normalize: + if version_cls is not None: + raise ValueError( + "Providing a custom `version_cls` is not permitted when " + "`normalize=False`" + ) + return NonNormalizedVersion + else: + # Use `version_cls` if provided, default to packaging or pkg_resources + if version_cls is None: + return Version + elif isinstance(version_cls, str): + try: + return cast(Type[_VersionT], import_name(version_cls)) + except: # noqa + raise ValueError( + f"Unable to import version_cls='{version_cls}'" + ) from None + else: + return version_cls diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py new file mode 100644 index 00000000000..7c1be381f4b --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py @@ -0,0 +1,70 @@ +from __future__ import annotations + +import os + +from pathlib import Path +from typing import Iterable +from typing import Iterator + +from . import _entrypoints +from . import _log +from . import _types as _t +from ._config import Configuration + +log = _log.log.getChild("discover") + + +def walk_potential_roots(root: _t.PathT, search_parents: bool = True) -> Iterator[Path]: + """ + Iterate though a path and each of its parents. + :param root: File path. + :param search_parents: If ``False`` the parents are not considered. + """ + root = Path(root) + yield root + if search_parents: + yield from root.parents + + +def match_entrypoint(root: _t.PathT, name: str) -> bool: + """ + Consider a ``root`` as entry-point. + :param root: File path. + :param name: Subdirectory name. + :return: ``True`` if a subdirectory ``name`` exits in ``root``. + """ + + if os.path.exists(os.path.join(root, name)): + if not os.path.isabs(name): + return True + log.debug("ignoring bad ep %s", name) + + return False + + +# blocked entrypints from legacy plugins +_BLOCKED_EP_TARGETS = {"setuptools_scm_git_archive:parse"} + + +def iter_matching_entrypoints( + root: _t.PathT, entrypoint: str, config: Configuration +) -> Iterable[_entrypoints.EntryPoint]: + """ + Consider different entry-points in ``root`` and optionally its parents. + :param root: File path. + :param entrypoint: Entry-point to consider. + :param config: Configuration, + read ``search_parent_directories``, write found parent to ``parent``. + """ + + log.debug("looking for ep %s in %s", entrypoint, root) + from ._entrypoints import iter_entry_points + + for wd in walk_potential_roots(root, config.search_parent_directories): + for ep in iter_entry_points(entrypoint): + if ep.value in _BLOCKED_EP_TARGETS: + continue + if match_entrypoint(wd, ep.name): + log.debug("found ep %s in %s", ep, wd) + config.parent = wd + yield ep diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py new file mode 100644 index 00000000000..45a75351c9a --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import logging +import os + +from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from . import _types as _t +from . import Configuration +from .integration import data_from_mime +from .version import ScmVersion +from .version import meta +from .version import tag_to_version + +log = logging.getLogger(__name__) + +_UNKNOWN = "UNKNOWN" + + +def parse_pkginfo(root: _t.PathT, config: Configuration) -> ScmVersion | None: + pkginfo = Path(root) / "PKG-INFO" + log.debug("pkginfo %s", pkginfo) + data = data_from_mime(pkginfo) + version = data.get("Version", _UNKNOWN) + if version != _UNKNOWN: + return meta(version, preformatted=True, config=config) + else: + return None + + +def fallback_version(root: _t.PathT, config: Configuration) -> ScmVersion | None: + if config.parentdir_prefix_version is not None: + _, parent_name = os.path.split(os.path.abspath(root)) + if parent_name.startswith(config.parentdir_prefix_version): + version = tag_to_version( + parent_name[len(config.parentdir_prefix_version) :], config + ) + if version is not None: + return meta(str(version), preformatted=True, config=config) + if config.fallback_version is not None: + log.debug("FALLBACK %s", config.fallback_version) + return meta(config.fallback_version, preformatted=True, config=config) + return None diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py new file mode 100644 index 00000000000..eb1d519ab1d --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py @@ -0,0 +1,340 @@ +from __future__ import annotations + +import dataclasses +import logging +import os +import re +import shlex +import sys +import warnings + +from datetime import date +from datetime import datetime +from datetime import timezone +from os.path import samefile +from pathlib import Path +from typing import TYPE_CHECKING +from typing import Callable +from typing import Sequence + +from . import Configuration +from . import _types as _t +from . import discover +from ._run_cmd import CompletedProcess as _CompletedProcess +from ._run_cmd import require_command as _require_command +from ._run_cmd import run as _run +from .integration import data_from_mime +from .scm_workdir import Workdir +from .version import ScmVersion +from .version import meta +from .version import tag_to_version + +if TYPE_CHECKING: + from . import hg_git +log = logging.getLogger(__name__) + +REF_TAG_RE = re.compile(r"(?<=\btag: )([^,]+)\b") +DESCRIBE_UNSUPPORTED = "%(describe" + +# If testing command in shell make sure to quote the match argument like +# '*[0-9]*' as it will expand before being sent to git if there are any matching +# files in current directory. +DEFAULT_DESCRIBE = [ + "git", + "describe", + "--dirty", + "--tags", + "--long", + "--match", + "*[0-9]*", +] + + +def run_git( + args: Sequence[str | os.PathLike[str]], + repo: Path, + *, + check: bool = False, + timeout: int | None = None, +) -> _CompletedProcess: + return _run( + ["git", "--git-dir", repo / ".git", *args], + cwd=repo, + check=check, + timeout=timeout, + ) + + +class GitWorkdir(Workdir): + """experimental, may change at any time""" + + @classmethod + def from_potential_worktree(cls, wd: _t.PathT) -> GitWorkdir | None: + wd = Path(wd).resolve() + real_wd = run_git(["rev-parse", "--show-prefix"], wd).parse_success(parse=str) + if real_wd is None: + return None + else: + real_wd = real_wd[:-1] # remove the trailing pathsep + + if not real_wd: + real_wd = os.fspath(wd) + else: + str_wd = os.fspath(wd) + assert str_wd.replace("\\", "/").endswith(real_wd) + # In windows wd contains ``\`` which should be replaced by ``/`` + # for this assertion to work. Length of string isn't changed by replace + # ``\\`` is just and escape for `\` + real_wd = str_wd[: -len(real_wd)] + log.debug("real root %s", real_wd) + if not samefile(real_wd, wd): + return None + + return cls(Path(real_wd)) + + def is_dirty(self) -> bool: + return run_git( + ["status", "--porcelain", "--untracked-files=no"], self.path + ).parse_success( + parse=bool, + default=False, + ) + + def get_branch(self) -> str | None: + return run_git( + ["rev-parse", "--abbrev-ref", "HEAD"], + self.path, + ).parse_success( + parse=str, + error_msg="branch err (abbrev-err)", + ) or run_git( + ["symbolic-ref", "--short", "HEAD"], + self.path, + ).parse_success( + parse=str, + error_msg="branch err (symbolic-ref)", + ) + + def get_head_date(self) -> date | None: + def parse_timestamp(timestamp_text: str) -> date | None: + if "%c" in timestamp_text: + log.warning("git too old -> timestamp is %r", timestamp_text) + return None + if sys.version_info < (3, 11) and timestamp_text.endswith("Z"): + timestamp_text = timestamp_text[:-1] + "+00:00" + return datetime.fromisoformat(timestamp_text).date() + + res = run_git( + [ + *("-c", "log.showSignature=false"), + *("log", "-n", "1", "HEAD"), + "--format=%cI", + ], + self.path, + ) + return res.parse_success( + parse=parse_timestamp, + error_msg="logging the iso date for head failed", + ) + + def is_shallow(self) -> bool: + return self.path.joinpath(".git/shallow").is_file() + + def fetch_shallow(self) -> None: + run_git(["fetch", "--unshallow"], self.path, check=True, timeout=240) + + def node(self) -> str | None: + def _unsafe_short_node(node: str) -> str: + return node[:7] + + return run_git( + ["rev-parse", "--verify", "--quiet", "HEAD"], self.path + ).parse_success( + parse=_unsafe_short_node, + ) + + def count_all_nodes(self) -> int: + res = run_git(["rev-list", "HEAD"], self.path) + return res.stdout.count("\n") + 1 + + def default_describe(self) -> _CompletedProcess: + return run_git(DEFAULT_DESCRIBE[1:], self.path) + + +def warn_on_shallow(wd: GitWorkdir) -> None: + """experimental, may change at any time""" + if wd.is_shallow(): + warnings.warn(f'"{wd.path}" is shallow and may cause errors') + + +def fetch_on_shallow(wd: GitWorkdir) -> None: + """experimental, may change at any time""" + if wd.is_shallow(): + warnings.warn(f'"{wd.path}" was shallow, git fetch was used to rectify') + wd.fetch_shallow() + + +def fail_on_shallow(wd: GitWorkdir) -> None: + """experimental, may change at any time""" + if wd.is_shallow(): + raise ValueError( + f'{wd.path} is shallow, please correct with "git fetch --unshallow"' + ) + + +def get_working_directory(config: Configuration, root: _t.PathT) -> GitWorkdir | None: + """ + Return the working directory (``GitWorkdir``). + """ + + if config.parent: # todo broken + return GitWorkdir.from_potential_worktree(config.parent) + + for potential_root in discover.walk_potential_roots( + root, search_parents=config.search_parent_directories + ): + potential_wd = GitWorkdir.from_potential_worktree(potential_root) + if potential_wd is not None: + return potential_wd + + return GitWorkdir.from_potential_worktree(root) + + +def parse( + root: _t.PathT, + config: Configuration, + describe_command: str | list[str] | None = None, + pre_parse: Callable[[GitWorkdir], None] = warn_on_shallow, +) -> ScmVersion | None: + """ + :param pre_parse: experimental pre_parse action, may change at any time + """ + _require_command("git") + wd = get_working_directory(config, root) + if wd: + return _git_parse_inner( + config, wd, describe_command=describe_command, pre_parse=pre_parse + ) + else: + return None + + +def version_from_describe( + wd: GitWorkdir | hg_git.GitWorkdirHgClient, + config: Configuration, + describe_command: _t.CMD_TYPE | None, +) -> ScmVersion | None: + pass + + if config.git_describe_command is not None: + describe_command = config.git_describe_command + + if describe_command is not None: + if isinstance(describe_command, str): + describe_command = shlex.split(describe_command) + # todo: figure how to ensure git with gitdir gets correctly invoked + if describe_command[0] == "git": + describe_res = run_git(describe_command[1:], wd.path) + else: + describe_res = _run(describe_command, wd.path) + else: + describe_res = wd.default_describe() + + def parse_describe(output: str) -> ScmVersion: + tag, distance, node, dirty = _git_parse_describe(output) + return meta(tag=tag, distance=distance, dirty=dirty, node=node, config=config) + + return describe_res.parse_success(parse=parse_describe) + + +def _git_parse_inner( + config: Configuration, + wd: GitWorkdir | hg_git.GitWorkdirHgClient, + pre_parse: None | (Callable[[GitWorkdir | hg_git.GitWorkdirHgClient], None]) = None, + describe_command: _t.CMD_TYPE | None = None, +) -> ScmVersion: + if pre_parse: + pre_parse(wd) + + version = version_from_describe(wd, config, describe_command) + + if version is None: + # If 'git git_describe_command' failed, try to get the information otherwise. + tag = config.version_cls("0.0") + node = wd.node() + if node is None: + distance = 0 + dirty = True + else: + distance = wd.count_all_nodes() + node = "g" + node + dirty = wd.is_dirty() + version = meta( + tag=tag, distance=distance, dirty=dirty, node=node, config=config + ) + branch = wd.get_branch() + node_date = wd.get_head_date() or datetime.now(timezone.utc).date() + return dataclasses.replace(version, branch=branch, node_date=node_date) + + +def _git_parse_describe( + describe_output: str, +) -> tuple[str, int, str | None, bool]: + # 'describe_output' looks e.g. like 'v1.5.0-0-g4060507' or + # 'v1.15.1rc1-37-g9bd1298-dirty'. + # It may also just be a bare tag name if this is a tagged commit and we are + # parsing a .git_archival.txt file. + + if describe_output.endswith("-dirty"): + dirty = True + describe_output = describe_output[:-6] + else: + dirty = False + + split = describe_output.rsplit("-", 2) + if len(split) < 3: # probably a tagged commit + tag = describe_output + number = 0 + node = None + else: + tag, number_, node = split + number = int(number_) + return tag, number, node, dirty + + +def archival_to_version( + data: dict[str, str], config: Configuration +) -> ScmVersion | None: + node: str | None + log.debug("data %s", data) + archival_describe = data.get("describe-name", DESCRIBE_UNSUPPORTED) + if DESCRIBE_UNSUPPORTED in archival_describe: + warnings.warn("git archive did not support describe output") + else: + tag, number, node, _ = _git_parse_describe(archival_describe) + return meta( + tag, + config=config, + distance=number, + node=node, + ) + + for ref in REF_TAG_RE.findall(data.get("ref-names", "")): + version = tag_to_version(ref, config) + if version is not None: + return meta(version, config=config) + else: + node = data.get("node") + if node is None: + return None + elif "$FORMAT" in node.upper(): + warnings.warn("unprocessed git archival found (no export subst applied)") + return None + else: + return meta("0.0", node=node, config=config) + + +def parse_archival(root: _t.PathT, config: Configuration) -> ScmVersion | None: + archival = os.path.join(root, ".git_archival.txt") + data = data_from_mime(archival) + return archival_to_version(data, config=config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py new file mode 100644 index 00000000000..dbffb0aeaaa --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py @@ -0,0 +1,192 @@ +from __future__ import annotations + +import datetime +import logging +import os + +from pathlib import Path +from typing import TYPE_CHECKING + +from . import Configuration +from ._version_cls import Version +from .integration import data_from_mime +from .scm_workdir import Workdir +from .version import ScmVersion +from .version import meta +from .version import tag_to_version + +if TYPE_CHECKING: + from . import _types as _t + +from ._run_cmd import require_command as _require_command +from ._run_cmd import run as _run + +log = logging.getLogger(__name__) + + +class HgWorkdir(Workdir): + @classmethod + def from_potential_worktree(cls, wd: _t.PathT) -> HgWorkdir | None: + res = _run(["hg", "root"], wd) + if res.returncode: + return None + return cls(Path(res.stdout)) + + def get_meta(self, config: Configuration) -> ScmVersion | None: + node: str + tags_str: str + node_date_str: str + node, tags_str, node_date_str = self.hg_log( + ".", "{node}\n{tag}\n{date|shortdate}" + ).split("\n") + + # TODO: support bookmarks and topics (but nowadays bookmarks are + # mainly used to emulate Git branches, which is already supported with + # the dedicated class GitWorkdirHgClient) + + branch, dirty_str, dirty_date = _run( + ["hg", "id", "-T", "{branch}\n{if(dirty, 1, 0)}\n{date|shortdate}"], + cwd=self.path, + check=True, + ).stdout.split("\n") + dirty = bool(int(dirty_str)) + node_date = datetime.date.fromisoformat(dirty_date if dirty else node_date_str) + + if node == "0" * len(node): + log.debug("initial node %s", self.path) + return meta( + Version("0.0"), + config=config, + dirty=dirty, + branch=branch, + node_date=node_date, + ) + + node = "h" + node[:7] + + tags = tags_str.split() + if "tip" in tags: + # tip is not a real tag + tags.remove("tip") + + if tags: + tag = tag_to_version(tags[0], config) + if tag: + return meta(tag, dirty=dirty, branch=branch, config=config) + + try: + tag_str = self.get_latest_normalizable_tag() + if tag_str is None: + dist = self.get_distance_revs("") + else: + dist = self.get_distance_revs(tag_str) + + if tag_str == "null" or tag_str is None: + tag = Version("0.0") + dist += 1 + else: + tag = tag_to_version(tag_str, config=config) + assert tag is not None + + if self.check_changes_since_tag(tag_str) or dirty: + return meta( + tag, + distance=dist, + node=node, + dirty=dirty, + branch=branch, + config=config, + node_date=node_date, + ) + else: + return meta(tag, config=config, node_date=node_date) + + except ValueError as e: + log.exception("error %s", e) + pass # unpacking failed, old hg + + return None + + def hg_log(self, revset: str, template: str) -> str: + cmd = ["hg", "log", "-r", revset, "-T", template] + + return _run(cmd, cwd=self.path, check=True).stdout + + def get_latest_normalizable_tag(self) -> str | None: + # Gets all tags containing a '.' (see #229) from oldest to newest + outlines = self.hg_log( + revset="ancestors(.) and tag('re:\\.')", + template="{tags}{if(tags, '\n', '')}", + ).split() + if not outlines: + return None + tag = outlines[-1].split()[-1] + return tag + + def get_distance_revs(self, rev1: str, rev2: str = ".") -> int: + revset = f"({rev1}::{rev2})" + out = self.hg_log(revset, ".") + return len(out) - 1 + + def check_changes_since_tag(self, tag: str | None) -> bool: + if tag == "0.0" or tag is None: + return True + + revset = ( + "(branch(.)" # look for revisions in this branch only + f" and tag({tag!r})::." # after the last tag + # ignore commits that only modify .hgtags and nothing else: + " and (merge() or file('re:^(?!\\.hgtags).*$'))" + f" and not tag({tag!r}))" # ignore the tagged commit itself + ) + + return bool(self.hg_log(revset, ".")) + + +def parse(root: _t.PathT, config: Configuration) -> ScmVersion | None: + _require_command("hg") + if os.path.exists(os.path.join(root, ".hg/git")): + res = _run(["hg", "path"], root) + if not res.returncode: + for line in res.stdout.split("\n"): + if line.startswith("default ="): + path = Path(line.split()[2]) + if path.name.endswith(".git") or (path / ".git").exists(): + from .git import _git_parse_inner + from .hg_git import GitWorkdirHgClient + + wd_hggit = GitWorkdirHgClient.from_potential_worktree(root) + if wd_hggit: + return _git_parse_inner(config, wd_hggit) + + wd = HgWorkdir.from_potential_worktree(config.absolute_root) + + if wd is None: + return None + + return wd.get_meta(config) + + +def archival_to_version(data: dict[str, str], config: Configuration) -> ScmVersion: + log.debug("data %s", data) + node = data.get("node", "")[:12] + if node: + node = "h" + node + if "tag" in data: + return meta(data["tag"], config=config) + elif "latesttag" in data: + return meta( + data["latesttag"], + distance=int(data["latesttagdistance"]), + node=node, + branch=data.get("branch"), + config=config, + ) + else: + return meta(config.version_cls("0.0"), node=node, config=config) + + +def parse_archival(root: _t.PathT, config: Configuration) -> ScmVersion: + archival = os.path.join(root, ".hg_archival.txt") + data = data_from_mime(archival) + return archival_to_version(data, config=config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py new file mode 100644 index 00000000000..9cab6f4528d --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py @@ -0,0 +1,156 @@ +from __future__ import annotations + +import logging +import os + +from contextlib import suppress +from datetime import date +from pathlib import Path + +from . import _types as _t +from ._run_cmd import CompletedProcess as _CompletedProcess +from ._run_cmd import require_command +from ._run_cmd import run as _run +from .git import GitWorkdir +from .hg import HgWorkdir + +log = logging.getLogger(__name__) + +_FAKE_GIT_DESCRIBE_ERROR = _CompletedProcess( + "fake git describe output for hg", + 1, + "<>hg git failed to describe", +) + + +class GitWorkdirHgClient(GitWorkdir, HgWorkdir): + COMMAND = "hg" + + @classmethod + def from_potential_worktree(cls, wd: _t.PathT) -> GitWorkdirHgClient | None: + require_command("hg") + res = _run(["hg", "root"], cwd=wd).parse_success(parse=Path) + if res is None: + return None + return cls(res) + + def is_dirty(self) -> bool: + res = _run(["hg", "id", "-T", "{dirty}"], cwd=self.path, check=True) + return bool(res.stdout) + + def get_branch(self) -> str | None: + res = _run(["hg", "id", "-T", "{bookmarks}"], cwd=self.path) + if res.returncode: + log.info("branch err %s", res) + return None + return res.stdout + + def get_head_date(self) -> date | None: + return _run('hg log -r . -T "{shortdate(date)}"', cwd=self.path).parse_success( + parse=date.fromisoformat, error_msg="head date err" + ) + + def is_shallow(self) -> bool: + return False + + def fetch_shallow(self) -> None: + pass + + def get_hg_node(self) -> str | None: + res = _run('hg log -r . -T "{node}"', cwd=self.path) + if res.returncode: + return None + else: + return res.stdout + + def _hg2git(self, hg_node: str) -> str | None: + with suppress(FileNotFoundError): + with open(os.path.join(self.path, ".hg/git-mapfile")) as map_items: + for item in map_items: + if hg_node in item: + git_node, hg_node = item.split() + return git_node + return None + + def node(self) -> str | None: + hg_node = self.get_hg_node() + if hg_node is None: + return None + + git_node = self._hg2git(hg_node) + + if git_node is None: + # trying again after hg -> git + _run(["hg", "gexport"], cwd=self.path) + git_node = self._hg2git(hg_node) + + if git_node is None: + log.debug("Cannot get git node so we use hg node %s", hg_node) + + if hg_node == "0" * len(hg_node): + # mimic Git behavior + return None + + return hg_node + + return git_node[:7] + + def count_all_nodes(self) -> int: + res = _run(["hg", "log", "-r", "ancestors(.)", "-T", "."], cwd=self.path) + return len(res.stdout) + + def default_describe(self) -> _CompletedProcess: + """ + Tentative to reproduce the output of + + `git describe --dirty --tags --long --match *[0-9]*` + + """ + res = _run( + [ + "hg", + "log", + "-r", + "(reverse(ancestors(.)) and tag(r're:v?[0-9].*'))", + "-T", + "{tags}{if(tags, ' ', '')}", + ], + cwd=self.path, + ) + if res.returncode: + return _FAKE_GIT_DESCRIBE_ERROR + hg_tags: list[str] = res.stdout.split() + + if not hg_tags: + return _FAKE_GIT_DESCRIBE_ERROR + + with self.path.joinpath(".hg/git-tags").open() as fp: + git_tags: dict[str, str] = dict(line.split()[::-1] for line in fp) + + tag: str + for hg_tag in hg_tags: + if hg_tag in git_tags: + tag = hg_tag + break + else: + logging.warning("tag not found hg=%s git=%s", hg_tags, git_tags) + return _FAKE_GIT_DESCRIBE_ERROR + + res = _run(["hg", "log", "-r", f"'{tag}'::.", "-T", "."], cwd=self.path) + if res.returncode: + return _FAKE_GIT_DESCRIBE_ERROR + distance = len(res.stdout) - 1 + + node = self.node() + assert node is not None + desc = f"{tag}-{distance}-g{node}" + + if self.is_dirty(): + desc += "-dirty" + log.debug("faked describe %r", desc) + return _CompletedProcess( + ["setuptools-scm", "faked", "describe"], + returncode=0, + stdout=desc, + stderr="", + ) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py new file mode 100644 index 00000000000..48874e3847e --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +import logging +import textwrap + +from pathlib import Path + +from . import _types as _t + +log = logging.getLogger(__name__) + + +def data_from_mime(path: _t.PathT, content: None | str = None) -> dict[str, str]: + """return a mapping from mime/pseudo-mime content + :param path: path to the mime file + :param content: content of the mime file, if None, read from path + :rtype: dict[str, str] + + """ + + if content is None: + content = Path(path).read_text(encoding="utf-8") + log.debug("mime %s content:\n%s", path, textwrap.indent(content, " ")) + + from email.parser import HeaderParser + + parser = HeaderParser() + message = parser.parsestr(content) + data = dict(message.items()) + log.debug("mime %s data:\n%s", path, data) + return data diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py new file mode 100644 index 00000000000..9879549d6d0 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path + +from ._config import Configuration +from .version import ScmVersion + + +@dataclass() +class Workdir: + path: Path + + def run_describe(self, config: Configuration) -> ScmVersion: + raise NotImplementedError(self.run_describe) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py new file mode 100644 index 00000000000..0a367423392 --- /dev/null +++ b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py @@ -0,0 +1,454 @@ +from __future__ import annotations + +import dataclasses +import logging +import os +import re +import warnings + +from datetime import date +from datetime import datetime +from datetime import timezone +from typing import TYPE_CHECKING +from typing import Any +from typing import Callable +from typing import Match + +from . import _entrypoints +from . import _modify_version + +if TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 10): + from typing import Concatenate + from typing import ParamSpec + else: + from typing_extensions import Concatenate + from typing_extensions import ParamSpec + + _P = ParamSpec("_P") + +from typing import TypedDict + +from . import _config +from . import _version_cls as _v +from ._version_cls import Version as PkgVersion +from ._version_cls import _VersionT + +log = logging.getLogger(__name__) + + +SEMVER_MINOR = 2 +SEMVER_PATCH = 3 +SEMVER_LEN = 3 + + +class _TagDict(TypedDict): + version: str + prefix: str + suffix: str + + +def _parse_version_tag( + tag: str | object, config: _config.Configuration +) -> _TagDict | None: + match = config.tag_regex.match(str(tag)) + + if match: + key: str | int = 1 if len(match.groups()) == 1 else "version" + full = match.group(0) + log.debug("%r %r %s", tag, config.tag_regex, match) + log.debug( + "key %s data %s, %s, %r", key, match.groupdict(), match.groups(), full + ) + result = _TagDict( + version=match.group(key), + prefix=full[: match.start(key)], + suffix=full[match.end(key) :], + ) + + log.debug("tag %r parsed to %r", tag, result) + assert result["version"] + return result + else: + log.debug("tag %r did not parse", tag) + + return None + + +def callable_or_entrypoint(group: str, callable_or_name: str | Any) -> Any: + log.debug("ep %r %r", group, callable_or_name) + + if callable(callable_or_name): + return callable_or_name + from ._entrypoints import iter_entry_points + + for ep in iter_entry_points(group, callable_or_name): + log.debug("ep found: %s", ep.name) + return ep.load() + + +def tag_to_version( + tag: _VersionT | str, config: _config.Configuration +) -> _VersionT | None: + """ + take a tag that might be prefixed with a keyword and return only the version part + """ + log.debug("tag %s", tag) + + tag_dict = _parse_version_tag(tag, config) + if tag_dict is None or not tag_dict.get("version", None): + warnings.warn(f"tag {tag!r} no version found") + return None + + version_str = tag_dict["version"] + log.debug("version pre parse %s", version_str) + + if suffix := tag_dict.get("suffix", ""): + warnings.warn(f"tag {tag!r} will be stripped of its suffix {suffix!r}") + + version: _VersionT = config.version_cls(version_str) + log.debug("version=%r", version) + + return version + + +def _source_epoch_or_utc_now() -> datetime: + if "SOURCE_DATE_EPOCH" in os.environ: + date_epoch = int(os.environ["SOURCE_DATE_EPOCH"]) + return datetime.fromtimestamp(date_epoch, timezone.utc) + else: + return datetime.now(timezone.utc) + + +@dataclasses.dataclass +class ScmVersion: + """represents a parsed version from scm""" + + tag: _v.Version | _v.NonNormalizedVersion | str + """the related tag or preformatted version string""" + config: _config.Configuration + """the configuration used to parse the version""" + distance: int = 0 + """the number of commits since the tag""" + node: str | None = None + """the shortened node id""" + dirty: bool = False + """whether the working copy had uncommitted changes""" + preformatted: bool = False + """whether the version string was preformatted""" + branch: str | None = None + """the branch name if any""" + node_date: date | None = None + """the date of the commit if available""" + time: datetime = dataclasses.field(default_factory=_source_epoch_or_utc_now) + """the current time or source epoch time + only set for unit-testing version schemes + for real usage it must be `now(utc)` or `SOURCE_EPOCH` + """ + + @property + def exact(self) -> bool: + """returns true checked out exactly on a tag and no local changes apply""" + return self.distance == 0 and not self.dirty + + def __repr__(self) -> str: + return ( + f"" + ) + + def format_with(self, fmt: str, **kw: object) -> str: + """format a given format string with attributes of this object""" + return fmt.format( + time=self.time, + tag=self.tag, + distance=self.distance, + node=self.node, + dirty=self.dirty, + branch=self.branch, + node_date=self.node_date, + **kw, + ) + + def format_choice(self, clean_format: str, dirty_format: str, **kw: object) -> str: + """given `clean_format` and `dirty_format` + + choose one based on `self.dirty` and format it using `self.format_with`""" + + return self.format_with(dirty_format if self.dirty else clean_format, **kw) + + def format_next_version( + self, + guess_next: Callable[Concatenate[ScmVersion, _P], str], + fmt: str = "{guessed}.dev{distance}", + *k: _P.args, + **kw: _P.kwargs, + ) -> str: + guessed = guess_next(self, *k, **kw) + return self.format_with(fmt, guessed=guessed) + + +def _parse_tag( + tag: _VersionT | str, preformatted: bool, config: _config.Configuration +) -> _VersionT | str: + if preformatted: + return tag + elif not isinstance(tag, config.version_cls): + version = tag_to_version(tag, config) + assert version is not None + return version + else: + return tag + + +def meta( + tag: str | _VersionT, + *, + distance: int = 0, + dirty: bool = False, + node: str | None = None, + preformatted: bool = False, + branch: str | None = None, + config: _config.Configuration, + node_date: date | None = None, +) -> ScmVersion: + parsed_version = _parse_tag(tag, preformatted, config) + log.info("version %s -> %s", tag, parsed_version) + assert parsed_version is not None, "Can't parse version %s" % tag + return ScmVersion( + parsed_version, + distance=distance, + node=node, + dirty=dirty, + preformatted=preformatted, + branch=branch, + config=config, + node_date=node_date, + ) + + +def guess_next_version(tag_version: ScmVersion) -> str: + version = _modify_version.strip_local(str(tag_version.tag)) + return _modify_version._bump_dev(version) or _modify_version._bump_regex(version) + + +def guess_next_dev_version(version: ScmVersion) -> str: + if version.exact: + return version.format_with("{tag}") + else: + return version.format_next_version(guess_next_version) + + +def guess_next_simple_semver( + version: ScmVersion, retain: int, increment: bool = True +) -> str: + if isinstance(version.tag, _v.Version): + parts = list(version.tag.release[:retain]) + else: + try: + parts = [int(i) for i in str(version.tag).split(".")[:retain]] + except ValueError: + raise ValueError(f"{version} can't be parsed as numeric version") from None + while len(parts) < retain: + parts.append(0) + if increment: + parts[-1] += 1 + while len(parts) < SEMVER_LEN: + parts.append(0) + return ".".join(str(i) for i in parts) + + +def simplified_semver_version(version: ScmVersion) -> str: + if version.exact: + return guess_next_simple_semver(version, retain=SEMVER_LEN, increment=False) + else: + if version.branch is not None and "feature" in version.branch: + return version.format_next_version( + guess_next_simple_semver, retain=SEMVER_MINOR + ) + else: + return version.format_next_version( + guess_next_simple_semver, retain=SEMVER_PATCH + ) + + +def release_branch_semver_version(version: ScmVersion) -> str: + if version.exact: + return version.format_with("{tag}") + if version.branch is not None: + # Does the branch name (stripped of namespace) parse as a version? + branch_ver_data = _parse_version_tag( + version.branch.split("/")[-1], version.config + ) + if branch_ver_data is not None: + branch_ver = branch_ver_data["version"] + if branch_ver[0] == "v": + # Allow branches that start with 'v', similar to Version. + branch_ver = branch_ver[1:] + # Does the branch version up to the minor part match the tag? If not it + # might be like, an issue number or something and not a version number, so + # we only want to use it if it matches. + tag_ver_up_to_minor = str(version.tag).split(".")[:SEMVER_MINOR] + branch_ver_up_to_minor = branch_ver.split(".")[:SEMVER_MINOR] + if branch_ver_up_to_minor == tag_ver_up_to_minor: + # We're in a release/maintenance branch, next is a patch/rc/beta bump: + return version.format_next_version(guess_next_version) + # We're in a development branch, next is a minor bump: + return version.format_next_version(guess_next_simple_semver, retain=SEMVER_MINOR) + + +def release_branch_semver(version: ScmVersion) -> str: + warnings.warn( + "release_branch_semver is deprecated and will be removed in the future. " + "Use release_branch_semver_version instead", + category=DeprecationWarning, + stacklevel=2, + ) + return release_branch_semver_version(version) + + +def only_version(version: ScmVersion) -> str: + return version.format_with("{tag}") + + +def no_guess_dev_version(version: ScmVersion) -> str: + if version.exact: + return version.format_with("{tag}") + else: + return version.format_next_version(_modify_version._dont_guess_next_version) + + +_DATE_REGEX = re.compile( + r""" + ^(?P + (?P[vV]?) + (?P\d{2}|\d{4})(?:\.\d{1,2}){2}) + (?:\.(?P\d*))?$ + """, + re.VERBOSE, +) + + +def date_ver_match(ver: str) -> Match[str] | None: + return _DATE_REGEX.match(ver) + + +def guess_next_date_ver( + version: ScmVersion, + node_date: date | None = None, + date_fmt: str | None = None, + version_cls: type | None = None, +) -> str: + """ + same-day -> patch +1 + other-day -> today + + distance is always added as .devX + """ + match = date_ver_match(str(version.tag)) + if match is None: + warnings.warn( + f"{version} does not correspond to a valid versioning date, " + "assuming legacy version" + ) + if date_fmt is None: + date_fmt = "%y.%m.%d" + else: + # deduct date format if not provided + if date_fmt is None: + date_fmt = "%Y.%m.%d" if len(match.group("year")) == 4 else "%y.%m.%d" + if prefix := match.group("prefix"): + if not date_fmt.startswith(prefix): + date_fmt = prefix + date_fmt + + today = version.time.date() + head_date = node_date or today + # compute patch + if match is None: + tag_date = today + else: + tag_date = ( + datetime.strptime(match.group("date"), date_fmt) + .replace(tzinfo=timezone.utc) + .date() + ) + if tag_date == head_date: + patch = "0" if match is None else (match.group("patch") or "0") + patch = int(patch) + 1 + else: + if tag_date > head_date and match is not None: + # warn on future times + warnings.warn( + f"your previous tag ({tag_date})" + f" is ahead your node date ({head_date})" + ) + patch = 0 + next_version = "{node_date:{date_fmt}}.{patch}".format( + node_date=head_date, date_fmt=date_fmt, patch=patch + ) + # rely on the Version object to ensure consistency (e.g. remove leading 0s) + if version_cls is None: + version_cls = PkgVersion + next_version = str(version_cls(next_version)) + return next_version + + +def calver_by_date(version: ScmVersion) -> str: + if version.exact and not version.dirty: + return version.format_with("{tag}") + # TODO: move the release-X check to a new scheme + if version.branch is not None and version.branch.startswith("release-"): + branch_ver = _parse_version_tag(version.branch.split("-")[-1], version.config) + if branch_ver is not None: + ver = branch_ver["version"] + match = date_ver_match(ver) + if match: + return ver + return version.format_next_version( + guess_next_date_ver, + node_date=version.node_date, + version_cls=version.config.version_cls, + ) + + +def get_local_node_and_date(version: ScmVersion) -> str: + return _modify_version._format_local_with_time(version, time_format="%Y%m%d") + + +def get_local_node_and_timestamp(version: ScmVersion) -> str: + return _modify_version._format_local_with_time(version, time_format="%Y%m%d%H%M%S") + + +def get_local_dirty_tag(version: ScmVersion) -> str: + return version.format_choice("", "+dirty") + + +def get_no_local_node(version: ScmVersion) -> str: + return "" + + +def postrelease_version(version: ScmVersion) -> str: + if version.exact: + return version.format_with("{tag}") + else: + return version.format_with("{tag}.post{distance}") + + +def format_version(version: ScmVersion) -> str: + log.debug("scm version %s", version) + log.debug("config %s", version.config) + if version.preformatted: + assert isinstance(version.tag, str) + return version.tag + main_version = _entrypoints._call_version_scheme( + version, "setuptools_scm.version_scheme", version.config.version_scheme, None + ) + log.debug("version %s", main_version) + assert main_version is not None + local_version = _entrypoints._call_version_scheme( + version, "setuptools_scm.local_scheme", version.config.local_scheme, "+unknown" + ) + log.debug("local_version %s", local_version) + return main_version + local_version diff --git a/panda/scripts/build_libosi.sh b/panda/scripts/build_libosi.sh new file mode 100755 index 00000000000..9ed28f04a80 --- /dev/null +++ b/panda/scripts/build_libosi.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e +echo "Building libosi..." +if [ ! -d "libosi" ]; then + git clone https://github.com/panda-re/libosi.git +else + echo "Directory 'libosi' already exists. Skipping clone." +fi + +pushd libosi +mkdir -p build && cd build +cmake -GNinja .. +ninja +ninja package +sudo dpkg -i libosi-*.deb +popd +rm -rf libosi diff --git a/panda/scripts/build_llvm.sh b/panda/scripts/build_llvm.sh new file mode 100755 index 00000000000..b79f319ee0c --- /dev/null +++ b/panda/scripts/build_llvm.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# https://gist.github.com/ouankou/27c1fc22aee9125190492ea126125249 +export LLVM_VERSION=11 +export LLVM_SRC=$HOME/llvm/llvm_src +export LLVM_PATH=$HOME/llvm/llvm_install +export LLVM_BUILD=$HOME/llvm/llvm_build +export CC=`which clang` +export CXX=`which clang++` + +mkdir -p $LLVM_SRC +mkdir -p $LLVM_PATH +mkdir -p $LLVM_BUILD + +cd $LLVM_SRC + +# Clone the repository from the old URL (replace the $LLVM_VERSION with actual version, e.g., 11) +git clone --depth 1 -b release/$LLVM_VERSION.x https://github.com/llvm/llvm-project . + +# siglans-missing-cstdint-include-patch +sed -i '/#include /a #include ' $LLVM_SRC/llvm/include/llvm/Support/Signals.h +# fix-missing-header-limits-patch +sed -i '/^#include /a #include ' $LLVM_SRC/llvm/utils/benchmark/src/benchmark_register.cc +sed -i '/^#include /a #include ' $LLVM_SRC/llvm/utils/benchmark/src/benchmark_register.h + +cd $LLVM_BUILD + +# Configure the build using CMake +cmake -G Ninja -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX -DLLVM_USE_LINKER=gold -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$LLVM_PATH -DLLVM_ENABLE_PROJECTS="clang" $LLVM_SRC/llvm + +# Build and install LLVM +# Use j1 for less memory consumption -> fixes kill clang process +ninja -j2 -l2 +ninja install -j2 + +# Update environment variables for LLVM +export PATH=$LLVM_PATH/bin:$PATH +export LD_LIBRARY_PATH=$LLVM_PATH/libexec:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH=$LLVM_PATH/lib:$LD_LIBRARY_PATH +export LIBRARY_PATH=$LLVM_PATH/libexec:$LIBRARY_PATH +export LIBRARY_PATH=$LLVM_PATH/lib:$LIBRARY_PATH +export MANPATH=$LLVM_PATH/share/man:$MANPATH +export C_INCLUDE_PATH=$LLVM_PATH/include:$C_INCLUDE_PATH +export CPLUS_INCLUDE_PATH=$LLVM_PATH/include:$CPLUS_INCLUDE_PATH +export LLVM_CONFIG_BINARY=$LLVM_PATH/bin/llvm-config diff --git a/panda/scripts/install_ubuntu.sh b/panda/scripts/install_ubuntu.sh index 73b853e7281..d1ce48cd1df 100755 --- a/panda/scripts/install_ubuntu.sh +++ b/panda/scripts/install_ubuntu.sh @@ -64,7 +64,9 @@ else exit 1 fi -progress "Installing PANDA dependencies..." +progress "Installing PANDA dependencies..." +# Ignore errors +set +e # Read file in dependencies directory and install those. If no dependency file present, error $SUDO apt-get update @@ -90,6 +92,17 @@ else exit 1 fi +set -e + +if [ "$version" -eq 24 ]; then + if [ -f "$HOME/llvm/llvm_install/bin/clang" ]; then + progress "LLVM is already built in $HOME/llvm/llvm_install." + else + progress "Building LLVM..." + ./panda/scripts/build_llvm.sh + fi +fi + progress "Installing Rust..." curl https://sh.rustup.rs -sSf | sh -s -- -y @@ -107,7 +120,7 @@ if [ "$version" -eq 18 ]; then fi # Install libcapstone v5 release if it's not present -if [[ !$(ldconfig -p | grep -q libcapstone.so.5) ]]; then +if ! ldconfig -p | grep -q libcapstone.so.5; then echo "Installing libcapstone v5" pushd /tmp && \ git clone https://github.com/capstone-engine/capstone/ -b v5 && \ @@ -117,19 +130,26 @@ if [[ !$(ldconfig -p | grep -q libcapstone.so.5) ]]; then popd fi +LIBOSI_URL="https://github.com/panda-re/libosi/releases/download/v${LIBOSI_VERSION}/libosi_${UBUNTU_VERSION}.deb" + # if the windows introspection library is not installed, clone and install -if [[ !$(dpkg -l | grep -q libosi) ]]; then - pushd /tmp - curl -LJO https://github.com/panda-re/libosi/releases/download/v${LIBOSI_VERSION}/libosi_${UBUNTU_VERSION}.deb - $SUDO dpkg -i /tmp/libosi_${UBUNTU_VERSION}.deb - rm -rf /tmp/libosi_${UBUNTU_VERSION}.deb - popd +if ! dpkg -l | grep -q libosi; then + if curl --output /dev/null --silent --head --fail "${LIBOSI_URL}"; then + pushd /tmp + curl -LO "${LIBOSI_URL}" + $SUDO dpkg -i "libosi_${UBUNTU_VERSION}.deb" + rm -rf "libosi_${UBUNTU_VERSION}.deb" + popd + else + echo "Realse libosi not found. Building from source..." + ./panda/scripts/build_libosi.sh + fi fi # PyPANDA needs CFFI from pip (the version in apt is too old) # Install system-wide since PyPANDA install will also be system-wide -$SUDO python3 -m pip install pip -$SUDO python3 -m pip install "cffi>1.14.3" +$SUDO python3 -m pip install --break-system-packages pip +$SUDO python3 -m pip install --break-system-packages "cffi>1.14.3" progress "Trying to update DTC submodule" git submodule update --init dtc || true @@ -147,7 +167,7 @@ pushd build progress "PANDA is built and ready to use in panda/build/[arch]-softmmu/panda-system-[arch]." cd ../panda/python/core -$SUDO python3 -m pip install -r requirements.txt +$SUDO python3 -m pip install --break-system-packages -r requirements.txt $SUDO python3 setup.py install python3 -c "import pandare; panda = pandare.Panda(generic='i386')" # Make sure it worked progress "Pypanda successfully installed" From fe4c4c9f2232de94b7e940f8ed4913dfdb26083f Mon Sep 17 00:00:00 2001 From: SneakyFoxy Date: Tue, 21 Jan 2025 18:41:22 +0300 Subject: [PATCH 2/2] Remove python .eggs folder --- panda/python/core/.eggs/README.txt | 6 - .../EGG-INFO/LICENSE | 17 - .../EGG-INFO/PKG-INFO | 166 ------- .../EGG-INFO/RECORD | 36 -- .../EGG-INFO/WHEEL | 5 - .../EGG-INFO/entry_points.txt | 42 -- .../EGG-INFO/requires.txt | 21 - .../EGG-INFO/top_level.txt | 1 - .../setuptools_scm/.git_archival.txt | 3 - .../setuptools_scm/__init__.py | 30 -- .../setuptools_scm/__main__.py | 6 - .../setuptools_scm/_cli.py | 186 ------- .../setuptools_scm/_config.py | 152 ------ .../setuptools_scm/_entrypoints.py | 139 ------ .../setuptools_scm/_file_finders/__init__.py | 113 ----- .../setuptools_scm/_file_finders/git.py | 117 ----- .../setuptools_scm/_file_finders/hg.py | 72 --- .../setuptools_scm/_file_finders/pathtools.py | 9 - .../setuptools_scm/_get_version_impl.py | 175 ------- .../setuptools_scm/_integration/__init__.py | 0 .../_integration/dump_version.py | 94 ---- .../_integration/pyproject_reading.py | 85 ---- .../setuptools_scm/_integration/setuptools.py | 123 ----- .../setuptools_scm/_integration/toml.py | 59 --- .../setuptools_scm/_log.py | 87 ---- .../setuptools_scm/_modify_version.py | 61 --- .../setuptools_scm/_overrides.py | 55 --- .../setuptools_scm/_run_cmd.py | 214 --------- .../setuptools_scm/_types.py | 28 -- .../setuptools_scm/_version_cls.py | 91 ---- .../setuptools_scm/discover.py | 70 --- .../setuptools_scm/fallbacks.py | 45 -- .../setuptools_scm/git.py | 340 ------------- .../setuptools_scm/hg.py | 192 -------- .../setuptools_scm/hg_git.py | 156 ------ .../setuptools_scm/integration.py | 31 -- .../setuptools_scm/scm_workdir.py | 15 - .../setuptools_scm/version.py | 454 ------------------ 38 files changed, 3496 deletions(-) delete mode 100644 panda/python/core/.eggs/README.txt delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py delete mode 100644 panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py diff --git a/panda/python/core/.eggs/README.txt b/panda/python/core/.eggs/README.txt deleted file mode 100644 index 5d01668824f..00000000000 --- a/panda/python/core/.eggs/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. - -This directory caches those eggs to prevent repeated downloads. - -However, it is safe to delete this directory. - diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE deleted file mode 100644 index 89de354795e..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/LICENSE +++ /dev/null @@ -1,17 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO deleted file mode 100644 index edf8a1d4a17..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/PKG-INFO +++ /dev/null @@ -1,166 +0,0 @@ -Metadata-Version: 2.1 -Name: setuptools-scm -Version: 8.1.0 -Summary: the blessed package to manage your versions by scm tags -Author-email: Ronny Pfannschmidt -License: Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -Project-URL: documentation, https://setuptools-scm.readthedocs.io/ -Project-URL: repository, https://github.com/pypa/setuptools_scm/ -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: Software Development :: Version Control -Classifier: Topic :: System :: Software Distribution -Classifier: Topic :: Utilities -Requires-Python: >=3.8 -Description-Content-Type: text/markdown -License-File: LICENSE -Requires-Dist: packaging >=20 -Requires-Dist: setuptools -Requires-Dist: typing-extensions ; python_version < "3.10" -Requires-Dist: tomli >=1 ; python_version < "3.11" -Provides-Extra: docs -Requires-Dist: entangled-cli ~=2.0 ; extra == 'docs' -Requires-Dist: mkdocs ; extra == 'docs' -Requires-Dist: mkdocs-entangled-plugin ; extra == 'docs' -Requires-Dist: mkdocs-material ; extra == 'docs' -Requires-Dist: mkdocstrings[python] ; extra == 'docs' -Requires-Dist: pygments ; extra == 'docs' -Provides-Extra: rich -Requires-Dist: rich ; extra == 'rich' -Provides-Extra: test -Requires-Dist: build ; extra == 'test' -Requires-Dist: pytest ; extra == 'test' -Requires-Dist: rich ; extra == 'test' -Requires-Dist: wheel ; extra == 'test' -Requires-Dist: typing-extensions ; (python_version < "3.11") and extra == 'test' -Provides-Extra: toml - -# setuptools_scm -[![github ci](https://github.com/pypa/setuptools_scm/workflows/python%20tests+artifacts+release/badge.svg)](https://github.com/pypa/setuptools_scm/actions) -[![Documentation Status](https://readthedocs.org/projects/setuptools-scm/badge/?version=latest)](https://setuptools-scm.readthedocs.io/en/latest/?badge=latest) -[![tidelift](https://tidelift.com/badges/package/pypi/setuptools-scm) ](https://tidelift.com/subscription/pkg/pypi-setuptools-scm?utm_source=pypi-setuptools-scm&utm_medium=readme) - -## about - -[setuptools-scm] extracts Python package versions from `git` or -`hg` metadata instead of declaring them as the version argument -or in an SCM managed file. - -Additionally, [setuptools-scm] provides setuptools -with a list of files that are managed by the SCM
-(i.e. it automatically adds **all of** the SCM-managed files to the sdist).
-Unwanted files must be excluded via `MANIFEST.in`. - - -## `pyproject.toml` usage - -The preferred way to configure [setuptools-scm] is to author -settings in a `tool.setuptools_scm` section of `pyproject.toml`. - -This feature requires setuptools 61 or later. -First, ensure that [setuptools-scm] is present during the project's -build step by specifying it as one of the build requirements. - -```toml title="pyproject.toml" -[build-system] -requires = ["setuptools>=64", "setuptools_scm>=8"] -build-backend = "setuptools.build_meta" -``` - -That will be sufficient to require [setuptools-scm] for projects -that support [PEP 518] like [pip] and [build]. - -[pip]: https://pypi.org/project/pip -[build]: https://pypi.org/project/build -[PEP 518]: https://peps.python.org/pep-0518/ - - -To enable version inference, you need to set the version -dynamically in the `project` section of `pyproject.toml`: - -```toml title="pyproject.toml" -[project] -# version = "0.0.1" # Remove any existing version parameter. -dynamic = ["version"] - -[tool.setuptools_scm] -``` - -Additionally, a version file can be written by specifying: - -```toml title="pyproject.toml" -[tool.setuptools_scm] -version_file = "pkg/_version.py" -``` - -Where `pkg` is the name of your package. - -If you need to confirm which version string is being generated or debug the configuration, -you can install [setuptools-scm] directly in your working environment and run: - -```console -$ python -m setuptools_scm -# To explore other options, try: -$ python -m setuptools_scm --help -``` - -For further configuration see the [documentation]. - -[setuptools-scm]: https://github.com/pypa/setuptools_scm -[documentation]: https://setuptools-scm.readthedocs.io/ - - -## Interaction with Enterprise Distributions - -Some enterprise distributions like RHEL7 -ship rather old setuptools versions. - -In those cases its typically possible to build by using an sdist against `setuptools_scm<2.0`. -As those old setuptools versions lack sensible types for versions, -modern [setuptools-scm] is unable to support them sensibly. - -It's strongly recommended to build a wheel artifact using modern Python and setuptools, -then installing the artifact instead of trying to run against old setuptools versions. - - -## Code of Conduct - - -Everyone interacting in the [setuptools-scm] project's codebases, issue -trackers, chat rooms, and mailing lists is expected to follow the -[PSF Code of Conduct]. - -[PSF Code of Conduct]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md - - -## Security Contact - -To report a security vulnerability, please use the -[Tidelift security contact](https://tidelift.com/security). -Tidelift will coordinate the fix and disclosure. diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD deleted file mode 100644 index 161a093c43f..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/RECORD +++ /dev/null @@ -1,36 +0,0 @@ -setuptools_scm/.git_archival.txt,sha256=2_90kdS1POSQMuZfBCUw6qNjObu7Ijp8DmptEAmlGkU,102 -setuptools_scm/__init__.py,sha256=k4jjJK8ejFI95amIoLWNCFECWIQW9NlxF9Had4RqOHM,785 -setuptools_scm/__main__.py,sha256=AhntzdNH3Jhcio_Ohoc6_EW7CuIN02OM-0irpGEXXh0,116 -setuptools_scm/_cli.py,sha256=c1OtDXCGl7IzCdZ8z8yJg9TEBt1eXjh3mgqr16Qc5dQ,5597 -setuptools_scm/_config.py,sha256=Zf9jOxr7BWQ8RN863MPOfzO6x8Os_pwYi7VuA0Bbr4U,4968 -setuptools_scm/_entrypoints.py,sha256=GX3Lqs4YFUbQMa0mKCVYpXsfP8kR8nIuYbXRYkPaz7Y,3843 -setuptools_scm/_get_version_impl.py,sha256=P72m2imnte-J7IXD3nTjYk7gBUoLk6hrZZv5O5r9akY,5940 -setuptools_scm/_log.py,sha256=BFsXD-s2fcLV3zZaSQkQfRKPS-MjcI0tsmthJ3a2HqA,2137 -setuptools_scm/_modify_version.py,sha256=9VU-juFg2IZjrcyz9kLGRfBq4RyZZElhjPMipqjB3Xc,1738 -setuptools_scm/_overrides.py,sha256=2-ld0PSoi8IPVUAS3H2aBWM7yxJneDcyydq9ueQRdsE,1655 -setuptools_scm/_run_cmd.py,sha256=6AB6Kv1kg75Yx6-p7NHMrXSWTCPWDAN5id8cSF8XW6s,6094 -setuptools_scm/_types.py,sha256=QhY9jqXTH8sSxHXNQg2toQduk60s0vXya_Mdfv5rQAg,708 -setuptools_scm/_version_cls.py,sha256=9wEWl4WY_sUvqZhN1PQbVETVq9OAQKu1Y47ZPg9vx-c,2925 -setuptools_scm/discover.py,sha256=Kfm8S5I078vw8Cvbs9qpKOg5dr2TqBp1us-W579Dlts,2027 -setuptools_scm/fallbacks.py,sha256=x3Xv1p89AqJiBX6oxuoo8Di0yR5ijOFOwKBJGAeWTbY,1448 -setuptools_scm/git.py,sha256=-FbDzrVeEYd6jgEEzpWfuaeIfksS2QPktHZINXeSyzA,10526 -setuptools_scm/hg.py,sha256=iY294X0ZOqLEv_KXmPWwXXsPDhgx4wsOVoxFkM9WiPc,6207 -setuptools_scm/hg_git.py,sha256=hx2rq1kwW9Zs23xK9ZCn509emze22iyXvT3zIZh7JFM,4546 -setuptools_scm/integration.py,sha256=0l04N6IhRKW32vD9DPvvJuiZ1HrVCYupmNYDcYXu8lQ,806 -setuptools_scm/scm_workdir.py,sha256=oreoRhJfvhhxVGIhDPWH8-dg9umsmZM0sV2oRIzGXc8,327 -setuptools_scm/version.py,sha256=TzdIjApX5t-aWBwGZoJLykpGWVVStRxH2Fui0RVVXvU,14215 -setuptools_scm/_file_finders/__init__.py,sha256=QBZkrT7FLNfclH7taOohnNAPkVtaLJva3cHpX0sozbc,3751 -setuptools_scm/_file_finders/git.py,sha256=vW_SGVGTXNFyC4dHOhNjh3ER2Aqp0QNe1qc0XLUIZEQ,4156 -setuptools_scm/_file_finders/hg.py,sha256=1I4LPr_k7lIVMTqSl9_h1_csIEYMfRow2ta5FEo0Rjs,2246 -setuptools_scm/_file_finders/pathtools.py,sha256=AgOl5u_WHxCQeiUCwlN8bUE3B4vs5BxSJEK1LJutyus,179 -setuptools_scm/_integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -setuptools_scm/_integration/dump_version.py,sha256=2VYFa0Aa1YRcrQQVit-COg7w1QaRjmZFM22LYZWuvEg,2584 -setuptools_scm/_integration/pyproject_reading.py,sha256=Wz-_ncjggrC-YfCsclIsSd2BkH0OYLdQhl9Insobpcg,2604 -setuptools_scm/_integration/setuptools.py,sha256=DcYqpUUMMu_gD2XxdyY3enPFr12pqV9fZa06PuFqBSU,3468 -setuptools_scm/_integration/toml.py,sha256=GYXDZOUC-AfQ_WmOIESP1ARBnc6WKIBQy3oDvsF-bUQ,1467 -setuptools_scm-8.1.0.dist-info/LICENSE,sha256=iYB6zyMJvShfAzQE7nhYFgLzzZuBmhasLw5fYP9KRz4,1023 -setuptools_scm-8.1.0.dist-info/METADATA,sha256=JstkuN1RJAjyijO1FYrd2ZfrphMgbl-j1LyiGmVbzrQ,6614 -setuptools_scm-8.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92 -setuptools_scm-8.1.0.dist-info/entry_points.txt,sha256=7VjBrJmw12qwaWG0yLbRs5fYIf7g4ySdOwHNsJMhy4A,1776 -setuptools_scm-8.1.0.dist-info/top_level.txt,sha256=kiu-91q3_rJLUoc2wl8_lC4cIlpgtgdD_4NaChF4hOA,15 -setuptools_scm-8.1.0.dist-info/RECORD,, diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL deleted file mode 100644 index bab98d67588..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.43.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt deleted file mode 100644 index 2212baa8d1c..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/entry_points.txt +++ /dev/null @@ -1,42 +0,0 @@ -[distutils.setup_keywords] -use_scm_version = setuptools_scm._integration.setuptools:version_keyword - -[setuptools.file_finders] -setuptools_scm = setuptools_scm._file_finders:find_files - -[setuptools.finalize_distribution_options] -setuptools_scm = setuptools_scm._integration.setuptools:infer_version - -[setuptools_scm.files_command] -.git = setuptools_scm._file_finders.git:git_find_files -.hg = setuptools_scm._file_finders.hg:hg_find_files - -[setuptools_scm.files_command_fallback] -.git_archival.txt = setuptools_scm._file_finders.git:git_archive_find_files -.hg_archival.txt = setuptools_scm._file_finders.hg:hg_archive_find_files - -[setuptools_scm.local_scheme] -dirty-tag = setuptools_scm.version:get_local_dirty_tag -no-local-version = setuptools_scm.version:get_no_local_node -node-and-date = setuptools_scm.version:get_local_node_and_date -node-and-timestamp = setuptools_scm.version:get_local_node_and_timestamp - -[setuptools_scm.parse_scm] -.git = setuptools_scm.git:parse -.hg = setuptools_scm.hg:parse - -[setuptools_scm.parse_scm_fallback] -.git_archival.txt = setuptools_scm.git:parse_archival -.hg_archival.txt = setuptools_scm.hg:parse_archival -PKG-INFO = setuptools_scm.fallbacks:parse_pkginfo -pyproject.toml = setuptools_scm.fallbacks:fallback_version -setup.py = setuptools_scm.fallbacks:fallback_version - -[setuptools_scm.version_scheme] -calver-by-date = setuptools_scm.version:calver_by_date -guess-next-dev = setuptools_scm.version:guess_next_dev_version -no-guess-dev = setuptools_scm.version:no_guess_dev_version -only-version = setuptools_scm.version:only_version -post-release = setuptools_scm.version:postrelease_version -python-simplified-semver = setuptools_scm.version:simplified_semver_version -release-branch-semver = setuptools_scm.version:release_branch_semver_version diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt deleted file mode 100644 index 84a7b7d4911..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/requires.txt +++ /dev/null @@ -1,21 +0,0 @@ -packaging>=20 -setuptools - -[docs] -entangled-cli~=2.0 -mkdocs -mkdocs-entangled-plugin -mkdocs-material -mkdocstrings[python] -pygments - -[rich] -rich - -[test] -build -pytest -rich -wheel - -[toml] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt deleted file mode 100644 index cba8d886074..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/EGG-INFO/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -setuptools_scm diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt deleted file mode 100644 index 7c5100942aa..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/.git_archival.txt +++ /dev/null @@ -1,3 +0,0 @@ -node: $Format:%H$ -node-date: $Format:%cI$ -describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py deleted file mode 100644 index e265e859ca1..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -:copyright: 2010-2023 by Ronny Pfannschmidt -:license: MIT -""" - -from __future__ import annotations - -from ._config import DEFAULT_LOCAL_SCHEME -from ._config import DEFAULT_VERSION_SCHEME -from ._config import Configuration -from ._get_version_impl import _get_version -from ._get_version_impl import get_version -from ._integration.dump_version import dump_version # soft deprecated -from ._version_cls import NonNormalizedVersion -from ._version_cls import Version -from .version import ScmVersion - -# Public API -__all__ = [ - "DEFAULT_LOCAL_SCHEME", - "DEFAULT_VERSION_SCHEME", - "Configuration", - "NonNormalizedVersion", - "ScmVersion", - "Version", - "_get_version", - "dump_version", - # soft deprecated imports, left for backward compatibility - "get_version", -] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py deleted file mode 100644 index 3f56d42a0c6..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import annotations - -from ._cli import main - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py deleted file mode 100644 index 8c815237a0f..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_cli.py +++ /dev/null @@ -1,186 +0,0 @@ -from __future__ import annotations - -import argparse -import json -import os -import sys - -from typing import Any - -from setuptools_scm import Configuration -from setuptools_scm._file_finders import find_files -from setuptools_scm._get_version_impl import _get_version -from setuptools_scm.discover import walk_potential_roots - - -def main(args: list[str] | None = None) -> int: - opts = _get_cli_opts(args) - inferred_root: str = opts.root or "." - - pyproject = opts.config or _find_pyproject(inferred_root) - - try: - config = Configuration.from_file( - pyproject, - root=(os.path.abspath(opts.root) if opts.root is not None else None), - ) - except (LookupError, FileNotFoundError) as ex: - # no pyproject.toml OR no [tool.setuptools_scm] - print( - f"Warning: could not use {os.path.relpath(pyproject)}," - " using default configuration.\n" - f" Reason: {ex}.", - file=sys.stderr, - ) - config = Configuration(root=inferred_root) - - version = _get_version( - config, force_write_version_files=opts.force_write_version_files - ) - if version is None: - raise SystemExit("ERROR: no version found for", opts) - if opts.strip_dev: - version = version.partition(".dev")[0] - - return command(opts, version, config) - - -def _get_cli_opts(args: list[str] | None) -> argparse.Namespace: - prog = "python -m setuptools_scm" - desc = "Print project version according to SCM metadata" - parser = argparse.ArgumentParser(prog, description=desc) - # By default, help for `--help` starts with lower case, so we keep the pattern: - parser.add_argument( - "-r", - "--root", - default=None, - help='directory managed by the SCM, default: inferred from config file, or "."', - ) - parser.add_argument( - "-c", - "--config", - default=None, - metavar="PATH", - help="path to 'pyproject.toml' with setuptools_scm config, " - "default: looked up in the current or parent directories", - ) - parser.add_argument( - "--strip-dev", - action="store_true", - help="remove the dev/local parts of the version before printing the version", - ) - parser.add_argument( - "-N", - "--no-version", - action="store_true", - help="do not include package version in the output", - ) - output_formats = ["json", "plain", "key-value"] - parser.add_argument( - "-f", - "--format", - type=str.casefold, - default="plain", - help="specify output format", - choices=output_formats, - ) - parser.add_argument( - "-q", - "--query", - type=str.casefold, - nargs="*", - help="display setuptools_scm settings according to query, " - "e.g. dist_name, do not supply an argument in order to " - "print a list of valid queries.", - ) - parser.add_argument( - "--force-write-version-files", - action="store_true", - help="trigger to write the content of the version files\n" - "its recommended to use normal/editable installation instead)", - ) - sub = parser.add_subparsers(title="extra commands", dest="command", metavar="") - # We avoid `metavar` to prevent printing repetitive information - desc = "List information about the package, e.g. included files" - sub.add_parser("ls", help=desc[0].lower() + desc[1:], description=desc) - return parser.parse_args(args) - - -# flake8: noqa: C901 -def command(opts: argparse.Namespace, version: str, config: Configuration) -> int: - data: dict[str, Any] = {} - - if opts.command == "ls": - opts.query = ["files"] - - if opts.query == []: - opts.no_version = True - sys.stderr.write("Available queries:\n\n") - opts.query = ["queries"] - data["queries"] = ["files", *config.__dataclass_fields__] - - if opts.query is None: - opts.query = [] - - if not opts.no_version: - data["version"] = version - - if "files" in opts.query: - data["files"] = find_files(config.root) - - for q in opts.query: - if q in ["files", "queries", "version"]: - continue - - try: - if q.startswith("_"): - raise AttributeError() - data[q] = getattr(config, q) - except AttributeError: - sys.stderr.write(f"Error: unknown query: '{q}'\n") - return 1 - - if opts.format == "json": - print(json.dumps(data, indent=2)) - - if opts.format == "plain": - _print_plain(data) - - if opts.format == "key-value": - _print_key_value(data) - - return 0 - - -def _print_plain(data: dict[str, Any]) -> None: - version = data.pop("version", None) - if version: - print(version) - files = data.pop("files", []) - for file_ in files: - print(file_) - queries = data.pop("queries", []) - for query in queries: - print(query) - if data: - print("\n".join(data.values())) - - -def _print_key_value(data: dict[str, Any]) -> None: - for key, value in data.items(): - if isinstance(value, str): - print(f"{key} = {value}") - else: - str_value = "\n ".join(value) - print(f"{key} = {str_value}") - - -def _find_pyproject(parent: str) -> str: - for directory in walk_potential_roots(os.path.abspath(parent)): - pyproject = os.path.join(directory, "pyproject.toml") - if os.path.isfile(pyproject): - return pyproject - - return os.path.abspath( - "pyproject.toml" - ) # use default name to trigger the default errors diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py deleted file mode 100644 index 6ed520f933d..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_config.py +++ /dev/null @@ -1,152 +0,0 @@ -"""configuration""" - -from __future__ import annotations - -import dataclasses -import os -import re -import warnings - -from pathlib import Path -from typing import Any -from typing import Pattern -from typing import Protocol - -from . import _log -from . import _types as _t -from ._integration.pyproject_reading import ( - get_args_for_pyproject as _get_args_for_pyproject, -) -from ._integration.pyproject_reading import read_pyproject as _read_pyproject -from ._overrides import read_toml_overrides -from ._version_cls import Version as _Version -from ._version_cls import _validate_version_cls -from ._version_cls import _VersionT - -log = _log.log.getChild("config") - -DEFAULT_TAG_REGEX = re.compile( - r"^(?:[\w-]+-)?(?P[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$" -) -"""default tag regex that tries to match PEP440 style versions -with prefix consisting of dashed words""" - -DEFAULT_VERSION_SCHEME = "guess-next-dev" -DEFAULT_LOCAL_SCHEME = "node-and-date" - - -def _check_tag_regex(value: str | Pattern[str] | None) -> Pattern[str]: - if not value: - regex = DEFAULT_TAG_REGEX - else: - regex = re.compile(value) - - group_names = regex.groupindex.keys() - if regex.groups == 0 or (regex.groups > 1 and "version" not in group_names): - warnings.warn( - "Expected tag_regex to contain a single match group or a group named" - " 'version' to identify the version part of any tag." - ) - - return regex - - -class ParseFunction(Protocol): - def __call__( - self, root: _t.PathT, *, config: Configuration - ) -> _t.SCMVERSION | None: ... - - -def _check_absolute_root(root: _t.PathT, relative_to: _t.PathT | None) -> str: - log.debug("check absolute root=%s relative_to=%s", root, relative_to) - if relative_to: - if ( - os.path.isabs(root) - and os.path.isabs(relative_to) - and not os.path.commonpath([root, relative_to]) == root - ): - warnings.warn( - f"absolute root path '{root}' overrides relative_to '{relative_to}'" - ) - if os.path.isdir(relative_to): - warnings.warn( - "relative_to is expected to be a file," - f" its the directory {relative_to}\n" - "assuming the parent directory was passed" - ) - log.debug("dir %s", relative_to) - root = os.path.join(relative_to, root) - else: - log.debug("file %s", relative_to) - root = os.path.join(os.path.dirname(relative_to), root) - return os.path.abspath(root) - - -@dataclasses.dataclass -class Configuration: - """Global configuration model""" - - relative_to: _t.PathT | None = None - root: _t.PathT = "." - version_scheme: _t.VERSION_SCHEME = DEFAULT_VERSION_SCHEME - local_scheme: _t.VERSION_SCHEME = DEFAULT_LOCAL_SCHEME - tag_regex: Pattern[str] = DEFAULT_TAG_REGEX - parentdir_prefix_version: str | None = None - fallback_version: str | None = None - fallback_root: _t.PathT = "." - write_to: _t.PathT | None = None - write_to_template: str | None = None - version_file: _t.PathT | None = None - version_file_template: str | None = None - parse: ParseFunction | None = None - git_describe_command: _t.CMD_TYPE | None = None - dist_name: str | None = None - version_cls: type[_VersionT] = _Version - search_parent_directories: bool = False - - parent: _t.PathT | None = None - - @property - def absolute_root(self) -> str: - return _check_absolute_root(self.root, self.relative_to) - - @classmethod - def from_file( - cls, - name: str | os.PathLike[str] = "pyproject.toml", - dist_name: str | None = None, - _require_section: bool = True, - **kwargs: Any, - ) -> Configuration: - """ - Read Configuration from pyproject.toml (or similar). - Raises exceptions when file is not found or toml is - not installed or the file has invalid format or does - not contain the [tool.setuptools_scm] section. - """ - - pyproject_data = _read_pyproject(Path(name), require_section=_require_section) - args = _get_args_for_pyproject(pyproject_data, dist_name, kwargs) - - args.update(read_toml_overrides(args["dist_name"])) - relative_to = args.pop("relative_to", name) - return cls.from_data(relative_to=relative_to, data=args) - - @classmethod - def from_data( - cls, relative_to: str | os.PathLike[str], data: dict[str, Any] - ) -> Configuration: - """ - given configuration data - create a config instance after validating tag regex/version class - """ - tag_regex = _check_tag_regex(data.pop("tag_regex", None)) - version_cls = _validate_version_cls( - data.pop("version_cls", None), data.pop("normalize", True) - ) - return cls( - relative_to=relative_to, - version_cls=version_cls, - tag_regex=tag_regex, - **data, - ) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py deleted file mode 100644 index 5eab1ed2b9a..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_entrypoints.py +++ /dev/null @@ -1,139 +0,0 @@ -from __future__ import annotations - -import sys - -from typing import TYPE_CHECKING -from typing import Any -from typing import Callable -from typing import Iterator -from typing import cast -from typing import overload - -from . import _log -from . import version - -if TYPE_CHECKING: - from . import _types as _t - from ._config import Configuration - from ._config import ParseFunction - - -from importlib.metadata import EntryPoint as EntryPoint - -if sys.version_info[:2] < (3, 10): - from importlib.metadata import entry_points as legacy_entry_points - - class EntryPoints: - _groupdata: list[EntryPoint] - - def __init__(self, groupdata: list[EntryPoint]) -> None: - self._groupdata = groupdata - - def select(self, name: str) -> EntryPoints: - return EntryPoints([x for x in self._groupdata if x.name == name]) - - def __iter__(self) -> Iterator[EntryPoint]: - return iter(self._groupdata) - - def entry_points(group: str) -> EntryPoints: - return EntryPoints(legacy_entry_points()[group]) - -else: - from importlib.metadata import EntryPoints - from importlib.metadata import entry_points - - -log = _log.log.getChild("entrypoints") - - -def version_from_entrypoint( - config: Configuration, *, entrypoint: str, root: _t.PathT -) -> version.ScmVersion | None: - from .discover import iter_matching_entrypoints - - log.debug("version_from_ep %s in %s", entrypoint, root) - for ep in iter_matching_entrypoints(root, entrypoint, config): - fn: ParseFunction = ep.load() - maybe_version: version.ScmVersion | None = fn(root, config=config) - log.debug("%s found %r", ep, maybe_version) - if maybe_version is not None: - return maybe_version - return None - - -def iter_entry_points(group: str, name: str | None = None) -> Iterator[EntryPoint]: - eps: EntryPoints = entry_points(group=group) - res = eps if name is None else eps.select(name=name) - - return iter(res) - - -def _get_ep(group: str, name: str) -> Any | None: - for ep in iter_entry_points(group, name): - log.debug("ep found: %s", ep.name) - return ep.load() - else: - return None - - -def _get_from_object_reference_str(path: str, group: str) -> Any | None: - # todo: remove for importlib native spelling - ep = EntryPoint(path, path, group) - try: - return ep.load() - except (AttributeError, ModuleNotFoundError): - return None - - -def _iter_version_schemes( - entrypoint: str, - scheme_value: _t.VERSION_SCHEMES, - _memo: set[object] | None = None, -) -> Iterator[Callable[[version.ScmVersion], str]]: - if _memo is None: - _memo = set() - if isinstance(scheme_value, str): - scheme_value = cast( - "_t.VERSION_SCHEMES", - _get_ep(entrypoint, scheme_value) - or _get_from_object_reference_str(scheme_value, entrypoint), - ) - - if isinstance(scheme_value, (list, tuple)): - for variant in scheme_value: - if variant not in _memo: - _memo.add(variant) - yield from _iter_version_schemes(entrypoint, variant, _memo=_memo) - elif callable(scheme_value): - yield scheme_value - - -@overload -def _call_version_scheme( - version: version.ScmVersion, - entrypoint: str, - given_value: _t.VERSION_SCHEMES, - default: str, -) -> str: ... - - -@overload -def _call_version_scheme( - version: version.ScmVersion, - entrypoint: str, - given_value: _t.VERSION_SCHEMES, - default: None, -) -> str | None: ... - - -def _call_version_scheme( - version: version.ScmVersion, - entrypoint: str, - given_value: _t.VERSION_SCHEMES, - default: str | None, -) -> str | None: - for scheme in _iter_version_schemes(entrypoint, given_value): - result = scheme(version) - if result is not None: - return result - return default diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py deleted file mode 100644 index 8201bae1713..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/__init__.py +++ /dev/null @@ -1,113 +0,0 @@ -from __future__ import annotations - -import itertools -import os - -from typing import TYPE_CHECKING -from typing import Callable - -from .. import _log -from .. import _types as _t -from .._entrypoints import iter_entry_points -from .pathtools import norm_real - -if TYPE_CHECKING: - import sys - - if sys.version_info >= (3, 10): - from typing import TypeGuard - else: - from typing_extensions import TypeGuard - - -log = _log.log.getChild("file_finder") - - -def scm_find_files( - path: _t.PathT, - scm_files: set[str], - scm_dirs: set[str], - force_all_files: bool = False, -) -> list[str]: - """ setuptools compatible file finder that follows symlinks - - - path: the root directory from which to search - - scm_files: set of scm controlled files and symlinks - (including symlinks to directories) - - scm_dirs: set of scm controlled directories - (including directories containing no scm controlled files) - - force_all_files: ignore ``scm_files`` and ``scm_dirs`` and list everything. - - scm_files and scm_dirs must be absolute with symlinks resolved (realpath), - with normalized case (normcase) - - Spec here: https://setuptools.pypa.io/en/latest/userguide/extension.html#\ - adding-support-for-revision-control-systems - """ - realpath = norm_real(path) - seen: set[str] = set() - res: list[str] = [] - for dirpath, dirnames, filenames in os.walk(realpath, followlinks=True): - # dirpath with symlinks resolved - realdirpath = norm_real(dirpath) - - def _link_not_in_scm(n: str, realdirpath: str = realdirpath) -> bool: - fn = os.path.join(realdirpath, os.path.normcase(n)) - return os.path.islink(fn) and fn not in scm_files - - if not force_all_files and realdirpath not in scm_dirs: - # directory not in scm, don't walk it's content - dirnames[:] = [] - continue - if os.path.islink(dirpath) and not os.path.relpath( - realdirpath, realpath - ).startswith(os.pardir): - # a symlink to a directory not outside path: - # we keep it in the result and don't walk its content - res.append(os.path.join(path, os.path.relpath(dirpath, path))) - dirnames[:] = [] - continue - if realdirpath in seen: - # symlink loop protection - dirnames[:] = [] - continue - dirnames[:] = [ - dn for dn in dirnames if force_all_files or not _link_not_in_scm(dn) - ] - for filename in filenames: - if not force_all_files and _link_not_in_scm(filename): - continue - # dirpath + filename with symlinks preserved - fullfilename = os.path.join(dirpath, filename) - is_tracked = norm_real(fullfilename) in scm_files - if force_all_files or is_tracked: - res.append(os.path.join(path, os.path.relpath(fullfilename, realpath))) - seen.add(realdirpath) - return res - - -def is_toplevel_acceptable(toplevel: str | None) -> TypeGuard[str]: - """ """ - if toplevel is None: - return False - - ignored: list[str] = os.environ.get("SETUPTOOLS_SCM_IGNORE_VCS_ROOTS", "").split( - os.pathsep - ) - ignored = [os.path.normcase(p) for p in ignored] - - log.debug("toplevel: %r\n ignored %s", toplevel, ignored) - - return toplevel not in ignored - - -def find_files(path: _t.PathT = "") -> list[str]: - for ep in itertools.chain( - iter_entry_points("setuptools_scm.files_command"), - iter_entry_points("setuptools_scm.files_command_fallback"), - ): - command: Callable[[_t.PathT], list[str]] = ep.load() - res: list[str] = command(path) - if res: - return res - return [] diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py deleted file mode 100644 index 7b23f886420..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/git.py +++ /dev/null @@ -1,117 +0,0 @@ -from __future__ import annotations - -import logging -import os -import subprocess -import tarfile - -from typing import IO - -from .. import _types as _t -from .._run_cmd import run as _run -from ..integration import data_from_mime -from . import is_toplevel_acceptable -from . import scm_find_files -from .pathtools import norm_real - -log = logging.getLogger(__name__) - - -def _git_toplevel(path: str) -> str | None: - try: - cwd = os.path.abspath(path or ".") - res = _run(["git", "rev-parse", "HEAD"], cwd=cwd) - if res.returncode: - # BAIL if there is no commit - log.error("listing git files failed - pretending there aren't any") - return None - res = _run( - ["git", "rev-parse", "--show-prefix"], - cwd=cwd, - ) - if res.returncode: - return None - out = res.stdout[:-1] # remove the trailing pathsep - if not out: - out = cwd - else: - # Here, ``out`` is a relative path to root of git. - # ``cwd`` is absolute path to current working directory. - # the below method removes the length of ``out`` from - # ``cwd``, which gives the git toplevel - assert cwd.replace("\\", "/").endswith(out), f"cwd={cwd!r}\nout={out!r}" - # In windows cwd contains ``\`` which should be replaced by ``/`` - # for this assertion to work. Length of string isn't changed by replace - # ``\\`` is just and escape for `\` - out = cwd[: -len(out)] - log.debug("find files toplevel %s", out) - return norm_real(out) - except subprocess.CalledProcessError: - # git returned error, we are not in a git repo - return None - except OSError: - # git command not found, probably - return None - - -def _git_interpret_archive(fd: IO[bytes], toplevel: str) -> tuple[set[str], set[str]]: - with tarfile.open(fileobj=fd, mode="r|*") as tf: - git_files = set() - git_dirs = {toplevel} - for member in tf.getmembers(): - name = os.path.normcase(member.name).replace("/", os.path.sep) - if member.type == tarfile.DIRTYPE: - git_dirs.add(name) - else: - git_files.add(name) - return git_files, git_dirs - - -def _git_ls_files_and_dirs(toplevel: str) -> tuple[set[str], set[str]]: - # use git archive instead of git ls-file to honor - # export-ignore git attribute - - cmd = ["git", "archive", "--prefix", toplevel + os.path.sep, "HEAD"] - proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, cwd=toplevel, stderr=subprocess.DEVNULL - ) - assert proc.stdout is not None - try: - try: - return _git_interpret_archive(proc.stdout, toplevel) - finally: - # ensure we avoid resource warnings by cleaning up the process - proc.stdout.close() - proc.terminate() - except Exception: - if proc.wait() != 0: - log.error("listing git files failed - pretending there aren't any") - return set(), set() - - -def git_find_files(path: _t.PathT = "") -> list[str]: - toplevel = _git_toplevel(os.fspath(path)) - if not is_toplevel_acceptable(toplevel): - return [] - fullpath = norm_real(path) - if not fullpath.startswith(toplevel): - log.warning("toplevel mismatch computed %s vs resolved %s ", toplevel, fullpath) - git_files, git_dirs = _git_ls_files_and_dirs(toplevel) - return scm_find_files(path, git_files, git_dirs) - - -def git_archive_find_files(path: _t.PathT = "") -> list[str]: - # This function assumes that ``path`` is obtained from a git archive - # and therefore all the files that should be ignored were already removed. - archival = os.path.join(path, ".git_archival.txt") - if not os.path.exists(archival): - return [] - - data = data_from_mime(archival) - - if "$Format" in data.get("node", ""): - # Substitutions have not been performed, so not a reliable archive - return [] - - log.warning("git archive detected - fallback to listing all files") - return scm_find_files(path, set(), set(), force_all_files=True) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py deleted file mode 100644 index 9115a5fa8ac..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/hg.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import annotations - -import logging -import os -import subprocess - -from .. import _types as _t -from .._file_finders import is_toplevel_acceptable -from .._file_finders import scm_find_files -from .._run_cmd import run as _run -from ..integration import data_from_mime -from .pathtools import norm_real - -log = logging.getLogger(__name__) - - -def _hg_toplevel(path: str) -> str | None: - try: - return _run( - ["hg", "root"], - cwd=(path or "."), - check=True, - ).parse_success(norm_real) - except subprocess.CalledProcessError: - # hg returned error, we are not in a mercurial repo - return None - except OSError: - # hg command not found, probably - return None - - -def _hg_ls_files_and_dirs(toplevel: str) -> tuple[set[str], set[str]]: - hg_files: set[str] = set() - hg_dirs = {toplevel} - res = _run(["hg", "files"], cwd=toplevel) - if res.returncode: - return set(), set() - for name in res.stdout.splitlines(): - name = os.path.normcase(name).replace("/", os.path.sep) - fullname = os.path.join(toplevel, name) - hg_files.add(fullname) - dirname = os.path.dirname(fullname) - while len(dirname) > len(toplevel) and dirname not in hg_dirs: - hg_dirs.add(dirname) - dirname = os.path.dirname(dirname) - return hg_files, hg_dirs - - -def hg_find_files(path: str = "") -> list[str]: - toplevel = _hg_toplevel(path) - if not is_toplevel_acceptable(toplevel): - return [] - assert toplevel is not None - hg_files, hg_dirs = _hg_ls_files_and_dirs(toplevel) - return scm_find_files(path, hg_files, hg_dirs) - - -def hg_archive_find_files(path: _t.PathT = "") -> list[str]: - # This function assumes that ``path`` is obtained from a mercurial archive - # and therefore all the files that should be ignored were already removed. - archival = os.path.join(path, ".hg_archival.txt") - if not os.path.exists(archival): - return [] - - data = data_from_mime(archival) - - if "node" not in data: - # Ensure file is valid - return [] - - log.warning("hg archive detected - fallback to listing all files") - return scm_find_files(path, set(), set(), force_all_files=True) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py deleted file mode 100644 index 6de850897b9..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_file_finders/pathtools.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import annotations - -import os - -from setuptools_scm import _types as _t - - -def norm_real(path: _t.PathT) -> str: - return os.path.normcase(os.path.realpath(path)) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py deleted file mode 100644 index 877804c18bf..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_get_version_impl.py +++ /dev/null @@ -1,175 +0,0 @@ -from __future__ import annotations - -import logging -import re -import warnings - -from pathlib import Path -from typing import Any -from typing import NoReturn -from typing import Pattern - -from . import _config -from . import _entrypoints -from . import _run_cmd -from . import _types as _t -from ._config import Configuration -from ._overrides import _read_pretended_version_for -from ._version_cls import _validate_version_cls -from .version import ScmVersion -from .version import format_version as _format_version - -EMPTY_TAG_REGEX_DEPRECATION = DeprecationWarning( - "empty regex for tag regex is invalid, using default" -) - -_log = logging.getLogger(__name__) - - -def parse_scm_version(config: Configuration) -> ScmVersion | None: - try: - if config.parse is not None: - parse_result = config.parse(config.absolute_root, config=config) - if parse_result is not None and not isinstance(parse_result, ScmVersion): - raise TypeError( - f"version parse result was {str!r}\n" - "please return a parsed version (ScmVersion)" - ) - return parse_result - else: - return _entrypoints.version_from_entrypoint( - config, - entrypoint="setuptools_scm.parse_scm", - root=config.absolute_root, - ) - except _run_cmd.CommandNotFoundError as e: - _log.exception("command %s not found while parsing the scm, using fallbacks", e) - return None - - -def parse_fallback_version(config: Configuration) -> ScmVersion | None: - return _entrypoints.version_from_entrypoint( - config, - entrypoint="setuptools_scm.parse_scm_fallback", - root=config.fallback_root, - ) - - -def parse_version(config: Configuration) -> ScmVersion | None: - return ( - _read_pretended_version_for(config) - or parse_scm_version(config) - or parse_fallback_version(config) - ) - - -def write_version_files( - config: Configuration, version: str, scm_version: ScmVersion -) -> None: - if config.write_to is not None: - from ._integration.dump_version import dump_version - - dump_version( - root=config.root, - version=version, - scm_version=scm_version, - write_to=config.write_to, - template=config.write_to_template, - ) - if config.version_file: - from ._integration.dump_version import write_version_to_path - - version_file = Path(config.version_file) - assert not version_file.is_absolute(), f"{version_file=}" - # todo: use a better name than fallback root - assert config.relative_to is not None - target = Path(config.relative_to).parent.joinpath(version_file) - write_version_to_path( - target, - template=config.version_file_template, - version=version, - scm_version=scm_version, - ) - - -def _get_version( - config: Configuration, force_write_version_files: bool | None = None -) -> str | None: - parsed_version = parse_version(config) - if parsed_version is None: - return None - version_string = _format_version(parsed_version) - if force_write_version_files is None: - force_write_version_files = True - warnings.warn( - "force_write_version_files ought to be set," - " presuming the legacy True value", - DeprecationWarning, - ) - - if force_write_version_files: - write_version_files(config, version=version_string, scm_version=parsed_version) - - return version_string - - -def _version_missing(config: Configuration) -> NoReturn: - raise LookupError( - f"setuptools-scm was unable to detect version for {config.absolute_root}.\n\n" - "Make sure you're either building from a fully intact git repository " - "or PyPI tarballs. Most other sources (such as GitHub's tarballs, a " - "git checkout without the .git folder) don't contain the necessary " - "metadata and will not work.\n\n" - "For example, if you're using pip, instead of " - "https://github.com/user/proj/archive/master.zip " - "use git+https://github.com/user/proj.git#egg=proj" - ) - - -def get_version( - root: _t.PathT = ".", - version_scheme: _t.VERSION_SCHEME = _config.DEFAULT_VERSION_SCHEME, - local_scheme: _t.VERSION_SCHEME = _config.DEFAULT_LOCAL_SCHEME, - write_to: _t.PathT | None = None, - write_to_template: str | None = None, - version_file: _t.PathT | None = None, - version_file_template: str | None = None, - relative_to: _t.PathT | None = None, - tag_regex: str | Pattern[str] = _config.DEFAULT_TAG_REGEX, - parentdir_prefix_version: str | None = None, - fallback_version: str | None = None, - fallback_root: _t.PathT = ".", - parse: Any | None = None, - git_describe_command: _t.CMD_TYPE | None = None, - dist_name: str | None = None, - version_cls: Any | None = None, - normalize: bool = True, - search_parent_directories: bool = False, -) -> str: - """ - If supplied, relative_to should be a file from which root may - be resolved. Typically called by a script or module that is not - in the root of the repository to direct setuptools_scm to the - root of the repository by supplying ``__file__``. - """ - - version_cls = _validate_version_cls(version_cls, normalize) - del normalize - tag_regex = parse_tag_regex(tag_regex) - config = Configuration(**locals()) - maybe_version = _get_version(config, force_write_version_files=True) - - if maybe_version is None: - _version_missing(config) - return maybe_version - - -def parse_tag_regex(tag_regex: str | Pattern[str]) -> Pattern[str]: - if isinstance(tag_regex, str): - if tag_regex == "": - warnings.warn(EMPTY_TAG_REGEX_DEPRECATION) - return _config.DEFAULT_TAG_REGEX - else: - return re.compile(tag_regex) - else: - return tag_regex diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py deleted file mode 100644 index 1901b1d3ba7..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/dump_version.py +++ /dev/null @@ -1,94 +0,0 @@ -from __future__ import annotations - -import warnings - -from pathlib import Path - -from .. import _types as _t -from .._log import log as parent_log -from .._version_cls import _version_as_tuple -from ..version import ScmVersion - -log = parent_log.getChild("dump_version") - -TEMPLATES = { - ".py": """\ -# file generated by setuptools_scm -# don't change, don't track in version control -TYPE_CHECKING = False -if TYPE_CHECKING: - from typing import Tuple, Union - VERSION_TUPLE = Tuple[Union[int, str], ...] -else: - VERSION_TUPLE = object - -version: str -__version__: str -__version_tuple__: VERSION_TUPLE -version_tuple: VERSION_TUPLE - -__version__ = version = {version!r} -__version_tuple__ = version_tuple = {version_tuple!r} -""", - ".txt": "{version}", -} - - -def dump_version( - root: _t.PathT, - version: str, - write_to: _t.PathT, - template: str | None = None, - scm_version: ScmVersion | None = None, -) -> None: - assert isinstance(version, str) - root = Path(root) - write_to = Path(write_to) - if write_to.is_absolute(): - # trigger warning on escape - write_to.relative_to(root) - warnings.warn( - f"{write_to=!s} is a absolute path," - " please switch to using a relative version file", - DeprecationWarning, - ) - target = write_to - else: - target = Path(root).joinpath(write_to) - write_version_to_path( - target, template=template, version=version, scm_version=scm_version - ) - - -def _validate_template(target: Path, template: str | None) -> str: - if template == "": - warnings.warn(f"{template=} looks like a error, using default instead") - template = None - if template is None: - template = TEMPLATES.get(target.suffix) - - if template is None: - raise ValueError( - f"bad file format: {target.suffix!r} (of {target})\n" - "only *.txt and *.py have a default template" - ) - else: - return template - - -def write_version_to_path( - target: Path, template: str | None, version: str, scm_version: ScmVersion | None -) -> None: - final_template = _validate_template(target, template) - log.debug("dump %s into %s", version, target) - version_tuple = _version_as_tuple(version) - if scm_version is not None: - content = final_template.format( - version=version, - version_tuple=version_tuple, - scm_version=scm_version, - ) - else: - content = final_template.format(version=version, version_tuple=version_tuple) - - target.write_text(content, encoding="utf-8") diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py deleted file mode 100644 index 0e4f9aa11b7..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/pyproject_reading.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import annotations - -import warnings - -from pathlib import Path -from typing import NamedTuple - -from .. import _log -from .setuptools import read_dist_name_from_setup_cfg -from .toml import TOML_RESULT -from .toml import read_toml_content - -log = _log.log.getChild("pyproject_reading") - -_ROOT = "root" - - -class PyProjectData(NamedTuple): - path: Path - tool_name: str - project: TOML_RESULT - section: TOML_RESULT - - @property - def project_name(self) -> str | None: - return self.project.get("name") - - -def read_pyproject( - path: Path = Path("pyproject.toml"), - tool_name: str = "setuptools_scm", - require_section: bool = True, -) -> PyProjectData: - defn = read_toml_content(path, None if require_section else {}) - try: - section = defn.get("tool", {})[tool_name] - except LookupError as e: - error = f"{path} does not contain a tool.{tool_name} section" - if require_section: - raise LookupError(error) from e - else: - log.warning("toml section missing %r", error, exc_info=True) - section = {} - - project = defn.get("project", {}) - return PyProjectData(path, tool_name, project, section) - - -def get_args_for_pyproject( - pyproject: PyProjectData, - dist_name: str | None, - kwargs: TOML_RESULT, -) -> TOML_RESULT: - """drops problematic details and figures the distribution name""" - section = pyproject.section.copy() - kwargs = kwargs.copy() - if "relative_to" in section: - relative = section.pop("relative_to") - warnings.warn( - f"{pyproject.path}: at [tool.{pyproject.tool_name}]\n" - f"ignoring value relative_to={relative!r}" - " as its always relative to the config file" - ) - if "dist_name" in section: - if dist_name is None: - dist_name = section.pop("dist_name") - else: - assert dist_name == section["dist_name"] - section.pop("dist_name") - if dist_name is None: - # minimal pep 621 support for figuring the pretend keys - dist_name = pyproject.project_name - if dist_name is None: - dist_name = read_dist_name_from_setup_cfg() - if _ROOT in kwargs: - if kwargs[_ROOT] is None: - kwargs.pop(_ROOT, None) - elif _ROOT in section: - if section[_ROOT] != kwargs[_ROOT]: - warnings.warn( - f"root {section[_ROOT]} is overridden" - f" by the cli arg {kwargs[_ROOT]}" - ) - section.pop(_ROOT, None) - return {"dist_name": dist_name, **section, **kwargs} diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py deleted file mode 100644 index dfc5a286430..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/setuptools.py +++ /dev/null @@ -1,123 +0,0 @@ -from __future__ import annotations - -import logging -import os -import warnings - -from typing import Any -from typing import Callable - -import setuptools - -from .. import _config - -log = logging.getLogger(__name__) - - -def read_dist_name_from_setup_cfg( - input: str | os.PathLike[str] = "setup.cfg", -) -> str | None: - # minimal effort to read dist_name off setup.cfg metadata - import configparser - - parser = configparser.ConfigParser() - parser.read([input], encoding="utf-8") - dist_name = parser.get("metadata", "name", fallback=None) - return dist_name - - -def _warn_on_old_setuptools(_version: str = setuptools.__version__) -> None: - if int(_version.split(".")[0]) < 61: - warnings.warn( - RuntimeWarning( - f""" -ERROR: setuptools=={_version} is used in combination with setuptools_scm>=8.x - -Your build configuration is incomplete and previously worked by accident! -setuptools_scm requires setuptools>=61 - -Suggested workaround if applicable: - - migrating from the deprecated setup_requires mechanism to pep517/518 - and using a pyproject.toml to declare build dependencies - which are reliably pre-installed before running the build tools -""" - ) - ) - - -def _assign_version( - dist: setuptools.Distribution, config: _config.Configuration -) -> None: - from .._get_version_impl import _get_version - from .._get_version_impl import _version_missing - - # todo: build time plugin - maybe_version = _get_version(config, force_write_version_files=True) - - if maybe_version is None: - _version_missing(config) - else: - assert dist.metadata.version is None - dist.metadata.version = maybe_version - - -_warn_on_old_setuptools() - - -def _log_hookstart(hook: str, dist: setuptools.Distribution) -> None: - log.debug("%s %r", hook, vars(dist.metadata)) - - -def version_keyword( - dist: setuptools.Distribution, - keyword: str, - value: bool | dict[str, Any] | Callable[[], dict[str, Any]], -) -> None: - overrides: dict[str, Any] - if value is True: - overrides = {} - elif callable(value): - overrides = value() - else: - assert isinstance(value, dict), "version_keyword expects a dict or True" - overrides = value - - assert ( - "dist_name" not in overrides - ), "dist_name may not be specified in the setup keyword " - dist_name: str | None = dist.metadata.name - _log_hookstart("version_keyword", dist) - - if dist.metadata.version is not None: - warnings.warn(f"version of {dist_name} already set") - return - - if dist_name is None: - dist_name = read_dist_name_from_setup_cfg() - - config = _config.Configuration.from_file( - dist_name=dist_name, - _require_section=False, - **overrides, - ) - _assign_version(dist, config) - - -def infer_version(dist: setuptools.Distribution) -> None: - _log_hookstart("infer_version", dist) - log.debug("dist %s %s", id(dist), id(dist.metadata)) - if dist.metadata.version is not None: - return # metadata already added by hook - dist_name = dist.metadata.name - if dist_name is None: - dist_name = read_dist_name_from_setup_cfg() - if not os.path.isfile("pyproject.toml"): - return - if dist_name == "setuptools_scm": - return - try: - config = _config.Configuration.from_file(dist_name=dist_name) - except LookupError as e: - log.info(e, exc_info=True) - else: - _assign_version(dist, config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py deleted file mode 100644 index 8ca38d975ab..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_integration/toml.py +++ /dev/null @@ -1,59 +0,0 @@ -from __future__ import annotations - -import sys - -from pathlib import Path -from typing import TYPE_CHECKING -from typing import Any -from typing import Callable -from typing import Dict -from typing import TypedDict -from typing import cast - -if sys.version_info >= (3, 11): - from tomllib import loads as load_toml -else: - from tomli import loads as load_toml - -if TYPE_CHECKING: - if sys.version_info >= (3, 10): - from typing import TypeAlias - else: - from typing_extensions import TypeAlias - -from .. import _log - -log = _log.log.getChild("toml") - -TOML_RESULT: TypeAlias = Dict[str, Any] -TOML_LOADER: TypeAlias = Callable[[str], TOML_RESULT] - - -def read_toml_content(path: Path, default: TOML_RESULT | None = None) -> TOML_RESULT: - try: - data = path.read_text(encoding="utf-8") - except FileNotFoundError: - if default is None: - raise - else: - log.debug("%s missing, presuming default %r", path, default) - return default - else: - return load_toml(data) - - -class _CheatTomlData(TypedDict): - cheat: dict[str, Any] - - -def load_toml_or_inline_map(data: str | None) -> dict[str, Any]: - """ - load toml data - with a special hack if only a inline map is given - """ - if not data: - return {} - elif data[0] == "{": - data = "cheat=" + data - loaded: _CheatTomlData = cast(_CheatTomlData, load_toml(data)) - return loaded["cheat"] - return load_toml(data) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py deleted file mode 100644 index 7e4b7db7da1..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_log.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -logging helpers, supports vendoring -""" - -from __future__ import annotations - -import contextlib -import logging -import os -import sys - -from typing import IO -from typing import Iterator -from typing import Mapping - -log = logging.getLogger(__name__.rsplit(".", 1)[0]) -log.propagate = False - - -class AlwaysStdErrHandler(logging.StreamHandler): # type: ignore[type-arg] - def __init___(self) -> None: - super().__init__(sys.stderr) - - @property # type: ignore [override] - def stream(self) -> IO[str]: - return sys.stderr - - @stream.setter - def stream(self, value: IO[str]) -> None: - assert value is sys.stderr - - -def make_default_handler() -> logging.Handler: - try: - from rich.console import Console - - console = Console(stderr=True) - from rich.logging import RichHandler - - return RichHandler(console=console) - except ImportError: - handler = AlwaysStdErrHandler() - handler.setFormatter(logging.Formatter("%(levelname)s %(name)s %(message)s")) - return handler - - -_default_handler = make_default_handler() - -log.addHandler(_default_handler) - - -def _default_log_level(_env: Mapping[str, str] = os.environ) -> int: - val: str | None = _env.get("SETUPTOOLS_SCM_DEBUG") - return logging.WARN if val is None else logging.DEBUG - - -log.setLevel(_default_log_level()) - - -@contextlib.contextmanager -def defer_to_pytest() -> Iterator[None]: - log.propagate = True - old_level = log.level - log.setLevel(logging.NOTSET) - log.removeHandler(_default_handler) - try: - yield - finally: - log.addHandler(_default_handler) - log.propagate = False - log.setLevel(old_level) - - -@contextlib.contextmanager -def enable_debug(handler: logging.Handler = _default_handler) -> Iterator[None]: - log.addHandler(handler) - old_level = log.level - log.setLevel(logging.DEBUG) - old_handler_level = handler.level - handler.setLevel(logging.DEBUG) - try: - yield - finally: - log.setLevel(old_level) - handler.setLevel(old_handler_level) - if handler is not _default_handler: - log.removeHandler(handler) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py deleted file mode 100644 index aae41a632fc..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_modify_version.py +++ /dev/null @@ -1,61 +0,0 @@ -from __future__ import annotations - -import re - -from . import _types as _t - - -def strip_local(version_string: str) -> str: - public = version_string.partition("+")[0] - return public - - -def _add_post(version: str) -> str: - if "post" in version: - raise ValueError( - f"{version} already is a post release, refusing to guess the update" - ) - return f"{version}.post1" - - -def _bump_dev(version: str) -> str | None: - if ".dev" not in version: - return None - - prefix, tail = version.rsplit(".dev", 1) - if tail != "0": - raise ValueError( - "choosing custom numbers for the `.devX` distance " - "is not supported.\n " - f"The {version} can't be bumped\n" - "Please drop the tag or create a new supported one ending in .dev0" - ) - return prefix - - -def _bump_regex(version: str) -> str: - match = re.match(r"(.*?)(\d+)$", version) - if match is None: - raise ValueError( - f"{version} does not end with a number to bump, " - "please correct or use a custom version scheme" - ) - else: - prefix, tail = match.groups() - return f"{prefix}{int(tail) + 1}" - - -def _format_local_with_time(version: _t.SCMVERSION, time_format: str) -> str: - if version.exact or version.node is None: - return version.format_choice( - "", "+d{time:{time_format}}", time_format=time_format - ) - else: - return version.format_choice( - "+{node}", "+{node}.d{time:{time_format}}", time_format=time_format - ) - - -def _dont_guess_next_version(tag_version: _t.SCMVERSION) -> str: - version = strip_local(str(tag_version.tag)) - return _bump_dev(version) or _add_post(version) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py deleted file mode 100644 index ee9269a719f..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_overrides.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import annotations - -import os -import re - -from typing import Any - -from . import _config -from . import _log -from . import version -from ._integration.toml import load_toml_or_inline_map - -log = _log.log.getChild("overrides") - -PRETEND_KEY = "SETUPTOOLS_SCM_PRETEND_VERSION" -PRETEND_KEY_NAMED = PRETEND_KEY + "_FOR_{name}" - - -def read_named_env( - *, tool: str = "SETUPTOOLS_SCM", name: str, dist_name: str | None -) -> str | None: - """ """ - if dist_name is not None: - # Normalize the dist name as per PEP 503. - normalized_dist_name = re.sub(r"[-_.]+", "-", dist_name) - env_var_dist_name = normalized_dist_name.replace("-", "_").upper() - val = os.environ.get(f"{tool}_{name}_FOR_{env_var_dist_name}") - if val is not None: - return val - return os.environ.get(f"{tool}_{name}") - - -def _read_pretended_version_for( - config: _config.Configuration, -) -> version.ScmVersion | None: - """read a a overridden version from the environment - - tries ``SETUPTOOLS_SCM_PRETEND_VERSION`` - and ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_$UPPERCASE_DIST_NAME`` - """ - log.debug("dist name: %s", config.dist_name) - - pretended = read_named_env(name="PRETEND_VERSION", dist_name=config.dist_name) - - if pretended: - # we use meta here since the pretended version - # must adhere to the pep to begin with - return version.meta(tag=pretended, preformatted=True, config=config) - else: - return None - - -def read_toml_overrides(dist_name: str | None) -> dict[str, Any]: - data = read_named_env(name="OVERRIDES", dist_name=dist_name) - return load_toml_or_inline_map(data) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py deleted file mode 100644 index f2a82852c31..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_run_cmd.py +++ /dev/null @@ -1,214 +0,0 @@ -from __future__ import annotations - -import os -import shlex -import subprocess -import textwrap -import warnings - -from typing import TYPE_CHECKING -from typing import Callable -from typing import Final -from typing import Mapping -from typing import Sequence -from typing import TypeVar -from typing import overload - -from . import _log -from . import _types as _t - -if TYPE_CHECKING: - BaseCompletedProcess = subprocess.CompletedProcess[str] -else: - BaseCompletedProcess = subprocess.CompletedProcess - -# pick 40 seconds -# unfortunately github CI for windows sometimes needs -# up to 30 seconds to start a command - - -def _get_timeout(env: Mapping[str, str]) -> int: - return int(env.get("SETUPTOOLS_SCM_SUBPROCESS_TIMEOUT") or 40) - - -BROKEN_TIMEOUT: Final[int] = _get_timeout(os.environ) - -log = _log.log.getChild("run_cmd") - -PARSE_RESULT = TypeVar("PARSE_RESULT") -T = TypeVar("T") - - -class CompletedProcess(BaseCompletedProcess): - @classmethod - def from_raw( - cls, input: BaseCompletedProcess, strip: bool = True - ) -> CompletedProcess: - return cls( - args=input.args, - returncode=input.returncode, - stdout=input.stdout.strip() if strip and input.stdout else input.stdout, - stderr=input.stderr.strip() if strip and input.stderr else input.stderr, - ) - - @overload - def parse_success( - self, - parse: Callable[[str], PARSE_RESULT], - default: None = None, - error_msg: str | None = None, - ) -> PARSE_RESULT | None: ... - - @overload - def parse_success( - self, - parse: Callable[[str], PARSE_RESULT], - default: T, - error_msg: str | None = None, - ) -> PARSE_RESULT | T: ... - - def parse_success( - self, - parse: Callable[[str], PARSE_RESULT], - default: T | None = None, - error_msg: str | None = None, - ) -> PARSE_RESULT | T | None: - if self.returncode: - if error_msg: - log.warning("%s %s", error_msg, self) - return default - else: - return parse(self.stdout) - - -def no_git_env(env: Mapping[str, str]) -> dict[str, str]: - # adapted from pre-commit - # Too many bugs dealing with environment variables and GIT: - # https://github.com/pre-commit/pre-commit/issues/300 - # In git 2.6.3 (maybe others), git exports GIT_WORK_TREE while running - # pre-commit hooks - # In git 1.9.1 (maybe others), git exports GIT_DIR and GIT_INDEX_FILE - # while running pre-commit hooks in submodules. - # GIT_DIR: Causes git clone to clone wrong thing - # GIT_INDEX_FILE: Causes 'error invalid object ...' during commit - for k, v in env.items(): - if k.startswith("GIT_"): - log.debug("%s: %s", k, v) - return { - k: v - for k, v in env.items() - if not k.startswith("GIT_") - or k in ("GIT_EXEC_PATH", "GIT_SSH", "GIT_SSH_COMMAND") - } - - -def avoid_pip_isolation(env: Mapping[str, str]) -> dict[str, str]: - """ - pip build isolation can break Mercurial - (see https://github.com/pypa/pip/issues/10635) - - pip uses PYTHONNOUSERSITE and a path in PYTHONPATH containing "pip-build-env-". - """ - new_env = {k: v for k, v in env.items() if k != "PYTHONNOUSERSITE"} - if "PYTHONPATH" not in new_env: - return new_env - - new_env["PYTHONPATH"] = os.pathsep.join( - [ - path - for path in new_env["PYTHONPATH"].split(os.pathsep) - if "pip-build-env-" not in path - ] - ) - return new_env - - -def ensure_stripped_str(str_or_bytes: str | bytes) -> str: - if isinstance(str_or_bytes, str): - return str_or_bytes.strip() - else: - return str_or_bytes.decode("utf-8", "surrogateescape").strip() - - -def run( - cmd: _t.CMD_TYPE, - cwd: _t.PathT, - *, - strip: bool = True, - trace: bool = True, - timeout: int | None = None, - check: bool = False, -) -> CompletedProcess: - if isinstance(cmd, str): - cmd = shlex.split(cmd) - else: - cmd = [os.fspath(x) for x in cmd] - cmd_4_trace = " ".join(map(_unsafe_quote_for_display, cmd)) - log.debug("at %s\n $ %s ", cwd, cmd_4_trace) - if timeout is None: - timeout = BROKEN_TIMEOUT - res = subprocess.run( - cmd, - capture_output=True, - cwd=os.fspath(cwd), - env=dict( - avoid_pip_isolation(no_git_env(os.environ)), - # os.environ, - # try to disable i18n, but still allow UTF-8 encoded text. - LC_ALL="C.UTF-8", - LANGUAGE="", - HGPLAIN="1", - ), - text=True, - encoding="utf-8", - timeout=timeout, - ) - - res = CompletedProcess.from_raw(res, strip=strip) - if trace: - if res.stdout: - log.debug("out:\n%s", textwrap.indent(res.stdout, " ")) - if res.stderr: - log.debug("err:\n%s", textwrap.indent(res.stderr, " ")) - if res.returncode: - log.debug("ret: %s", res.returncode) - if check: - res.check_returncode() - return res - - -def _unsafe_quote_for_display(item: _t.PathT) -> str: - # give better results than shlex.join in our cases - text = os.fspath(item) - return text if all(c not in text for c in " {[:") else f'"{text}"' - - -def has_command( - name: str, args: Sequence[str] = ["version"], warn: bool = True -) -> bool: - try: - p = run([name, *args], cwd=".") - if p.returncode != 0: - log.error(f"Command '{name}' returned non-zero. This is stderr:") - log.error(p.stderr) - except OSError as e: - log.warning("command %s missing: %s", name, e) - res = False - except subprocess.TimeoutExpired as e: - log.warning("command %s timed out %s", name, e) - res = False - - else: - res = not p.returncode - if not res and warn: - warnings.warn("%r was not found" % name, category=RuntimeWarning) - return res - - -class CommandNotFoundError(LookupError, FileNotFoundError): - pass - - -def require_command(name: str) -> None: - if not has_command(name, warn=False): - raise CommandNotFoundError(name) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py deleted file mode 100644 index b655c76f290..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_types.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import annotations - -import os - -from typing import TYPE_CHECKING -from typing import Callable -from typing import List -from typing import Sequence -from typing import Tuple -from typing import Union - -if TYPE_CHECKING: - import sys - - if sys.version_info >= (3, 10): - from typing import TypeAlias - else: - from typing_extensions import TypeAlias - - from . import version - -PathT: TypeAlias = Union["os.PathLike[str]", str] - -CMD_TYPE: TypeAlias = Union[Sequence[PathT], str] - -VERSION_SCHEME: TypeAlias = Union[str, Callable[["version.ScmVersion"], str]] -VERSION_SCHEMES: TypeAlias = Union[List[str], Tuple[str, ...], VERSION_SCHEME] -SCMVERSION: TypeAlias = "version.ScmVersion" diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py deleted file mode 100644 index bb89bbb1250..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/_version_cls.py +++ /dev/null @@ -1,91 +0,0 @@ -from __future__ import annotations - -from typing import Type -from typing import Union -from typing import cast - -try: - from packaging.version import InvalidVersion - from packaging.version import Version as Version -except ImportError: - from setuptools.extern.packaging.version import InvalidVersion # type: ignore - from setuptools.extern.packaging.version import Version as Version # type: ignore -from . import _log - -log = _log.log.getChild("version_cls") - - -class NonNormalizedVersion(Version): - """A non-normalizing version handler. - - You can use this class to preserve version verification but skip normalization. - For example you can use this to avoid git release candidate version tags - ("1.0.0-rc1") to be normalized to "1.0.0rc1". Only use this if you fully - trust the version tags. - """ - - def __init__(self, version: str) -> None: - # parse and validate using parent - super().__init__(version) - - # store raw for str - self._raw_version = version - - def __str__(self) -> str: - # return the non-normalized version (parent returns the normalized) - return self._raw_version - - def __repr__(self) -> str: - # same pattern as parent - return f"" - - -def _version_as_tuple(version_str: str) -> tuple[int | str, ...]: - try: - parsed_version = Version(version_str) - except InvalidVersion as e: - log.error("failed to parse version %s: %s", e, version_str) - return (version_str,) - else: - version_fields: tuple[int | str, ...] = parsed_version.release - if parsed_version.dev is not None: - version_fields += (f"dev{parsed_version.dev}",) - if parsed_version.local is not None: - version_fields += (parsed_version.local,) - return version_fields - - -_VersionT = Union[Version, NonNormalizedVersion] - - -def import_name(name: str) -> object: - import importlib - - pkg_name, cls_name = name.rsplit(".", 1) - pkg = importlib.import_module(pkg_name) - return getattr(pkg, cls_name) - - -def _validate_version_cls( - version_cls: type[_VersionT] | str | None, normalize: bool -) -> type[_VersionT]: - if not normalize: - if version_cls is not None: - raise ValueError( - "Providing a custom `version_cls` is not permitted when " - "`normalize=False`" - ) - return NonNormalizedVersion - else: - # Use `version_cls` if provided, default to packaging or pkg_resources - if version_cls is None: - return Version - elif isinstance(version_cls, str): - try: - return cast(Type[_VersionT], import_name(version_cls)) - except: # noqa - raise ValueError( - f"Unable to import version_cls='{version_cls}'" - ) from None - else: - return version_cls diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py deleted file mode 100644 index 7c1be381f4b..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/discover.py +++ /dev/null @@ -1,70 +0,0 @@ -from __future__ import annotations - -import os - -from pathlib import Path -from typing import Iterable -from typing import Iterator - -from . import _entrypoints -from . import _log -from . import _types as _t -from ._config import Configuration - -log = _log.log.getChild("discover") - - -def walk_potential_roots(root: _t.PathT, search_parents: bool = True) -> Iterator[Path]: - """ - Iterate though a path and each of its parents. - :param root: File path. - :param search_parents: If ``False`` the parents are not considered. - """ - root = Path(root) - yield root - if search_parents: - yield from root.parents - - -def match_entrypoint(root: _t.PathT, name: str) -> bool: - """ - Consider a ``root`` as entry-point. - :param root: File path. - :param name: Subdirectory name. - :return: ``True`` if a subdirectory ``name`` exits in ``root``. - """ - - if os.path.exists(os.path.join(root, name)): - if not os.path.isabs(name): - return True - log.debug("ignoring bad ep %s", name) - - return False - - -# blocked entrypints from legacy plugins -_BLOCKED_EP_TARGETS = {"setuptools_scm_git_archive:parse"} - - -def iter_matching_entrypoints( - root: _t.PathT, entrypoint: str, config: Configuration -) -> Iterable[_entrypoints.EntryPoint]: - """ - Consider different entry-points in ``root`` and optionally its parents. - :param root: File path. - :param entrypoint: Entry-point to consider. - :param config: Configuration, - read ``search_parent_directories``, write found parent to ``parent``. - """ - - log.debug("looking for ep %s in %s", entrypoint, root) - from ._entrypoints import iter_entry_points - - for wd in walk_potential_roots(root, config.search_parent_directories): - for ep in iter_entry_points(entrypoint): - if ep.value in _BLOCKED_EP_TARGETS: - continue - if match_entrypoint(wd, ep.name): - log.debug("found ep %s in %s", ep, wd) - config.parent = wd - yield ep diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py deleted file mode 100644 index 45a75351c9a..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/fallbacks.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import annotations - -import logging -import os - -from pathlib import Path -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from . import _types as _t -from . import Configuration -from .integration import data_from_mime -from .version import ScmVersion -from .version import meta -from .version import tag_to_version - -log = logging.getLogger(__name__) - -_UNKNOWN = "UNKNOWN" - - -def parse_pkginfo(root: _t.PathT, config: Configuration) -> ScmVersion | None: - pkginfo = Path(root) / "PKG-INFO" - log.debug("pkginfo %s", pkginfo) - data = data_from_mime(pkginfo) - version = data.get("Version", _UNKNOWN) - if version != _UNKNOWN: - return meta(version, preformatted=True, config=config) - else: - return None - - -def fallback_version(root: _t.PathT, config: Configuration) -> ScmVersion | None: - if config.parentdir_prefix_version is not None: - _, parent_name = os.path.split(os.path.abspath(root)) - if parent_name.startswith(config.parentdir_prefix_version): - version = tag_to_version( - parent_name[len(config.parentdir_prefix_version) :], config - ) - if version is not None: - return meta(str(version), preformatted=True, config=config) - if config.fallback_version is not None: - log.debug("FALLBACK %s", config.fallback_version) - return meta(config.fallback_version, preformatted=True, config=config) - return None diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py deleted file mode 100644 index eb1d519ab1d..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/git.py +++ /dev/null @@ -1,340 +0,0 @@ -from __future__ import annotations - -import dataclasses -import logging -import os -import re -import shlex -import sys -import warnings - -from datetime import date -from datetime import datetime -from datetime import timezone -from os.path import samefile -from pathlib import Path -from typing import TYPE_CHECKING -from typing import Callable -from typing import Sequence - -from . import Configuration -from . import _types as _t -from . import discover -from ._run_cmd import CompletedProcess as _CompletedProcess -from ._run_cmd import require_command as _require_command -from ._run_cmd import run as _run -from .integration import data_from_mime -from .scm_workdir import Workdir -from .version import ScmVersion -from .version import meta -from .version import tag_to_version - -if TYPE_CHECKING: - from . import hg_git -log = logging.getLogger(__name__) - -REF_TAG_RE = re.compile(r"(?<=\btag: )([^,]+)\b") -DESCRIBE_UNSUPPORTED = "%(describe" - -# If testing command in shell make sure to quote the match argument like -# '*[0-9]*' as it will expand before being sent to git if there are any matching -# files in current directory. -DEFAULT_DESCRIBE = [ - "git", - "describe", - "--dirty", - "--tags", - "--long", - "--match", - "*[0-9]*", -] - - -def run_git( - args: Sequence[str | os.PathLike[str]], - repo: Path, - *, - check: bool = False, - timeout: int | None = None, -) -> _CompletedProcess: - return _run( - ["git", "--git-dir", repo / ".git", *args], - cwd=repo, - check=check, - timeout=timeout, - ) - - -class GitWorkdir(Workdir): - """experimental, may change at any time""" - - @classmethod - def from_potential_worktree(cls, wd: _t.PathT) -> GitWorkdir | None: - wd = Path(wd).resolve() - real_wd = run_git(["rev-parse", "--show-prefix"], wd).parse_success(parse=str) - if real_wd is None: - return None - else: - real_wd = real_wd[:-1] # remove the trailing pathsep - - if not real_wd: - real_wd = os.fspath(wd) - else: - str_wd = os.fspath(wd) - assert str_wd.replace("\\", "/").endswith(real_wd) - # In windows wd contains ``\`` which should be replaced by ``/`` - # for this assertion to work. Length of string isn't changed by replace - # ``\\`` is just and escape for `\` - real_wd = str_wd[: -len(real_wd)] - log.debug("real root %s", real_wd) - if not samefile(real_wd, wd): - return None - - return cls(Path(real_wd)) - - def is_dirty(self) -> bool: - return run_git( - ["status", "--porcelain", "--untracked-files=no"], self.path - ).parse_success( - parse=bool, - default=False, - ) - - def get_branch(self) -> str | None: - return run_git( - ["rev-parse", "--abbrev-ref", "HEAD"], - self.path, - ).parse_success( - parse=str, - error_msg="branch err (abbrev-err)", - ) or run_git( - ["symbolic-ref", "--short", "HEAD"], - self.path, - ).parse_success( - parse=str, - error_msg="branch err (symbolic-ref)", - ) - - def get_head_date(self) -> date | None: - def parse_timestamp(timestamp_text: str) -> date | None: - if "%c" in timestamp_text: - log.warning("git too old -> timestamp is %r", timestamp_text) - return None - if sys.version_info < (3, 11) and timestamp_text.endswith("Z"): - timestamp_text = timestamp_text[:-1] + "+00:00" - return datetime.fromisoformat(timestamp_text).date() - - res = run_git( - [ - *("-c", "log.showSignature=false"), - *("log", "-n", "1", "HEAD"), - "--format=%cI", - ], - self.path, - ) - return res.parse_success( - parse=parse_timestamp, - error_msg="logging the iso date for head failed", - ) - - def is_shallow(self) -> bool: - return self.path.joinpath(".git/shallow").is_file() - - def fetch_shallow(self) -> None: - run_git(["fetch", "--unshallow"], self.path, check=True, timeout=240) - - def node(self) -> str | None: - def _unsafe_short_node(node: str) -> str: - return node[:7] - - return run_git( - ["rev-parse", "--verify", "--quiet", "HEAD"], self.path - ).parse_success( - parse=_unsafe_short_node, - ) - - def count_all_nodes(self) -> int: - res = run_git(["rev-list", "HEAD"], self.path) - return res.stdout.count("\n") + 1 - - def default_describe(self) -> _CompletedProcess: - return run_git(DEFAULT_DESCRIBE[1:], self.path) - - -def warn_on_shallow(wd: GitWorkdir) -> None: - """experimental, may change at any time""" - if wd.is_shallow(): - warnings.warn(f'"{wd.path}" is shallow and may cause errors') - - -def fetch_on_shallow(wd: GitWorkdir) -> None: - """experimental, may change at any time""" - if wd.is_shallow(): - warnings.warn(f'"{wd.path}" was shallow, git fetch was used to rectify') - wd.fetch_shallow() - - -def fail_on_shallow(wd: GitWorkdir) -> None: - """experimental, may change at any time""" - if wd.is_shallow(): - raise ValueError( - f'{wd.path} is shallow, please correct with "git fetch --unshallow"' - ) - - -def get_working_directory(config: Configuration, root: _t.PathT) -> GitWorkdir | None: - """ - Return the working directory (``GitWorkdir``). - """ - - if config.parent: # todo broken - return GitWorkdir.from_potential_worktree(config.parent) - - for potential_root in discover.walk_potential_roots( - root, search_parents=config.search_parent_directories - ): - potential_wd = GitWorkdir.from_potential_worktree(potential_root) - if potential_wd is not None: - return potential_wd - - return GitWorkdir.from_potential_worktree(root) - - -def parse( - root: _t.PathT, - config: Configuration, - describe_command: str | list[str] | None = None, - pre_parse: Callable[[GitWorkdir], None] = warn_on_shallow, -) -> ScmVersion | None: - """ - :param pre_parse: experimental pre_parse action, may change at any time - """ - _require_command("git") - wd = get_working_directory(config, root) - if wd: - return _git_parse_inner( - config, wd, describe_command=describe_command, pre_parse=pre_parse - ) - else: - return None - - -def version_from_describe( - wd: GitWorkdir | hg_git.GitWorkdirHgClient, - config: Configuration, - describe_command: _t.CMD_TYPE | None, -) -> ScmVersion | None: - pass - - if config.git_describe_command is not None: - describe_command = config.git_describe_command - - if describe_command is not None: - if isinstance(describe_command, str): - describe_command = shlex.split(describe_command) - # todo: figure how to ensure git with gitdir gets correctly invoked - if describe_command[0] == "git": - describe_res = run_git(describe_command[1:], wd.path) - else: - describe_res = _run(describe_command, wd.path) - else: - describe_res = wd.default_describe() - - def parse_describe(output: str) -> ScmVersion: - tag, distance, node, dirty = _git_parse_describe(output) - return meta(tag=tag, distance=distance, dirty=dirty, node=node, config=config) - - return describe_res.parse_success(parse=parse_describe) - - -def _git_parse_inner( - config: Configuration, - wd: GitWorkdir | hg_git.GitWorkdirHgClient, - pre_parse: None | (Callable[[GitWorkdir | hg_git.GitWorkdirHgClient], None]) = None, - describe_command: _t.CMD_TYPE | None = None, -) -> ScmVersion: - if pre_parse: - pre_parse(wd) - - version = version_from_describe(wd, config, describe_command) - - if version is None: - # If 'git git_describe_command' failed, try to get the information otherwise. - tag = config.version_cls("0.0") - node = wd.node() - if node is None: - distance = 0 - dirty = True - else: - distance = wd.count_all_nodes() - node = "g" + node - dirty = wd.is_dirty() - version = meta( - tag=tag, distance=distance, dirty=dirty, node=node, config=config - ) - branch = wd.get_branch() - node_date = wd.get_head_date() or datetime.now(timezone.utc).date() - return dataclasses.replace(version, branch=branch, node_date=node_date) - - -def _git_parse_describe( - describe_output: str, -) -> tuple[str, int, str | None, bool]: - # 'describe_output' looks e.g. like 'v1.5.0-0-g4060507' or - # 'v1.15.1rc1-37-g9bd1298-dirty'. - # It may also just be a bare tag name if this is a tagged commit and we are - # parsing a .git_archival.txt file. - - if describe_output.endswith("-dirty"): - dirty = True - describe_output = describe_output[:-6] - else: - dirty = False - - split = describe_output.rsplit("-", 2) - if len(split) < 3: # probably a tagged commit - tag = describe_output - number = 0 - node = None - else: - tag, number_, node = split - number = int(number_) - return tag, number, node, dirty - - -def archival_to_version( - data: dict[str, str], config: Configuration -) -> ScmVersion | None: - node: str | None - log.debug("data %s", data) - archival_describe = data.get("describe-name", DESCRIBE_UNSUPPORTED) - if DESCRIBE_UNSUPPORTED in archival_describe: - warnings.warn("git archive did not support describe output") - else: - tag, number, node, _ = _git_parse_describe(archival_describe) - return meta( - tag, - config=config, - distance=number, - node=node, - ) - - for ref in REF_TAG_RE.findall(data.get("ref-names", "")): - version = tag_to_version(ref, config) - if version is not None: - return meta(version, config=config) - else: - node = data.get("node") - if node is None: - return None - elif "$FORMAT" in node.upper(): - warnings.warn("unprocessed git archival found (no export subst applied)") - return None - else: - return meta("0.0", node=node, config=config) - - -def parse_archival(root: _t.PathT, config: Configuration) -> ScmVersion | None: - archival = os.path.join(root, ".git_archival.txt") - data = data_from_mime(archival) - return archival_to_version(data, config=config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py deleted file mode 100644 index dbffb0aeaaa..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg.py +++ /dev/null @@ -1,192 +0,0 @@ -from __future__ import annotations - -import datetime -import logging -import os - -from pathlib import Path -from typing import TYPE_CHECKING - -from . import Configuration -from ._version_cls import Version -from .integration import data_from_mime -from .scm_workdir import Workdir -from .version import ScmVersion -from .version import meta -from .version import tag_to_version - -if TYPE_CHECKING: - from . import _types as _t - -from ._run_cmd import require_command as _require_command -from ._run_cmd import run as _run - -log = logging.getLogger(__name__) - - -class HgWorkdir(Workdir): - @classmethod - def from_potential_worktree(cls, wd: _t.PathT) -> HgWorkdir | None: - res = _run(["hg", "root"], wd) - if res.returncode: - return None - return cls(Path(res.stdout)) - - def get_meta(self, config: Configuration) -> ScmVersion | None: - node: str - tags_str: str - node_date_str: str - node, tags_str, node_date_str = self.hg_log( - ".", "{node}\n{tag}\n{date|shortdate}" - ).split("\n") - - # TODO: support bookmarks and topics (but nowadays bookmarks are - # mainly used to emulate Git branches, which is already supported with - # the dedicated class GitWorkdirHgClient) - - branch, dirty_str, dirty_date = _run( - ["hg", "id", "-T", "{branch}\n{if(dirty, 1, 0)}\n{date|shortdate}"], - cwd=self.path, - check=True, - ).stdout.split("\n") - dirty = bool(int(dirty_str)) - node_date = datetime.date.fromisoformat(dirty_date if dirty else node_date_str) - - if node == "0" * len(node): - log.debug("initial node %s", self.path) - return meta( - Version("0.0"), - config=config, - dirty=dirty, - branch=branch, - node_date=node_date, - ) - - node = "h" + node[:7] - - tags = tags_str.split() - if "tip" in tags: - # tip is not a real tag - tags.remove("tip") - - if tags: - tag = tag_to_version(tags[0], config) - if tag: - return meta(tag, dirty=dirty, branch=branch, config=config) - - try: - tag_str = self.get_latest_normalizable_tag() - if tag_str is None: - dist = self.get_distance_revs("") - else: - dist = self.get_distance_revs(tag_str) - - if tag_str == "null" or tag_str is None: - tag = Version("0.0") - dist += 1 - else: - tag = tag_to_version(tag_str, config=config) - assert tag is not None - - if self.check_changes_since_tag(tag_str) or dirty: - return meta( - tag, - distance=dist, - node=node, - dirty=dirty, - branch=branch, - config=config, - node_date=node_date, - ) - else: - return meta(tag, config=config, node_date=node_date) - - except ValueError as e: - log.exception("error %s", e) - pass # unpacking failed, old hg - - return None - - def hg_log(self, revset: str, template: str) -> str: - cmd = ["hg", "log", "-r", revset, "-T", template] - - return _run(cmd, cwd=self.path, check=True).stdout - - def get_latest_normalizable_tag(self) -> str | None: - # Gets all tags containing a '.' (see #229) from oldest to newest - outlines = self.hg_log( - revset="ancestors(.) and tag('re:\\.')", - template="{tags}{if(tags, '\n', '')}", - ).split() - if not outlines: - return None - tag = outlines[-1].split()[-1] - return tag - - def get_distance_revs(self, rev1: str, rev2: str = ".") -> int: - revset = f"({rev1}::{rev2})" - out = self.hg_log(revset, ".") - return len(out) - 1 - - def check_changes_since_tag(self, tag: str | None) -> bool: - if tag == "0.0" or tag is None: - return True - - revset = ( - "(branch(.)" # look for revisions in this branch only - f" and tag({tag!r})::." # after the last tag - # ignore commits that only modify .hgtags and nothing else: - " and (merge() or file('re:^(?!\\.hgtags).*$'))" - f" and not tag({tag!r}))" # ignore the tagged commit itself - ) - - return bool(self.hg_log(revset, ".")) - - -def parse(root: _t.PathT, config: Configuration) -> ScmVersion | None: - _require_command("hg") - if os.path.exists(os.path.join(root, ".hg/git")): - res = _run(["hg", "path"], root) - if not res.returncode: - for line in res.stdout.split("\n"): - if line.startswith("default ="): - path = Path(line.split()[2]) - if path.name.endswith(".git") or (path / ".git").exists(): - from .git import _git_parse_inner - from .hg_git import GitWorkdirHgClient - - wd_hggit = GitWorkdirHgClient.from_potential_worktree(root) - if wd_hggit: - return _git_parse_inner(config, wd_hggit) - - wd = HgWorkdir.from_potential_worktree(config.absolute_root) - - if wd is None: - return None - - return wd.get_meta(config) - - -def archival_to_version(data: dict[str, str], config: Configuration) -> ScmVersion: - log.debug("data %s", data) - node = data.get("node", "")[:12] - if node: - node = "h" + node - if "tag" in data: - return meta(data["tag"], config=config) - elif "latesttag" in data: - return meta( - data["latesttag"], - distance=int(data["latesttagdistance"]), - node=node, - branch=data.get("branch"), - config=config, - ) - else: - return meta(config.version_cls("0.0"), node=node, config=config) - - -def parse_archival(root: _t.PathT, config: Configuration) -> ScmVersion: - archival = os.path.join(root, ".hg_archival.txt") - data = data_from_mime(archival) - return archival_to_version(data, config=config) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py deleted file mode 100644 index 9cab6f4528d..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/hg_git.py +++ /dev/null @@ -1,156 +0,0 @@ -from __future__ import annotations - -import logging -import os - -from contextlib import suppress -from datetime import date -from pathlib import Path - -from . import _types as _t -from ._run_cmd import CompletedProcess as _CompletedProcess -from ._run_cmd import require_command -from ._run_cmd import run as _run -from .git import GitWorkdir -from .hg import HgWorkdir - -log = logging.getLogger(__name__) - -_FAKE_GIT_DESCRIBE_ERROR = _CompletedProcess( - "fake git describe output for hg", - 1, - "<>hg git failed to describe", -) - - -class GitWorkdirHgClient(GitWorkdir, HgWorkdir): - COMMAND = "hg" - - @classmethod - def from_potential_worktree(cls, wd: _t.PathT) -> GitWorkdirHgClient | None: - require_command("hg") - res = _run(["hg", "root"], cwd=wd).parse_success(parse=Path) - if res is None: - return None - return cls(res) - - def is_dirty(self) -> bool: - res = _run(["hg", "id", "-T", "{dirty}"], cwd=self.path, check=True) - return bool(res.stdout) - - def get_branch(self) -> str | None: - res = _run(["hg", "id", "-T", "{bookmarks}"], cwd=self.path) - if res.returncode: - log.info("branch err %s", res) - return None - return res.stdout - - def get_head_date(self) -> date | None: - return _run('hg log -r . -T "{shortdate(date)}"', cwd=self.path).parse_success( - parse=date.fromisoformat, error_msg="head date err" - ) - - def is_shallow(self) -> bool: - return False - - def fetch_shallow(self) -> None: - pass - - def get_hg_node(self) -> str | None: - res = _run('hg log -r . -T "{node}"', cwd=self.path) - if res.returncode: - return None - else: - return res.stdout - - def _hg2git(self, hg_node: str) -> str | None: - with suppress(FileNotFoundError): - with open(os.path.join(self.path, ".hg/git-mapfile")) as map_items: - for item in map_items: - if hg_node in item: - git_node, hg_node = item.split() - return git_node - return None - - def node(self) -> str | None: - hg_node = self.get_hg_node() - if hg_node is None: - return None - - git_node = self._hg2git(hg_node) - - if git_node is None: - # trying again after hg -> git - _run(["hg", "gexport"], cwd=self.path) - git_node = self._hg2git(hg_node) - - if git_node is None: - log.debug("Cannot get git node so we use hg node %s", hg_node) - - if hg_node == "0" * len(hg_node): - # mimic Git behavior - return None - - return hg_node - - return git_node[:7] - - def count_all_nodes(self) -> int: - res = _run(["hg", "log", "-r", "ancestors(.)", "-T", "."], cwd=self.path) - return len(res.stdout) - - def default_describe(self) -> _CompletedProcess: - """ - Tentative to reproduce the output of - - `git describe --dirty --tags --long --match *[0-9]*` - - """ - res = _run( - [ - "hg", - "log", - "-r", - "(reverse(ancestors(.)) and tag(r're:v?[0-9].*'))", - "-T", - "{tags}{if(tags, ' ', '')}", - ], - cwd=self.path, - ) - if res.returncode: - return _FAKE_GIT_DESCRIBE_ERROR - hg_tags: list[str] = res.stdout.split() - - if not hg_tags: - return _FAKE_GIT_DESCRIBE_ERROR - - with self.path.joinpath(".hg/git-tags").open() as fp: - git_tags: dict[str, str] = dict(line.split()[::-1] for line in fp) - - tag: str - for hg_tag in hg_tags: - if hg_tag in git_tags: - tag = hg_tag - break - else: - logging.warning("tag not found hg=%s git=%s", hg_tags, git_tags) - return _FAKE_GIT_DESCRIBE_ERROR - - res = _run(["hg", "log", "-r", f"'{tag}'::.", "-T", "."], cwd=self.path) - if res.returncode: - return _FAKE_GIT_DESCRIBE_ERROR - distance = len(res.stdout) - 1 - - node = self.node() - assert node is not None - desc = f"{tag}-{distance}-g{node}" - - if self.is_dirty(): - desc += "-dirty" - log.debug("faked describe %r", desc) - return _CompletedProcess( - ["setuptools-scm", "faked", "describe"], - returncode=0, - stdout=desc, - stderr="", - ) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py deleted file mode 100644 index 48874e3847e..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/integration.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import annotations - -import logging -import textwrap - -from pathlib import Path - -from . import _types as _t - -log = logging.getLogger(__name__) - - -def data_from_mime(path: _t.PathT, content: None | str = None) -> dict[str, str]: - """return a mapping from mime/pseudo-mime content - :param path: path to the mime file - :param content: content of the mime file, if None, read from path - :rtype: dict[str, str] - - """ - - if content is None: - content = Path(path).read_text(encoding="utf-8") - log.debug("mime %s content:\n%s", path, textwrap.indent(content, " ")) - - from email.parser import HeaderParser - - parser = HeaderParser() - message = parser.parsestr(content) - data = dict(message.items()) - log.debug("mime %s data:\n%s", path, data) - return data diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py deleted file mode 100644 index 9879549d6d0..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/scm_workdir.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import annotations - -from dataclasses import dataclass -from pathlib import Path - -from ._config import Configuration -from .version import ScmVersion - - -@dataclass() -class Workdir: - path: Path - - def run_describe(self, config: Configuration) -> ScmVersion: - raise NotImplementedError(self.run_describe) diff --git a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py b/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py deleted file mode 100644 index 0a367423392..00000000000 --- a/panda/python/core/.eggs/setuptools_scm-8.1.0-py3.12.egg/setuptools_scm/version.py +++ /dev/null @@ -1,454 +0,0 @@ -from __future__ import annotations - -import dataclasses -import logging -import os -import re -import warnings - -from datetime import date -from datetime import datetime -from datetime import timezone -from typing import TYPE_CHECKING -from typing import Any -from typing import Callable -from typing import Match - -from . import _entrypoints -from . import _modify_version - -if TYPE_CHECKING: - import sys - - if sys.version_info >= (3, 10): - from typing import Concatenate - from typing import ParamSpec - else: - from typing_extensions import Concatenate - from typing_extensions import ParamSpec - - _P = ParamSpec("_P") - -from typing import TypedDict - -from . import _config -from . import _version_cls as _v -from ._version_cls import Version as PkgVersion -from ._version_cls import _VersionT - -log = logging.getLogger(__name__) - - -SEMVER_MINOR = 2 -SEMVER_PATCH = 3 -SEMVER_LEN = 3 - - -class _TagDict(TypedDict): - version: str - prefix: str - suffix: str - - -def _parse_version_tag( - tag: str | object, config: _config.Configuration -) -> _TagDict | None: - match = config.tag_regex.match(str(tag)) - - if match: - key: str | int = 1 if len(match.groups()) == 1 else "version" - full = match.group(0) - log.debug("%r %r %s", tag, config.tag_regex, match) - log.debug( - "key %s data %s, %s, %r", key, match.groupdict(), match.groups(), full - ) - result = _TagDict( - version=match.group(key), - prefix=full[: match.start(key)], - suffix=full[match.end(key) :], - ) - - log.debug("tag %r parsed to %r", tag, result) - assert result["version"] - return result - else: - log.debug("tag %r did not parse", tag) - - return None - - -def callable_or_entrypoint(group: str, callable_or_name: str | Any) -> Any: - log.debug("ep %r %r", group, callable_or_name) - - if callable(callable_or_name): - return callable_or_name - from ._entrypoints import iter_entry_points - - for ep in iter_entry_points(group, callable_or_name): - log.debug("ep found: %s", ep.name) - return ep.load() - - -def tag_to_version( - tag: _VersionT | str, config: _config.Configuration -) -> _VersionT | None: - """ - take a tag that might be prefixed with a keyword and return only the version part - """ - log.debug("tag %s", tag) - - tag_dict = _parse_version_tag(tag, config) - if tag_dict is None or not tag_dict.get("version", None): - warnings.warn(f"tag {tag!r} no version found") - return None - - version_str = tag_dict["version"] - log.debug("version pre parse %s", version_str) - - if suffix := tag_dict.get("suffix", ""): - warnings.warn(f"tag {tag!r} will be stripped of its suffix {suffix!r}") - - version: _VersionT = config.version_cls(version_str) - log.debug("version=%r", version) - - return version - - -def _source_epoch_or_utc_now() -> datetime: - if "SOURCE_DATE_EPOCH" in os.environ: - date_epoch = int(os.environ["SOURCE_DATE_EPOCH"]) - return datetime.fromtimestamp(date_epoch, timezone.utc) - else: - return datetime.now(timezone.utc) - - -@dataclasses.dataclass -class ScmVersion: - """represents a parsed version from scm""" - - tag: _v.Version | _v.NonNormalizedVersion | str - """the related tag or preformatted version string""" - config: _config.Configuration - """the configuration used to parse the version""" - distance: int = 0 - """the number of commits since the tag""" - node: str | None = None - """the shortened node id""" - dirty: bool = False - """whether the working copy had uncommitted changes""" - preformatted: bool = False - """whether the version string was preformatted""" - branch: str | None = None - """the branch name if any""" - node_date: date | None = None - """the date of the commit if available""" - time: datetime = dataclasses.field(default_factory=_source_epoch_or_utc_now) - """the current time or source epoch time - only set for unit-testing version schemes - for real usage it must be `now(utc)` or `SOURCE_EPOCH` - """ - - @property - def exact(self) -> bool: - """returns true checked out exactly on a tag and no local changes apply""" - return self.distance == 0 and not self.dirty - - def __repr__(self) -> str: - return ( - f"" - ) - - def format_with(self, fmt: str, **kw: object) -> str: - """format a given format string with attributes of this object""" - return fmt.format( - time=self.time, - tag=self.tag, - distance=self.distance, - node=self.node, - dirty=self.dirty, - branch=self.branch, - node_date=self.node_date, - **kw, - ) - - def format_choice(self, clean_format: str, dirty_format: str, **kw: object) -> str: - """given `clean_format` and `dirty_format` - - choose one based on `self.dirty` and format it using `self.format_with`""" - - return self.format_with(dirty_format if self.dirty else clean_format, **kw) - - def format_next_version( - self, - guess_next: Callable[Concatenate[ScmVersion, _P], str], - fmt: str = "{guessed}.dev{distance}", - *k: _P.args, - **kw: _P.kwargs, - ) -> str: - guessed = guess_next(self, *k, **kw) - return self.format_with(fmt, guessed=guessed) - - -def _parse_tag( - tag: _VersionT | str, preformatted: bool, config: _config.Configuration -) -> _VersionT | str: - if preformatted: - return tag - elif not isinstance(tag, config.version_cls): - version = tag_to_version(tag, config) - assert version is not None - return version - else: - return tag - - -def meta( - tag: str | _VersionT, - *, - distance: int = 0, - dirty: bool = False, - node: str | None = None, - preformatted: bool = False, - branch: str | None = None, - config: _config.Configuration, - node_date: date | None = None, -) -> ScmVersion: - parsed_version = _parse_tag(tag, preformatted, config) - log.info("version %s -> %s", tag, parsed_version) - assert parsed_version is not None, "Can't parse version %s" % tag - return ScmVersion( - parsed_version, - distance=distance, - node=node, - dirty=dirty, - preformatted=preformatted, - branch=branch, - config=config, - node_date=node_date, - ) - - -def guess_next_version(tag_version: ScmVersion) -> str: - version = _modify_version.strip_local(str(tag_version.tag)) - return _modify_version._bump_dev(version) or _modify_version._bump_regex(version) - - -def guess_next_dev_version(version: ScmVersion) -> str: - if version.exact: - return version.format_with("{tag}") - else: - return version.format_next_version(guess_next_version) - - -def guess_next_simple_semver( - version: ScmVersion, retain: int, increment: bool = True -) -> str: - if isinstance(version.tag, _v.Version): - parts = list(version.tag.release[:retain]) - else: - try: - parts = [int(i) for i in str(version.tag).split(".")[:retain]] - except ValueError: - raise ValueError(f"{version} can't be parsed as numeric version") from None - while len(parts) < retain: - parts.append(0) - if increment: - parts[-1] += 1 - while len(parts) < SEMVER_LEN: - parts.append(0) - return ".".join(str(i) for i in parts) - - -def simplified_semver_version(version: ScmVersion) -> str: - if version.exact: - return guess_next_simple_semver(version, retain=SEMVER_LEN, increment=False) - else: - if version.branch is not None and "feature" in version.branch: - return version.format_next_version( - guess_next_simple_semver, retain=SEMVER_MINOR - ) - else: - return version.format_next_version( - guess_next_simple_semver, retain=SEMVER_PATCH - ) - - -def release_branch_semver_version(version: ScmVersion) -> str: - if version.exact: - return version.format_with("{tag}") - if version.branch is not None: - # Does the branch name (stripped of namespace) parse as a version? - branch_ver_data = _parse_version_tag( - version.branch.split("/")[-1], version.config - ) - if branch_ver_data is not None: - branch_ver = branch_ver_data["version"] - if branch_ver[0] == "v": - # Allow branches that start with 'v', similar to Version. - branch_ver = branch_ver[1:] - # Does the branch version up to the minor part match the tag? If not it - # might be like, an issue number or something and not a version number, so - # we only want to use it if it matches. - tag_ver_up_to_minor = str(version.tag).split(".")[:SEMVER_MINOR] - branch_ver_up_to_minor = branch_ver.split(".")[:SEMVER_MINOR] - if branch_ver_up_to_minor == tag_ver_up_to_minor: - # We're in a release/maintenance branch, next is a patch/rc/beta bump: - return version.format_next_version(guess_next_version) - # We're in a development branch, next is a minor bump: - return version.format_next_version(guess_next_simple_semver, retain=SEMVER_MINOR) - - -def release_branch_semver(version: ScmVersion) -> str: - warnings.warn( - "release_branch_semver is deprecated and will be removed in the future. " - "Use release_branch_semver_version instead", - category=DeprecationWarning, - stacklevel=2, - ) - return release_branch_semver_version(version) - - -def only_version(version: ScmVersion) -> str: - return version.format_with("{tag}") - - -def no_guess_dev_version(version: ScmVersion) -> str: - if version.exact: - return version.format_with("{tag}") - else: - return version.format_next_version(_modify_version._dont_guess_next_version) - - -_DATE_REGEX = re.compile( - r""" - ^(?P - (?P[vV]?) - (?P\d{2}|\d{4})(?:\.\d{1,2}){2}) - (?:\.(?P\d*))?$ - """, - re.VERBOSE, -) - - -def date_ver_match(ver: str) -> Match[str] | None: - return _DATE_REGEX.match(ver) - - -def guess_next_date_ver( - version: ScmVersion, - node_date: date | None = None, - date_fmt: str | None = None, - version_cls: type | None = None, -) -> str: - """ - same-day -> patch +1 - other-day -> today - - distance is always added as .devX - """ - match = date_ver_match(str(version.tag)) - if match is None: - warnings.warn( - f"{version} does not correspond to a valid versioning date, " - "assuming legacy version" - ) - if date_fmt is None: - date_fmt = "%y.%m.%d" - else: - # deduct date format if not provided - if date_fmt is None: - date_fmt = "%Y.%m.%d" if len(match.group("year")) == 4 else "%y.%m.%d" - if prefix := match.group("prefix"): - if not date_fmt.startswith(prefix): - date_fmt = prefix + date_fmt - - today = version.time.date() - head_date = node_date or today - # compute patch - if match is None: - tag_date = today - else: - tag_date = ( - datetime.strptime(match.group("date"), date_fmt) - .replace(tzinfo=timezone.utc) - .date() - ) - if tag_date == head_date: - patch = "0" if match is None else (match.group("patch") or "0") - patch = int(patch) + 1 - else: - if tag_date > head_date and match is not None: - # warn on future times - warnings.warn( - f"your previous tag ({tag_date})" - f" is ahead your node date ({head_date})" - ) - patch = 0 - next_version = "{node_date:{date_fmt}}.{patch}".format( - node_date=head_date, date_fmt=date_fmt, patch=patch - ) - # rely on the Version object to ensure consistency (e.g. remove leading 0s) - if version_cls is None: - version_cls = PkgVersion - next_version = str(version_cls(next_version)) - return next_version - - -def calver_by_date(version: ScmVersion) -> str: - if version.exact and not version.dirty: - return version.format_with("{tag}") - # TODO: move the release-X check to a new scheme - if version.branch is not None and version.branch.startswith("release-"): - branch_ver = _parse_version_tag(version.branch.split("-")[-1], version.config) - if branch_ver is not None: - ver = branch_ver["version"] - match = date_ver_match(ver) - if match: - return ver - return version.format_next_version( - guess_next_date_ver, - node_date=version.node_date, - version_cls=version.config.version_cls, - ) - - -def get_local_node_and_date(version: ScmVersion) -> str: - return _modify_version._format_local_with_time(version, time_format="%Y%m%d") - - -def get_local_node_and_timestamp(version: ScmVersion) -> str: - return _modify_version._format_local_with_time(version, time_format="%Y%m%d%H%M%S") - - -def get_local_dirty_tag(version: ScmVersion) -> str: - return version.format_choice("", "+dirty") - - -def get_no_local_node(version: ScmVersion) -> str: - return "" - - -def postrelease_version(version: ScmVersion) -> str: - if version.exact: - return version.format_with("{tag}") - else: - return version.format_with("{tag}.post{distance}") - - -def format_version(version: ScmVersion) -> str: - log.debug("scm version %s", version) - log.debug("config %s", version.config) - if version.preformatted: - assert isinstance(version.tag, str) - return version.tag - main_version = _entrypoints._call_version_scheme( - version, "setuptools_scm.version_scheme", version.config.version_scheme, None - ) - log.debug("version %s", main_version) - assert main_version is not None - local_version = _entrypoints._call_version_scheme( - version, "setuptools_scm.local_scheme", version.config.local_scheme, "+unknown" - ) - log.debug("local_version %s", local_version) - return main_version + local_version