From c1e9d0d81950d61cadf130192144f511e08382b2 Mon Sep 17 00:00:00 2001 From: Jacob Woliver Date: Fri, 24 Jan 2025 17:27:28 -0500 Subject: [PATCH] chore: update to match twine 6.1.0 output --- .snapshots/TestParse-appdirs_signed_tarball | 16 ++---------- .snapshots/TestParse-appdirs_signed_wheel | 14 +---------- .snapshots/TestParse-appdirs_unsigned_tarball | 16 ++---------- .snapshots/TestParse-appdirs_unsigned_wheel | 14 +---------- .../TestParse-cachetools_signed_tarball | 22 ++-------------- .snapshots/TestParse-cachetools_signed_wheel | 20 +-------------- .../TestParse-cachetools_unsigned_tarball | 22 ++-------------- .../TestParse-cachetools_unsigned_wheel | 20 +-------------- .snapshots/TestParse-chardet_signed_tarball | 15 +++-------- .snapshots/TestParse-chardet_signed_wheel | 13 ++-------- .snapshots/TestParse-chardet_unsigned_tarball | 15 +++-------- .snapshots/TestParse-chardet_unsigned_wheel | 13 ++-------- .snapshots/TestParse-click_signed_tarball | 19 ++------------ .snapshots/TestParse-click_signed_wheel | 17 +------------ .snapshots/TestParse-click_unsigned_tarball | 19 ++------------ .snapshots/TestParse-click_unsigned_wheel | 17 +------------ .../TestParse-configparser_signed_tarball | 16 ++---------- .../TestParse-configparser_signed_wheel | 14 +---------- .../TestParse-configparser_unsigned_tarball | 16 ++---------- .../TestParse-configparser_unsigned_wheel | 14 +---------- .../TestParse-coveragepy_signed_tarball | 16 ++---------- .snapshots/TestParse-coveragepy_signed_wheel | 14 +---------- .../TestParse-coveragepy_unsigned_tarball | 16 ++---------- .../TestParse-coveragepy_unsigned_wheel | 14 +---------- .snapshots/TestParse-decorator_signed_tarball | 19 ++------------ .snapshots/TestParse-decorator_signed_wheel | 17 +------------ .../TestParse-decorator_unsigned_tarball | 19 ++------------ .snapshots/TestParse-decorator_unsigned_wheel | 17 +------------ .../TestParse-defusedxml_signed_tarball | 10 ++------ .snapshots/TestParse-defusedxml_signed_wheel | 8 +----- .../TestParse-defusedxml_unsigned_tarball | 10 ++------ .../TestParse-defusedxml_unsigned_wheel | 8 +----- ...estParse-importlib_metadata_signed_tarball | 25 ++----------------- .../TestParse-importlib_metadata_signed_wheel | 23 +---------------- ...tParse-importlib_metadata_unsigned_tarball | 25 ++----------------- ...estParse-importlib_metadata_unsigned_wheel | 23 +---------------- .../TestParse-matplotlib_signed_tarball | 16 ++---------- .snapshots/TestParse-matplotlib_signed_wheel | 14 +---------- .../TestParse-matplotlib_unsigned_tarball | 16 ++---------- .../TestParse-matplotlib_unsigned_wheel | 14 +---------- .snapshots/TestParse-pytest_signed_tarball | 21 +++------------- .snapshots/TestParse-pytest_signed_wheel | 19 ++------------ .snapshots/TestParse-pytest_unsigned_tarball | 21 +++------------- .snapshots/TestParse-pytest_unsigned_wheel | 19 ++------------ .../TestParse-python-certifi_signed_tarball | 25 ++----------------- .../TestParse-python-certifi_signed_wheel | 23 +---------------- .../TestParse-python-certifi_unsigned_tarball | 25 ++----------------- .../TestParse-python-certifi_unsigned_wheel | 23 +---------------- internal/distributions/distribution.go | 5 ++++ internal/distributions/metadata.go | 2 +- types/types.go | 17 ------------- 51 files changed, 86 insertions(+), 770 deletions(-) diff --git a/.snapshots/TestParse-appdirs_signed_tarball b/.snapshots/TestParse-appdirs_signed_tarball index 3a226b1..49caf68 100644 --- a/.snapshots/TestParse-appdirs_signed_tarball +++ b/.snapshots/TestParse-appdirs_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=59) "Programming Language :: Python :: Implementation :: CPython", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=7788) "\n.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png\n :target: http://travis-ci.org/ActiveState/appdirs\n\nthe problem\n===========\n\nWhat directory should your app use for storing user data? If running on Mac OS X, you\nshould use::\n\n ~/Library/Application Support/\n\nIf on Windows (at least English Win XP) that should be::\n\n C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\\n\nor possibly::\n\n C:\\Documents and Settings\\\\Application Data\\\\\n\nfor `roaming profiles `_ but that is another story.\n\nOn Linux (and other Unices) the dir, according to the `XDG\nspec `_, is::\n\n ~/.local/share/\n\n\n``appdirs`` to the rescue\n=========================\n\nThis kind of thing is what the ``appdirs`` module is for. ``appdirs`` will\nhelp you choose an appropriate:\n\n- user data dir (``user_data_dir``)\n- user config dir (``user_config_dir``)\n- user cache dir (``user_cache_dir``)\n- site data dir (``site_data_dir``)\n- site config dir (``site_config_dir``)\n- user log dir (``user_log_dir``)\n\nand also:\n\n- is a single module so other Python packages can include their own private copy\n- is slightly opinionated on the directory names used. Look for \"OPINION\" in\n documentation and code for when an opinion is being applied.\n\n\nsome example output\n===================\n\nOn Mac OS X::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> site_data_dir(appname, appauthor)\n '/Library/Application Support/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/Users/trentm/Library/Caches/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/Users/trentm/Library/Logs/SuperApp'\n\nOn Windows 7::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp'\n >>> user_data_dir(appname, appauthor, roaming=True)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Roaming\\\\Acme\\\\SuperApp'\n >>> user_cache_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Cache'\n >>> user_log_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Logs'\n\nOn Linux::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/home/trentm/.local/share/SuperApp\n >>> site_data_dir(appname, appauthor)\n '/usr/local/share/SuperApp'\n >>> site_data_dir(appname, appauthor, multipath=True)\n '/usr/local/share/SuperApp:/usr/share/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp/log'\n >>> user_config_dir(appname)\n '/home/trentm/.config/SuperApp'\n >>> site_config_dir(appname)\n '/etc/xdg/SuperApp'\n >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc'\n >>> site_config_dir(appname, multipath=True)\n '/etc/SuperApp:/usr/local/etc/SuperApp'\n\n\n``AppDirs`` for convenience\n===========================\n\n::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp'\n\n\n \nPer-version isolation\n=====================\n\nIf you have multiple versions of your app in use that you want to be\nable to run side-by-side, then you may want version-isolation for these\ndirs::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp/1.0'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp/1.0'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp/1.0'\n\n\n\nappdirs Changelog\n=================\n\nappdirs 1.4.4\n-------------\n- [PR #92] Don't import appdirs from setup.py\n\nProject officially classified as Stable which is important\nfor inclusion in other distros such as ActivePython.\n\nFirst of several incremental releases to catch up on maintenance.\n\nappdirs 1.4.3\n-------------\n- [PR #76] Python 3.6 invalid escape sequence deprecation fixes\n- Fix for Python 3.6 support\n\nappdirs 1.4.2\n-------------\n- [PR #84] Allow installing without setuptools\n- [PR #86] Fix string delimiters in setup.py description\n- Add Python 3.6 support\n\nappdirs 1.4.1\n-------------\n- [issue #38] Fix _winreg import on Windows Py3\n- [issue #55] Make appname optional\n\nappdirs 1.4.0\n-------------\n- [PR #42] AppAuthor is now optional on Windows\n- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows\n support requires `JNA `_.\n- [PR #44] Fix incorrect behaviour of the site_config_dir method\n\nappdirs 1.3.0\n-------------\n- [Unix, issue 16] Conform to XDG standard, instead of breaking it for\n everybody\n- [Unix] Removes gratuitous case mangling of the case, since \\*nix-es are\n usually case sensitive, so mangling is not wise\n- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result\n based on XDG_DATA_DIRS and make room for respecting the standard which\n specifies XDG_DATA_DIRS is a multiple-value variable\n- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to\n XDG specs; on Windows and Mac return the corresponding ``*_data_dir``\n\nappdirs 1.2.0\n-------------\n\n- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more\n typical.\n- [issue 9] Make ``unicode`` work on py3k.\n\nappdirs 1.1.0\n-------------\n\n- [issue 4] Add ``AppDirs.user_log_dir``.\n- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec\n `_.\n- [Mac, issue 5] Fix ``site_data_dir()`` on Mac.\n- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports\n Python3 now.\n- [Windows] Append \"Cache\" to ``user_cache_dir`` on Windows by default. Use\n ``opinion=False`` option to disable this.\n- Add ``appdirs.AppDirs`` convenience class. Usage:\n\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n\n- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short\n paths if there are high bit chars.\n- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g.\n \"~/.superapp/cache\".\n- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only)\n and change the default ``user_data_dir`` behaviour to use a *non*-roaming\n profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because\n a large roaming profile can cause login speed issues. The \"only syncs on\n logout\" behaviour can cause surprises in appdata info.\n\n\nappdirs 1.0.1 (never released)\n------------------------------\n\nStarted this changelog 27 July 2010. Before that this module originated in the\n`Komodo `_ product as ``applib.py`` and then\nas `applib/location.py\n`_ (used by\n`PyPM `_ in `ActivePython\n`_). This is basically a fork of\napplib.py 1.0.1 and applib/location.py 1.0.1.\n\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -84,10 +75,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" - }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" diff --git a/.snapshots/TestParse-appdirs_signed_wheel b/.snapshots/TestParse-appdirs_signed_wheel index f01b7f9..178be42 100644 --- a/.snapshots/TestParse-appdirs_signed_wheel +++ b/.snapshots/TestParse-appdirs_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=59) "Programming Language :: Python :: Implementation :: CPython", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=7788) "\n.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png\n :target: http://travis-ci.org/ActiveState/appdirs\n\nthe problem\n===========\n\nWhat directory should your app use for storing user data? If running on Mac OS X, you\nshould use::\n\n ~/Library/Application Support/\n\nIf on Windows (at least English Win XP) that should be::\n\n C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\\n\nor possibly::\n\n C:\\Documents and Settings\\\\Application Data\\\\\n\nfor `roaming profiles `_ but that is another story.\n\nOn Linux (and other Unices) the dir, according to the `XDG\nspec `_, is::\n\n ~/.local/share/\n\n\n``appdirs`` to the rescue\n=========================\n\nThis kind of thing is what the ``appdirs`` module is for. ``appdirs`` will\nhelp you choose an appropriate:\n\n- user data dir (``user_data_dir``)\n- user config dir (``user_config_dir``)\n- user cache dir (``user_cache_dir``)\n- site data dir (``site_data_dir``)\n- site config dir (``site_config_dir``)\n- user log dir (``user_log_dir``)\n\nand also:\n\n- is a single module so other Python packages can include their own private copy\n- is slightly opinionated on the directory names used. Look for \"OPINION\" in\n documentation and code for when an opinion is being applied.\n\n\nsome example output\n===================\n\nOn Mac OS X::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> site_data_dir(appname, appauthor)\n '/Library/Application Support/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/Users/trentm/Library/Caches/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/Users/trentm/Library/Logs/SuperApp'\n\nOn Windows 7::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp'\n >>> user_data_dir(appname, appauthor, roaming=True)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Roaming\\\\Acme\\\\SuperApp'\n >>> user_cache_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Cache'\n >>> user_log_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Logs'\n\nOn Linux::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/home/trentm/.local/share/SuperApp\n >>> site_data_dir(appname, appauthor)\n '/usr/local/share/SuperApp'\n >>> site_data_dir(appname, appauthor, multipath=True)\n '/usr/local/share/SuperApp:/usr/share/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp/log'\n >>> user_config_dir(appname)\n '/home/trentm/.config/SuperApp'\n >>> site_config_dir(appname)\n '/etc/xdg/SuperApp'\n >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc'\n >>> site_config_dir(appname, multipath=True)\n '/etc/SuperApp:/usr/local/etc/SuperApp'\n\n\n``AppDirs`` for convenience\n===========================\n\n::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp'\n\n\n \nPer-version isolation\n=====================\n\nIf you have multiple versions of your app in use that you want to be\nable to run side-by-side, then you may want version-isolation for these\ndirs::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp/1.0'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp/1.0'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp/1.0'\n\n\n\nappdirs Changelog\n=================\n\nappdirs 1.4.4\n-------------\n- [PR #92] Don't import appdirs from setup.py\n\nProject officially classified as Stable which is important\nfor inclusion in other distros such as ActivePython.\n\nFirst of several incremental releases to catch up on maintenance.\n\nappdirs 1.4.3\n-------------\n- [PR #76] Python 3.6 invalid escape sequence deprecation fixes\n- Fix for Python 3.6 support\n\nappdirs 1.4.2\n-------------\n- [PR #84] Allow installing without setuptools\n- [PR #86] Fix string delimiters in setup.py description\n- Add Python 3.6 support\n\nappdirs 1.4.1\n-------------\n- [issue #38] Fix _winreg import on Windows Py3\n- [issue #55] Make appname optional\n\nappdirs 1.4.0\n-------------\n- [PR #42] AppAuthor is now optional on Windows\n- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows\n support requires `JNA `_.\n- [PR #44] Fix incorrect behaviour of the site_config_dir method\n\nappdirs 1.3.0\n-------------\n- [Unix, issue 16] Conform to XDG standard, instead of breaking it for\n everybody\n- [Unix] Removes gratuitous case mangling of the case, since \\*nix-es are\n usually case sensitive, so mangling is not wise\n- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result\n based on XDG_DATA_DIRS and make room for respecting the standard which\n specifies XDG_DATA_DIRS is a multiple-value variable\n- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to\n XDG specs; on Windows and Mac return the corresponding ``*_data_dir``\n\nappdirs 1.2.0\n-------------\n\n- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more\n typical.\n- [issue 9] Make ``unicode`` work on py3k.\n\nappdirs 1.1.0\n-------------\n\n- [issue 4] Add ``AppDirs.user_log_dir``.\n- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec\n `_.\n- [Mac, issue 5] Fix ``site_data_dir()`` on Mac.\n- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports\n Python3 now.\n- [Windows] Append \"Cache\" to ``user_cache_dir`` on Windows by default. Use\n ``opinion=False`` option to disable this.\n- Add ``appdirs.AppDirs`` convenience class. Usage:\n\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n\n- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short\n paths if there are high bit chars.\n- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g.\n \"~/.superapp/cache\".\n- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only)\n and change the default ``user_data_dir`` behaviour to use a *non*-roaming\n profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because\n a large roaming profile can cause login speed issues. The \"only syncs on\n logout\" behaviour can cause surprises in appdata info.\n\n\nappdirs 1.0.1 (never released)\n------------------------------\n\nStarted this changelog 27 July 2010. Before that this module originated in the\n`Komodo `_ product as ``applib.py`` and then\nas `applib/location.py\n`_ (used by\n`PyPM `_ in `ActivePython\n`_). This is basically a fork of\napplib.py 1.0.1 and applib/location.py 1.0.1.\n\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -86,9 +77,6 @@ (string) (len=9) "pyversion": ([]string) (len=1) { (string) (len=7) "py2.py3" }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" - }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" }, diff --git a/.snapshots/TestParse-appdirs_unsigned_tarball b/.snapshots/TestParse-appdirs_unsigned_tarball index 116ec86..f46c310 100644 --- a/.snapshots/TestParse-appdirs_unsigned_tarball +++ b/.snapshots/TestParse-appdirs_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=59) "Programming Language :: Python :: Implementation :: CPython", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=7788) "\n.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png\n :target: http://travis-ci.org/ActiveState/appdirs\n\nthe problem\n===========\n\nWhat directory should your app use for storing user data? If running on Mac OS X, you\nshould use::\n\n ~/Library/Application Support/\n\nIf on Windows (at least English Win XP) that should be::\n\n C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\\n\nor possibly::\n\n C:\\Documents and Settings\\\\Application Data\\\\\n\nfor `roaming profiles `_ but that is another story.\n\nOn Linux (and other Unices) the dir, according to the `XDG\nspec `_, is::\n\n ~/.local/share/\n\n\n``appdirs`` to the rescue\n=========================\n\nThis kind of thing is what the ``appdirs`` module is for. ``appdirs`` will\nhelp you choose an appropriate:\n\n- user data dir (``user_data_dir``)\n- user config dir (``user_config_dir``)\n- user cache dir (``user_cache_dir``)\n- site data dir (``site_data_dir``)\n- site config dir (``site_config_dir``)\n- user log dir (``user_log_dir``)\n\nand also:\n\n- is a single module so other Python packages can include their own private copy\n- is slightly opinionated on the directory names used. Look for \"OPINION\" in\n documentation and code for when an opinion is being applied.\n\n\nsome example output\n===================\n\nOn Mac OS X::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> site_data_dir(appname, appauthor)\n '/Library/Application Support/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/Users/trentm/Library/Caches/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/Users/trentm/Library/Logs/SuperApp'\n\nOn Windows 7::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp'\n >>> user_data_dir(appname, appauthor, roaming=True)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Roaming\\\\Acme\\\\SuperApp'\n >>> user_cache_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Cache'\n >>> user_log_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Logs'\n\nOn Linux::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/home/trentm/.local/share/SuperApp\n >>> site_data_dir(appname, appauthor)\n '/usr/local/share/SuperApp'\n >>> site_data_dir(appname, appauthor, multipath=True)\n '/usr/local/share/SuperApp:/usr/share/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp/log'\n >>> user_config_dir(appname)\n '/home/trentm/.config/SuperApp'\n >>> site_config_dir(appname)\n '/etc/xdg/SuperApp'\n >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc'\n >>> site_config_dir(appname, multipath=True)\n '/etc/SuperApp:/usr/local/etc/SuperApp'\n\n\n``AppDirs`` for convenience\n===========================\n\n::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp'\n\n\n \nPer-version isolation\n=====================\n\nIf you have multiple versions of your app in use that you want to be\nable to run side-by-side, then you may want version-isolation for these\ndirs::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp/1.0'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp/1.0'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp/1.0'\n\n\n\nappdirs Changelog\n=================\n\nappdirs 1.4.4\n-------------\n- [PR #92] Don't import appdirs from setup.py\n\nProject officially classified as Stable which is important\nfor inclusion in other distros such as ActivePython.\n\nFirst of several incremental releases to catch up on maintenance.\n\nappdirs 1.4.3\n-------------\n- [PR #76] Python 3.6 invalid escape sequence deprecation fixes\n- Fix for Python 3.6 support\n\nappdirs 1.4.2\n-------------\n- [PR #84] Allow installing without setuptools\n- [PR #86] Fix string delimiters in setup.py description\n- Add Python 3.6 support\n\nappdirs 1.4.1\n-------------\n- [issue #38] Fix _winreg import on Windows Py3\n- [issue #55] Make appname optional\n\nappdirs 1.4.0\n-------------\n- [PR #42] AppAuthor is now optional on Windows\n- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows\n support requires `JNA `_.\n- [PR #44] Fix incorrect behaviour of the site_config_dir method\n\nappdirs 1.3.0\n-------------\n- [Unix, issue 16] Conform to XDG standard, instead of breaking it for\n everybody\n- [Unix] Removes gratuitous case mangling of the case, since \\*nix-es are\n usually case sensitive, so mangling is not wise\n- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result\n based on XDG_DATA_DIRS and make room for respecting the standard which\n specifies XDG_DATA_DIRS is a multiple-value variable\n- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to\n XDG specs; on Windows and Mac return the corresponding ``*_data_dir``\n\nappdirs 1.2.0\n-------------\n\n- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more\n typical.\n- [issue 9] Make ``unicode`` work on py3k.\n\nappdirs 1.1.0\n-------------\n\n- [issue 4] Add ``AppDirs.user_log_dir``.\n- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec\n `_.\n- [Mac, issue 5] Fix ``site_data_dir()`` on Mac.\n- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports\n Python3 now.\n- [Windows] Append \"Cache\" to ``user_cache_dir`` on Windows by default. Use\n ``opinion=False`` option to disable this.\n- Add ``appdirs.AppDirs`` convenience class. Usage:\n\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n\n- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short\n paths if there are high bit chars.\n- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g.\n \"~/.superapp/cache\".\n- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only)\n and change the default ``user_data_dir`` behaviour to use a *non*-roaming\n profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because\n a large roaming profile can cause login speed issues. The \"only syncs on\n logout\" behaviour can cause surprises in appdata info.\n\n\nappdirs 1.0.1 (never released)\n------------------------------\n\nStarted this changelog 27 July 2010. Before that this module originated in the\n`Komodo `_ product as ``applib.py`` and then\nas `applib/location.py\n`_ (used by\n`PyPM `_ in `ActivePython\n`_). This is basically a fork of\napplib.py 1.0.1 and applib/location.py 1.0.1.\n\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -84,10 +75,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" - }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" diff --git a/.snapshots/TestParse-appdirs_unsigned_wheel b/.snapshots/TestParse-appdirs_unsigned_wheel index afec2f2..a733e86 100644 --- a/.snapshots/TestParse-appdirs_unsigned_wheel +++ b/.snapshots/TestParse-appdirs_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=59) "Programming Language :: Python :: Implementation :: CPython", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=7788) "\n.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png\n :target: http://travis-ci.org/ActiveState/appdirs\n\nthe problem\n===========\n\nWhat directory should your app use for storing user data? If running on Mac OS X, you\nshould use::\n\n ~/Library/Application Support/\n\nIf on Windows (at least English Win XP) that should be::\n\n C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\\n\nor possibly::\n\n C:\\Documents and Settings\\\\Application Data\\\\\n\nfor `roaming profiles `_ but that is another story.\n\nOn Linux (and other Unices) the dir, according to the `XDG\nspec `_, is::\n\n ~/.local/share/\n\n\n``appdirs`` to the rescue\n=========================\n\nThis kind of thing is what the ``appdirs`` module is for. ``appdirs`` will\nhelp you choose an appropriate:\n\n- user data dir (``user_data_dir``)\n- user config dir (``user_config_dir``)\n- user cache dir (``user_cache_dir``)\n- site data dir (``site_data_dir``)\n- site config dir (``site_config_dir``)\n- user log dir (``user_log_dir``)\n\nand also:\n\n- is a single module so other Python packages can include their own private copy\n- is slightly opinionated on the directory names used. Look for \"OPINION\" in\n documentation and code for when an opinion is being applied.\n\n\nsome example output\n===================\n\nOn Mac OS X::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> site_data_dir(appname, appauthor)\n '/Library/Application Support/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/Users/trentm/Library/Caches/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/Users/trentm/Library/Logs/SuperApp'\n\nOn Windows 7::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp'\n >>> user_data_dir(appname, appauthor, roaming=True)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Roaming\\\\Acme\\\\SuperApp'\n >>> user_cache_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Cache'\n >>> user_log_dir(appname, appauthor)\n 'C:\\\\Users\\\\trentm\\\\AppData\\\\Local\\\\Acme\\\\SuperApp\\\\Logs'\n\nOn Linux::\n\n >>> from appdirs import *\n >>> appname = \"SuperApp\"\n >>> appauthor = \"Acme\"\n >>> user_data_dir(appname, appauthor)\n '/home/trentm/.local/share/SuperApp\n >>> site_data_dir(appname, appauthor)\n '/usr/local/share/SuperApp'\n >>> site_data_dir(appname, appauthor, multipath=True)\n '/usr/local/share/SuperApp:/usr/share/SuperApp'\n >>> user_cache_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp'\n >>> user_log_dir(appname, appauthor)\n '/home/trentm/.cache/SuperApp/log'\n >>> user_config_dir(appname)\n '/home/trentm/.config/SuperApp'\n >>> site_config_dir(appname)\n '/etc/xdg/SuperApp'\n >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc'\n >>> site_config_dir(appname, multipath=True)\n '/etc/SuperApp:/usr/local/etc/SuperApp'\n\n\n``AppDirs`` for convenience\n===========================\n\n::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp'\n\n\n \nPer-version isolation\n=====================\n\nIf you have multiple versions of your app in use that you want to be\nable to run side-by-side, then you may want version-isolation for these\ndirs::\n\n >>> from appdirs import AppDirs\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n >>> dirs.site_data_dir\n '/Library/Application Support/SuperApp/1.0'\n >>> dirs.user_cache_dir\n '/Users/trentm/Library/Caches/SuperApp/1.0'\n >>> dirs.user_log_dir\n '/Users/trentm/Library/Logs/SuperApp/1.0'\n\n\n\nappdirs Changelog\n=================\n\nappdirs 1.4.4\n-------------\n- [PR #92] Don't import appdirs from setup.py\n\nProject officially classified as Stable which is important\nfor inclusion in other distros such as ActivePython.\n\nFirst of several incremental releases to catch up on maintenance.\n\nappdirs 1.4.3\n-------------\n- [PR #76] Python 3.6 invalid escape sequence deprecation fixes\n- Fix for Python 3.6 support\n\nappdirs 1.4.2\n-------------\n- [PR #84] Allow installing without setuptools\n- [PR #86] Fix string delimiters in setup.py description\n- Add Python 3.6 support\n\nappdirs 1.4.1\n-------------\n- [issue #38] Fix _winreg import on Windows Py3\n- [issue #55] Make appname optional\n\nappdirs 1.4.0\n-------------\n- [PR #42] AppAuthor is now optional on Windows\n- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows\n support requires `JNA `_.\n- [PR #44] Fix incorrect behaviour of the site_config_dir method\n\nappdirs 1.3.0\n-------------\n- [Unix, issue 16] Conform to XDG standard, instead of breaking it for\n everybody\n- [Unix] Removes gratuitous case mangling of the case, since \\*nix-es are\n usually case sensitive, so mangling is not wise\n- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result\n based on XDG_DATA_DIRS and make room for respecting the standard which\n specifies XDG_DATA_DIRS is a multiple-value variable\n- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to\n XDG specs; on Windows and Mac return the corresponding ``*_data_dir``\n\nappdirs 1.2.0\n-------------\n\n- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more\n typical.\n- [issue 9] Make ``unicode`` work on py3k.\n\nappdirs 1.1.0\n-------------\n\n- [issue 4] Add ``AppDirs.user_log_dir``.\n- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec\n `_.\n- [Mac, issue 5] Fix ``site_data_dir()`` on Mac.\n- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports\n Python3 now.\n- [Windows] Append \"Cache\" to ``user_cache_dir`` on Windows by default. Use\n ``opinion=False`` option to disable this.\n- Add ``appdirs.AppDirs`` convenience class. Usage:\n\n >>> dirs = AppDirs(\"SuperApp\", \"Acme\", version=\"1.0\")\n >>> dirs.user_data_dir\n '/Users/trentm/Library/Application Support/SuperApp/1.0'\n\n- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short\n paths if there are high bit chars.\n- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g.\n \"~/.superapp/cache\".\n- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only)\n and change the default ``user_data_dir`` behaviour to use a *non*-roaming\n profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because\n a large roaming profile can cause login speed issues. The \"only syncs on\n logout\" behaviour can cause surprises in appdata info.\n\n\nappdirs 1.0.1 (never released)\n------------------------------\n\nStarted this changelog 27 July 2010. Before that this module originated in the\n`Komodo `_ product as ``applib.py`` and then\nas `applib/location.py\n`_ (used by\n`PyPM `_ in `ActivePython\n`_). This is basically a fork of\napplib.py 1.0.1 and applib/location.py 1.0.1.\n\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -86,9 +77,6 @@ (string) (len=9) "pyversion": ([]string) (len=1) { (string) (len=7) "py2.py3" }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" - }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" }, diff --git a/.snapshots/TestParse-cachetools_signed_tarball b/.snapshots/TestParse-cachetools_signed_tarball index cd3c9fe..8f2a514 100644 --- a/.snapshots/TestParse-cachetools_signed_tarball +++ b/.snapshots/TestParse-cachetools_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=24) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,36 +28,18 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=4254) "cachetools\n========================================================================\n\n.. image:: https://img.shields.io/pypi/v/cachetools\n :target: https://pypi.org/project/cachetools/\n :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/github/actions/workflow/status/tkem/cachetools/ci.yml\n :target: https://github.com/tkem/cachetools/actions/workflows/ci.yml\n :alt: CI build status\n\n.. image:: https://img.shields.io/readthedocs/cachetools\n :target: https://cachetools.readthedocs.io/\n :alt: Documentation build status\n\n.. image:: https://img.shields.io/codecov/c/github/tkem/cachetools/master.svg\n :target: https://codecov.io/gh/tkem/cachetools\n :alt: Test coverage\n\n.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools\n :target: https://libraries.io/pypi/cachetools\n :alt: Libraries.io SourceRank\n\n.. image:: https://img.shields.io/github/license/tkem/cachetools\n :target: https://raw.github.com/tkem/cachetools/master/LICENSE\n :alt: License\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n\nThis module provides various memoizing collections and decorators,\nincluding variants of the Python Standard Library's `@lru_cache`_\nfunction decorator.\n\n.. code-block:: python\n\n from cachetools import cached, LRUCache, TTLCache\n\n # speed up calculating Fibonacci numbers with dynamic programming\n @cached(cache={})\n def fib(n):\n return n if n < 2 else fib(n - 1) + fib(n - 2)\n\n # cache least recently used Python Enhancement Proposals\n @cached(cache=LRUCache(maxsize=32))\n def get_pep(num):\n url = 'http://www.python.org/dev/peps/pep-%04d/' % num\n with urllib.request.urlopen(url) as s:\n return s.read()\n\n # cache weather data for no longer than ten minutes\n @cached(cache=TTLCache(maxsize=1024, ttl=600))\n def get_weather(place):\n return owm.weather_at_place(place).get_weather()\n\nFor the purpose of this module, a *cache* is a mutable_ mapping_ of a\nfixed maximum size. When the cache is full, i.e. by adding another\nitem the cache would exceed its maximum size, the cache must choose\nwhich item(s) to discard based on a suitable `cache algorithm`_.\n\nThis module provides multiple cache classes based on different cache\nalgorithms, as well as decorators for easily memoizing function and\nmethod calls.\n\n\nInstallation\n------------------------------------------------------------------------\n\ncachetools is available from PyPI_ and can be installed by running::\n\n pip install cachetools\n\nTyping stubs for this package are provided by typeshed_ and can be\ninstalled by running::\n\n pip install types-cachetools\n\n\nProject Resources\n------------------------------------------------------------------------\n\n- `Documentation`_\n- `Issue tracker`_\n- `Source code`_\n- `Change log`_\n\n\nRelated Projects\n------------------------------------------------------------------------\n\n- asyncache_: Helpers to use cachetools with async functions\n- CacheToolsUtils_: Cachetools Utilities\n- `kids.cache`_: Kids caching library\n- shelved-cache_: Persistent cache for Python cachetools\n\n\nLicense\n------------------------------------------------------------------------\n\nCopyright (c) 2014-2023 Thomas Kemmer.\n\nLicensed under the `MIT License`_.\n\n\n.. _@lru_cache: https://docs.python.org/3/library/functools.html#functools.lru_cache\n.. _mutable: https://docs.python.org/dev/glossary.html#term-mutable\n.. _mapping: https://docs.python.org/dev/glossary.html#term-mapping\n.. _cache algorithm: https://en.wikipedia.org/wiki/Cache_algorithms\n\n.. _PyPI: https://pypi.org/project/cachetools/\n.. _typeshed: https://github.com/python/typeshed/\n.. _Documentation: https://cachetools.readthedocs.io/\n.. _Issue tracker: https://github.com/tkem/cachetools/issues/\n.. _Source code: https://github.com/tkem/cachetools/\n.. _Change log: https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst\n.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE\n\n.. _asyncache: https://pypi.org/project/asyncache/\n.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/\n.. _kids.cache: https://pypi.org/project/kids.cache/\n.. _shelved-cache: https://pypi.org/project/shelved-cache/\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=35) "https://github.com/tkem/cachetools/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -71,7 +53,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=5) ">=3.7" diff --git a/.snapshots/TestParse-cachetools_signed_wheel b/.snapshots/TestParse-cachetools_signed_wheel index 0991059..e3b9b1b 100644 --- a/.snapshots/TestParse-cachetools_signed_wheel +++ b/.snapshots/TestParse-cachetools_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=24) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,36 +28,18 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=4254) "cachetools\n========================================================================\n\n.. image:: https://img.shields.io/pypi/v/cachetools\n :target: https://pypi.org/project/cachetools/\n :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/github/actions/workflow/status/tkem/cachetools/ci.yml\n :target: https://github.com/tkem/cachetools/actions/workflows/ci.yml\n :alt: CI build status\n\n.. image:: https://img.shields.io/readthedocs/cachetools\n :target: https://cachetools.readthedocs.io/\n :alt: Documentation build status\n\n.. image:: https://img.shields.io/codecov/c/github/tkem/cachetools/master.svg\n :target: https://codecov.io/gh/tkem/cachetools\n :alt: Test coverage\n\n.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools\n :target: https://libraries.io/pypi/cachetools\n :alt: Libraries.io SourceRank\n\n.. image:: https://img.shields.io/github/license/tkem/cachetools\n :target: https://raw.github.com/tkem/cachetools/master/LICENSE\n :alt: License\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n\nThis module provides various memoizing collections and decorators,\nincluding variants of the Python Standard Library's `@lru_cache`_\nfunction decorator.\n\n.. code-block:: python\n\n from cachetools import cached, LRUCache, TTLCache\n\n # speed up calculating Fibonacci numbers with dynamic programming\n @cached(cache={})\n def fib(n):\n return n if n < 2 else fib(n - 1) + fib(n - 2)\n\n # cache least recently used Python Enhancement Proposals\n @cached(cache=LRUCache(maxsize=32))\n def get_pep(num):\n url = 'http://www.python.org/dev/peps/pep-%04d/' % num\n with urllib.request.urlopen(url) as s:\n return s.read()\n\n # cache weather data for no longer than ten minutes\n @cached(cache=TTLCache(maxsize=1024, ttl=600))\n def get_weather(place):\n return owm.weather_at_place(place).get_weather()\n\nFor the purpose of this module, a *cache* is a mutable_ mapping_ of a\nfixed maximum size. When the cache is full, i.e. by adding another\nitem the cache would exceed its maximum size, the cache must choose\nwhich item(s) to discard based on a suitable `cache algorithm`_.\n\nThis module provides multiple cache classes based on different cache\nalgorithms, as well as decorators for easily memoizing function and\nmethod calls.\n\n\nInstallation\n------------------------------------------------------------------------\n\ncachetools is available from PyPI_ and can be installed by running::\n\n pip install cachetools\n\nTyping stubs for this package are provided by typeshed_ and can be\ninstalled by running::\n\n pip install types-cachetools\n\n\nProject Resources\n------------------------------------------------------------------------\n\n- `Documentation`_\n- `Issue tracker`_\n- `Source code`_\n- `Change log`_\n\n\nRelated Projects\n------------------------------------------------------------------------\n\n- asyncache_: Helpers to use cachetools with async functions\n- CacheToolsUtils_: Cachetools Utilities\n- `kids.cache`_: Kids caching library\n- shelved-cache_: Persistent cache for Python cachetools\n\n\nLicense\n------------------------------------------------------------------------\n\nCopyright (c) 2014-2023 Thomas Kemmer.\n\nLicensed under the `MIT License`_.\n\n\n.. _@lru_cache: https://docs.python.org/3/library/functools.html#functools.lru_cache\n.. _mutable: https://docs.python.org/dev/glossary.html#term-mutable\n.. _mapping: https://docs.python.org/dev/glossary.html#term-mapping\n.. _cache algorithm: https://en.wikipedia.org/wiki/Cache_algorithms\n\n.. _PyPI: https://pypi.org/project/cachetools/\n.. _typeshed: https://github.com/python/typeshed/\n.. _Documentation: https://cachetools.readthedocs.io/\n.. _Issue tracker: https://github.com/tkem/cachetools/issues/\n.. _Source code: https://github.com/tkem/cachetools/\n.. _Change log: https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst\n.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE\n\n.. _asyncache: https://pypi.org/project/asyncache/\n.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/\n.. _kids.cache: https://pypi.org/project/kids.cache/\n.. _shelved-cache: https://pypi.org/project/shelved-cache/\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=35) "https://github.com/tkem/cachetools/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-cachetools_unsigned_tarball b/.snapshots/TestParse-cachetools_unsigned_tarball index ffac1fb..a7b2e4c 100644 --- a/.snapshots/TestParse-cachetools_unsigned_tarball +++ b/.snapshots/TestParse-cachetools_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=24) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,36 +28,18 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=4254) "cachetools\n========================================================================\n\n.. image:: https://img.shields.io/pypi/v/cachetools\n :target: https://pypi.org/project/cachetools/\n :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/github/actions/workflow/status/tkem/cachetools/ci.yml\n :target: https://github.com/tkem/cachetools/actions/workflows/ci.yml\n :alt: CI build status\n\n.. image:: https://img.shields.io/readthedocs/cachetools\n :target: https://cachetools.readthedocs.io/\n :alt: Documentation build status\n\n.. image:: https://img.shields.io/codecov/c/github/tkem/cachetools/master.svg\n :target: https://codecov.io/gh/tkem/cachetools\n :alt: Test coverage\n\n.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools\n :target: https://libraries.io/pypi/cachetools\n :alt: Libraries.io SourceRank\n\n.. image:: https://img.shields.io/github/license/tkem/cachetools\n :target: https://raw.github.com/tkem/cachetools/master/LICENSE\n :alt: License\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n\nThis module provides various memoizing collections and decorators,\nincluding variants of the Python Standard Library's `@lru_cache`_\nfunction decorator.\n\n.. code-block:: python\n\n from cachetools import cached, LRUCache, TTLCache\n\n # speed up calculating Fibonacci numbers with dynamic programming\n @cached(cache={})\n def fib(n):\n return n if n < 2 else fib(n - 1) + fib(n - 2)\n\n # cache least recently used Python Enhancement Proposals\n @cached(cache=LRUCache(maxsize=32))\n def get_pep(num):\n url = 'http://www.python.org/dev/peps/pep-%04d/' % num\n with urllib.request.urlopen(url) as s:\n return s.read()\n\n # cache weather data for no longer than ten minutes\n @cached(cache=TTLCache(maxsize=1024, ttl=600))\n def get_weather(place):\n return owm.weather_at_place(place).get_weather()\n\nFor the purpose of this module, a *cache* is a mutable_ mapping_ of a\nfixed maximum size. When the cache is full, i.e. by adding another\nitem the cache would exceed its maximum size, the cache must choose\nwhich item(s) to discard based on a suitable `cache algorithm`_.\n\nThis module provides multiple cache classes based on different cache\nalgorithms, as well as decorators for easily memoizing function and\nmethod calls.\n\n\nInstallation\n------------------------------------------------------------------------\n\ncachetools is available from PyPI_ and can be installed by running::\n\n pip install cachetools\n\nTyping stubs for this package are provided by typeshed_ and can be\ninstalled by running::\n\n pip install types-cachetools\n\n\nProject Resources\n------------------------------------------------------------------------\n\n- `Documentation`_\n- `Issue tracker`_\n- `Source code`_\n- `Change log`_\n\n\nRelated Projects\n------------------------------------------------------------------------\n\n- asyncache_: Helpers to use cachetools with async functions\n- CacheToolsUtils_: Cachetools Utilities\n- `kids.cache`_: Kids caching library\n- shelved-cache_: Persistent cache for Python cachetools\n\n\nLicense\n------------------------------------------------------------------------\n\nCopyright (c) 2014-2023 Thomas Kemmer.\n\nLicensed under the `MIT License`_.\n\n\n.. _@lru_cache: https://docs.python.org/3/library/functools.html#functools.lru_cache\n.. _mutable: https://docs.python.org/dev/glossary.html#term-mutable\n.. _mapping: https://docs.python.org/dev/glossary.html#term-mapping\n.. _cache algorithm: https://en.wikipedia.org/wiki/Cache_algorithms\n\n.. _PyPI: https://pypi.org/project/cachetools/\n.. _typeshed: https://github.com/python/typeshed/\n.. _Documentation: https://cachetools.readthedocs.io/\n.. _Issue tracker: https://github.com/tkem/cachetools/issues/\n.. _Source code: https://github.com/tkem/cachetools/\n.. _Change log: https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst\n.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE\n\n.. _asyncache: https://pypi.org/project/asyncache/\n.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/\n.. _kids.cache: https://pypi.org/project/kids.cache/\n.. _shelved-cache: https://pypi.org/project/shelved-cache/\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=35) "https://github.com/tkem/cachetools/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -71,7 +53,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=5) ">=3.7" diff --git a/.snapshots/TestParse-cachetools_unsigned_wheel b/.snapshots/TestParse-cachetools_unsigned_wheel index ab644c5..0e9a377 100644 --- a/.snapshots/TestParse-cachetools_unsigned_wheel +++ b/.snapshots/TestParse-cachetools_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=24) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,36 +28,18 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=4254) "cachetools\n========================================================================\n\n.. image:: https://img.shields.io/pypi/v/cachetools\n :target: https://pypi.org/project/cachetools/\n :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/github/actions/workflow/status/tkem/cachetools/ci.yml\n :target: https://github.com/tkem/cachetools/actions/workflows/ci.yml\n :alt: CI build status\n\n.. image:: https://img.shields.io/readthedocs/cachetools\n :target: https://cachetools.readthedocs.io/\n :alt: Documentation build status\n\n.. image:: https://img.shields.io/codecov/c/github/tkem/cachetools/master.svg\n :target: https://codecov.io/gh/tkem/cachetools\n :alt: Test coverage\n\n.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools\n :target: https://libraries.io/pypi/cachetools\n :alt: Libraries.io SourceRank\n\n.. image:: https://img.shields.io/github/license/tkem/cachetools\n :target: https://raw.github.com/tkem/cachetools/master/LICENSE\n :alt: License\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n\nThis module provides various memoizing collections and decorators,\nincluding variants of the Python Standard Library's `@lru_cache`_\nfunction decorator.\n\n.. code-block:: python\n\n from cachetools import cached, LRUCache, TTLCache\n\n # speed up calculating Fibonacci numbers with dynamic programming\n @cached(cache={})\n def fib(n):\n return n if n < 2 else fib(n - 1) + fib(n - 2)\n\n # cache least recently used Python Enhancement Proposals\n @cached(cache=LRUCache(maxsize=32))\n def get_pep(num):\n url = 'http://www.python.org/dev/peps/pep-%04d/' % num\n with urllib.request.urlopen(url) as s:\n return s.read()\n\n # cache weather data for no longer than ten minutes\n @cached(cache=TTLCache(maxsize=1024, ttl=600))\n def get_weather(place):\n return owm.weather_at_place(place).get_weather()\n\nFor the purpose of this module, a *cache* is a mutable_ mapping_ of a\nfixed maximum size. When the cache is full, i.e. by adding another\nitem the cache would exceed its maximum size, the cache must choose\nwhich item(s) to discard based on a suitable `cache algorithm`_.\n\nThis module provides multiple cache classes based on different cache\nalgorithms, as well as decorators for easily memoizing function and\nmethod calls.\n\n\nInstallation\n------------------------------------------------------------------------\n\ncachetools is available from PyPI_ and can be installed by running::\n\n pip install cachetools\n\nTyping stubs for this package are provided by typeshed_ and can be\ninstalled by running::\n\n pip install types-cachetools\n\n\nProject Resources\n------------------------------------------------------------------------\n\n- `Documentation`_\n- `Issue tracker`_\n- `Source code`_\n- `Change log`_\n\n\nRelated Projects\n------------------------------------------------------------------------\n\n- asyncache_: Helpers to use cachetools with async functions\n- CacheToolsUtils_: Cachetools Utilities\n- `kids.cache`_: Kids caching library\n- shelved-cache_: Persistent cache for Python cachetools\n\n\nLicense\n------------------------------------------------------------------------\n\nCopyright (c) 2014-2023 Thomas Kemmer.\n\nLicensed under the `MIT License`_.\n\n\n.. _@lru_cache: https://docs.python.org/3/library/functools.html#functools.lru_cache\n.. _mutable: https://docs.python.org/dev/glossary.html#term-mutable\n.. _mapping: https://docs.python.org/dev/glossary.html#term-mapping\n.. _cache algorithm: https://en.wikipedia.org/wiki/Cache_algorithms\n\n.. _PyPI: https://pypi.org/project/cachetools/\n.. _typeshed: https://github.com/python/typeshed/\n.. _Documentation: https://cachetools.readthedocs.io/\n.. _Issue tracker: https://github.com/tkem/cachetools/issues/\n.. _Source code: https://github.com/tkem/cachetools/\n.. _Change log: https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst\n.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE\n\n.. _asyncache: https://pypi.org/project/asyncache/\n.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/\n.. _kids.cache: https://pypi.org/project/kids.cache/\n.. _shelved-cache: https://pypi.org/project/shelved-cache/\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=35) "https://github.com/tkem/cachetools/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-chardet_signed_tarball b/.snapshots/TestParse-chardet_signed_tarball index 273bbb9..2e052ce 100644 --- a/.snapshots/TestParse-chardet_signed_tarball +++ b/.snapshots/TestParse-chardet_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules", (string) (len=38) "Topic :: Text Processing :: Linguistic" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2011) "Chardet: The Universal Character Encoding Detector\n--------------------------------------------------\n\n.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg\n :alt: Build status\n :target: https://travis-ci.org/chardet/chardet\n\n.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg\n :target: https://coveralls.io/r/chardet/chardet\n\n.. image:: https://img.shields.io/pypi/v/chardet.svg\n :target: https://warehouse.python.org/project/chardet/\n :alt: Latest version on PyPI\n\n.. image:: https://img.shields.io/pypi/l/chardet.svg\n :alt: License\n\n\nDetects\n - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants)\n - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese)\n - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese)\n - EUC-KR, ISO-2022-KR, Johab (Korean)\n - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic)\n - ISO-8859-5, windows-1251 (Bulgarian)\n - ISO-8859-1, windows-1252, MacRoman (Western European languages)\n - ISO-8859-7, windows-1253 (Greek)\n - ISO-8859-8, windows-1255 (Visual and Logical Hebrew)\n - TIS-620 (Thai)\n\n.. note::\n Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily\n disabled until we can retrain the models.\n\nRequires Python 3.7+.\n\nInstallation\n------------\n\nInstall from `PyPI `_::\n\n pip install chardet\n\nDocumentation\n-------------\n\nFor users, docs are now available at https://chardet.readthedocs.io/.\n\nCommand-line Tool\n-----------------\n\nchardet comes with a command-line script which reports on the encodings of one\nor more files::\n\n % chardetect somefile someotherfile\n somefile: windows-1252 with confidence 0.5\n someotherfile: ascii with confidence 1.0\n\nAbout\n-----\n\nThis is a continuation of Mark Pilgrim's excellent original chardet port from C, and `Ian Cordasco `_'s\n`charade `_ Python 3-compatible fork.\n\n:maintainer: Dan Blanchard\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -48,7 +39,7 @@ (string) (len=34) "https://github.com/chardet/chardet" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=17) "encoding,i18n,xml" + (string) (len=19) "encoding, i18n, xml" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=4) "LGPL" @@ -77,7 +68,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=5) ">=3.7" diff --git a/.snapshots/TestParse-chardet_signed_wheel b/.snapshots/TestParse-chardet_signed_wheel index 3e85fd9..6c18e5e 100644 --- a/.snapshots/TestParse-chardet_signed_wheel +++ b/.snapshots/TestParse-chardet_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules", (string) (len=38) "Topic :: Text Processing :: Linguistic" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2011) "Chardet: The Universal Character Encoding Detector\n--------------------------------------------------\n\n.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg\n :alt: Build status\n :target: https://travis-ci.org/chardet/chardet\n\n.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg\n :target: https://coveralls.io/r/chardet/chardet\n\n.. image:: https://img.shields.io/pypi/v/chardet.svg\n :target: https://warehouse.python.org/project/chardet/\n :alt: Latest version on PyPI\n\n.. image:: https://img.shields.io/pypi/l/chardet.svg\n :alt: License\n\n\nDetects\n - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants)\n - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese)\n - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese)\n - EUC-KR, ISO-2022-KR, Johab (Korean)\n - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic)\n - ISO-8859-5, windows-1251 (Bulgarian)\n - ISO-8859-1, windows-1252, MacRoman (Western European languages)\n - ISO-8859-7, windows-1253 (Greek)\n - ISO-8859-8, windows-1255 (Visual and Logical Hebrew)\n - TIS-620 (Thai)\n\n.. note::\n Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily\n disabled until we can retrain the models.\n\nRequires Python 3.7+.\n\nInstallation\n------------\n\nInstall from `PyPI `_::\n\n pip install chardet\n\nDocumentation\n-------------\n\nFor users, docs are now available at https://chardet.readthedocs.io/.\n\nCommand-line Tool\n-----------------\n\nchardet comes with a command-line script which reports on the encodings of one\nor more files::\n\n % chardetect somefile someotherfile\n somefile: windows-1252 with confidence 0.5\n someotherfile: ascii with confidence 1.0\n\nAbout\n-----\n\nThis is a continuation of Mark Pilgrim's excellent original chardet port from C, and `Ian Cordasco `_'s\n`charade `_ Python 3-compatible fork.\n\n:maintainer: Dan Blanchard\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -48,7 +39,7 @@ (string) (len=34) "https://github.com/chardet/chardet" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=17) "encoding,i18n,xml" + (string) (len=19) "encoding, i18n, xml" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=4) "LGPL" diff --git a/.snapshots/TestParse-chardet_unsigned_tarball b/.snapshots/TestParse-chardet_unsigned_tarball index 2a38e58..fb10531 100644 --- a/.snapshots/TestParse-chardet_unsigned_tarball +++ b/.snapshots/TestParse-chardet_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules", (string) (len=38) "Topic :: Text Processing :: Linguistic" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2011) "Chardet: The Universal Character Encoding Detector\n--------------------------------------------------\n\n.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg\n :alt: Build status\n :target: https://travis-ci.org/chardet/chardet\n\n.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg\n :target: https://coveralls.io/r/chardet/chardet\n\n.. image:: https://img.shields.io/pypi/v/chardet.svg\n :target: https://warehouse.python.org/project/chardet/\n :alt: Latest version on PyPI\n\n.. image:: https://img.shields.io/pypi/l/chardet.svg\n :alt: License\n\n\nDetects\n - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants)\n - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese)\n - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese)\n - EUC-KR, ISO-2022-KR, Johab (Korean)\n - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic)\n - ISO-8859-5, windows-1251 (Bulgarian)\n - ISO-8859-1, windows-1252, MacRoman (Western European languages)\n - ISO-8859-7, windows-1253 (Greek)\n - ISO-8859-8, windows-1255 (Visual and Logical Hebrew)\n - TIS-620 (Thai)\n\n.. note::\n Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily\n disabled until we can retrain the models.\n\nRequires Python 3.7+.\n\nInstallation\n------------\n\nInstall from `PyPI `_::\n\n pip install chardet\n\nDocumentation\n-------------\n\nFor users, docs are now available at https://chardet.readthedocs.io/.\n\nCommand-line Tool\n-----------------\n\nchardet comes with a command-line script which reports on the encodings of one\nor more files::\n\n % chardetect somefile someotherfile\n somefile: windows-1252 with confidence 0.5\n someotherfile: ascii with confidence 1.0\n\nAbout\n-----\n\nThis is a continuation of Mark Pilgrim's excellent original chardet port from C, and `Ian Cordasco `_'s\n`charade `_ Python 3-compatible fork.\n\n:maintainer: Dan Blanchard\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -48,7 +39,7 @@ (string) (len=34) "https://github.com/chardet/chardet" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=17) "encoding,i18n,xml" + (string) (len=19) "encoding, i18n, xml" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=4) "LGPL" @@ -77,7 +68,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=5) ">=3.7" diff --git a/.snapshots/TestParse-chardet_unsigned_wheel b/.snapshots/TestParse-chardet_unsigned_wheel index 44f780d..25c5c4e 100644 --- a/.snapshots/TestParse-chardet_unsigned_wheel +++ b/.snapshots/TestParse-chardet_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -29,18 +29,9 @@ (string) (len=60) "Topic :: Software Development :: Libraries :: Python Modules", (string) (len=38) "Topic :: Text Processing :: Linguistic" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2011) "Chardet: The Universal Character Encoding Detector\n--------------------------------------------------\n\n.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg\n :alt: Build status\n :target: https://travis-ci.org/chardet/chardet\n\n.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg\n :target: https://coveralls.io/r/chardet/chardet\n\n.. image:: https://img.shields.io/pypi/v/chardet.svg\n :target: https://warehouse.python.org/project/chardet/\n :alt: Latest version on PyPI\n\n.. image:: https://img.shields.io/pypi/l/chardet.svg\n :alt: License\n\n\nDetects\n - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants)\n - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese)\n - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese)\n - EUC-KR, ISO-2022-KR, Johab (Korean)\n - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic)\n - ISO-8859-5, windows-1251 (Bulgarian)\n - ISO-8859-1, windows-1252, MacRoman (Western European languages)\n - ISO-8859-7, windows-1253 (Greek)\n - ISO-8859-8, windows-1255 (Visual and Logical Hebrew)\n - TIS-620 (Thai)\n\n.. note::\n Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily\n disabled until we can retrain the models.\n\nRequires Python 3.7+.\n\nInstallation\n------------\n\nInstall from `PyPI `_::\n\n pip install chardet\n\nDocumentation\n-------------\n\nFor users, docs are now available at https://chardet.readthedocs.io/.\n\nCommand-line Tool\n-----------------\n\nchardet comes with a command-line script which reports on the encodings of one\nor more files::\n\n % chardetect somefile someotherfile\n somefile: windows-1252 with confidence 0.5\n someotherfile: ascii with confidence 1.0\n\nAbout\n-----\n\nThis is a continuation of Mark Pilgrim's excellent original chardet port from C, and `Ian Cordasco `_'s\n`charade `_ Python 3-compatible fork.\n\n:maintainer: Dan Blanchard\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -48,7 +39,7 @@ (string) (len=34) "https://github.com/chardet/chardet" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=17) "encoding,i18n,xml" + (string) (len=19) "encoding, i18n, xml" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=4) "LGPL" diff --git a/.snapshots/TestParse-click_signed_tarball b/.snapshots/TestParse-click_signed_tarball index 6d5f33b..2b58135 100644 --- a/.snapshots/TestParse-click_signed_tarball +++ b/.snapshots/TestParse-click_signed_tarball @@ -1,14 +1,8 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, - (string) (len=6) "author": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -19,18 +13,12 @@ (string) (len=34) "Operating System :: OS Independent", (string) (len=30) "Programming Language :: Python" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=1977) "\\$ click\\_\n==========\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U click\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n import click\n\n @click.command()\n @click.option(\"--count\", default=1, help=\"Number of greetings.\")\n @click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\n def hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\n if __name__ == '__main__':\n hello()\n\n.. code-block:: text\n\n $ python hello.py --count=3\n Your name: Click\n Hello, Click!\n Hello, Click!\n Hello, Click!\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, `please\ndonate today`_.\n\n.. _please donate today: https://palletsprojects.com/donate\n\n\nLinks\n-----\n\n- Documentation: https://click.palletsprojects.com/\n- Changes: https://click.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/click/\n- Source Code: https://github.com/pallets/click\n- Issue Tracker: https://github.com/pallets/click/issues\n- Chat: https://discord.gg/pallets\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=1) { (string) (len=13) "requires-dist" }, @@ -40,9 +28,6 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=36) "https://palletsprojects.com/p/click/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=12) "BSD-3-Clause" }, @@ -73,7 +58,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=2) { (string) (len=38) "colorama; platform_system == \"Windows\"", diff --git a/.snapshots/TestParse-click_signed_wheel b/.snapshots/TestParse-click_signed_wheel index 103d5be..52d209b 100644 --- a/.snapshots/TestParse-click_signed_wheel +++ b/.snapshots/TestParse-click_signed_wheel @@ -1,14 +1,8 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, - (string) (len=6) "author": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -19,18 +13,12 @@ (string) (len=34) "Operating System :: OS Independent", (string) (len=30) "Programming Language :: Python" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=1977) "\\$ click\\_\n==========\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U click\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n import click\n\n @click.command()\n @click.option(\"--count\", default=1, help=\"Number of greetings.\")\n @click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\n def hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\n if __name__ == '__main__':\n hello()\n\n.. code-block:: text\n\n $ python hello.py --count=3\n Your name: Click\n Hello, Click!\n Hello, Click!\n Hello, Click!\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, `please\ndonate today`_.\n\n.. _please donate today: https://palletsprojects.com/donate\n\n\nLinks\n-----\n\n- Documentation: https://click.palletsprojects.com/\n- Changes: https://click.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/click/\n- Source Code: https://github.com/pallets/click\n- Issue Tracker: https://github.com/pallets/click/issues\n- Chat: https://discord.gg/pallets\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=1) { (string) (len=13) "requires-dist" }, @@ -40,9 +28,6 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=36) "https://palletsprojects.com/p/click/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=12) "BSD-3-Clause" }, diff --git a/.snapshots/TestParse-click_unsigned_tarball b/.snapshots/TestParse-click_unsigned_tarball index efa84d8..3dd16eb 100644 --- a/.snapshots/TestParse-click_unsigned_tarball +++ b/.snapshots/TestParse-click_unsigned_tarball @@ -1,14 +1,8 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, - (string) (len=6) "author": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -19,18 +13,12 @@ (string) (len=34) "Operating System :: OS Independent", (string) (len=30) "Programming Language :: Python" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=1977) "\\$ click\\_\n==========\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U click\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n import click\n\n @click.command()\n @click.option(\"--count\", default=1, help=\"Number of greetings.\")\n @click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\n def hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\n if __name__ == '__main__':\n hello()\n\n.. code-block:: text\n\n $ python hello.py --count=3\n Your name: Click\n Hello, Click!\n Hello, Click!\n Hello, Click!\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, `please\ndonate today`_.\n\n.. _please donate today: https://palletsprojects.com/donate\n\n\nLinks\n-----\n\n- Documentation: https://click.palletsprojects.com/\n- Changes: https://click.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/click/\n- Source Code: https://github.com/pallets/click\n- Issue Tracker: https://github.com/pallets/click/issues\n- Chat: https://discord.gg/pallets\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=1) { (string) (len=13) "requires-dist" }, @@ -40,9 +28,6 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=36) "https://palletsprojects.com/p/click/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=12) "BSD-3-Clause" }, @@ -73,7 +58,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=2) { (string) (len=38) "colorama; platform_system == \"Windows\"", diff --git a/.snapshots/TestParse-click_unsigned_wheel b/.snapshots/TestParse-click_unsigned_wheel index e53880d..ab62f87 100644 --- a/.snapshots/TestParse-click_unsigned_wheel +++ b/.snapshots/TestParse-click_unsigned_wheel @@ -1,14 +1,8 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=22) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, - (string) (len=6) "author": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -19,18 +13,12 @@ (string) (len=34) "Operating System :: OS Independent", (string) (len=30) "Programming Language :: Python" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=1977) "\\$ click\\_\n==========\n\nClick is a Python package for creating beautiful command line interfaces\nin a composable way with as little code as necessary. It's the \"Command\nLine Interface Creation Kit\". It's highly configurable but comes with\nsensible defaults out of the box.\n\nIt aims to make the process of writing command line tools quick and fun\nwhile also preventing any frustration caused by the inability to\nimplement an intended CLI API.\n\nClick in three points:\n\n- Arbitrary nesting of commands\n- Automatic help page generation\n- Supports lazy loading of subcommands at runtime\n\n\nInstalling\n----------\n\nInstall and update using `pip`_:\n\n.. code-block:: text\n\n $ pip install -U click\n\n.. _pip: https://pip.pypa.io/en/stable/getting-started/\n\n\nA Simple Example\n----------------\n\n.. code-block:: python\n\n import click\n\n @click.command()\n @click.option(\"--count\", default=1, help=\"Number of greetings.\")\n @click.option(\"--name\", prompt=\"Your name\", help=\"The person to greet.\")\n def hello(count, name):\n \"\"\"Simple program that greets NAME for a total of COUNT times.\"\"\"\n for _ in range(count):\n click.echo(f\"Hello, {name}!\")\n\n if __name__ == '__main__':\n hello()\n\n.. code-block:: text\n\n $ python hello.py --count=3\n Your name: Click\n Hello, Click!\n Hello, Click!\n Hello, Click!\n\n\nDonate\n------\n\nThe Pallets organization develops and supports Click and other popular\npackages. In order to grow the community of contributors and users, and\nallow the maintainers to devote more time to the projects, `please\ndonate today`_.\n\n.. _please donate today: https://palletsprojects.com/donate\n\n\nLinks\n-----\n\n- Documentation: https://click.palletsprojects.com/\n- Changes: https://click.palletsprojects.com/changes/\n- PyPI Releases: https://pypi.org/project/click/\n- Source Code: https://github.com/pallets/click\n- Issue Tracker: https://github.com/pallets/click/issues\n- Chat: https://discord.gg/pallets\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=1) { (string) (len=13) "requires-dist" }, @@ -40,9 +28,6 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=36) "https://palletsprojects.com/p/click/" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=12) "BSD-3-Clause" }, diff --git a/.snapshots/TestParse-configparser_signed_tarball b/.snapshots/TestParse-configparser_signed_tarball index e27c672..7d79d80 100644 --- a/.snapshots/TestParse-configparser_signed_tarball +++ b/.snapshots/TestParse-configparser_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,18 +19,9 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=9485) ".. image:: https://img.shields.io/pypi/v/configparser.svg\n :target: https://pypi.org/project/configparser\n\n.. image:: https://img.shields.io/pypi/pyversions/configparser.svg\n\n.. image:: https://github.com/jaraco/configparser/workflows/tests/badge.svg\n :target: https://github.com/jaraco/configparser/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/configparser/badge/?version=latest\n :target: https://configparser.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/configparser\n :target: https://tidelift.com/subscription/pkg/pypi-configparser?utm_source=pypi-configparser&utm_medium=readme\n\n\nThis package is a backport of the refreshed and enhanced ConfigParser from\nlater Python versions. To use the backport instead of the built-in version,\nsimply import it explicitly as a backport::\n\n from backports import configparser\n\nTo use the backport on Python 2 and the built-in version on\nPython 3, use the standard invocation::\n\n import configparser\n\nFor detailed documentation consult the vanilla version at\nhttp://docs.python.org/3/library/configparser.html.\n\nWhy you'll love ``configparser``\n================================\n\nWhereas almost completely compatible with its older brother, ``configparser``\nsports a bunch of interesting new features:\n\n* full mapping protocol access (`more info\n `_)::\n\n >>> parser = ConfigParser()\n >>> parser.read_string(\"\"\"\n [DEFAULT]\n location = upper left\n visible = yes\n editable = no\n color = blue\n\n [main]\n title = Main Menu\n color = green\n\n [options]\n title = Options\n \"\"\")\n >>> parser['main']['color']\n 'green'\n >>> parser['main']['editable']\n 'no'\n >>> section = parser['options']\n >>> section['title']\n 'Options'\n >>> section['title'] = 'Options (editable: %(editable)s)'\n >>> section['title']\n 'Options (editable: no)'\n\n* there's now one default ``ConfigParser`` class, which basically is the old\n ``SafeConfigParser`` with a bunch of tweaks which make it more predictable for\n users. Don't need interpolation? Simply use\n ``ConfigParser(interpolation=None)``, no need to use a distinct\n ``RawConfigParser`` anymore.\n\n* the parser is highly `customizable upon instantiation\n `__\n supporting things like changing option delimiters, comment characters, the\n name of the DEFAULT section, the interpolation syntax, etc.\n\n* you can easily create your own interpolation syntax but there are two powerful\n implementations built-in (`more info\n `__):\n\n * the classic ``%(string-like)s`` syntax (called ``BasicInterpolation``)\n\n * a new ``${buildout:like}`` syntax (called ``ExtendedInterpolation``)\n\n* fallback values may be specified in getters (`more info\n `__)::\n\n >>> config.get('closet', 'monster',\n ... fallback='No such things as monsters')\n 'No such things as monsters'\n\n* ``ConfigParser`` objects can now read data directly `from strings\n `__\n and `from dictionaries\n `__.\n That means importing configuration from JSON or specifying default values for\n the whole configuration (multiple sections) is now a single line of code. Same\n goes for copying data from another ``ConfigParser`` instance, thanks to its\n mapping protocol support.\n\n* many smaller tweaks, updates and fixes\n\nA few words about Unicode\n=========================\n\n``configparser`` comes from Python 3 and as such it works well with Unicode.\nThe library is generally cleaned up in terms of internal data storage and\nreading/writing files. There are a couple of incompatibilities with the old\n``ConfigParser`` due to that. However, the work required to migrate is well\nworth it as it shows the issues that would likely come up during migration of\nyour project to Python 3.\n\nThe design assumes that Unicode strings are used whenever possible [1]_. That\ngives you the certainty that what's stored in a configuration object is text.\nOnce your configuration is read, the rest of your application doesn't have to\ndeal with encoding issues. All you have is text [2]_. The only two phases when\nyou should explicitly state encoding is when you either read from an external\nsource (e.g. a file) or write back.\n\nVersioning\n==========\n\nThis project uses `semver `_ to\ncommunicate the impact of various releases while periodically syncing\nwith the upstream implementation in CPython.\nThe `history `_\nserves as a reference indicating which versions incorporate\nwhich upstream functionality.\n\nPrior to the ``4.0.0`` release, `another scheme\n`_\nwas used to associate the CPython and backports releases.\n\nMaintenance\n===========\n\nThis backport was originally authored by Łukasz Langa, the current vanilla\n``configparser`` maintainer for CPython and is currently maintained by\nJason R. Coombs:\n\n* `configparser repository `_\n\n* `configparser issue tracker `_\n\nConversion Process\n==================\n\nThis section is technical and should bother you only if you are wondering how\nthis backport is produced. If the implementation details of this backport are\nnot important for you, feel free to ignore the following content.\n\nThe project takes the following branching approach:\n\n* The ``3.x`` branch holds unchanged files synchronized from the upstream\n CPython repository. The synchronization is currently done by manually copying\n the required files and stating from which CPython changeset they come.\n\n* The ``main`` branch holds a version of the ``3.x`` code with some tweaks\n that make it compatible with older Pythons. Code on this branch must work\n on all supported Python versions. Test with ``tox`` or in CI.\n\nThe process works like this:\n\n1. In the ``3.x`` branch, run ``pip-run -- sync-upstream.py``, which\n downloads the latest stable release of Python and copies the relevant\n files from there into their new locations and then commits those\n changes with a nice reference to the relevant upstream commit hash.\n\n2. Check for new names in ``__all__`` and update imports in\n ``configparser.py`` accordingly. Commit.\n\n3. Merge the new commit to ``main``. Run tests. Commit.\n\n4. Make any compatibility changes on ``main``. Run tests. Commit.\n\n5. Update the docs and release the new version.\n\n\nFootnotes\n=========\n\n.. [1] To somewhat ease migration, passing bytestrings is still supported but\n they are converted to Unicode for internal storage anyway. This means\n that for the vast majority of strings used in configuration files, it\n won't matter if you pass them as bytestrings or Unicode. However, if you\n pass a bytestring that cannot be converted to Unicode using the naive\n ASCII codec, a ``UnicodeDecodeError`` will be raised. This is purposeful\n and helps you manage proper encoding for all content you store in\n memory, read from various sources and write back.\n\n.. [2] Life gets much easier when you understand that you basically manage\n **text** in your application. You don't care about bytes but about\n letters. In that regard the concept of content encoding is meaningless.\n The only time when you deal with raw bytes is when you write the data to\n a file. Then you have to specify how your text should be encoded. On\n the other end, to get meaningful text from a file, the application\n reading it has to know which encoding was used during its creation. But\n once the bytes are read and properly decoded, all you have is text. This\n is especially powerful when you start interacting with multiple data\n sources. Even if each of them uses a different encoding, inside your\n application data is held in abstract text form. You can program your\n business logic without worrying about which data came from which source.\n You can freely exchange the data you store between sources. Only\n reading/writing files requires encoding your text to bytes.\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -40,9 +31,6 @@ (string) (len=8) "keywords": ([]string) (len=1) { (string) (len=52) "configparser ini parsing conf cfg configuration file" }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "maintainer": ([]string) (len=1) { (string) (len=15) "Jason R. Coombs" }, @@ -69,7 +57,7 @@ (string) (len=4) "docs" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=14) { (string) (len=29) "pytest>=6; extra == \"testing\"", diff --git a/.snapshots/TestParse-configparser_signed_wheel b/.snapshots/TestParse-configparser_signed_wheel index 4bebf65..03d3586 100644 --- a/.snapshots/TestParse-configparser_signed_wheel +++ b/.snapshots/TestParse-configparser_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,18 +19,9 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=9485) ".. image:: https://img.shields.io/pypi/v/configparser.svg\n :target: https://pypi.org/project/configparser\n\n.. image:: https://img.shields.io/pypi/pyversions/configparser.svg\n\n.. image:: https://github.com/jaraco/configparser/workflows/tests/badge.svg\n :target: https://github.com/jaraco/configparser/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/configparser/badge/?version=latest\n :target: https://configparser.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/configparser\n :target: https://tidelift.com/subscription/pkg/pypi-configparser?utm_source=pypi-configparser&utm_medium=readme\n\n\nThis package is a backport of the refreshed and enhanced ConfigParser from\nlater Python versions. To use the backport instead of the built-in version,\nsimply import it explicitly as a backport::\n\n from backports import configparser\n\nTo use the backport on Python 2 and the built-in version on\nPython 3, use the standard invocation::\n\n import configparser\n\nFor detailed documentation consult the vanilla version at\nhttp://docs.python.org/3/library/configparser.html.\n\nWhy you'll love ``configparser``\n================================\n\nWhereas almost completely compatible with its older brother, ``configparser``\nsports a bunch of interesting new features:\n\n* full mapping protocol access (`more info\n `_)::\n\n >>> parser = ConfigParser()\n >>> parser.read_string(\"\"\"\n [DEFAULT]\n location = upper left\n visible = yes\n editable = no\n color = blue\n\n [main]\n title = Main Menu\n color = green\n\n [options]\n title = Options\n \"\"\")\n >>> parser['main']['color']\n 'green'\n >>> parser['main']['editable']\n 'no'\n >>> section = parser['options']\n >>> section['title']\n 'Options'\n >>> section['title'] = 'Options (editable: %(editable)s)'\n >>> section['title']\n 'Options (editable: no)'\n\n* there's now one default ``ConfigParser`` class, which basically is the old\n ``SafeConfigParser`` with a bunch of tweaks which make it more predictable for\n users. Don't need interpolation? Simply use\n ``ConfigParser(interpolation=None)``, no need to use a distinct\n ``RawConfigParser`` anymore.\n\n* the parser is highly `customizable upon instantiation\n `__\n supporting things like changing option delimiters, comment characters, the\n name of the DEFAULT section, the interpolation syntax, etc.\n\n* you can easily create your own interpolation syntax but there are two powerful\n implementations built-in (`more info\n `__):\n\n * the classic ``%(string-like)s`` syntax (called ``BasicInterpolation``)\n\n * a new ``${buildout:like}`` syntax (called ``ExtendedInterpolation``)\n\n* fallback values may be specified in getters (`more info\n `__)::\n\n >>> config.get('closet', 'monster',\n ... fallback='No such things as monsters')\n 'No such things as monsters'\n\n* ``ConfigParser`` objects can now read data directly `from strings\n `__\n and `from dictionaries\n `__.\n That means importing configuration from JSON or specifying default values for\n the whole configuration (multiple sections) is now a single line of code. Same\n goes for copying data from another ``ConfigParser`` instance, thanks to its\n mapping protocol support.\n\n* many smaller tweaks, updates and fixes\n\nA few words about Unicode\n=========================\n\n``configparser`` comes from Python 3 and as such it works well with Unicode.\nThe library is generally cleaned up in terms of internal data storage and\nreading/writing files. There are a couple of incompatibilities with the old\n``ConfigParser`` due to that. However, the work required to migrate is well\nworth it as it shows the issues that would likely come up during migration of\nyour project to Python 3.\n\nThe design assumes that Unicode strings are used whenever possible [1]_. That\ngives you the certainty that what's stored in a configuration object is text.\nOnce your configuration is read, the rest of your application doesn't have to\ndeal with encoding issues. All you have is text [2]_. The only two phases when\nyou should explicitly state encoding is when you either read from an external\nsource (e.g. a file) or write back.\n\nVersioning\n==========\n\nThis project uses `semver `_ to\ncommunicate the impact of various releases while periodically syncing\nwith the upstream implementation in CPython.\nThe `history `_\nserves as a reference indicating which versions incorporate\nwhich upstream functionality.\n\nPrior to the ``4.0.0`` release, `another scheme\n`_\nwas used to associate the CPython and backports releases.\n\nMaintenance\n===========\n\nThis backport was originally authored by Łukasz Langa, the current vanilla\n``configparser`` maintainer for CPython and is currently maintained by\nJason R. Coombs:\n\n* `configparser repository `_\n\n* `configparser issue tracker `_\n\nConversion Process\n==================\n\nThis section is technical and should bother you only if you are wondering how\nthis backport is produced. If the implementation details of this backport are\nnot important for you, feel free to ignore the following content.\n\nThe project takes the following branching approach:\n\n* The ``3.x`` branch holds unchanged files synchronized from the upstream\n CPython repository. The synchronization is currently done by manually copying\n the required files and stating from which CPython changeset they come.\n\n* The ``main`` branch holds a version of the ``3.x`` code with some tweaks\n that make it compatible with older Pythons. Code on this branch must work\n on all supported Python versions. Test with ``tox`` or in CI.\n\nThe process works like this:\n\n1. In the ``3.x`` branch, run ``pip-run -- sync-upstream.py``, which\n downloads the latest stable release of Python and copies the relevant\n files from there into their new locations and then commits those\n changes with a nice reference to the relevant upstream commit hash.\n\n2. Check for new names in ``__all__`` and update imports in\n ``configparser.py`` accordingly. Commit.\n\n3. Merge the new commit to ``main``. Run tests. Commit.\n\n4. Make any compatibility changes on ``main``. Run tests. Commit.\n\n5. Update the docs and release the new version.\n\n\nFootnotes\n=========\n\n.. [1] To somewhat ease migration, passing bytestrings is still supported but\n they are converted to Unicode for internal storage anyway. This means\n that for the vast majority of strings used in configuration files, it\n won't matter if you pass them as bytestrings or Unicode. However, if you\n pass a bytestring that cannot be converted to Unicode using the naive\n ASCII codec, a ``UnicodeDecodeError`` will be raised. This is purposeful\n and helps you manage proper encoding for all content you store in\n memory, read from various sources and write back.\n\n.. [2] Life gets much easier when you understand that you basically manage\n **text** in your application. You don't care about bytes but about\n letters. In that regard the concept of content encoding is meaningless.\n The only time when you deal with raw bytes is when you write the data to\n a file. Then you have to specify how your text should be encoded. On\n the other end, to get meaningful text from a file, the application\n reading it has to know which encoding was used during its creation. But\n once the bytes are read and properly decoded, all you have is text. This\n is especially powerful when you start interacting with multiple data\n sources. Even if each of them uses a different encoding, inside your\n application data is held in abstract text form. You can program your\n business logic without worrying about which data came from which source.\n You can freely exchange the data you store between sources. Only\n reading/writing files requires encoding your text to bytes.\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -40,9 +31,6 @@ (string) (len=8) "keywords": ([]string) (len=1) { (string) (len=52) "configparser ini parsing conf cfg configuration file" }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "maintainer": ([]string) (len=1) { (string) (len=15) "Jason R. Coombs" }, diff --git a/.snapshots/TestParse-configparser_unsigned_tarball b/.snapshots/TestParse-configparser_unsigned_tarball index 3a31bb4..9453ce0 100644 --- a/.snapshots/TestParse-configparser_unsigned_tarball +++ b/.snapshots/TestParse-configparser_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,18 +19,9 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=9485) ".. image:: https://img.shields.io/pypi/v/configparser.svg\n :target: https://pypi.org/project/configparser\n\n.. image:: https://img.shields.io/pypi/pyversions/configparser.svg\n\n.. image:: https://github.com/jaraco/configparser/workflows/tests/badge.svg\n :target: https://github.com/jaraco/configparser/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/configparser/badge/?version=latest\n :target: https://configparser.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/configparser\n :target: https://tidelift.com/subscription/pkg/pypi-configparser?utm_source=pypi-configparser&utm_medium=readme\n\n\nThis package is a backport of the refreshed and enhanced ConfigParser from\nlater Python versions. To use the backport instead of the built-in version,\nsimply import it explicitly as a backport::\n\n from backports import configparser\n\nTo use the backport on Python 2 and the built-in version on\nPython 3, use the standard invocation::\n\n import configparser\n\nFor detailed documentation consult the vanilla version at\nhttp://docs.python.org/3/library/configparser.html.\n\nWhy you'll love ``configparser``\n================================\n\nWhereas almost completely compatible with its older brother, ``configparser``\nsports a bunch of interesting new features:\n\n* full mapping protocol access (`more info\n `_)::\n\n >>> parser = ConfigParser()\n >>> parser.read_string(\"\"\"\n [DEFAULT]\n location = upper left\n visible = yes\n editable = no\n color = blue\n\n [main]\n title = Main Menu\n color = green\n\n [options]\n title = Options\n \"\"\")\n >>> parser['main']['color']\n 'green'\n >>> parser['main']['editable']\n 'no'\n >>> section = parser['options']\n >>> section['title']\n 'Options'\n >>> section['title'] = 'Options (editable: %(editable)s)'\n >>> section['title']\n 'Options (editable: no)'\n\n* there's now one default ``ConfigParser`` class, which basically is the old\n ``SafeConfigParser`` with a bunch of tweaks which make it more predictable for\n users. Don't need interpolation? Simply use\n ``ConfigParser(interpolation=None)``, no need to use a distinct\n ``RawConfigParser`` anymore.\n\n* the parser is highly `customizable upon instantiation\n `__\n supporting things like changing option delimiters, comment characters, the\n name of the DEFAULT section, the interpolation syntax, etc.\n\n* you can easily create your own interpolation syntax but there are two powerful\n implementations built-in (`more info\n `__):\n\n * the classic ``%(string-like)s`` syntax (called ``BasicInterpolation``)\n\n * a new ``${buildout:like}`` syntax (called ``ExtendedInterpolation``)\n\n* fallback values may be specified in getters (`more info\n `__)::\n\n >>> config.get('closet', 'monster',\n ... fallback='No such things as monsters')\n 'No such things as monsters'\n\n* ``ConfigParser`` objects can now read data directly `from strings\n `__\n and `from dictionaries\n `__.\n That means importing configuration from JSON or specifying default values for\n the whole configuration (multiple sections) is now a single line of code. Same\n goes for copying data from another ``ConfigParser`` instance, thanks to its\n mapping protocol support.\n\n* many smaller tweaks, updates and fixes\n\nA few words about Unicode\n=========================\n\n``configparser`` comes from Python 3 and as such it works well with Unicode.\nThe library is generally cleaned up in terms of internal data storage and\nreading/writing files. There are a couple of incompatibilities with the old\n``ConfigParser`` due to that. However, the work required to migrate is well\nworth it as it shows the issues that would likely come up during migration of\nyour project to Python 3.\n\nThe design assumes that Unicode strings are used whenever possible [1]_. That\ngives you the certainty that what's stored in a configuration object is text.\nOnce your configuration is read, the rest of your application doesn't have to\ndeal with encoding issues. All you have is text [2]_. The only two phases when\nyou should explicitly state encoding is when you either read from an external\nsource (e.g. a file) or write back.\n\nVersioning\n==========\n\nThis project uses `semver `_ to\ncommunicate the impact of various releases while periodically syncing\nwith the upstream implementation in CPython.\nThe `history `_\nserves as a reference indicating which versions incorporate\nwhich upstream functionality.\n\nPrior to the ``4.0.0`` release, `another scheme\n`_\nwas used to associate the CPython and backports releases.\n\nMaintenance\n===========\n\nThis backport was originally authored by Łukasz Langa, the current vanilla\n``configparser`` maintainer for CPython and is currently maintained by\nJason R. Coombs:\n\n* `configparser repository `_\n\n* `configparser issue tracker `_\n\nConversion Process\n==================\n\nThis section is technical and should bother you only if you are wondering how\nthis backport is produced. If the implementation details of this backport are\nnot important for you, feel free to ignore the following content.\n\nThe project takes the following branching approach:\n\n* The ``3.x`` branch holds unchanged files synchronized from the upstream\n CPython repository. The synchronization is currently done by manually copying\n the required files and stating from which CPython changeset they come.\n\n* The ``main`` branch holds a version of the ``3.x`` code with some tweaks\n that make it compatible with older Pythons. Code on this branch must work\n on all supported Python versions. Test with ``tox`` or in CI.\n\nThe process works like this:\n\n1. In the ``3.x`` branch, run ``pip-run -- sync-upstream.py``, which\n downloads the latest stable release of Python and copies the relevant\n files from there into their new locations and then commits those\n changes with a nice reference to the relevant upstream commit hash.\n\n2. Check for new names in ``__all__`` and update imports in\n ``configparser.py`` accordingly. Commit.\n\n3. Merge the new commit to ``main``. Run tests. Commit.\n\n4. Make any compatibility changes on ``main``. Run tests. Commit.\n\n5. Update the docs and release the new version.\n\n\nFootnotes\n=========\n\n.. [1] To somewhat ease migration, passing bytestrings is still supported but\n they are converted to Unicode for internal storage anyway. This means\n that for the vast majority of strings used in configuration files, it\n won't matter if you pass them as bytestrings or Unicode. However, if you\n pass a bytestring that cannot be converted to Unicode using the naive\n ASCII codec, a ``UnicodeDecodeError`` will be raised. This is purposeful\n and helps you manage proper encoding for all content you store in\n memory, read from various sources and write back.\n\n.. [2] Life gets much easier when you understand that you basically manage\n **text** in your application. You don't care about bytes but about\n letters. In that regard the concept of content encoding is meaningless.\n The only time when you deal with raw bytes is when you write the data to\n a file. Then you have to specify how your text should be encoded. On\n the other end, to get meaningful text from a file, the application\n reading it has to know which encoding was used during its creation. But\n once the bytes are read and properly decoded, all you have is text. This\n is especially powerful when you start interacting with multiple data\n sources. Even if each of them uses a different encoding, inside your\n application data is held in abstract text form. You can program your\n business logic without worrying about which data came from which source.\n You can freely exchange the data you store between sources. Only\n reading/writing files requires encoding your text to bytes.\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -40,9 +31,6 @@ (string) (len=8) "keywords": ([]string) (len=1) { (string) (len=52) "configparser ini parsing conf cfg configuration file" }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "maintainer": ([]string) (len=1) { (string) (len=15) "Jason R. Coombs" }, @@ -69,7 +57,7 @@ (string) (len=4) "docs" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=14) { (string) (len=29) "pytest>=6; extra == \"testing\"", diff --git a/.snapshots/TestParse-configparser_unsigned_wheel b/.snapshots/TestParse-configparser_unsigned_wheel index 7b9789e..0f5470d 100644 --- a/.snapshots/TestParse-configparser_unsigned_wheel +++ b/.snapshots/TestParse-configparser_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=27) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,18 +19,9 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=9485) ".. image:: https://img.shields.io/pypi/v/configparser.svg\n :target: https://pypi.org/project/configparser\n\n.. image:: https://img.shields.io/pypi/pyversions/configparser.svg\n\n.. image:: https://github.com/jaraco/configparser/workflows/tests/badge.svg\n :target: https://github.com/jaraco/configparser/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/configparser/badge/?version=latest\n :target: https://configparser.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/configparser\n :target: https://tidelift.com/subscription/pkg/pypi-configparser?utm_source=pypi-configparser&utm_medium=readme\n\n\nThis package is a backport of the refreshed and enhanced ConfigParser from\nlater Python versions. To use the backport instead of the built-in version,\nsimply import it explicitly as a backport::\n\n from backports import configparser\n\nTo use the backport on Python 2 and the built-in version on\nPython 3, use the standard invocation::\n\n import configparser\n\nFor detailed documentation consult the vanilla version at\nhttp://docs.python.org/3/library/configparser.html.\n\nWhy you'll love ``configparser``\n================================\n\nWhereas almost completely compatible with its older brother, ``configparser``\nsports a bunch of interesting new features:\n\n* full mapping protocol access (`more info\n `_)::\n\n >>> parser = ConfigParser()\n >>> parser.read_string(\"\"\"\n [DEFAULT]\n location = upper left\n visible = yes\n editable = no\n color = blue\n\n [main]\n title = Main Menu\n color = green\n\n [options]\n title = Options\n \"\"\")\n >>> parser['main']['color']\n 'green'\n >>> parser['main']['editable']\n 'no'\n >>> section = parser['options']\n >>> section['title']\n 'Options'\n >>> section['title'] = 'Options (editable: %(editable)s)'\n >>> section['title']\n 'Options (editable: no)'\n\n* there's now one default ``ConfigParser`` class, which basically is the old\n ``SafeConfigParser`` with a bunch of tweaks which make it more predictable for\n users. Don't need interpolation? Simply use\n ``ConfigParser(interpolation=None)``, no need to use a distinct\n ``RawConfigParser`` anymore.\n\n* the parser is highly `customizable upon instantiation\n `__\n supporting things like changing option delimiters, comment characters, the\n name of the DEFAULT section, the interpolation syntax, etc.\n\n* you can easily create your own interpolation syntax but there are two powerful\n implementations built-in (`more info\n `__):\n\n * the classic ``%(string-like)s`` syntax (called ``BasicInterpolation``)\n\n * a new ``${buildout:like}`` syntax (called ``ExtendedInterpolation``)\n\n* fallback values may be specified in getters (`more info\n `__)::\n\n >>> config.get('closet', 'monster',\n ... fallback='No such things as monsters')\n 'No such things as monsters'\n\n* ``ConfigParser`` objects can now read data directly `from strings\n `__\n and `from dictionaries\n `__.\n That means importing configuration from JSON or specifying default values for\n the whole configuration (multiple sections) is now a single line of code. Same\n goes for copying data from another ``ConfigParser`` instance, thanks to its\n mapping protocol support.\n\n* many smaller tweaks, updates and fixes\n\nA few words about Unicode\n=========================\n\n``configparser`` comes from Python 3 and as such it works well with Unicode.\nThe library is generally cleaned up in terms of internal data storage and\nreading/writing files. There are a couple of incompatibilities with the old\n``ConfigParser`` due to that. However, the work required to migrate is well\nworth it as it shows the issues that would likely come up during migration of\nyour project to Python 3.\n\nThe design assumes that Unicode strings are used whenever possible [1]_. That\ngives you the certainty that what's stored in a configuration object is text.\nOnce your configuration is read, the rest of your application doesn't have to\ndeal with encoding issues. All you have is text [2]_. The only two phases when\nyou should explicitly state encoding is when you either read from an external\nsource (e.g. a file) or write back.\n\nVersioning\n==========\n\nThis project uses `semver `_ to\ncommunicate the impact of various releases while periodically syncing\nwith the upstream implementation in CPython.\nThe `history `_\nserves as a reference indicating which versions incorporate\nwhich upstream functionality.\n\nPrior to the ``4.0.0`` release, `another scheme\n`_\nwas used to associate the CPython and backports releases.\n\nMaintenance\n===========\n\nThis backport was originally authored by Łukasz Langa, the current vanilla\n``configparser`` maintainer for CPython and is currently maintained by\nJason R. Coombs:\n\n* `configparser repository `_\n\n* `configparser issue tracker `_\n\nConversion Process\n==================\n\nThis section is technical and should bother you only if you are wondering how\nthis backport is produced. If the implementation details of this backport are\nnot important for you, feel free to ignore the following content.\n\nThe project takes the following branching approach:\n\n* The ``3.x`` branch holds unchanged files synchronized from the upstream\n CPython repository. The synchronization is currently done by manually copying\n the required files and stating from which CPython changeset they come.\n\n* The ``main`` branch holds a version of the ``3.x`` code with some tweaks\n that make it compatible with older Pythons. Code on this branch must work\n on all supported Python versions. Test with ``tox`` or in CI.\n\nThe process works like this:\n\n1. In the ``3.x`` branch, run ``pip-run -- sync-upstream.py``, which\n downloads the latest stable release of Python and copies the relevant\n files from there into their new locations and then commits those\n changes with a nice reference to the relevant upstream commit hash.\n\n2. Check for new names in ``__all__`` and update imports in\n ``configparser.py`` accordingly. Commit.\n\n3. Merge the new commit to ``main``. Run tests. Commit.\n\n4. Make any compatibility changes on ``main``. Run tests. Commit.\n\n5. Update the docs and release the new version.\n\n\nFootnotes\n=========\n\n.. [1] To somewhat ease migration, passing bytestrings is still supported but\n they are converted to Unicode for internal storage anyway. This means\n that for the vast majority of strings used in configuration files, it\n won't matter if you pass them as bytestrings or Unicode. However, if you\n pass a bytestring that cannot be converted to Unicode using the naive\n ASCII codec, a ``UnicodeDecodeError`` will be raised. This is purposeful\n and helps you manage proper encoding for all content you store in\n memory, read from various sources and write back.\n\n.. [2] Life gets much easier when you understand that you basically manage\n **text** in your application. You don't care about bytes but about\n letters. In that regard the concept of content encoding is meaningless.\n The only time when you deal with raw bytes is when you write the data to\n a file. Then you have to specify how your text should be encoded. On\n the other end, to get meaningful text from a file, the application\n reading it has to know which encoding was used during its creation. But\n once the bytes are read and properly decoded, all you have is text. This\n is especially powerful when you start interacting with multiple data\n sources. Even if each of them uses a different encoding, inside your\n application data is held in abstract text form. You can program your\n business logic without worrying about which data came from which source.\n You can freely exchange the data you store between sources. Only\n reading/writing files requires encoding your text to bytes.\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -40,9 +31,6 @@ (string) (len=8) "keywords": ([]string) (len=1) { (string) (len=52) "configparser ini parsing conf cfg configuration file" }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "maintainer": ([]string) (len=1) { (string) (len=15) "Jason R. Coombs" }, diff --git a/.snapshots/TestParse-coveragepy_signed_tarball b/.snapshots/TestParse-coveragepy_signed_tarball index 1e177ef..4954184 100644 --- a/.snapshots/TestParse-coveragepy_signed_tarball +++ b/.snapshots/TestParse-coveragepy_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -33,18 +33,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=43) "Development Status :: 5 - Production/Stable" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=6267) ".. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0\n.. For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n===========\nCoverage.py\n===========\n\nCode coverage testing for Python.\n\n| |license| |versions| |status|\n| |test-status| |quality-status| |docs| |codecov|\n| |kit| |format| |repos| |downloads|\n| |stars| |forks| |contributors|\n| |tidelift| |twitter-coveragepy| |twitter-nedbat|\n\nCoverage.py measures code coverage, typically during test execution. It uses\nthe code analysis tools and tracing hooks provided in the Python standard\nlibrary to determine which lines are executable, and which have been executed.\n\nCoverage.py runs on many versions of Python:\n\n* CPython 2.7.\n* CPython 3.5 through 3.10 alpha.\n* PyPy2 7.3.3 and PyPy3 7.3.3.\n\nDocumentation is on `Read the Docs`_. Code repository and issue tracker are on\n`GitHub`_.\n\n.. _Read the Docs: https://coverage.readthedocs.io/\n.. _GitHub: https://github.com/nedbat/coveragepy\n\n\n**New in 5.x:** SQLite data storage, JSON report, contexts, relative filenames,\ndropped support for Python 2.6, 3.3 and 3.4.\n\n\nFor Enterprise\n--------------\n\n.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logo_small.png\n :alt: Tidelift\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n\n.. list-table::\n :widths: 10 100\n\n * - |tideliftlogo|\n - `Available as part of the Tidelift Subscription. `_\n Coverage and thousands of other packages are working with\n Tidelift to deliver one enterprise subscription that covers all of the open\n source you use. If you want the flexibility of open source and the confidence\n of commercial-grade software, this is for you.\n `Learn more. `_\n\n\nGetting Started\n---------------\n\nSee the `Quick Start section`_ of the docs.\n\n.. _Quick Start section: https://coverage.readthedocs.io/#quick-start\n\n\nChange history\n--------------\n\nThe complete history of changes is on the `change history page`_.\n\n.. _change history page: https://coverage.readthedocs.io/en/latest/changes.html\n\n\nContributing\n------------\n\nSee the `Contributing section`_ of the docs.\n\n.. _Contributing section: https://coverage.readthedocs.io/en/latest/contributing.html\n\n\nSecurity\n--------\n\nTo report a security vulnerability, please use the `Tidelift security\ncontact`_. Tidelift will coordinate the fix and disclosure.\n\n.. _Tidelift security contact: https://tidelift.com/security\n\n\nLicense\n-------\n\nLicensed under the `Apache 2.0 License`_. For details, see `NOTICE.txt`_.\n\n.. _Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0\n.. _NOTICE.txt: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n\n.. |test-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml\n :alt: Test suite status\n.. |quality-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml\n :alt: Quality check status\n.. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat\n :target: https://coverage.readthedocs.io/\n :alt: Documentation\n.. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master\n :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master\n :alt: Requirements status\n.. |kit| image:: https://badge.fury.io/py/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: PyPI status\n.. |format| image:: https://img.shields.io/pypi/format/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Kit format\n.. |downloads| image:: https://img.shields.io/pypi/dw/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Weekly PyPI downloads\n.. |versions| image:: https://img.shields.io/pypi/pyversions/coverage.svg?logo=python&logoColor=FBE072\n :target: https://pypi.org/project/coverage/\n :alt: Python versions supported\n.. |status| image:: https://img.shields.io/pypi/status/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Package stability\n.. |license| image:: https://img.shields.io/pypi/l/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: License\n.. |codecov| image:: https://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master&precision=2\n :target: https://codecov.io/github/nedbat/coveragepy?branch=master\n :alt: Coverage!\n.. |repos| image:: https://repology.org/badge/tiny-repos/python:coverage.svg\n :target: https://repology.org/metapackage/python:coverage/versions\n :alt: Packaging status\n.. |tidelift| image:: https://tidelift.com/badges/package/pypi/coverage\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n :alt: Tidelift\n.. |stars| image:: https://img.shields.io/github/stars/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/stargazers\n :alt: Github stars\n.. |forks| image:: https://img.shields.io/github/forks/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/network/members\n :alt: Github forks\n.. |contributors| image:: https://img.shields.io/github/contributors/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/graphs/contributors\n :alt: Contributors\n.. |twitter-coveragepy| image:: https://img.shields.io/twitter/follow/coveragepy.svg?label=coveragepy&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/coveragepy\n :alt: coverage.py on Twitter\n.. |twitter-nedbat| image:: https://img.shields.io/twitter/follow/nedbat.svg?label=nedbat&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/nedbat\n :alt: nedbat on Twitter\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=12) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +65,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=10) "Apache 2.0" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -98,7 +86,7 @@ (string) (len=4) "toml" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=1) { (string) (len=21) "toml; extra == \"toml\"" diff --git a/.snapshots/TestParse-coveragepy_signed_wheel b/.snapshots/TestParse-coveragepy_signed_wheel index 66920dc..edb4be2 100644 --- a/.snapshots/TestParse-coveragepy_signed_wheel +++ b/.snapshots/TestParse-coveragepy_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -33,18 +33,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=43) "Development Status :: 5 - Production/Stable" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=6267) ".. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0\n.. For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n===========\nCoverage.py\n===========\n\nCode coverage testing for Python.\n\n| |license| |versions| |status|\n| |test-status| |quality-status| |docs| |codecov|\n| |kit| |format| |repos| |downloads|\n| |stars| |forks| |contributors|\n| |tidelift| |twitter-coveragepy| |twitter-nedbat|\n\nCoverage.py measures code coverage, typically during test execution. It uses\nthe code analysis tools and tracing hooks provided in the Python standard\nlibrary to determine which lines are executable, and which have been executed.\n\nCoverage.py runs on many versions of Python:\n\n* CPython 2.7.\n* CPython 3.5 through 3.10 alpha.\n* PyPy2 7.3.3 and PyPy3 7.3.3.\n\nDocumentation is on `Read the Docs`_. Code repository and issue tracker are on\n`GitHub`_.\n\n.. _Read the Docs: https://coverage.readthedocs.io/\n.. _GitHub: https://github.com/nedbat/coveragepy\n\n\n**New in 5.x:** SQLite data storage, JSON report, contexts, relative filenames,\ndropped support for Python 2.6, 3.3 and 3.4.\n\n\nFor Enterprise\n--------------\n\n.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logo_small.png\n :alt: Tidelift\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n\n.. list-table::\n :widths: 10 100\n\n * - |tideliftlogo|\n - `Available as part of the Tidelift Subscription. `_\n Coverage and thousands of other packages are working with\n Tidelift to deliver one enterprise subscription that covers all of the open\n source you use. If you want the flexibility of open source and the confidence\n of commercial-grade software, this is for you.\n `Learn more. `_\n\n\nGetting Started\n---------------\n\nSee the `Quick Start section`_ of the docs.\n\n.. _Quick Start section: https://coverage.readthedocs.io/#quick-start\n\n\nChange history\n--------------\n\nThe complete history of changes is on the `change history page`_.\n\n.. _change history page: https://coverage.readthedocs.io/en/latest/changes.html\n\n\nContributing\n------------\n\nSee the `Contributing section`_ of the docs.\n\n.. _Contributing section: https://coverage.readthedocs.io/en/latest/contributing.html\n\n\nSecurity\n--------\n\nTo report a security vulnerability, please use the `Tidelift security\ncontact`_. Tidelift will coordinate the fix and disclosure.\n\n.. _Tidelift security contact: https://tidelift.com/security\n\n\nLicense\n-------\n\nLicensed under the `Apache 2.0 License`_. For details, see `NOTICE.txt`_.\n\n.. _Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0\n.. _NOTICE.txt: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n\n.. |test-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml\n :alt: Test suite status\n.. |quality-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml\n :alt: Quality check status\n.. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat\n :target: https://coverage.readthedocs.io/\n :alt: Documentation\n.. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master\n :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master\n :alt: Requirements status\n.. |kit| image:: https://badge.fury.io/py/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: PyPI status\n.. |format| image:: https://img.shields.io/pypi/format/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Kit format\n.. |downloads| image:: https://img.shields.io/pypi/dw/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Weekly PyPI downloads\n.. |versions| image:: https://img.shields.io/pypi/pyversions/coverage.svg?logo=python&logoColor=FBE072\n :target: https://pypi.org/project/coverage/\n :alt: Python versions supported\n.. |status| image:: https://img.shields.io/pypi/status/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Package stability\n.. |license| image:: https://img.shields.io/pypi/l/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: License\n.. |codecov| image:: https://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master&precision=2\n :target: https://codecov.io/github/nedbat/coveragepy?branch=master\n :alt: Coverage!\n.. |repos| image:: https://repology.org/badge/tiny-repos/python:coverage.svg\n :target: https://repology.org/metapackage/python:coverage/versions\n :alt: Packaging status\n.. |tidelift| image:: https://tidelift.com/badges/package/pypi/coverage\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n :alt: Tidelift\n.. |stars| image:: https://img.shields.io/github/stars/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/stargazers\n :alt: Github stars\n.. |forks| image:: https://img.shields.io/github/forks/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/network/members\n :alt: Github forks\n.. |contributors| image:: https://img.shields.io/github/contributors/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/graphs/contributors\n :alt: Contributors\n.. |twitter-coveragepy| image:: https://img.shields.io/twitter/follow/coveragepy.svg?label=coveragepy&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/coveragepy\n :alt: coverage.py on Twitter\n.. |twitter-nedbat| image:: https://img.shields.io/twitter/follow/nedbat.svg?label=nedbat&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/nedbat\n :alt: nedbat on Twitter\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=12) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +65,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=10) "Apache 2.0" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-coveragepy_unsigned_tarball b/.snapshots/TestParse-coveragepy_unsigned_tarball index 4455c6c..7863d0f 100644 --- a/.snapshots/TestParse-coveragepy_unsigned_tarball +++ b/.snapshots/TestParse-coveragepy_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -33,18 +33,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=43) "Development Status :: 5 - Production/Stable" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=6267) ".. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0\n.. For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n===========\nCoverage.py\n===========\n\nCode coverage testing for Python.\n\n| |license| |versions| |status|\n| |test-status| |quality-status| |docs| |codecov|\n| |kit| |format| |repos| |downloads|\n| |stars| |forks| |contributors|\n| |tidelift| |twitter-coveragepy| |twitter-nedbat|\n\nCoverage.py measures code coverage, typically during test execution. It uses\nthe code analysis tools and tracing hooks provided in the Python standard\nlibrary to determine which lines are executable, and which have been executed.\n\nCoverage.py runs on many versions of Python:\n\n* CPython 2.7.\n* CPython 3.5 through 3.10 alpha.\n* PyPy2 7.3.3 and PyPy3 7.3.3.\n\nDocumentation is on `Read the Docs`_. Code repository and issue tracker are on\n`GitHub`_.\n\n.. _Read the Docs: https://coverage.readthedocs.io/\n.. _GitHub: https://github.com/nedbat/coveragepy\n\n\n**New in 5.x:** SQLite data storage, JSON report, contexts, relative filenames,\ndropped support for Python 2.6, 3.3 and 3.4.\n\n\nFor Enterprise\n--------------\n\n.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logo_small.png\n :alt: Tidelift\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n\n.. list-table::\n :widths: 10 100\n\n * - |tideliftlogo|\n - `Available as part of the Tidelift Subscription. `_\n Coverage and thousands of other packages are working with\n Tidelift to deliver one enterprise subscription that covers all of the open\n source you use. If you want the flexibility of open source and the confidence\n of commercial-grade software, this is for you.\n `Learn more. `_\n\n\nGetting Started\n---------------\n\nSee the `Quick Start section`_ of the docs.\n\n.. _Quick Start section: https://coverage.readthedocs.io/#quick-start\n\n\nChange history\n--------------\n\nThe complete history of changes is on the `change history page`_.\n\n.. _change history page: https://coverage.readthedocs.io/en/latest/changes.html\n\n\nContributing\n------------\n\nSee the `Contributing section`_ of the docs.\n\n.. _Contributing section: https://coverage.readthedocs.io/en/latest/contributing.html\n\n\nSecurity\n--------\n\nTo report a security vulnerability, please use the `Tidelift security\ncontact`_. Tidelift will coordinate the fix and disclosure.\n\n.. _Tidelift security contact: https://tidelift.com/security\n\n\nLicense\n-------\n\nLicensed under the `Apache 2.0 License`_. For details, see `NOTICE.txt`_.\n\n.. _Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0\n.. _NOTICE.txt: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n\n.. |test-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml\n :alt: Test suite status\n.. |quality-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml\n :alt: Quality check status\n.. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat\n :target: https://coverage.readthedocs.io/\n :alt: Documentation\n.. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master\n :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master\n :alt: Requirements status\n.. |kit| image:: https://badge.fury.io/py/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: PyPI status\n.. |format| image:: https://img.shields.io/pypi/format/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Kit format\n.. |downloads| image:: https://img.shields.io/pypi/dw/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Weekly PyPI downloads\n.. |versions| image:: https://img.shields.io/pypi/pyversions/coverage.svg?logo=python&logoColor=FBE072\n :target: https://pypi.org/project/coverage/\n :alt: Python versions supported\n.. |status| image:: https://img.shields.io/pypi/status/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Package stability\n.. |license| image:: https://img.shields.io/pypi/l/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: License\n.. |codecov| image:: https://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master&precision=2\n :target: https://codecov.io/github/nedbat/coveragepy?branch=master\n :alt: Coverage!\n.. |repos| image:: https://repology.org/badge/tiny-repos/python:coverage.svg\n :target: https://repology.org/metapackage/python:coverage/versions\n :alt: Packaging status\n.. |tidelift| image:: https://tidelift.com/badges/package/pypi/coverage\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n :alt: Tidelift\n.. |stars| image:: https://img.shields.io/github/stars/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/stargazers\n :alt: Github stars\n.. |forks| image:: https://img.shields.io/github/forks/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/network/members\n :alt: Github forks\n.. |contributors| image:: https://img.shields.io/github/contributors/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/graphs/contributors\n :alt: Contributors\n.. |twitter-coveragepy| image:: https://img.shields.io/twitter/follow/coveragepy.svg?label=coveragepy&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/coveragepy\n :alt: coverage.py on Twitter\n.. |twitter-nedbat| image:: https://img.shields.io/twitter/follow/nedbat.svg?label=nedbat&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/nedbat\n :alt: nedbat on Twitter\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=12) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +65,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=10) "Apache 2.0" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -98,7 +86,7 @@ (string) (len=4) "toml" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=1) { (string) (len=21) "toml; extra == \"toml\"" diff --git a/.snapshots/TestParse-coveragepy_unsigned_wheel b/.snapshots/TestParse-coveragepy_unsigned_wheel index 64c9983..a79aca9 100644 --- a/.snapshots/TestParse-coveragepy_unsigned_wheel +++ b/.snapshots/TestParse-coveragepy_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -33,18 +33,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=43) "Development Status :: 5 - Production/Stable" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=6267) ".. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0\n.. For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n===========\nCoverage.py\n===========\n\nCode coverage testing for Python.\n\n| |license| |versions| |status|\n| |test-status| |quality-status| |docs| |codecov|\n| |kit| |format| |repos| |downloads|\n| |stars| |forks| |contributors|\n| |tidelift| |twitter-coveragepy| |twitter-nedbat|\n\nCoverage.py measures code coverage, typically during test execution. It uses\nthe code analysis tools and tracing hooks provided in the Python standard\nlibrary to determine which lines are executable, and which have been executed.\n\nCoverage.py runs on many versions of Python:\n\n* CPython 2.7.\n* CPython 3.5 through 3.10 alpha.\n* PyPy2 7.3.3 and PyPy3 7.3.3.\n\nDocumentation is on `Read the Docs`_. Code repository and issue tracker are on\n`GitHub`_.\n\n.. _Read the Docs: https://coverage.readthedocs.io/\n.. _GitHub: https://github.com/nedbat/coveragepy\n\n\n**New in 5.x:** SQLite data storage, JSON report, contexts, relative filenames,\ndropped support for Python 2.6, 3.3 and 3.4.\n\n\nFor Enterprise\n--------------\n\n.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logo_small.png\n :alt: Tidelift\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n\n.. list-table::\n :widths: 10 100\n\n * - |tideliftlogo|\n - `Available as part of the Tidelift Subscription. `_\n Coverage and thousands of other packages are working with\n Tidelift to deliver one enterprise subscription that covers all of the open\n source you use. If you want the flexibility of open source and the confidence\n of commercial-grade software, this is for you.\n `Learn more. `_\n\n\nGetting Started\n---------------\n\nSee the `Quick Start section`_ of the docs.\n\n.. _Quick Start section: https://coverage.readthedocs.io/#quick-start\n\n\nChange history\n--------------\n\nThe complete history of changes is on the `change history page`_.\n\n.. _change history page: https://coverage.readthedocs.io/en/latest/changes.html\n\n\nContributing\n------------\n\nSee the `Contributing section`_ of the docs.\n\n.. _Contributing section: https://coverage.readthedocs.io/en/latest/contributing.html\n\n\nSecurity\n--------\n\nTo report a security vulnerability, please use the `Tidelift security\ncontact`_. Tidelift will coordinate the fix and disclosure.\n\n.. _Tidelift security contact: https://tidelift.com/security\n\n\nLicense\n-------\n\nLicensed under the `Apache 2.0 License`_. For details, see `NOTICE.txt`_.\n\n.. _Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0\n.. _NOTICE.txt: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt\n\n\n.. |test-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/testsuite.yml\n :alt: Test suite status\n.. |quality-status| image:: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml/badge.svg?branch=master&event=push\n :target: https://github.com/nedbat/coveragepy/actions/workflows/quality.yml\n :alt: Quality check status\n.. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat\n :target: https://coverage.readthedocs.io/\n :alt: Documentation\n.. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master\n :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master\n :alt: Requirements status\n.. |kit| image:: https://badge.fury.io/py/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: PyPI status\n.. |format| image:: https://img.shields.io/pypi/format/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Kit format\n.. |downloads| image:: https://img.shields.io/pypi/dw/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Weekly PyPI downloads\n.. |versions| image:: https://img.shields.io/pypi/pyversions/coverage.svg?logo=python&logoColor=FBE072\n :target: https://pypi.org/project/coverage/\n :alt: Python versions supported\n.. |status| image:: https://img.shields.io/pypi/status/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: Package stability\n.. |license| image:: https://img.shields.io/pypi/l/coverage.svg\n :target: https://pypi.org/project/coverage/\n :alt: License\n.. |codecov| image:: https://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master&precision=2\n :target: https://codecov.io/github/nedbat/coveragepy?branch=master\n :alt: Coverage!\n.. |repos| image:: https://repology.org/badge/tiny-repos/python:coverage.svg\n :target: https://repology.org/metapackage/python:coverage/versions\n :alt: Packaging status\n.. |tidelift| image:: https://tidelift.com/badges/package/pypi/coverage\n :target: https://tidelift.com/subscription/pkg/pypi-coverage?utm_source=pypi-coverage&utm_medium=referral&utm_campaign=readme\n :alt: Tidelift\n.. |stars| image:: https://img.shields.io/github/stars/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/stargazers\n :alt: Github stars\n.. |forks| image:: https://img.shields.io/github/forks/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/network/members\n :alt: Github forks\n.. |contributors| image:: https://img.shields.io/github/contributors/nedbat/coveragepy.svg?logo=github\n :target: https://github.com/nedbat/coveragepy/graphs/contributors\n :alt: Contributors\n.. |twitter-coveragepy| image:: https://img.shields.io/twitter/follow/coveragepy.svg?label=coveragepy&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/coveragepy\n :alt: coverage.py on Twitter\n.. |twitter-nedbat| image:: https://img.shields.io/twitter/follow/nedbat.svg?label=nedbat&style=flat&logo=twitter&logoColor=4FADFF\n :target: https://twitter.com/nedbat\n :alt: nedbat on Twitter\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=12) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +65,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=10) "Apache 2.0" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-decorator_signed_tarball b/.snapshots/TestParse-decorator_signed_tarball index 47d9842..13457e6 100644 --- a/.snapshots/TestParse-decorator_signed_tarball +++ b/.snapshots/TestParse-decorator_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -35,18 +35,9 @@ (string) (len=42) "Topic :: Software Development :: Libraries", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2912) "Decorators for Humans\n=====================\n\nThe goal of the decorator module is to make it easy to define\nsignature-preserving function decorators and decorator factories.\nIt also includes an implementation of multiple dispatch and other niceties\n(please check the docs). It is released under a two-clauses\nBSD license, i.e. basically you can do whatever you want with it but I am not\nresponsible.\n\nInstallation\n-------------\n\nIf you are lazy, just perform\n\n ``$ pip install decorator``\n\nwhich will install just the module on your system.\n\nIf you prefer to install the full distribution from source, including\nthe documentation, clone the `GitHub repo`_ or download the tarball_, unpack it and run\n\n ``$ pip install .``\n\nin the main directory, possibly as superuser.\n\n.. _tarball: https://pypi.org/project/decorator/#files\n.. _GitHub repo: https://github.com/micheles/decorator\n\nTesting\n--------\n\nIf you have the source code installation you can run the tests with\n\n `$ python src/tests/test.py -v`\n\nor (if you have setuptools installed)\n\n `$ python setup.py test`\n\nNotice that you may run into trouble if in your system there\nis an older version of the decorator module; in such a case remove the\nold version. It is safe even to copy the module `decorator.py` over\nan existing one, since we kept backward-compatibility for a long time.\n\nRepository\n---------------\n\nThe project is hosted on GitHub. You can look at the source here:\n\n https://github.com/micheles/decorator\n\nDocumentation\n---------------\n\nThe documentation has been moved to https://github.com/micheles/decorator/blob/master/docs/documentation.md\n\nFrom there you can get a PDF version by simply using the print\nfunctionality of your browser.\n\nHere is the documentation for previous versions of the module:\n\nhttps://github.com/micheles/decorator/blob/4.3.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.2.1/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.1.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.0.0/documentation.rst\nhttps://github.com/micheles/decorator/blob/3.4.2/documentation.rst\n\nFor the impatient\n-----------------\n\nHere is an example of how to define a family of decorators tracing slow\noperations:\n\n.. code-block:: python\n\n from decorator import decorator\n\n @decorator\n def warn_slow(func, timelimit=60, *args, **kw):\n t0 = time.time()\n result = func(*args, **kw)\n dt = time.time() - t0\n if dt > timelimit:\n logging.warn('%s took %d seconds', func.__name__, dt)\n else:\n logging.info('%s took %d seconds', func.__name__, dt)\n return result\n\n @warn_slow # warn if it takes more than 1 minute\n def preprocess_input_files(inputdir, tempdir):\n ...\n\n @warn_slow(timelimit=600) # warn if it takes more than 10 minutes\n def run_calculation(tempdir, outdir):\n ...\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +62,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=15) "new BSD License" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -93,7 +78,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=23) ">=2.6, !=3.0.*, !=3.1.*" diff --git a/.snapshots/TestParse-decorator_signed_wheel b/.snapshots/TestParse-decorator_signed_wheel index a96cd56..45dd186 100644 --- a/.snapshots/TestParse-decorator_signed_wheel +++ b/.snapshots/TestParse-decorator_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -35,18 +35,9 @@ (string) (len=42) "Topic :: Software Development :: Libraries", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2912) "Decorators for Humans\n=====================\n\nThe goal of the decorator module is to make it easy to define\nsignature-preserving function decorators and decorator factories.\nIt also includes an implementation of multiple dispatch and other niceties\n(please check the docs). It is released under a two-clauses\nBSD license, i.e. basically you can do whatever you want with it but I am not\nresponsible.\n\nInstallation\n-------------\n\nIf you are lazy, just perform\n\n ``$ pip install decorator``\n\nwhich will install just the module on your system.\n\nIf you prefer to install the full distribution from source, including\nthe documentation, clone the `GitHub repo`_ or download the tarball_, unpack it and run\n\n ``$ pip install .``\n\nin the main directory, possibly as superuser.\n\n.. _tarball: https://pypi.org/project/decorator/#files\n.. _GitHub repo: https://github.com/micheles/decorator\n\nTesting\n--------\n\nIf you have the source code installation you can run the tests with\n\n `$ python src/tests/test.py -v`\n\nor (if you have setuptools installed)\n\n `$ python setup.py test`\n\nNotice that you may run into trouble if in your system there\nis an older version of the decorator module; in such a case remove the\nold version. It is safe even to copy the module `decorator.py` over\nan existing one, since we kept backward-compatibility for a long time.\n\nRepository\n---------------\n\nThe project is hosted on GitHub. You can look at the source here:\n\n https://github.com/micheles/decorator\n\nDocumentation\n---------------\n\nThe documentation has been moved to https://github.com/micheles/decorator/blob/master/docs/documentation.md\n\nFrom there you can get a PDF version by simply using the print\nfunctionality of your browser.\n\nHere is the documentation for previous versions of the module:\n\nhttps://github.com/micheles/decorator/blob/4.3.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.2.1/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.1.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.0.0/documentation.rst\nhttps://github.com/micheles/decorator/blob/3.4.2/documentation.rst\n\nFor the impatient\n-----------------\n\nHere is an example of how to define a family of decorators tracing slow\noperations:\n\n.. code-block:: python\n\n from decorator import decorator\n\n @decorator\n def warn_slow(func, timelimit=60, *args, **kw):\n t0 = time.time()\n result = func(*args, **kw)\n dt = time.time() - t0\n if dt > timelimit:\n logging.warn('%s took %d seconds', func.__name__, dt)\n else:\n logging.info('%s took %d seconds', func.__name__, dt)\n return result\n\n @warn_slow # warn if it takes more than 1 minute\n def preprocess_input_files(inputdir, tempdir):\n ...\n\n @warn_slow(timelimit=600) # warn if it takes more than 10 minutes\n def run_calculation(tempdir, outdir):\n ...\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +62,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=15) "new BSD License" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-decorator_unsigned_tarball b/.snapshots/TestParse-decorator_unsigned_tarball index 9c1c290..be7e125 100644 --- a/.snapshots/TestParse-decorator_unsigned_tarball +++ b/.snapshots/TestParse-decorator_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -35,18 +35,9 @@ (string) (len=42) "Topic :: Software Development :: Libraries", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2912) "Decorators for Humans\n=====================\n\nThe goal of the decorator module is to make it easy to define\nsignature-preserving function decorators and decorator factories.\nIt also includes an implementation of multiple dispatch and other niceties\n(please check the docs). It is released under a two-clauses\nBSD license, i.e. basically you can do whatever you want with it but I am not\nresponsible.\n\nInstallation\n-------------\n\nIf you are lazy, just perform\n\n ``$ pip install decorator``\n\nwhich will install just the module on your system.\n\nIf you prefer to install the full distribution from source, including\nthe documentation, clone the `GitHub repo`_ or download the tarball_, unpack it and run\n\n ``$ pip install .``\n\nin the main directory, possibly as superuser.\n\n.. _tarball: https://pypi.org/project/decorator/#files\n.. _GitHub repo: https://github.com/micheles/decorator\n\nTesting\n--------\n\nIf you have the source code installation you can run the tests with\n\n `$ python src/tests/test.py -v`\n\nor (if you have setuptools installed)\n\n `$ python setup.py test`\n\nNotice that you may run into trouble if in your system there\nis an older version of the decorator module; in such a case remove the\nold version. It is safe even to copy the module `decorator.py` over\nan existing one, since we kept backward-compatibility for a long time.\n\nRepository\n---------------\n\nThe project is hosted on GitHub. You can look at the source here:\n\n https://github.com/micheles/decorator\n\nDocumentation\n---------------\n\nThe documentation has been moved to https://github.com/micheles/decorator/blob/master/docs/documentation.md\n\nFrom there you can get a PDF version by simply using the print\nfunctionality of your browser.\n\nHere is the documentation for previous versions of the module:\n\nhttps://github.com/micheles/decorator/blob/4.3.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.2.1/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.1.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.0.0/documentation.rst\nhttps://github.com/micheles/decorator/blob/3.4.2/documentation.rst\n\nFor the impatient\n-----------------\n\nHere is an example of how to define a family of decorators tracing slow\noperations:\n\n.. code-block:: python\n\n from decorator import decorator\n\n @decorator\n def warn_slow(func, timelimit=60, *args, **kw):\n t0 = time.time()\n result = func(*args, **kw)\n dt = time.time() - t0\n if dt > timelimit:\n logging.warn('%s took %d seconds', func.__name__, dt)\n else:\n logging.info('%s took %d seconds', func.__name__, dt)\n return result\n\n @warn_slow # warn if it takes more than 1 minute\n def preprocess_input_files(inputdir, tempdir):\n ...\n\n @warn_slow(timelimit=600) # warn if it takes more than 10 minutes\n def run_calculation(tempdir, outdir):\n ...\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +62,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=15) "new BSD License" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -93,7 +78,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=23) ">=2.6, !=3.0.*, !=3.1.*" diff --git a/.snapshots/TestParse-decorator_unsigned_wheel b/.snapshots/TestParse-decorator_unsigned_wheel index 90a0401..bf5d62e 100644 --- a/.snapshots/TestParse-decorator_unsigned_wheel +++ b/.snapshots/TestParse-decorator_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=21) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -35,18 +35,9 @@ (string) (len=42) "Topic :: Software Development :: Libraries", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=2912) "Decorators for Humans\n=====================\n\nThe goal of the decorator module is to make it easy to define\nsignature-preserving function decorators and decorator factories.\nIt also includes an implementation of multiple dispatch and other niceties\n(please check the docs). It is released under a two-clauses\nBSD license, i.e. basically you can do whatever you want with it but I am not\nresponsible.\n\nInstallation\n-------------\n\nIf you are lazy, just perform\n\n ``$ pip install decorator``\n\nwhich will install just the module on your system.\n\nIf you prefer to install the full distribution from source, including\nthe documentation, clone the `GitHub repo`_ or download the tarball_, unpack it and run\n\n ``$ pip install .``\n\nin the main directory, possibly as superuser.\n\n.. _tarball: https://pypi.org/project/decorator/#files\n.. _GitHub repo: https://github.com/micheles/decorator\n\nTesting\n--------\n\nIf you have the source code installation you can run the tests with\n\n `$ python src/tests/test.py -v`\n\nor (if you have setuptools installed)\n\n `$ python setup.py test`\n\nNotice that you may run into trouble if in your system there\nis an older version of the decorator module; in such a case remove the\nold version. It is safe even to copy the module `decorator.py` over\nan existing one, since we kept backward-compatibility for a long time.\n\nRepository\n---------------\n\nThe project is hosted on GitHub. You can look at the source here:\n\n https://github.com/micheles/decorator\n\nDocumentation\n---------------\n\nThe documentation has been moved to https://github.com/micheles/decorator/blob/master/docs/documentation.md\n\nFrom there you can get a PDF version by simply using the print\nfunctionality of your browser.\n\nHere is the documentation for previous versions of the module:\n\nhttps://github.com/micheles/decorator/blob/4.3.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.2.1/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.1.2/docs/tests.documentation.rst\nhttps://github.com/micheles/decorator/blob/4.0.0/documentation.rst\nhttps://github.com/micheles/decorator/blob/3.4.2/documentation.rst\n\nFor the impatient\n-----------------\n\nHere is an example of how to define a family of decorators tracing slow\noperations:\n\n.. code-block:: python\n\n from decorator import decorator\n\n @decorator\n def warn_slow(func, timelimit=60, *args, **kw):\n t0 = time.time()\n result = func(*args, **kw)\n dt = time.time() - t0\n if dt > timelimit:\n logging.warn('%s took %d seconds', func.__name__, dt)\n else:\n logging.info('%s took %d seconds', func.__name__, dt)\n return result\n\n @warn_slow # warn if it takes more than 1 minute\n def preprocess_input_files(inputdir, tempdir):\n ...\n\n @warn_slow(timelimit=600) # warn if it takes more than 10 minutes\n def run_calculation(tempdir, outdir):\n ...\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=10) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -71,12 +62,6 @@ (string) (len=7) "license": ([]string) (len=1) { (string) (len=15) "new BSD License" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-defusedxml_signed_tarball b/.snapshots/TestParse-defusedxml_signed_tarball index 672d251..944a673 100644 --- a/.snapshots/TestParse-defusedxml_signed_tarball +++ b/.snapshots/TestParse-defusedxml_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,15 +28,9 @@ (string) (len=37) "Programming Language :: Python :: 3.9", (string) (len=41) "Topic :: Text Processing :: Markup :: XML" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=31351) "===================================================\ndefusedxml -- defusing XML bombs and other exploits\n===================================================\n\n.. image:: https://img.shields.io/pypi/v/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Supported Python versions\n\n.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master\n :target: https://travis-ci.org/tiran/defusedxml\n :alt: Travis CI\n\n.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master\n :target: https://codecov.io/github/tiran/defusedxml?branch=master\n :alt: codecov\n\n.. image:: https://img.shields.io/pypi/dm/defusedxml.svg\n :target: https://pypistats.org/packages/defusedxml\n :alt: PyPI downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n..\n\n \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes \n\nSynopsis\n========\n\nThe results of an attack on a vulnerable XML library can be fairly dramatic.\nWith just a few hundred **Bytes** of XML data an attacker can occupy several\n**Gigabytes** of memory within **seconds**. An attacker can also keep\nCPUs busy for a long time with a small to medium size request. Under some\ncircumstances it is even possible to access local files on your\nserver, to circumvent a firewall, or to abuse services to rebound attacks to\nthird parties.\n\nThe attacks use and abuse less common features of XML and its parsers. The\nmajority of developers are unacquainted with features such as processing\ninstructions and entity expansions that XML inherited from SGML. At best\nthey know about ```` from experience with HTML but they are not\naware that a document type definition (DTD) can generate an HTTP request\nor load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not rely\nthat a library is always configured for security and potential harmful data\nby default.\n\n\n.. contents:: Table of Contents\n :depth: 2\n\n\nAttack vectors\n==============\n\nbillion laughs / exponential entity expansion\n---------------------------------------------\n\nThe `Billion Laughs`_ attack -- also known as exponential entity expansion --\nuses multiple levels of nested entities. The original example uses 9 levels\nof 10 expansions in each level to expand the string ``lol`` to a string of\n3 * 10 :sup:`9` bytes, hence the name \"billion laughs\". The resulting string\noccupies 3 GB (2.79 GiB) of memory; intermediate strings require additional\nmemory. Because most parsers don't cache the intermediate step for every\nexpansion it is repeated over and over again. It increases the CPU load even\nmore.\n\nAn XML document of just a few hundred bytes can disrupt all services on a\nmachine within seconds.\n\nExample XML::\n\n \n \n \n \n ]>\n &d;\n\n\nquadratic blowup entity expansion\n---------------------------------\n\nA quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large entity\nwith a couple of thousand chars over and over again. The attack isn't as\nefficient as the exponential case but it avoids triggering countermeasures of\nparsers against heavily nested entities. Some parsers limit the depth and\nbreadth of a single entity but not the total amount of expanded text\nthroughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can require a\ncouple of hundred MB to several GB of memory. When the attack is combined\nwith some level of nested expansion an attacker is able to achieve a higher\nratio of success.\n\n::\n\n \n ]>\n &a;&a;&a;... repeat\n\n\nexternal entity expansion (remote)\n----------------------------------\n\nEntity declarations can contain more than just text for replacement. They can\nalso point to external resources by public identifiers or system identifiers.\nSystem identifiers are standard URIs. When the URI is a URL (e.g. a\n``http://`` locator) some parsers download the resource from the remote\nlocation and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity::\n\n \n ]>\n \n\nThe case of parsed external entities works only for valid XML content. The\nXML standard also supports unparsed external entities with a\n``NData declaration``.\n\nExternal entity expansion opens the door to plenty of exploits. An attacker\ncan abuse a vulnerable XML library and application to rebound and forward\nnetwork requests with the IP address of the server. It highly depends\non the parser and the application what kind of exploit is possible. For\nexample:\n\n* An attacker can circumvent firewalls and gain access to restricted\n resources as all the requests are made from an internal and trustworthy\n IP address, not from the outside.\n* An attacker can abuse a service to attack, spy on or DoS your servers but\n also third party services. The attack is disguised with the IP address of\n the server and the attacker is able to utilize the high bandwidth of a big\n machine.\n* An attacker can exhaust additional resources on the machine, e.g. with\n requests to a service that doesn't respond or responds with very large\n files.\n* An attacker may gain knowledge, when, how often and from which IP address\n an XML document is accessed.\n* An attacker could send mail from inside your network if the URL handler\n supports ``smtp://`` URIs.\n\n\nexternal entity expansion (local file)\n--------------------------------------\n\nExternal entities with references to local files are a sub-case of external\nentity expansion. It's listed as an extra attack because it deserves extra\nattention. Some XML libraries such as lxml disable network access by default\nbut still allow entity expansion with local file access by default. Local\nfiles are either referenced with a ``file://`` URL or by a file path (either\nrelative or absolute).\n\nAn attacker may be able to access and download all files that can be read by\nthe application process. This may include critical configuration files, too.\n\n::\n\n \n ]>\n \n\n\nDTD retrieval\n-------------\n\nThis case is similar to external entity expansion, too. Some XML libraries\nlike Python's xml.dom.pulldom retrieve document type definitions from remote\nor local locations. Several attack scenarios from the external entity case\napply to this issue as well.\n\n::\n\n \n \n \n \n text\n \n\n\nPython XML Libraries\n====================\n\n.. csv-table:: vulnerabilities and features\n :header: \"kind\", \"sax\", \"etree\", \"minidom\", \"pulldom\", \"xmlrpc\", \"lxml\", \"genshi\"\n :widths: 24, 7, 8, 8, 7, 8, 8, 8\n :stub-columns: 0\n\n \"billion laughs\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (1)\", \"False (5)\"\n \"quadratic blowup\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (5)\"\n \"external entity expansion (remote)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"False (1)\", \"False (5)\"\n \"external entity expansion (local file)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"**True**\", \"False (5)\"\n \"DTD retrieval\", \"**True**\", \"False\", \"False\", \"**True**\", \"false\", \"False (1)\", \"False\"\n \"gzip bomb\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"**partly** (2)\", \"False\"\n \"xpath support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xsl(t) support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xinclude support (7)\", \"False\", \"**True** (6)\", \"False\", \"False\", \"False\", \"**True** (6)\", \"**True**\"\n \"C library\", \"expat\", \"expat\", \"expat\", \"expat\", \"expat\", \"libxml2\", \"expat\"\n\n1. Lxml is protected against billion laughs attacks and doesn't do network\n lookups by default.\n2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs\n but they don't protect you against them either.\n3. xml.etree doesn't expand entities and raises a ParserError when an entity\n occurs.\n4. minidom doesn't expand entities and simply returns the unexpanded entity\n verbatim.\n5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a\n ParserError when an entity occurs.\n6. Library has (limited) XInclude support but requires an additional step to\n process inclusion.\n7. These are features but they may introduce exploitable holes, see\n `Other things to consider`_\n\n\nSettings in standard library\n----------------------------\n\n\nxml.sax.handler Features\n........................\n\nfeature_external_ges (http://xml.org/sax/features/external-general-entities)\n disables external entity expansion\n\nfeature_external_pes (http://xml.org/sax/features/external-parameter-entities)\n the option is ignored and doesn't modify any functionality\n\nDOM xml.dom.xmlbuilder.Options\n..............................\n\nexternal_parameter_entities\n ignored\n\nexternal_general_entities\n ignored\n\nexternal_dtd_subset\n ignored\n\nentities\n unsure\n\n\ndefusedxml\n==========\n\nThe `defusedxml package`_ (`defusedxml on PyPI`_)\ncontains several Python-only workarounds and fixes\nfor denial of service and other vulnerabilities in Python's XML libraries.\nIn order to benefit from the protection you just have to import and use the\nlisted functions / classes from the right defusedxml module instead of the\noriginal module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.\n\nInstead of::\n\n >>> from xml.etree.ElementTree import parse\n >>> et = parse(xmlfile)\n\nalter code to::\n\n >>> from defusedxml.ElementTree import parse\n >>> et = parse(xmlfile)\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with ``defusedxml.defuse_stdlib()``.\n\nAll functions and parser classes accept three additional keyword arguments.\nThey return either the same objects as the original functions or compatible\nsubclasses.\n\nforbid_dtd (default: False)\n disallow XML with a ```` processing instruction and raise a\n *DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)\n disallow XML with ```` declarations inside the DTD and raise an\n *EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)\n disallow any access to remote or local resources in external entities\n or DTD and raising an *ExternalReferenceForbidden* exception when a DTD\n or entity references an external resource.\n\n\ndefusedxml (package)\n--------------------\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n\ndefusedxml.cElementTree\n-----------------------\n\n**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a\nfuture release. Import from ``defusedxml.ElementTree`` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.ElementTree\n-----------------------\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.expatreader\n----------------------\n\ncreate_parser(), DefusedExpatParser\n\n\ndefusedxml.sax\n--------------\n\nparse(), parseString(), make_parser()\n\n\ndefusedxml.expatbuilder\n-----------------------\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n\ndefusedxml.minidom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.pulldom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.xmlrpc\n-----------------\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)\nor xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,\n`unmonkey_patch()` removes the patch and puts the code in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The default\nsetting is 30 MB for requests, responses and gzip decompression. You can\nmodify the default by changing the module variable `MAX_DATA`. A value of\n`-1` disables the limit.\n\n\ndefusedxml.lxml\n---------------\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out\nEntity instances, a custom parser factory and a thread local storage for\nparser instances. It also has a check_docinfo() function which inspects\na tree for internal or external DTDs and entity declarations. In order to\ncheck for entities lxml > 3.0 is required.\n\nparse(), fromstring()\nRestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()\n\n\ndefusedexpat\n============\n\nThe `defusedexpat package`_ (`defusedexpat on PyPI`_)\ncomes with binary extensions and a\n`modified expat`_ library instead of the standard `expat parser`_. It's\nbasically a stand-alone version of the patches for Python's standard\nlibrary C extensions.\n\nModifications in expat\n----------------------\n\nnew definitions::\n\n XML_BOMB_PROTECTION\n XML_DEFAULT_MAX_ENTITY_INDIRECTIONS\n XML_DEFAULT_MAX_ENTITY_EXPANSIONS\n XML_DEFAULT_RESET_DTD\n\nnew XML_FeatureEnum members::\n\n XML_FEATURE_MAX_ENTITY_INDIRECTIONS\n XML_FEATURE_MAX_ENTITY_EXPANSIONS\n XML_FEATURE_IGNORE_DTD\n\nnew XML_Error members::\n\n XML_ERROR_ENTITY_INDIRECTIONS\n XML_ERROR_ENTITY_EXPANSION\n\nnew API functions::\n\n int XML_GetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long value);\n int XML_GetFeatureDefault(enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeatureDefault(enum XML_FeatureEnum feature,\n long value);\n\nXML_FEATURE_MAX_ENTITY_INDIRECTIONS\n Limit the amount of indirections that are allowed to occur during the\n expansion of a nested entity. A counter starts when an entity reference\n is encountered. It resets after the entity is fully expanded. The limit\n protects the parser against exponential entity expansion attacks (aka\n billion laughs attack). When the limit is exceeded the parser stops and\n fails with `XML_ERROR_ENTITY_INDIRECTIONS`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 40\n\nXML_FEATURE_MAX_ENTITY_EXPANSIONS\n Limit the total length of all entity expansions throughout the entire\n document. The lengths of all entities are accumulated in a parser variable.\n The setting protects against quadratic blowup attacks (lots of expansions\n of a large entity declaration). When the sum of all entities exceeds\n the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 8 MiB\n\nXML_FEATURE_RESET_DTD\n Reset all DTD information after the block has been parsed. When\n the flag is set (default: false) all DTD information after the\n endDoctypeDeclHandler has been called. The flag can be set inside the\n endDoctypeDeclHandler. Without DTD information any entity reference in\n the document body leads to `XML_ERROR_UNDEFINED_ENTITY`.\n\n Supported range\n 0, 1\n Default\n 0\n\n\nHow to avoid XML vulnerabilities\n================================\n\nBest practices\n--------------\n\n* Don't allow DTDs\n* Don't expand entities\n* Don't resolve externals\n* Limit parse depth\n* Limit total input size\n* Limit parse time\n* Favor a SAX or iterparse-like parser for potential large data\n* Validate and properly quote arguments to XSL transformations and\n XPath queries\n* Don't use XPath expression from untrusted sources\n* Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's `Attacking XML Security`_)\n\n\nOther things to consider\n========================\n\nXML, XML parsers and processing libraries have more features and possible\nissue that could lead to DoS vulnerabilities or security exploits in\napplications. I have compiled an incomplete list of theoretical issues that\nneed further research and more attention. The list is deliberately pessimistic\nand a bit paranoid, too. It contains things that might go wrong under daffy\ncircumstances.\n\n\nattribute blowup / hash collision attack\n----------------------------------------\n\nXML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to\nhandle attributes and namespaces. If it uses hash tables (dictionaries) to\nstore attributes and namespaces the implementation may be vulnerable to\nhash collision attacks, thus reducing the performance to O(n :sup:`2`) again.\nIn either case an attacker is able to forge a denial of service attack with\nan XML document that contains thousands upon thousands of attributes in\na single node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n\ndecompression bomb\n------------------\n\nThe issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries\nthat can parse compressed XML stream like gzipped HTTP streams or LZMA-ed\nfiles. For an attacker it can reduce the amount of transmitted data by three\nmagnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,\nlzma is even better::\n\n $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n $ ls -sh zeros.*\n 1020K zeros.gz\n 148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n``xmlrpclib``. The module is vulnerable \nto decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach can\nbe safe.\n\n\nProcessing Instruction\n----------------------\n\n`PI`_'s like::\n\n \n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval with\nnetwork or local file access apply to processing instructions, too.\n\n\nOther DTD features\n------------------\n\n`DTD`_ has more features like ````. I haven't researched how\nthese features may be a security threat.\n\n\nXPath\n-----\n\nXPath statements may introduce DoS vulnerabilities. Code should never execute\nqueries from untrusted sources. An attacker may also be able to create an XML\ndocument that makes certain XPath queries costly or resource hungry.\n\n\nXPath injection attacks\n-----------------------\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly, especially\nwhen they are taken from the user. The page `Avoid the dangers of XPath injection`_\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to use\nits xpath() method correctly::\n\n # DON'T\n >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n # instead do\n >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n\nXInclude\n--------\n\n`XML Inclusion`_ is another way to load and include external files::\n\n \n \n \n\nThis feature should be disabled when XML files from an untrusted source are\nprocessed. Some Python XML libraries and libxml2 support XInclude but don't\nhave an option to sandbox inclusion and limit it to allowed directories.\n\n\nXMLSchema location\n------------------\n\nA validating XML parser may download schema files from the information in a\n``xsi:schemaLocation`` attribute.\n\n::\n\n \n \n\n\nXSL Transformation\n------------------\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even imagine.\nSome processors even support extensions that allow read/write access to file\nsystem, access to JRE objects or scripting with Jython.\n\nExample from `Attacking XML Security`_ for Xalan-J::\n\n \n \n \n \n \n \n \n \n\n\nRelated CVEs\n============\n\nCVE-2013-1664\n Unrestricted entity expansion induces DoS vulnerabilities in Python XML\n libraries (XML bomb)\n\nCVE-2013-1665\n External entity expansion in Python XML libraries inflicts potential\n security flaws and DoS vulnerabilities\n\n\nOther languages / frameworks\n=============================\n\nSeveral other programming languages and frameworks are vulnerable as well. A\ncouple of them are affected by the fact that libxml2 up to 2.9.0 has no\nprotection against quadratic blowup attacks. Most of them have potential\ndangerous default settings for entity expansion and external entities, too.\n\nPerl\n----\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and external\nentity expansion (both local and remote).\n\n\nRuby\n----\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have to\ndisable the feature::\n\n REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default configuration.\n\n\nPHP\n---\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and loads\nentities from local and remote resources. The option ``LIBXML_NONET`` disables\nnetwork access but still allows local file access. ``LIBXML_NOENT`` seems to\nhave no effect on entity expansion in PHP 5.4.6.\n\n\nC# / .NET / Mono\n----------------\n\nInformation in `XML DoS and Defenses (MSDN)`_ suggest that .NET is\nvulnerable with its default settings. The article contains code snippets\nhow to create a secure XML reader::\n\n XmlReaderSettings settings = new XmlReaderSettings();\n settings.ProhibitDtd = false;\n settings.MaxCharactersFromEntities = 1024;\n settings.XmlResolver = null;\n XmlReader reader = XmlReader.Create(stream, settings);\n\n\nJava\n----\n\nUntested. The documentation of Xerces and its `Xerces SecurityMananger`_\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory::\n\n DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n builderFactory.setXIncludeAware(False);\n builderFactory.setExpandEntityReferences(False);\n builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n # either\n builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n # or if you need DTDs\n builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n\nTODO\n====\n\n* DOM: Use xml.dom.xmlbuilder options for entity handling\n* SAX: take feature_external_ges and feature_external_pes (?) into account\n* test experimental monkey patching of stdlib modules\n* improve documentation\n\n\nLicense\n=======\n\nCopyright (c) 2013-2017 by Christian Heimes \n\nLicensed to PSF under a Contributor Agreement.\n\nSee https://www.python.org/psf/license for licensing details.\n\n\nAcknowledgements\n================\n\nBrett Cannon (Python Core developer)\n review and code cleanup\n\nAntoine Pitrou (Python Core developer)\n code review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)\n Many thanks to Aaron, Ben and Michael from the Ruby community for their\n report and assistance.\n\nThierry Carrez (OpenStack)\n Many thanks to Thierry for his report to the Python Security Response\n Team on behalf of the OpenStack security team.\n\nCarl Meyer (Django)\n Many thanks to Carl for his report to PSRT on behalf of the Django security\n team.\n\nDaniel Veillard (libxml2)\n Many thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (https://www.semantics.de/)\n Many thanks to my employer semantics for letting me work on the issue\n during working hours as part of semantics's open source initiative.\n\n\nReferences\n==========\n\n* `XML DoS and Defenses (MSDN)`_\n* `Billion Laughs`_ on Wikipedia\n* `ZIP bomb`_ on Wikipedia\n* `Configure SAX parsers for secure processing`_\n* `Testing for XML Injection`_\n\n.. _defusedxml package: https://github.com/tiran/defusedxml\n.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml\n.. _defusedexpat package: https://github.com/tiran/defusedexpat\n.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat\n.. _modified expat: https://github.com/tiran/expat\n.. _expat parser: http://expat.sourceforge.net/\n.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf\n.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs\n.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx\n.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb\n.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition\n.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction\n.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html\n.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html\n.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)\n.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html\n.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element\n\nChangelog\n=========\n\ndefusedxml 0.7.1\n---------------------\n\n*Release date: 08-Mar-2021*\n\n- Fix regression ``defusedxml.ElementTree.ParseError`` (#63)\n The ``ParseError`` exception is now the same class object as\n ``xml.etree.ElementTree.ParseError`` again.\n\n\ndefusedxml 0.7.0\n----------------\n\n*Release date: 4-Mar-2021*\n\n- No changes\n\n\ndefusedxml 0.7.0rc2\n-------------------\n\n*Release date: 12-Jan-2021*\n\n- Re-add and deprecate ``defusedxml.cElementTree``\n- Use GitHub Actions instead of TravisCI\n- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching\n\ndefusedxml 0.7.0rc1\n-------------------\n\n*Release date: 04-May-2020*\n\n- Add support for Python 3.9\n- ``defusedxml.cElementTree`` is not available with Python 3.9.\n- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0.\n\n\ndefusedxml 0.6.0\n----------------\n\n*Release date: 17-Apr-2019*\n\n- Increase test coverage.\n- Add badges to README.\n\n\ndefusedxml 0.6.0rc1\n-------------------\n\n*Release date: 14-Apr-2019*\n\n- Test on Python 3.7 stable and 3.8-dev\n- Drop support for Python 3.4\n- No longer pass *html* argument to XMLParse. It has been deprecated and\n ignored for a long time. The DefusedXMLParser still takes a html argument.\n A deprecation warning is issued when the argument is False and a TypeError\n when it's True.\n- defusedxml now fails early when pyexpat stdlib module is not available or\n broken.\n- defusedxml.ElementTree.__all__ now lists ParseError as public attribute.\n- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo\n and used XMLParse instead of XMLParser as an alias for DefusedXMLParser.\n Both the old and fixed name are now available.\n\n\ndefusedxml 0.5.0\n----------------\n\n*Release date: 07-Feb-2017*\n\n- No changes\n\n\ndefusedxml 0.5.0.rc1\n--------------------\n\n*Release date: 28-Jan-2017*\n\n- Add compatibility with Python 3.6\n- Drop support for Python 2.6, 3.1, 3.2, 3.3\n- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n\ndefusedxml 0.4.1\n----------------\n\n*Release date: 28-Mar-2013*\n\n- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.\n- Improved documentation.\n\n\ndefusedxml 0.4\n--------------\n\n*Release date: 25-Feb-2013*\n\n- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT\n CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,\n CVE-2013-1665 for OpenStack/etc.\n- Add missing parser_list argument to sax.make_parser(). The argument is\n ignored, though. (thanks to Florian Apolloner)\n- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC\n and WebDAV.\n\n\ndefusedxml 0.3\n--------------\n\n*Release date: 19-Feb-2013*\n\n- Improve documentation\n\n\ndefusedxml 0.2\n--------------\n\n*Release date: 15-Feb-2013*\n\n- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n- Rename defusedxml.lxml.check_dtd() to check_docinfo()\n- Unify argument names in callbacks\n- Add arguments and formatted representation to exceptions\n- Add forbid_external argument to all functions and classes\n- More tests\n- LOTS of documentation\n- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)\n- Add protection against XML and gzip attacks to xmlrpclib\n\ndefusedxml 0.1\n--------------\n\n*Release date: 08-Feb-2013*\n\n- Initial and internal release for PSRT review\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, (string) (len=12) "download_url": ([]string) (len=1) { (string) (len=39) "https://pypi.python.org/pypi/defusedxml" }, @@ -89,7 +83,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=50) ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" diff --git a/.snapshots/TestParse-defusedxml_signed_wheel b/.snapshots/TestParse-defusedxml_signed_wheel index 9bc3e0d..43411e7 100644 --- a/.snapshots/TestParse-defusedxml_signed_wheel +++ b/.snapshots/TestParse-defusedxml_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,15 +28,9 @@ (string) (len=37) "Programming Language :: Python :: 3.9", (string) (len=41) "Topic :: Text Processing :: Markup :: XML" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=31351) "===================================================\ndefusedxml -- defusing XML bombs and other exploits\n===================================================\n\n.. image:: https://img.shields.io/pypi/v/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Supported Python versions\n\n.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master\n :target: https://travis-ci.org/tiran/defusedxml\n :alt: Travis CI\n\n.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master\n :target: https://codecov.io/github/tiran/defusedxml?branch=master\n :alt: codecov\n\n.. image:: https://img.shields.io/pypi/dm/defusedxml.svg\n :target: https://pypistats.org/packages/defusedxml\n :alt: PyPI downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n..\n\n \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes \n\nSynopsis\n========\n\nThe results of an attack on a vulnerable XML library can be fairly dramatic.\nWith just a few hundred **Bytes** of XML data an attacker can occupy several\n**Gigabytes** of memory within **seconds**. An attacker can also keep\nCPUs busy for a long time with a small to medium size request. Under some\ncircumstances it is even possible to access local files on your\nserver, to circumvent a firewall, or to abuse services to rebound attacks to\nthird parties.\n\nThe attacks use and abuse less common features of XML and its parsers. The\nmajority of developers are unacquainted with features such as processing\ninstructions and entity expansions that XML inherited from SGML. At best\nthey know about ```` from experience with HTML but they are not\naware that a document type definition (DTD) can generate an HTTP request\nor load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not rely\nthat a library is always configured for security and potential harmful data\nby default.\n\n\n.. contents:: Table of Contents\n :depth: 2\n\n\nAttack vectors\n==============\n\nbillion laughs / exponential entity expansion\n---------------------------------------------\n\nThe `Billion Laughs`_ attack -- also known as exponential entity expansion --\nuses multiple levels of nested entities. The original example uses 9 levels\nof 10 expansions in each level to expand the string ``lol`` to a string of\n3 * 10 :sup:`9` bytes, hence the name \"billion laughs\". The resulting string\noccupies 3 GB (2.79 GiB) of memory; intermediate strings require additional\nmemory. Because most parsers don't cache the intermediate step for every\nexpansion it is repeated over and over again. It increases the CPU load even\nmore.\n\nAn XML document of just a few hundred bytes can disrupt all services on a\nmachine within seconds.\n\nExample XML::\n\n \n \n \n \n ]>\n &d;\n\n\nquadratic blowup entity expansion\n---------------------------------\n\nA quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large entity\nwith a couple of thousand chars over and over again. The attack isn't as\nefficient as the exponential case but it avoids triggering countermeasures of\nparsers against heavily nested entities. Some parsers limit the depth and\nbreadth of a single entity but not the total amount of expanded text\nthroughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can require a\ncouple of hundred MB to several GB of memory. When the attack is combined\nwith some level of nested expansion an attacker is able to achieve a higher\nratio of success.\n\n::\n\n \n ]>\n &a;&a;&a;... repeat\n\n\nexternal entity expansion (remote)\n----------------------------------\n\nEntity declarations can contain more than just text for replacement. They can\nalso point to external resources by public identifiers or system identifiers.\nSystem identifiers are standard URIs. When the URI is a URL (e.g. a\n``http://`` locator) some parsers download the resource from the remote\nlocation and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity::\n\n \n ]>\n \n\nThe case of parsed external entities works only for valid XML content. The\nXML standard also supports unparsed external entities with a\n``NData declaration``.\n\nExternal entity expansion opens the door to plenty of exploits. An attacker\ncan abuse a vulnerable XML library and application to rebound and forward\nnetwork requests with the IP address of the server. It highly depends\non the parser and the application what kind of exploit is possible. For\nexample:\n\n* An attacker can circumvent firewalls and gain access to restricted\n resources as all the requests are made from an internal and trustworthy\n IP address, not from the outside.\n* An attacker can abuse a service to attack, spy on or DoS your servers but\n also third party services. The attack is disguised with the IP address of\n the server and the attacker is able to utilize the high bandwidth of a big\n machine.\n* An attacker can exhaust additional resources on the machine, e.g. with\n requests to a service that doesn't respond or responds with very large\n files.\n* An attacker may gain knowledge, when, how often and from which IP address\n an XML document is accessed.\n* An attacker could send mail from inside your network if the URL handler\n supports ``smtp://`` URIs.\n\n\nexternal entity expansion (local file)\n--------------------------------------\n\nExternal entities with references to local files are a sub-case of external\nentity expansion. It's listed as an extra attack because it deserves extra\nattention. Some XML libraries such as lxml disable network access by default\nbut still allow entity expansion with local file access by default. Local\nfiles are either referenced with a ``file://`` URL or by a file path (either\nrelative or absolute).\n\nAn attacker may be able to access and download all files that can be read by\nthe application process. This may include critical configuration files, too.\n\n::\n\n \n ]>\n \n\n\nDTD retrieval\n-------------\n\nThis case is similar to external entity expansion, too. Some XML libraries\nlike Python's xml.dom.pulldom retrieve document type definitions from remote\nor local locations. Several attack scenarios from the external entity case\napply to this issue as well.\n\n::\n\n \n \n \n \n text\n \n\n\nPython XML Libraries\n====================\n\n.. csv-table:: vulnerabilities and features\n :header: \"kind\", \"sax\", \"etree\", \"minidom\", \"pulldom\", \"xmlrpc\", \"lxml\", \"genshi\"\n :widths: 24, 7, 8, 8, 7, 8, 8, 8\n :stub-columns: 0\n\n \"billion laughs\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (1)\", \"False (5)\"\n \"quadratic blowup\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (5)\"\n \"external entity expansion (remote)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"False (1)\", \"False (5)\"\n \"external entity expansion (local file)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"**True**\", \"False (5)\"\n \"DTD retrieval\", \"**True**\", \"False\", \"False\", \"**True**\", \"false\", \"False (1)\", \"False\"\n \"gzip bomb\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"**partly** (2)\", \"False\"\n \"xpath support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xsl(t) support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xinclude support (7)\", \"False\", \"**True** (6)\", \"False\", \"False\", \"False\", \"**True** (6)\", \"**True**\"\n \"C library\", \"expat\", \"expat\", \"expat\", \"expat\", \"expat\", \"libxml2\", \"expat\"\n\n1. Lxml is protected against billion laughs attacks and doesn't do network\n lookups by default.\n2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs\n but they don't protect you against them either.\n3. xml.etree doesn't expand entities and raises a ParserError when an entity\n occurs.\n4. minidom doesn't expand entities and simply returns the unexpanded entity\n verbatim.\n5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a\n ParserError when an entity occurs.\n6. Library has (limited) XInclude support but requires an additional step to\n process inclusion.\n7. These are features but they may introduce exploitable holes, see\n `Other things to consider`_\n\n\nSettings in standard library\n----------------------------\n\n\nxml.sax.handler Features\n........................\n\nfeature_external_ges (http://xml.org/sax/features/external-general-entities)\n disables external entity expansion\n\nfeature_external_pes (http://xml.org/sax/features/external-parameter-entities)\n the option is ignored and doesn't modify any functionality\n\nDOM xml.dom.xmlbuilder.Options\n..............................\n\nexternal_parameter_entities\n ignored\n\nexternal_general_entities\n ignored\n\nexternal_dtd_subset\n ignored\n\nentities\n unsure\n\n\ndefusedxml\n==========\n\nThe `defusedxml package`_ (`defusedxml on PyPI`_)\ncontains several Python-only workarounds and fixes\nfor denial of service and other vulnerabilities in Python's XML libraries.\nIn order to benefit from the protection you just have to import and use the\nlisted functions / classes from the right defusedxml module instead of the\noriginal module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.\n\nInstead of::\n\n >>> from xml.etree.ElementTree import parse\n >>> et = parse(xmlfile)\n\nalter code to::\n\n >>> from defusedxml.ElementTree import parse\n >>> et = parse(xmlfile)\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with ``defusedxml.defuse_stdlib()``.\n\nAll functions and parser classes accept three additional keyword arguments.\nThey return either the same objects as the original functions or compatible\nsubclasses.\n\nforbid_dtd (default: False)\n disallow XML with a ```` processing instruction and raise a\n *DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)\n disallow XML with ```` declarations inside the DTD and raise an\n *EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)\n disallow any access to remote or local resources in external entities\n or DTD and raising an *ExternalReferenceForbidden* exception when a DTD\n or entity references an external resource.\n\n\ndefusedxml (package)\n--------------------\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n\ndefusedxml.cElementTree\n-----------------------\n\n**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a\nfuture release. Import from ``defusedxml.ElementTree`` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.ElementTree\n-----------------------\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.expatreader\n----------------------\n\ncreate_parser(), DefusedExpatParser\n\n\ndefusedxml.sax\n--------------\n\nparse(), parseString(), make_parser()\n\n\ndefusedxml.expatbuilder\n-----------------------\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n\ndefusedxml.minidom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.pulldom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.xmlrpc\n-----------------\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)\nor xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,\n`unmonkey_patch()` removes the patch and puts the code in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The default\nsetting is 30 MB for requests, responses and gzip decompression. You can\nmodify the default by changing the module variable `MAX_DATA`. A value of\n`-1` disables the limit.\n\n\ndefusedxml.lxml\n---------------\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out\nEntity instances, a custom parser factory and a thread local storage for\nparser instances. It also has a check_docinfo() function which inspects\na tree for internal or external DTDs and entity declarations. In order to\ncheck for entities lxml > 3.0 is required.\n\nparse(), fromstring()\nRestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()\n\n\ndefusedexpat\n============\n\nThe `defusedexpat package`_ (`defusedexpat on PyPI`_)\ncomes with binary extensions and a\n`modified expat`_ library instead of the standard `expat parser`_. It's\nbasically a stand-alone version of the patches for Python's standard\nlibrary C extensions.\n\nModifications in expat\n----------------------\n\nnew definitions::\n\n XML_BOMB_PROTECTION\n XML_DEFAULT_MAX_ENTITY_INDIRECTIONS\n XML_DEFAULT_MAX_ENTITY_EXPANSIONS\n XML_DEFAULT_RESET_DTD\n\nnew XML_FeatureEnum members::\n\n XML_FEATURE_MAX_ENTITY_INDIRECTIONS\n XML_FEATURE_MAX_ENTITY_EXPANSIONS\n XML_FEATURE_IGNORE_DTD\n\nnew XML_Error members::\n\n XML_ERROR_ENTITY_INDIRECTIONS\n XML_ERROR_ENTITY_EXPANSION\n\nnew API functions::\n\n int XML_GetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long value);\n int XML_GetFeatureDefault(enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeatureDefault(enum XML_FeatureEnum feature,\n long value);\n\nXML_FEATURE_MAX_ENTITY_INDIRECTIONS\n Limit the amount of indirections that are allowed to occur during the\n expansion of a nested entity. A counter starts when an entity reference\n is encountered. It resets after the entity is fully expanded. The limit\n protects the parser against exponential entity expansion attacks (aka\n billion laughs attack). When the limit is exceeded the parser stops and\n fails with `XML_ERROR_ENTITY_INDIRECTIONS`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 40\n\nXML_FEATURE_MAX_ENTITY_EXPANSIONS\n Limit the total length of all entity expansions throughout the entire\n document. The lengths of all entities are accumulated in a parser variable.\n The setting protects against quadratic blowup attacks (lots of expansions\n of a large entity declaration). When the sum of all entities exceeds\n the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 8 MiB\n\nXML_FEATURE_RESET_DTD\n Reset all DTD information after the block has been parsed. When\n the flag is set (default: false) all DTD information after the\n endDoctypeDeclHandler has been called. The flag can be set inside the\n endDoctypeDeclHandler. Without DTD information any entity reference in\n the document body leads to `XML_ERROR_UNDEFINED_ENTITY`.\n\n Supported range\n 0, 1\n Default\n 0\n\n\nHow to avoid XML vulnerabilities\n================================\n\nBest practices\n--------------\n\n* Don't allow DTDs\n* Don't expand entities\n* Don't resolve externals\n* Limit parse depth\n* Limit total input size\n* Limit parse time\n* Favor a SAX or iterparse-like parser for potential large data\n* Validate and properly quote arguments to XSL transformations and\n XPath queries\n* Don't use XPath expression from untrusted sources\n* Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's `Attacking XML Security`_)\n\n\nOther things to consider\n========================\n\nXML, XML parsers and processing libraries have more features and possible\nissue that could lead to DoS vulnerabilities or security exploits in\napplications. I have compiled an incomplete list of theoretical issues that\nneed further research and more attention. The list is deliberately pessimistic\nand a bit paranoid, too. It contains things that might go wrong under daffy\ncircumstances.\n\n\nattribute blowup / hash collision attack\n----------------------------------------\n\nXML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to\nhandle attributes and namespaces. If it uses hash tables (dictionaries) to\nstore attributes and namespaces the implementation may be vulnerable to\nhash collision attacks, thus reducing the performance to O(n :sup:`2`) again.\nIn either case an attacker is able to forge a denial of service attack with\nan XML document that contains thousands upon thousands of attributes in\na single node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n\ndecompression bomb\n------------------\n\nThe issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries\nthat can parse compressed XML stream like gzipped HTTP streams or LZMA-ed\nfiles. For an attacker it can reduce the amount of transmitted data by three\nmagnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,\nlzma is even better::\n\n $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n $ ls -sh zeros.*\n 1020K zeros.gz\n 148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n``xmlrpclib``. The module is vulnerable \nto decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach can\nbe safe.\n\n\nProcessing Instruction\n----------------------\n\n`PI`_'s like::\n\n \n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval with\nnetwork or local file access apply to processing instructions, too.\n\n\nOther DTD features\n------------------\n\n`DTD`_ has more features like ````. I haven't researched how\nthese features may be a security threat.\n\n\nXPath\n-----\n\nXPath statements may introduce DoS vulnerabilities. Code should never execute\nqueries from untrusted sources. An attacker may also be able to create an XML\ndocument that makes certain XPath queries costly or resource hungry.\n\n\nXPath injection attacks\n-----------------------\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly, especially\nwhen they are taken from the user. The page `Avoid the dangers of XPath injection`_\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to use\nits xpath() method correctly::\n\n # DON'T\n >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n # instead do\n >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n\nXInclude\n--------\n\n`XML Inclusion`_ is another way to load and include external files::\n\n \n \n \n\nThis feature should be disabled when XML files from an untrusted source are\nprocessed. Some Python XML libraries and libxml2 support XInclude but don't\nhave an option to sandbox inclusion and limit it to allowed directories.\n\n\nXMLSchema location\n------------------\n\nA validating XML parser may download schema files from the information in a\n``xsi:schemaLocation`` attribute.\n\n::\n\n \n \n\n\nXSL Transformation\n------------------\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even imagine.\nSome processors even support extensions that allow read/write access to file\nsystem, access to JRE objects or scripting with Jython.\n\nExample from `Attacking XML Security`_ for Xalan-J::\n\n \n \n \n \n \n \n \n \n\n\nRelated CVEs\n============\n\nCVE-2013-1664\n Unrestricted entity expansion induces DoS vulnerabilities in Python XML\n libraries (XML bomb)\n\nCVE-2013-1665\n External entity expansion in Python XML libraries inflicts potential\n security flaws and DoS vulnerabilities\n\n\nOther languages / frameworks\n=============================\n\nSeveral other programming languages and frameworks are vulnerable as well. A\ncouple of them are affected by the fact that libxml2 up to 2.9.0 has no\nprotection against quadratic blowup attacks. Most of them have potential\ndangerous default settings for entity expansion and external entities, too.\n\nPerl\n----\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and external\nentity expansion (both local and remote).\n\n\nRuby\n----\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have to\ndisable the feature::\n\n REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default configuration.\n\n\nPHP\n---\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and loads\nentities from local and remote resources. The option ``LIBXML_NONET`` disables\nnetwork access but still allows local file access. ``LIBXML_NOENT`` seems to\nhave no effect on entity expansion in PHP 5.4.6.\n\n\nC# / .NET / Mono\n----------------\n\nInformation in `XML DoS and Defenses (MSDN)`_ suggest that .NET is\nvulnerable with its default settings. The article contains code snippets\nhow to create a secure XML reader::\n\n XmlReaderSettings settings = new XmlReaderSettings();\n settings.ProhibitDtd = false;\n settings.MaxCharactersFromEntities = 1024;\n settings.XmlResolver = null;\n XmlReader reader = XmlReader.Create(stream, settings);\n\n\nJava\n----\n\nUntested. The documentation of Xerces and its `Xerces SecurityMananger`_\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory::\n\n DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n builderFactory.setXIncludeAware(False);\n builderFactory.setExpandEntityReferences(False);\n builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n # either\n builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n # or if you need DTDs\n builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n\nTODO\n====\n\n* DOM: Use xml.dom.xmlbuilder options for entity handling\n* SAX: take feature_external_ges and feature_external_pes (?) into account\n* test experimental monkey patching of stdlib modules\n* improve documentation\n\n\nLicense\n=======\n\nCopyright (c) 2013-2017 by Christian Heimes \n\nLicensed to PSF under a Contributor Agreement.\n\nSee https://www.python.org/psf/license for licensing details.\n\n\nAcknowledgements\n================\n\nBrett Cannon (Python Core developer)\n review and code cleanup\n\nAntoine Pitrou (Python Core developer)\n code review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)\n Many thanks to Aaron, Ben and Michael from the Ruby community for their\n report and assistance.\n\nThierry Carrez (OpenStack)\n Many thanks to Thierry for his report to the Python Security Response\n Team on behalf of the OpenStack security team.\n\nCarl Meyer (Django)\n Many thanks to Carl for his report to PSRT on behalf of the Django security\n team.\n\nDaniel Veillard (libxml2)\n Many thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (https://www.semantics.de/)\n Many thanks to my employer semantics for letting me work on the issue\n during working hours as part of semantics's open source initiative.\n\n\nReferences\n==========\n\n* `XML DoS and Defenses (MSDN)`_\n* `Billion Laughs`_ on Wikipedia\n* `ZIP bomb`_ on Wikipedia\n* `Configure SAX parsers for secure processing`_\n* `Testing for XML Injection`_\n\n.. _defusedxml package: https://github.com/tiran/defusedxml\n.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml\n.. _defusedexpat package: https://github.com/tiran/defusedexpat\n.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat\n.. _modified expat: https://github.com/tiran/expat\n.. _expat parser: http://expat.sourceforge.net/\n.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf\n.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs\n.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx\n.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb\n.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition\n.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction\n.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html\n.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html\n.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)\n.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html\n.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element\n\nChangelog\n=========\n\ndefusedxml 0.7.1\n---------------------\n\n*Release date: 08-Mar-2021*\n\n- Fix regression ``defusedxml.ElementTree.ParseError`` (#63)\n The ``ParseError`` exception is now the same class object as\n ``xml.etree.ElementTree.ParseError`` again.\n\n\ndefusedxml 0.7.0\n----------------\n\n*Release date: 4-Mar-2021*\n\n- No changes\n\n\ndefusedxml 0.7.0rc2\n-------------------\n\n*Release date: 12-Jan-2021*\n\n- Re-add and deprecate ``defusedxml.cElementTree``\n- Use GitHub Actions instead of TravisCI\n- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching\n\ndefusedxml 0.7.0rc1\n-------------------\n\n*Release date: 04-May-2020*\n\n- Add support for Python 3.9\n- ``defusedxml.cElementTree`` is not available with Python 3.9.\n- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0.\n\n\ndefusedxml 0.6.0\n----------------\n\n*Release date: 17-Apr-2019*\n\n- Increase test coverage.\n- Add badges to README.\n\n\ndefusedxml 0.6.0rc1\n-------------------\n\n*Release date: 14-Apr-2019*\n\n- Test on Python 3.7 stable and 3.8-dev\n- Drop support for Python 3.4\n- No longer pass *html* argument to XMLParse. It has been deprecated and\n ignored for a long time. The DefusedXMLParser still takes a html argument.\n A deprecation warning is issued when the argument is False and a TypeError\n when it's True.\n- defusedxml now fails early when pyexpat stdlib module is not available or\n broken.\n- defusedxml.ElementTree.__all__ now lists ParseError as public attribute.\n- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo\n and used XMLParse instead of XMLParser as an alias for DefusedXMLParser.\n Both the old and fixed name are now available.\n\n\ndefusedxml 0.5.0\n----------------\n\n*Release date: 07-Feb-2017*\n\n- No changes\n\n\ndefusedxml 0.5.0.rc1\n--------------------\n\n*Release date: 28-Jan-2017*\n\n- Add compatibility with Python 3.6\n- Drop support for Python 2.6, 3.1, 3.2, 3.3\n- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n\ndefusedxml 0.4.1\n----------------\n\n*Release date: 28-Mar-2013*\n\n- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.\n- Improved documentation.\n\n\ndefusedxml 0.4\n--------------\n\n*Release date: 25-Feb-2013*\n\n- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT\n CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,\n CVE-2013-1665 for OpenStack/etc.\n- Add missing parser_list argument to sax.make_parser(). The argument is\n ignored, though. (thanks to Florian Apolloner)\n- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC\n and WebDAV.\n\n\ndefusedxml 0.3\n--------------\n\n*Release date: 19-Feb-2013*\n\n- Improve documentation\n\n\ndefusedxml 0.2\n--------------\n\n*Release date: 15-Feb-2013*\n\n- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n- Rename defusedxml.lxml.check_dtd() to check_docinfo()\n- Unify argument names in callbacks\n- Add arguments and formatted representation to exceptions\n- Add forbid_external argument to all functions and classes\n- More tests\n- LOTS of documentation\n- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)\n- Add protection against XML and gzip attacks to xmlrpclib\n\ndefusedxml 0.1\n--------------\n\n*Release date: 08-Feb-2013*\n\n- Initial and internal release for PSRT review\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, (string) (len=12) "download_url": ([]string) (len=1) { (string) (len=39) "https://pypi.python.org/pypi/defusedxml" }, diff --git a/.snapshots/TestParse-defusedxml_unsigned_tarball b/.snapshots/TestParse-defusedxml_unsigned_tarball index e5bceae..056e984 100644 --- a/.snapshots/TestParse-defusedxml_unsigned_tarball +++ b/.snapshots/TestParse-defusedxml_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,15 +28,9 @@ (string) (len=37) "Programming Language :: Python :: 3.9", (string) (len=41) "Topic :: Text Processing :: Markup :: XML" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=31351) "===================================================\ndefusedxml -- defusing XML bombs and other exploits\n===================================================\n\n.. image:: https://img.shields.io/pypi/v/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Supported Python versions\n\n.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master\n :target: https://travis-ci.org/tiran/defusedxml\n :alt: Travis CI\n\n.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master\n :target: https://codecov.io/github/tiran/defusedxml?branch=master\n :alt: codecov\n\n.. image:: https://img.shields.io/pypi/dm/defusedxml.svg\n :target: https://pypistats.org/packages/defusedxml\n :alt: PyPI downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n..\n\n \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes \n\nSynopsis\n========\n\nThe results of an attack on a vulnerable XML library can be fairly dramatic.\nWith just a few hundred **Bytes** of XML data an attacker can occupy several\n**Gigabytes** of memory within **seconds**. An attacker can also keep\nCPUs busy for a long time with a small to medium size request. Under some\ncircumstances it is even possible to access local files on your\nserver, to circumvent a firewall, or to abuse services to rebound attacks to\nthird parties.\n\nThe attacks use and abuse less common features of XML and its parsers. The\nmajority of developers are unacquainted with features such as processing\ninstructions and entity expansions that XML inherited from SGML. At best\nthey know about ```` from experience with HTML but they are not\naware that a document type definition (DTD) can generate an HTTP request\nor load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not rely\nthat a library is always configured for security and potential harmful data\nby default.\n\n\n.. contents:: Table of Contents\n :depth: 2\n\n\nAttack vectors\n==============\n\nbillion laughs / exponential entity expansion\n---------------------------------------------\n\nThe `Billion Laughs`_ attack -- also known as exponential entity expansion --\nuses multiple levels of nested entities. The original example uses 9 levels\nof 10 expansions in each level to expand the string ``lol`` to a string of\n3 * 10 :sup:`9` bytes, hence the name \"billion laughs\". The resulting string\noccupies 3 GB (2.79 GiB) of memory; intermediate strings require additional\nmemory. Because most parsers don't cache the intermediate step for every\nexpansion it is repeated over and over again. It increases the CPU load even\nmore.\n\nAn XML document of just a few hundred bytes can disrupt all services on a\nmachine within seconds.\n\nExample XML::\n\n \n \n \n \n ]>\n &d;\n\n\nquadratic blowup entity expansion\n---------------------------------\n\nA quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large entity\nwith a couple of thousand chars over and over again. The attack isn't as\nefficient as the exponential case but it avoids triggering countermeasures of\nparsers against heavily nested entities. Some parsers limit the depth and\nbreadth of a single entity but not the total amount of expanded text\nthroughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can require a\ncouple of hundred MB to several GB of memory. When the attack is combined\nwith some level of nested expansion an attacker is able to achieve a higher\nratio of success.\n\n::\n\n \n ]>\n &a;&a;&a;... repeat\n\n\nexternal entity expansion (remote)\n----------------------------------\n\nEntity declarations can contain more than just text for replacement. They can\nalso point to external resources by public identifiers or system identifiers.\nSystem identifiers are standard URIs. When the URI is a URL (e.g. a\n``http://`` locator) some parsers download the resource from the remote\nlocation and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity::\n\n \n ]>\n \n\nThe case of parsed external entities works only for valid XML content. The\nXML standard also supports unparsed external entities with a\n``NData declaration``.\n\nExternal entity expansion opens the door to plenty of exploits. An attacker\ncan abuse a vulnerable XML library and application to rebound and forward\nnetwork requests with the IP address of the server. It highly depends\non the parser and the application what kind of exploit is possible. For\nexample:\n\n* An attacker can circumvent firewalls and gain access to restricted\n resources as all the requests are made from an internal and trustworthy\n IP address, not from the outside.\n* An attacker can abuse a service to attack, spy on or DoS your servers but\n also third party services. The attack is disguised with the IP address of\n the server and the attacker is able to utilize the high bandwidth of a big\n machine.\n* An attacker can exhaust additional resources on the machine, e.g. with\n requests to a service that doesn't respond or responds with very large\n files.\n* An attacker may gain knowledge, when, how often and from which IP address\n an XML document is accessed.\n* An attacker could send mail from inside your network if the URL handler\n supports ``smtp://`` URIs.\n\n\nexternal entity expansion (local file)\n--------------------------------------\n\nExternal entities with references to local files are a sub-case of external\nentity expansion. It's listed as an extra attack because it deserves extra\nattention. Some XML libraries such as lxml disable network access by default\nbut still allow entity expansion with local file access by default. Local\nfiles are either referenced with a ``file://`` URL or by a file path (either\nrelative or absolute).\n\nAn attacker may be able to access and download all files that can be read by\nthe application process. This may include critical configuration files, too.\n\n::\n\n \n ]>\n \n\n\nDTD retrieval\n-------------\n\nThis case is similar to external entity expansion, too. Some XML libraries\nlike Python's xml.dom.pulldom retrieve document type definitions from remote\nor local locations. Several attack scenarios from the external entity case\napply to this issue as well.\n\n::\n\n \n \n \n \n text\n \n\n\nPython XML Libraries\n====================\n\n.. csv-table:: vulnerabilities and features\n :header: \"kind\", \"sax\", \"etree\", \"minidom\", \"pulldom\", \"xmlrpc\", \"lxml\", \"genshi\"\n :widths: 24, 7, 8, 8, 7, 8, 8, 8\n :stub-columns: 0\n\n \"billion laughs\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (1)\", \"False (5)\"\n \"quadratic blowup\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (5)\"\n \"external entity expansion (remote)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"False (1)\", \"False (5)\"\n \"external entity expansion (local file)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"**True**\", \"False (5)\"\n \"DTD retrieval\", \"**True**\", \"False\", \"False\", \"**True**\", \"false\", \"False (1)\", \"False\"\n \"gzip bomb\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"**partly** (2)\", \"False\"\n \"xpath support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xsl(t) support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xinclude support (7)\", \"False\", \"**True** (6)\", \"False\", \"False\", \"False\", \"**True** (6)\", \"**True**\"\n \"C library\", \"expat\", \"expat\", \"expat\", \"expat\", \"expat\", \"libxml2\", \"expat\"\n\n1. Lxml is protected against billion laughs attacks and doesn't do network\n lookups by default.\n2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs\n but they don't protect you against them either.\n3. xml.etree doesn't expand entities and raises a ParserError when an entity\n occurs.\n4. minidom doesn't expand entities and simply returns the unexpanded entity\n verbatim.\n5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a\n ParserError when an entity occurs.\n6. Library has (limited) XInclude support but requires an additional step to\n process inclusion.\n7. These are features but they may introduce exploitable holes, see\n `Other things to consider`_\n\n\nSettings in standard library\n----------------------------\n\n\nxml.sax.handler Features\n........................\n\nfeature_external_ges (http://xml.org/sax/features/external-general-entities)\n disables external entity expansion\n\nfeature_external_pes (http://xml.org/sax/features/external-parameter-entities)\n the option is ignored and doesn't modify any functionality\n\nDOM xml.dom.xmlbuilder.Options\n..............................\n\nexternal_parameter_entities\n ignored\n\nexternal_general_entities\n ignored\n\nexternal_dtd_subset\n ignored\n\nentities\n unsure\n\n\ndefusedxml\n==========\n\nThe `defusedxml package`_ (`defusedxml on PyPI`_)\ncontains several Python-only workarounds and fixes\nfor denial of service and other vulnerabilities in Python's XML libraries.\nIn order to benefit from the protection you just have to import and use the\nlisted functions / classes from the right defusedxml module instead of the\noriginal module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.\n\nInstead of::\n\n >>> from xml.etree.ElementTree import parse\n >>> et = parse(xmlfile)\n\nalter code to::\n\n >>> from defusedxml.ElementTree import parse\n >>> et = parse(xmlfile)\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with ``defusedxml.defuse_stdlib()``.\n\nAll functions and parser classes accept three additional keyword arguments.\nThey return either the same objects as the original functions or compatible\nsubclasses.\n\nforbid_dtd (default: False)\n disallow XML with a ```` processing instruction and raise a\n *DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)\n disallow XML with ```` declarations inside the DTD and raise an\n *EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)\n disallow any access to remote or local resources in external entities\n or DTD and raising an *ExternalReferenceForbidden* exception when a DTD\n or entity references an external resource.\n\n\ndefusedxml (package)\n--------------------\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n\ndefusedxml.cElementTree\n-----------------------\n\n**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a\nfuture release. Import from ``defusedxml.ElementTree`` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.ElementTree\n-----------------------\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.expatreader\n----------------------\n\ncreate_parser(), DefusedExpatParser\n\n\ndefusedxml.sax\n--------------\n\nparse(), parseString(), make_parser()\n\n\ndefusedxml.expatbuilder\n-----------------------\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n\ndefusedxml.minidom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.pulldom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.xmlrpc\n-----------------\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)\nor xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,\n`unmonkey_patch()` removes the patch and puts the code in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The default\nsetting is 30 MB for requests, responses and gzip decompression. You can\nmodify the default by changing the module variable `MAX_DATA`. A value of\n`-1` disables the limit.\n\n\ndefusedxml.lxml\n---------------\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out\nEntity instances, a custom parser factory and a thread local storage for\nparser instances. It also has a check_docinfo() function which inspects\na tree for internal or external DTDs and entity declarations. In order to\ncheck for entities lxml > 3.0 is required.\n\nparse(), fromstring()\nRestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()\n\n\ndefusedexpat\n============\n\nThe `defusedexpat package`_ (`defusedexpat on PyPI`_)\ncomes with binary extensions and a\n`modified expat`_ library instead of the standard `expat parser`_. It's\nbasically a stand-alone version of the patches for Python's standard\nlibrary C extensions.\n\nModifications in expat\n----------------------\n\nnew definitions::\n\n XML_BOMB_PROTECTION\n XML_DEFAULT_MAX_ENTITY_INDIRECTIONS\n XML_DEFAULT_MAX_ENTITY_EXPANSIONS\n XML_DEFAULT_RESET_DTD\n\nnew XML_FeatureEnum members::\n\n XML_FEATURE_MAX_ENTITY_INDIRECTIONS\n XML_FEATURE_MAX_ENTITY_EXPANSIONS\n XML_FEATURE_IGNORE_DTD\n\nnew XML_Error members::\n\n XML_ERROR_ENTITY_INDIRECTIONS\n XML_ERROR_ENTITY_EXPANSION\n\nnew API functions::\n\n int XML_GetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long value);\n int XML_GetFeatureDefault(enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeatureDefault(enum XML_FeatureEnum feature,\n long value);\n\nXML_FEATURE_MAX_ENTITY_INDIRECTIONS\n Limit the amount of indirections that are allowed to occur during the\n expansion of a nested entity. A counter starts when an entity reference\n is encountered. It resets after the entity is fully expanded. The limit\n protects the parser against exponential entity expansion attacks (aka\n billion laughs attack). When the limit is exceeded the parser stops and\n fails with `XML_ERROR_ENTITY_INDIRECTIONS`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 40\n\nXML_FEATURE_MAX_ENTITY_EXPANSIONS\n Limit the total length of all entity expansions throughout the entire\n document. The lengths of all entities are accumulated in a parser variable.\n The setting protects against quadratic blowup attacks (lots of expansions\n of a large entity declaration). When the sum of all entities exceeds\n the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 8 MiB\n\nXML_FEATURE_RESET_DTD\n Reset all DTD information after the block has been parsed. When\n the flag is set (default: false) all DTD information after the\n endDoctypeDeclHandler has been called. The flag can be set inside the\n endDoctypeDeclHandler. Without DTD information any entity reference in\n the document body leads to `XML_ERROR_UNDEFINED_ENTITY`.\n\n Supported range\n 0, 1\n Default\n 0\n\n\nHow to avoid XML vulnerabilities\n================================\n\nBest practices\n--------------\n\n* Don't allow DTDs\n* Don't expand entities\n* Don't resolve externals\n* Limit parse depth\n* Limit total input size\n* Limit parse time\n* Favor a SAX or iterparse-like parser for potential large data\n* Validate and properly quote arguments to XSL transformations and\n XPath queries\n* Don't use XPath expression from untrusted sources\n* Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's `Attacking XML Security`_)\n\n\nOther things to consider\n========================\n\nXML, XML parsers and processing libraries have more features and possible\nissue that could lead to DoS vulnerabilities or security exploits in\napplications. I have compiled an incomplete list of theoretical issues that\nneed further research and more attention. The list is deliberately pessimistic\nand a bit paranoid, too. It contains things that might go wrong under daffy\ncircumstances.\n\n\nattribute blowup / hash collision attack\n----------------------------------------\n\nXML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to\nhandle attributes and namespaces. If it uses hash tables (dictionaries) to\nstore attributes and namespaces the implementation may be vulnerable to\nhash collision attacks, thus reducing the performance to O(n :sup:`2`) again.\nIn either case an attacker is able to forge a denial of service attack with\nan XML document that contains thousands upon thousands of attributes in\na single node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n\ndecompression bomb\n------------------\n\nThe issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries\nthat can parse compressed XML stream like gzipped HTTP streams or LZMA-ed\nfiles. For an attacker it can reduce the amount of transmitted data by three\nmagnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,\nlzma is even better::\n\n $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n $ ls -sh zeros.*\n 1020K zeros.gz\n 148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n``xmlrpclib``. The module is vulnerable \nto decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach can\nbe safe.\n\n\nProcessing Instruction\n----------------------\n\n`PI`_'s like::\n\n \n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval with\nnetwork or local file access apply to processing instructions, too.\n\n\nOther DTD features\n------------------\n\n`DTD`_ has more features like ````. I haven't researched how\nthese features may be a security threat.\n\n\nXPath\n-----\n\nXPath statements may introduce DoS vulnerabilities. Code should never execute\nqueries from untrusted sources. An attacker may also be able to create an XML\ndocument that makes certain XPath queries costly or resource hungry.\n\n\nXPath injection attacks\n-----------------------\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly, especially\nwhen they are taken from the user. The page `Avoid the dangers of XPath injection`_\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to use\nits xpath() method correctly::\n\n # DON'T\n >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n # instead do\n >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n\nXInclude\n--------\n\n`XML Inclusion`_ is another way to load and include external files::\n\n \n \n \n\nThis feature should be disabled when XML files from an untrusted source are\nprocessed. Some Python XML libraries and libxml2 support XInclude but don't\nhave an option to sandbox inclusion and limit it to allowed directories.\n\n\nXMLSchema location\n------------------\n\nA validating XML parser may download schema files from the information in a\n``xsi:schemaLocation`` attribute.\n\n::\n\n \n \n\n\nXSL Transformation\n------------------\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even imagine.\nSome processors even support extensions that allow read/write access to file\nsystem, access to JRE objects or scripting with Jython.\n\nExample from `Attacking XML Security`_ for Xalan-J::\n\n \n \n \n \n \n \n \n \n\n\nRelated CVEs\n============\n\nCVE-2013-1664\n Unrestricted entity expansion induces DoS vulnerabilities in Python XML\n libraries (XML bomb)\n\nCVE-2013-1665\n External entity expansion in Python XML libraries inflicts potential\n security flaws and DoS vulnerabilities\n\n\nOther languages / frameworks\n=============================\n\nSeveral other programming languages and frameworks are vulnerable as well. A\ncouple of them are affected by the fact that libxml2 up to 2.9.0 has no\nprotection against quadratic blowup attacks. Most of them have potential\ndangerous default settings for entity expansion and external entities, too.\n\nPerl\n----\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and external\nentity expansion (both local and remote).\n\n\nRuby\n----\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have to\ndisable the feature::\n\n REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default configuration.\n\n\nPHP\n---\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and loads\nentities from local and remote resources. The option ``LIBXML_NONET`` disables\nnetwork access but still allows local file access. ``LIBXML_NOENT`` seems to\nhave no effect on entity expansion in PHP 5.4.6.\n\n\nC# / .NET / Mono\n----------------\n\nInformation in `XML DoS and Defenses (MSDN)`_ suggest that .NET is\nvulnerable with its default settings. The article contains code snippets\nhow to create a secure XML reader::\n\n XmlReaderSettings settings = new XmlReaderSettings();\n settings.ProhibitDtd = false;\n settings.MaxCharactersFromEntities = 1024;\n settings.XmlResolver = null;\n XmlReader reader = XmlReader.Create(stream, settings);\n\n\nJava\n----\n\nUntested. The documentation of Xerces and its `Xerces SecurityMananger`_\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory::\n\n DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n builderFactory.setXIncludeAware(False);\n builderFactory.setExpandEntityReferences(False);\n builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n # either\n builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n # or if you need DTDs\n builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n\nTODO\n====\n\n* DOM: Use xml.dom.xmlbuilder options for entity handling\n* SAX: take feature_external_ges and feature_external_pes (?) into account\n* test experimental monkey patching of stdlib modules\n* improve documentation\n\n\nLicense\n=======\n\nCopyright (c) 2013-2017 by Christian Heimes \n\nLicensed to PSF under a Contributor Agreement.\n\nSee https://www.python.org/psf/license for licensing details.\n\n\nAcknowledgements\n================\n\nBrett Cannon (Python Core developer)\n review and code cleanup\n\nAntoine Pitrou (Python Core developer)\n code review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)\n Many thanks to Aaron, Ben and Michael from the Ruby community for their\n report and assistance.\n\nThierry Carrez (OpenStack)\n Many thanks to Thierry for his report to the Python Security Response\n Team on behalf of the OpenStack security team.\n\nCarl Meyer (Django)\n Many thanks to Carl for his report to PSRT on behalf of the Django security\n team.\n\nDaniel Veillard (libxml2)\n Many thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (https://www.semantics.de/)\n Many thanks to my employer semantics for letting me work on the issue\n during working hours as part of semantics's open source initiative.\n\n\nReferences\n==========\n\n* `XML DoS and Defenses (MSDN)`_\n* `Billion Laughs`_ on Wikipedia\n* `ZIP bomb`_ on Wikipedia\n* `Configure SAX parsers for secure processing`_\n* `Testing for XML Injection`_\n\n.. _defusedxml package: https://github.com/tiran/defusedxml\n.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml\n.. _defusedexpat package: https://github.com/tiran/defusedexpat\n.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat\n.. _modified expat: https://github.com/tiran/expat\n.. _expat parser: http://expat.sourceforge.net/\n.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf\n.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs\n.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx\n.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb\n.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition\n.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction\n.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html\n.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html\n.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)\n.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html\n.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element\n\nChangelog\n=========\n\ndefusedxml 0.7.1\n---------------------\n\n*Release date: 08-Mar-2021*\n\n- Fix regression ``defusedxml.ElementTree.ParseError`` (#63)\n The ``ParseError`` exception is now the same class object as\n ``xml.etree.ElementTree.ParseError`` again.\n\n\ndefusedxml 0.7.0\n----------------\n\n*Release date: 4-Mar-2021*\n\n- No changes\n\n\ndefusedxml 0.7.0rc2\n-------------------\n\n*Release date: 12-Jan-2021*\n\n- Re-add and deprecate ``defusedxml.cElementTree``\n- Use GitHub Actions instead of TravisCI\n- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching\n\ndefusedxml 0.7.0rc1\n-------------------\n\n*Release date: 04-May-2020*\n\n- Add support for Python 3.9\n- ``defusedxml.cElementTree`` is not available with Python 3.9.\n- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0.\n\n\ndefusedxml 0.6.0\n----------------\n\n*Release date: 17-Apr-2019*\n\n- Increase test coverage.\n- Add badges to README.\n\n\ndefusedxml 0.6.0rc1\n-------------------\n\n*Release date: 14-Apr-2019*\n\n- Test on Python 3.7 stable and 3.8-dev\n- Drop support for Python 3.4\n- No longer pass *html* argument to XMLParse. It has been deprecated and\n ignored for a long time. The DefusedXMLParser still takes a html argument.\n A deprecation warning is issued when the argument is False and a TypeError\n when it's True.\n- defusedxml now fails early when pyexpat stdlib module is not available or\n broken.\n- defusedxml.ElementTree.__all__ now lists ParseError as public attribute.\n- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo\n and used XMLParse instead of XMLParser as an alias for DefusedXMLParser.\n Both the old and fixed name are now available.\n\n\ndefusedxml 0.5.0\n----------------\n\n*Release date: 07-Feb-2017*\n\n- No changes\n\n\ndefusedxml 0.5.0.rc1\n--------------------\n\n*Release date: 28-Jan-2017*\n\n- Add compatibility with Python 3.6\n- Drop support for Python 2.6, 3.1, 3.2, 3.3\n- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n\ndefusedxml 0.4.1\n----------------\n\n*Release date: 28-Mar-2013*\n\n- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.\n- Improved documentation.\n\n\ndefusedxml 0.4\n--------------\n\n*Release date: 25-Feb-2013*\n\n- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT\n CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,\n CVE-2013-1665 for OpenStack/etc.\n- Add missing parser_list argument to sax.make_parser(). The argument is\n ignored, though. (thanks to Florian Apolloner)\n- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC\n and WebDAV.\n\n\ndefusedxml 0.3\n--------------\n\n*Release date: 19-Feb-2013*\n\n- Improve documentation\n\n\ndefusedxml 0.2\n--------------\n\n*Release date: 15-Feb-2013*\n\n- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n- Rename defusedxml.lxml.check_dtd() to check_docinfo()\n- Unify argument names in callbacks\n- Add arguments and formatted representation to exceptions\n- Add forbid_external argument to all functions and classes\n- More tests\n- LOTS of documentation\n- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)\n- Add protection against XML and gzip attacks to xmlrpclib\n\ndefusedxml 0.1\n--------------\n\n*Release date: 08-Feb-2013*\n\n- Initial and internal release for PSRT review\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, (string) (len=12) "download_url": ([]string) (len=1) { (string) (len=39) "https://pypi.python.org/pypi/defusedxml" }, @@ -89,7 +83,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=15) "requires_python": ([]string) (len=1) { (string) (len=50) ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" diff --git a/.snapshots/TestParse-defusedxml_unsigned_wheel b/.snapshots/TestParse-defusedxml_unsigned_wheel index 57e40b9..b3c68cd 100644 --- a/.snapshots/TestParse-defusedxml_unsigned_wheel +++ b/.snapshots/TestParse-defusedxml_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -28,15 +28,9 @@ (string) (len=37) "Programming Language :: Python :: 3.9", (string) (len=41) "Topic :: Text Processing :: Markup :: XML" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=31351) "===================================================\ndefusedxml -- defusing XML bombs and other exploits\n===================================================\n\n.. image:: https://img.shields.io/pypi/v/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg\n :target: https://pypi.org/project/defusedxml/\n :alt: Supported Python versions\n\n.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master\n :target: https://travis-ci.org/tiran/defusedxml\n :alt: Travis CI\n\n.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master\n :target: https://codecov.io/github/tiran/defusedxml?branch=master\n :alt: codecov\n\n.. image:: https://img.shields.io/pypi/dm/defusedxml.svg\n :target: https://pypistats.org/packages/defusedxml\n :alt: PyPI downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: black\n\n..\n\n \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes \n\nSynopsis\n========\n\nThe results of an attack on a vulnerable XML library can be fairly dramatic.\nWith just a few hundred **Bytes** of XML data an attacker can occupy several\n**Gigabytes** of memory within **seconds**. An attacker can also keep\nCPUs busy for a long time with a small to medium size request. Under some\ncircumstances it is even possible to access local files on your\nserver, to circumvent a firewall, or to abuse services to rebound attacks to\nthird parties.\n\nThe attacks use and abuse less common features of XML and its parsers. The\nmajority of developers are unacquainted with features such as processing\ninstructions and entity expansions that XML inherited from SGML. At best\nthey know about ```` from experience with HTML but they are not\naware that a document type definition (DTD) can generate an HTTP request\nor load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not rely\nthat a library is always configured for security and potential harmful data\nby default.\n\n\n.. contents:: Table of Contents\n :depth: 2\n\n\nAttack vectors\n==============\n\nbillion laughs / exponential entity expansion\n---------------------------------------------\n\nThe `Billion Laughs`_ attack -- also known as exponential entity expansion --\nuses multiple levels of nested entities. The original example uses 9 levels\nof 10 expansions in each level to expand the string ``lol`` to a string of\n3 * 10 :sup:`9` bytes, hence the name \"billion laughs\". The resulting string\noccupies 3 GB (2.79 GiB) of memory; intermediate strings require additional\nmemory. Because most parsers don't cache the intermediate step for every\nexpansion it is repeated over and over again. It increases the CPU load even\nmore.\n\nAn XML document of just a few hundred bytes can disrupt all services on a\nmachine within seconds.\n\nExample XML::\n\n \n \n \n \n ]>\n &d;\n\n\nquadratic blowup entity expansion\n---------------------------------\n\nA quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large entity\nwith a couple of thousand chars over and over again. The attack isn't as\nefficient as the exponential case but it avoids triggering countermeasures of\nparsers against heavily nested entities. Some parsers limit the depth and\nbreadth of a single entity but not the total amount of expanded text\nthroughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can require a\ncouple of hundred MB to several GB of memory. When the attack is combined\nwith some level of nested expansion an attacker is able to achieve a higher\nratio of success.\n\n::\n\n \n ]>\n &a;&a;&a;... repeat\n\n\nexternal entity expansion (remote)\n----------------------------------\n\nEntity declarations can contain more than just text for replacement. They can\nalso point to external resources by public identifiers or system identifiers.\nSystem identifiers are standard URIs. When the URI is a URL (e.g. a\n``http://`` locator) some parsers download the resource from the remote\nlocation and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity::\n\n \n ]>\n \n\nThe case of parsed external entities works only for valid XML content. The\nXML standard also supports unparsed external entities with a\n``NData declaration``.\n\nExternal entity expansion opens the door to plenty of exploits. An attacker\ncan abuse a vulnerable XML library and application to rebound and forward\nnetwork requests with the IP address of the server. It highly depends\non the parser and the application what kind of exploit is possible. For\nexample:\n\n* An attacker can circumvent firewalls and gain access to restricted\n resources as all the requests are made from an internal and trustworthy\n IP address, not from the outside.\n* An attacker can abuse a service to attack, spy on or DoS your servers but\n also third party services. The attack is disguised with the IP address of\n the server and the attacker is able to utilize the high bandwidth of a big\n machine.\n* An attacker can exhaust additional resources on the machine, e.g. with\n requests to a service that doesn't respond or responds with very large\n files.\n* An attacker may gain knowledge, when, how often and from which IP address\n an XML document is accessed.\n* An attacker could send mail from inside your network if the URL handler\n supports ``smtp://`` URIs.\n\n\nexternal entity expansion (local file)\n--------------------------------------\n\nExternal entities with references to local files are a sub-case of external\nentity expansion. It's listed as an extra attack because it deserves extra\nattention. Some XML libraries such as lxml disable network access by default\nbut still allow entity expansion with local file access by default. Local\nfiles are either referenced with a ``file://`` URL or by a file path (either\nrelative or absolute).\n\nAn attacker may be able to access and download all files that can be read by\nthe application process. This may include critical configuration files, too.\n\n::\n\n \n ]>\n \n\n\nDTD retrieval\n-------------\n\nThis case is similar to external entity expansion, too. Some XML libraries\nlike Python's xml.dom.pulldom retrieve document type definitions from remote\nor local locations. Several attack scenarios from the external entity case\napply to this issue as well.\n\n::\n\n \n \n \n \n text\n \n\n\nPython XML Libraries\n====================\n\n.. csv-table:: vulnerabilities and features\n :header: \"kind\", \"sax\", \"etree\", \"minidom\", \"pulldom\", \"xmlrpc\", \"lxml\", \"genshi\"\n :widths: 24, 7, 8, 8, 7, 8, 8, 8\n :stub-columns: 0\n\n \"billion laughs\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (1)\", \"False (5)\"\n \"quadratic blowup\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"**True**\", \"False (5)\"\n \"external entity expansion (remote)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"False (1)\", \"False (5)\"\n \"external entity expansion (local file)\", \"**True**\", \"False (3)\", \"False (4)\", \"**True**\", \"false\", \"**True**\", \"False (5)\"\n \"DTD retrieval\", \"**True**\", \"False\", \"False\", \"**True**\", \"false\", \"False (1)\", \"False\"\n \"gzip bomb\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"**partly** (2)\", \"False\"\n \"xpath support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xsl(t) support (7)\", \"False\", \"False\", \"False\", \"False\", \"False\", \"**True**\", \"False\"\n \"xinclude support (7)\", \"False\", \"**True** (6)\", \"False\", \"False\", \"False\", \"**True** (6)\", \"**True**\"\n \"C library\", \"expat\", \"expat\", \"expat\", \"expat\", \"expat\", \"libxml2\", \"expat\"\n\n1. Lxml is protected against billion laughs attacks and doesn't do network\n lookups by default.\n2. libxml2 and lxml are not directly vulnerable to gzip decompression bombs\n but they don't protect you against them either.\n3. xml.etree doesn't expand entities and raises a ParserError when an entity\n occurs.\n4. minidom doesn't expand entities and simply returns the unexpanded entity\n verbatim.\n5. genshi.input of genshi 0.6 doesn't support entity expansion and raises a\n ParserError when an entity occurs.\n6. Library has (limited) XInclude support but requires an additional step to\n process inclusion.\n7. These are features but they may introduce exploitable holes, see\n `Other things to consider`_\n\n\nSettings in standard library\n----------------------------\n\n\nxml.sax.handler Features\n........................\n\nfeature_external_ges (http://xml.org/sax/features/external-general-entities)\n disables external entity expansion\n\nfeature_external_pes (http://xml.org/sax/features/external-parameter-entities)\n the option is ignored and doesn't modify any functionality\n\nDOM xml.dom.xmlbuilder.Options\n..............................\n\nexternal_parameter_entities\n ignored\n\nexternal_general_entities\n ignored\n\nexternal_dtd_subset\n ignored\n\nentities\n unsure\n\n\ndefusedxml\n==========\n\nThe `defusedxml package`_ (`defusedxml on PyPI`_)\ncontains several Python-only workarounds and fixes\nfor denial of service and other vulnerabilities in Python's XML libraries.\nIn order to benefit from the protection you just have to import and use the\nlisted functions / classes from the right defusedxml module instead of the\noriginal module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.\n\nInstead of::\n\n >>> from xml.etree.ElementTree import parse\n >>> et = parse(xmlfile)\n\nalter code to::\n\n >>> from defusedxml.ElementTree import parse\n >>> et = parse(xmlfile)\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with ``defusedxml.defuse_stdlib()``.\n\nAll functions and parser classes accept three additional keyword arguments.\nThey return either the same objects as the original functions or compatible\nsubclasses.\n\nforbid_dtd (default: False)\n disallow XML with a ```` processing instruction and raise a\n *DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)\n disallow XML with ```` declarations inside the DTD and raise an\n *EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)\n disallow any access to remote or local resources in external entities\n or DTD and raising an *ExternalReferenceForbidden* exception when a DTD\n or entity references an external resource.\n\n\ndefusedxml (package)\n--------------------\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n\ndefusedxml.cElementTree\n-----------------------\n\n**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a\nfuture release. Import from ``defusedxml.ElementTree`` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.ElementTree\n-----------------------\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.expatreader\n----------------------\n\ncreate_parser(), DefusedExpatParser\n\n\ndefusedxml.sax\n--------------\n\nparse(), parseString(), make_parser()\n\n\ndefusedxml.expatbuilder\n-----------------------\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n\ndefusedxml.minidom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.pulldom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.xmlrpc\n-----------------\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)\nor xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,\n`unmonkey_patch()` removes the patch and puts the code in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The default\nsetting is 30 MB for requests, responses and gzip decompression. You can\nmodify the default by changing the module variable `MAX_DATA`. A value of\n`-1` disables the limit.\n\n\ndefusedxml.lxml\n---------------\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out\nEntity instances, a custom parser factory and a thread local storage for\nparser instances. It also has a check_docinfo() function which inspects\na tree for internal or external DTDs and entity declarations. In order to\ncheck for entities lxml > 3.0 is required.\n\nparse(), fromstring()\nRestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()\n\n\ndefusedexpat\n============\n\nThe `defusedexpat package`_ (`defusedexpat on PyPI`_)\ncomes with binary extensions and a\n`modified expat`_ library instead of the standard `expat parser`_. It's\nbasically a stand-alone version of the patches for Python's standard\nlibrary C extensions.\n\nModifications in expat\n----------------------\n\nnew definitions::\n\n XML_BOMB_PROTECTION\n XML_DEFAULT_MAX_ENTITY_INDIRECTIONS\n XML_DEFAULT_MAX_ENTITY_EXPANSIONS\n XML_DEFAULT_RESET_DTD\n\nnew XML_FeatureEnum members::\n\n XML_FEATURE_MAX_ENTITY_INDIRECTIONS\n XML_FEATURE_MAX_ENTITY_EXPANSIONS\n XML_FEATURE_IGNORE_DTD\n\nnew XML_Error members::\n\n XML_ERROR_ENTITY_INDIRECTIONS\n XML_ERROR_ENTITY_EXPANSION\n\nnew API functions::\n\n int XML_GetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeature(XML_Parser parser,\n enum XML_FeatureEnum feature,\n long value);\n int XML_GetFeatureDefault(enum XML_FeatureEnum feature,\n long *value);\n int XML_SetFeatureDefault(enum XML_FeatureEnum feature,\n long value);\n\nXML_FEATURE_MAX_ENTITY_INDIRECTIONS\n Limit the amount of indirections that are allowed to occur during the\n expansion of a nested entity. A counter starts when an entity reference\n is encountered. It resets after the entity is fully expanded. The limit\n protects the parser against exponential entity expansion attacks (aka\n billion laughs attack). When the limit is exceeded the parser stops and\n fails with `XML_ERROR_ENTITY_INDIRECTIONS`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 40\n\nXML_FEATURE_MAX_ENTITY_EXPANSIONS\n Limit the total length of all entity expansions throughout the entire\n document. The lengths of all entities are accumulated in a parser variable.\n The setting protects against quadratic blowup attacks (lots of expansions\n of a large entity declaration). When the sum of all entities exceeds\n the limit, the parser stops and fails with `XML_ERROR_ENTITY_EXPANSION`.\n A value of 0 disables the protection.\n\n Supported range\n 0 .. UINT_MAX\n Default\n 8 MiB\n\nXML_FEATURE_RESET_DTD\n Reset all DTD information after the block has been parsed. When\n the flag is set (default: false) all DTD information after the\n endDoctypeDeclHandler has been called. The flag can be set inside the\n endDoctypeDeclHandler. Without DTD information any entity reference in\n the document body leads to `XML_ERROR_UNDEFINED_ENTITY`.\n\n Supported range\n 0, 1\n Default\n 0\n\n\nHow to avoid XML vulnerabilities\n================================\n\nBest practices\n--------------\n\n* Don't allow DTDs\n* Don't expand entities\n* Don't resolve externals\n* Limit parse depth\n* Limit total input size\n* Limit parse time\n* Favor a SAX or iterparse-like parser for potential large data\n* Validate and properly quote arguments to XSL transformations and\n XPath queries\n* Don't use XPath expression from untrusted sources\n* Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's `Attacking XML Security`_)\n\n\nOther things to consider\n========================\n\nXML, XML parsers and processing libraries have more features and possible\nissue that could lead to DoS vulnerabilities or security exploits in\napplications. I have compiled an incomplete list of theoretical issues that\nneed further research and more attention. The list is deliberately pessimistic\nand a bit paranoid, too. It contains things that might go wrong under daffy\ncircumstances.\n\n\nattribute blowup / hash collision attack\n----------------------------------------\n\nXML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to\nhandle attributes and namespaces. If it uses hash tables (dictionaries) to\nstore attributes and namespaces the implementation may be vulnerable to\nhash collision attacks, thus reducing the performance to O(n :sup:`2`) again.\nIn either case an attacker is able to forge a denial of service attack with\nan XML document that contains thousands upon thousands of attributes in\na single node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n\ndecompression bomb\n------------------\n\nThe issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries\nthat can parse compressed XML stream like gzipped HTTP streams or LZMA-ed\nfiles. For an attacker it can reduce the amount of transmitted data by three\nmagnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,\nlzma is even better::\n\n $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n $ ls -sh zeros.*\n 1020K zeros.gz\n 148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n``xmlrpclib``. The module is vulnerable \nto decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach can\nbe safe.\n\n\nProcessing Instruction\n----------------------\n\n`PI`_'s like::\n\n \n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval with\nnetwork or local file access apply to processing instructions, too.\n\n\nOther DTD features\n------------------\n\n`DTD`_ has more features like ````. I haven't researched how\nthese features may be a security threat.\n\n\nXPath\n-----\n\nXPath statements may introduce DoS vulnerabilities. Code should never execute\nqueries from untrusted sources. An attacker may also be able to create an XML\ndocument that makes certain XPath queries costly or resource hungry.\n\n\nXPath injection attacks\n-----------------------\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly, especially\nwhen they are taken from the user. The page `Avoid the dangers of XPath injection`_\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to use\nits xpath() method correctly::\n\n # DON'T\n >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n # instead do\n >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n\nXInclude\n--------\n\n`XML Inclusion`_ is another way to load and include external files::\n\n \n \n \n\nThis feature should be disabled when XML files from an untrusted source are\nprocessed. Some Python XML libraries and libxml2 support XInclude but don't\nhave an option to sandbox inclusion and limit it to allowed directories.\n\n\nXMLSchema location\n------------------\n\nA validating XML parser may download schema files from the information in a\n``xsi:schemaLocation`` attribute.\n\n::\n\n \n \n\n\nXSL Transformation\n------------------\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even imagine.\nSome processors even support extensions that allow read/write access to file\nsystem, access to JRE objects or scripting with Jython.\n\nExample from `Attacking XML Security`_ for Xalan-J::\n\n \n \n \n \n \n \n \n \n\n\nRelated CVEs\n============\n\nCVE-2013-1664\n Unrestricted entity expansion induces DoS vulnerabilities in Python XML\n libraries (XML bomb)\n\nCVE-2013-1665\n External entity expansion in Python XML libraries inflicts potential\n security flaws and DoS vulnerabilities\n\n\nOther languages / frameworks\n=============================\n\nSeveral other programming languages and frameworks are vulnerable as well. A\ncouple of them are affected by the fact that libxml2 up to 2.9.0 has no\nprotection against quadratic blowup attacks. Most of them have potential\ndangerous default settings for entity expansion and external entities, too.\n\nPerl\n----\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and external\nentity expansion (both local and remote).\n\n\nRuby\n----\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have to\ndisable the feature::\n\n REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default configuration.\n\n\nPHP\n---\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and loads\nentities from local and remote resources. The option ``LIBXML_NONET`` disables\nnetwork access but still allows local file access. ``LIBXML_NOENT`` seems to\nhave no effect on entity expansion in PHP 5.4.6.\n\n\nC# / .NET / Mono\n----------------\n\nInformation in `XML DoS and Defenses (MSDN)`_ suggest that .NET is\nvulnerable with its default settings. The article contains code snippets\nhow to create a secure XML reader::\n\n XmlReaderSettings settings = new XmlReaderSettings();\n settings.ProhibitDtd = false;\n settings.MaxCharactersFromEntities = 1024;\n settings.XmlResolver = null;\n XmlReader reader = XmlReader.Create(stream, settings);\n\n\nJava\n----\n\nUntested. The documentation of Xerces and its `Xerces SecurityMananger`_\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory::\n\n DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n builderFactory.setXIncludeAware(False);\n builderFactory.setExpandEntityReferences(False);\n builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n # either\n builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n # or if you need DTDs\n builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n\nTODO\n====\n\n* DOM: Use xml.dom.xmlbuilder options for entity handling\n* SAX: take feature_external_ges and feature_external_pes (?) into account\n* test experimental monkey patching of stdlib modules\n* improve documentation\n\n\nLicense\n=======\n\nCopyright (c) 2013-2017 by Christian Heimes \n\nLicensed to PSF under a Contributor Agreement.\n\nSee https://www.python.org/psf/license for licensing details.\n\n\nAcknowledgements\n================\n\nBrett Cannon (Python Core developer)\n review and code cleanup\n\nAntoine Pitrou (Python Core developer)\n code review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)\n Many thanks to Aaron, Ben and Michael from the Ruby community for their\n report and assistance.\n\nThierry Carrez (OpenStack)\n Many thanks to Thierry for his report to the Python Security Response\n Team on behalf of the OpenStack security team.\n\nCarl Meyer (Django)\n Many thanks to Carl for his report to PSRT on behalf of the Django security\n team.\n\nDaniel Veillard (libxml2)\n Many thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (https://www.semantics.de/)\n Many thanks to my employer semantics for letting me work on the issue\n during working hours as part of semantics's open source initiative.\n\n\nReferences\n==========\n\n* `XML DoS and Defenses (MSDN)`_\n* `Billion Laughs`_ on Wikipedia\n* `ZIP bomb`_ on Wikipedia\n* `Configure SAX parsers for secure processing`_\n* `Testing for XML Injection`_\n\n.. _defusedxml package: https://github.com/tiran/defusedxml\n.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml\n.. _defusedexpat package: https://github.com/tiran/defusedexpat\n.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat\n.. _modified expat: https://github.com/tiran/expat\n.. _expat parser: http://expat.sourceforge.net/\n.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf\n.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs\n.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx\n.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb\n.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition\n.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction\n.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html\n.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html\n.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)\n.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html\n.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element\n\nChangelog\n=========\n\ndefusedxml 0.7.1\n---------------------\n\n*Release date: 08-Mar-2021*\n\n- Fix regression ``defusedxml.ElementTree.ParseError`` (#63)\n The ``ParseError`` exception is now the same class object as\n ``xml.etree.ElementTree.ParseError`` again.\n\n\ndefusedxml 0.7.0\n----------------\n\n*Release date: 4-Mar-2021*\n\n- No changes\n\n\ndefusedxml 0.7.0rc2\n-------------------\n\n*Release date: 12-Jan-2021*\n\n- Re-add and deprecate ``defusedxml.cElementTree``\n- Use GitHub Actions instead of TravisCI\n- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching\n\ndefusedxml 0.7.0rc1\n-------------------\n\n*Release date: 04-May-2020*\n\n- Add support for Python 3.9\n- ``defusedxml.cElementTree`` is not available with Python 3.9.\n- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0.\n\n\ndefusedxml 0.6.0\n----------------\n\n*Release date: 17-Apr-2019*\n\n- Increase test coverage.\n- Add badges to README.\n\n\ndefusedxml 0.6.0rc1\n-------------------\n\n*Release date: 14-Apr-2019*\n\n- Test on Python 3.7 stable and 3.8-dev\n- Drop support for Python 3.4\n- No longer pass *html* argument to XMLParse. It has been deprecated and\n ignored for a long time. The DefusedXMLParser still takes a html argument.\n A deprecation warning is issued when the argument is False and a TypeError\n when it's True.\n- defusedxml now fails early when pyexpat stdlib module is not available or\n broken.\n- defusedxml.ElementTree.__all__ now lists ParseError as public attribute.\n- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo\n and used XMLParse instead of XMLParser as an alias for DefusedXMLParser.\n Both the old and fixed name are now available.\n\n\ndefusedxml 0.5.0\n----------------\n\n*Release date: 07-Feb-2017*\n\n- No changes\n\n\ndefusedxml 0.5.0.rc1\n--------------------\n\n*Release date: 28-Jan-2017*\n\n- Add compatibility with Python 3.6\n- Drop support for Python 2.6, 3.1, 3.2, 3.3\n- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n\ndefusedxml 0.4.1\n----------------\n\n*Release date: 28-Mar-2013*\n\n- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.\n- Improved documentation.\n\n\ndefusedxml 0.4\n--------------\n\n*Release date: 25-Feb-2013*\n\n- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT\n CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,\n CVE-2013-1665 for OpenStack/etc.\n- Add missing parser_list argument to sax.make_parser(). The argument is\n ignored, though. (thanks to Florian Apolloner)\n- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC\n and WebDAV.\n\n\ndefusedxml 0.3\n--------------\n\n*Release date: 19-Feb-2013*\n\n- Improve documentation\n\n\ndefusedxml 0.2\n--------------\n\n*Release date: 15-Feb-2013*\n\n- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n- Rename defusedxml.lxml.check_dtd() to check_docinfo()\n- Unify argument names in callbacks\n- Add arguments and formatted representation to exceptions\n- Add forbid_external argument to all functions and classes\n- More tests\n- LOTS of documentation\n- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)\n- Add protection against XML and gzip attacks to xmlrpclib\n\ndefusedxml 0.1\n--------------\n\n*Release date: 08-Feb-2013*\n\n- Initial and internal release for PSRT review\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, (string) (len=12) "download_url": ([]string) (len=1) { (string) (len=39) "https://pypi.python.org/pypi/defusedxml" }, diff --git a/.snapshots/TestParse-importlib_metadata_signed_tarball b/.snapshots/TestParse-importlib_metadata_signed_tarball index 386ed0e..e37cfe1 100644 --- a/.snapshots/TestParse-importlib_metadata_signed_tarball +++ b/.snapshots/TestParse-importlib_metadata_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=19) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,36 +19,15 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3073) ".. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata `_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 6.5\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation `_\nfor usage details.\n\n`Finder authors\n`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib-metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=44) "https://github.com/python/importlib_metadata" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -67,7 +46,7 @@ (string) (len=4) "perf" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=22) { (string) (len=9) "zipp>=0.5", diff --git a/.snapshots/TestParse-importlib_metadata_signed_wheel b/.snapshots/TestParse-importlib_metadata_signed_wheel index f3b8a02..bcc313f 100644 --- a/.snapshots/TestParse-importlib_metadata_signed_wheel +++ b/.snapshots/TestParse-importlib_metadata_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=19) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,36 +19,15 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3073) ".. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata `_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 6.5\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation `_\nfor usage details.\n\n`Finder authors\n`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib-metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=44) "https://github.com/python/importlib_metadata" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-importlib_metadata_unsigned_tarball b/.snapshots/TestParse-importlib_metadata_unsigned_tarball index 9d6da99..97f2326 100644 --- a/.snapshots/TestParse-importlib_metadata_unsigned_tarball +++ b/.snapshots/TestParse-importlib_metadata_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=19) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,36 +19,15 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3073) ".. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata `_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 6.5\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation `_\nfor usage details.\n\n`Finder authors\n`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib-metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=44) "https://github.com/python/importlib_metadata" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -67,7 +46,7 @@ (string) (len=4) "perf" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=22) { (string) (len=9) "zipp>=0.5", diff --git a/.snapshots/TestParse-importlib_metadata_unsigned_wheel b/.snapshots/TestParse-importlib_metadata_unsigned_wheel index 80513e3..316323f 100644 --- a/.snapshots/TestParse-importlib_metadata_unsigned_wheel +++ b/.snapshots/TestParse-importlib_metadata_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=26) { + Metadata: (map[string][]string) (len=19) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -19,36 +19,15 @@ (string) (len=35) "Programming Language :: Python :: 3", (string) (len=43) "Programming Language :: Python :: 3 :: Only" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3073) ".. image:: https://img.shields.io/pypi/v/importlib_metadata.svg\n :target: https://pypi.org/project/importlib_metadata\n\n.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg\n\n.. image:: https://github.com/python/importlib_metadata/workflows/tests/badge.svg\n :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22\n :alt: tests\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n :alt: Ruff\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n :alt: Code style: Black\n\n.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest\n :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest\n\n.. image:: https://img.shields.io/badge/skeleton-2023-informational\n :target: https://blog.jaraco.com/skeleton\n\n.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata\n :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme\n\nLibrary to access the metadata for a Python package.\n\nThis package supplies third-party access to the functionality of\n`importlib.metadata `_\nincluding improvements added to subsequent Python versions.\n\n\nCompatibility\n=============\n\nNew features are introduced in this third-party library and later merged\ninto CPython. The following table indicates which versions of this library\nwere contributed to different versions in the standard library:\n\n.. list-table::\n :header-rows: 1\n\n * - importlib_metadata\n - stdlib\n * - 6.5\n - 3.12\n * - 4.13\n - 3.11\n * - 4.6\n - 3.10\n * - 1.4\n - 3.8\n\n\nUsage\n=====\n\nSee the `online documentation `_\nfor usage details.\n\n`Finder authors\n`_ can\nalso add support for custom package installers. See the above documentation\nfor details.\n\n\nCaveats\n=======\n\nThis project primarily supports third-party packages installed by PyPA\ntools (or other conforming packages). It does not support:\n\n- Packages in the stdlib.\n- Packages installed without metadata.\n\nProject details\n===============\n\n * Project home: https://github.com/python/importlib_metadata\n * Report bugs at: https://github.com/python/importlib_metadata/issues\n * Code hosting: https://github.com/python/importlib_metadata\n * Documentation: https://importlib-metadata.readthedocs.io/\n\nFor Enterprise\n==============\n\nAvailable as part of the Tidelift Subscription.\n\nThis project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use.\n\n`Learn more `_.\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=44) "https://github.com/python/importlib_metadata" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, - (string) (len=7) "license": ([]string) (len=1) { - (string) "" - }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-matplotlib_signed_tarball b/.snapshots/TestParse-matplotlib_signed_tarball index 67769b8..70c4d17 100644 --- a/.snapshots/TestParse-matplotlib_signed_tarball +++ b/.snapshots/TestParse-matplotlib_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -26,9 +26,6 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=48) "Topic :: Scientific/Engineering :: Visualization" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3641) "[![PyPi](https://img.shields.io/pypi/v/matplotlib)](https://pypi.org/project/matplotlib/)\n[![Conda](https://img.shields.io/conda/vn/conda-forge/matplotlib)](https://anaconda.org/conda-forge/matplotlib)\n[![Downloads](https://img.shields.io/pypi/dm/matplotlib)](https://pypi.org/project/matplotlib)\n[![NUMFocus](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](https://numfocus.org)\n\n[![Discourse help forum](https://img.shields.io/badge/help_forum-discourse-blue.svg)](https://discourse.matplotlib.org)\n[![Gitter](https://badges.gitter.im/matplotlib/matplotlib.svg)](https://gitter.im/matplotlib/matplotlib)\n[![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/matplotlib/matplotlib/issues)\n[![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://matplotlib.org/stable/devel/index.html)\n\n[![GitHub actions status](https://github.com/matplotlib/matplotlib/workflows/Tests/badge.svg)](https://github.com/matplotlib/matplotlib/actions?query=workflow%3ATests)\n[![Azure pipelines status](https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=main)](https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=main)\n[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=main&svg=true)](https://ci.appveyor.com/project/matplotlib/matplotlib)\n[![Codecov status](https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=main&service=github)](https://app.codecov.io/gh/matplotlib/matplotlib)\n\n![Matplotlib logotype](https://matplotlib.org/_static/logo2.svg)\n\nMatplotlib is a comprehensive library for creating static, animated, and\ninteractive visualizations in Python.\n\nCheck out our [home page](https://matplotlib.org/) for more information.\n\n![image](https://matplotlib.org/_static/readme_preview.png)\n\nMatplotlib produces publication-quality figures in a variety of hardcopy\nformats and interactive environments across platforms. Matplotlib can be\nused in Python scripts, Python/IPython shells, web application servers,\nand various graphical user interface toolkits.\n\n## Install\n\nSee the [install\ndocumentation](https://matplotlib.org/stable/users/installing/index.html),\nwhich is generated from `/doc/users/installing/index.rst`\n\n## Contribute\n\nYou've discovered a bug or something else you want to change — excellent!\n\nYou've worked out a way to fix it — even better!\n\nYou want to tell us about it — best of all!\n\nStart at the [contributing\nguide](https://matplotlib.org/devdocs/devel/contributing.html)!\n\n## Contact\n\n[Discourse](https://discourse.matplotlib.org/) is the discussion forum\nfor general questions and discussions and our recommended starting\npoint.\n\nOur active mailing lists (which are mirrored on Discourse) are:\n\n- [Users](https://mail.python.org/mailman/listinfo/matplotlib-users)\n mailing list: \n- [Announcement](https://mail.python.org/mailman/listinfo/matplotlib-announce)\n mailing list: \n- [Development](https://mail.python.org/mailman/listinfo/matplotlib-devel)\n mailing list: \n\n[Gitter](https://gitter.im/matplotlib/matplotlib) is for coordinating\ndevelopment and asking questions directly related to contributing to\nmatplotlib.\n\n## Citing Matplotlib\n\nIf Matplotlib contributes to a project that leads to publication, please\nacknowledge this by citing Matplotlib.\n\n[A ready-made citation\nentry](https://matplotlib.org/stable/users/project/citing.html) is\navailable.\n" }, @@ -60,18 +57,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=22) "https://matplotlib.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "PSF" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -95,7 +83,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=12) { (string) (len=16) "contourpy>=1.0.1", diff --git a/.snapshots/TestParse-matplotlib_signed_wheel b/.snapshots/TestParse-matplotlib_signed_wheel index c85b3a5..ea58e46 100644 --- a/.snapshots/TestParse-matplotlib_signed_wheel +++ b/.snapshots/TestParse-matplotlib_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -26,9 +26,6 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=48) "Topic :: Scientific/Engineering :: Visualization" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3641) "[![PyPi](https://img.shields.io/pypi/v/matplotlib)](https://pypi.org/project/matplotlib/)\n[![Conda](https://img.shields.io/conda/vn/conda-forge/matplotlib)](https://anaconda.org/conda-forge/matplotlib)\n[![Downloads](https://img.shields.io/pypi/dm/matplotlib)](https://pypi.org/project/matplotlib)\n[![NUMFocus](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](https://numfocus.org)\n\n[![Discourse help forum](https://img.shields.io/badge/help_forum-discourse-blue.svg)](https://discourse.matplotlib.org)\n[![Gitter](https://badges.gitter.im/matplotlib/matplotlib.svg)](https://gitter.im/matplotlib/matplotlib)\n[![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/matplotlib/matplotlib/issues)\n[![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://matplotlib.org/stable/devel/index.html)\n\n[![GitHub actions status](https://github.com/matplotlib/matplotlib/workflows/Tests/badge.svg)](https://github.com/matplotlib/matplotlib/actions?query=workflow%3ATests)\n[![Azure pipelines status](https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=main)](https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=main)\n[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=main&svg=true)](https://ci.appveyor.com/project/matplotlib/matplotlib)\n[![Codecov status](https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=main&service=github)](https://app.codecov.io/gh/matplotlib/matplotlib)\n\n![Matplotlib logotype](https://matplotlib.org/_static/logo2.svg)\n\nMatplotlib is a comprehensive library for creating static, animated, and\ninteractive visualizations in Python.\n\nCheck out our [home page](https://matplotlib.org/) for more information.\n\n![image](https://matplotlib.org/_static/readme_preview.png)\n\nMatplotlib produces publication-quality figures in a variety of hardcopy\nformats and interactive environments across platforms. Matplotlib can be\nused in Python scripts, Python/IPython shells, web application servers,\nand various graphical user interface toolkits.\n\n## Install\n\nSee the [install\ndocumentation](https://matplotlib.org/stable/users/installing/index.html),\nwhich is generated from `/doc/users/installing/index.rst`\n\n## Contribute\n\nYou've discovered a bug or something else you want to change — excellent!\n\nYou've worked out a way to fix it — even better!\n\nYou want to tell us about it — best of all!\n\nStart at the [contributing\nguide](https://matplotlib.org/devdocs/devel/contributing.html)!\n\n## Contact\n\n[Discourse](https://discourse.matplotlib.org/) is the discussion forum\nfor general questions and discussions and our recommended starting\npoint.\n\nOur active mailing lists (which are mirrored on Discourse) are:\n\n- [Users](https://mail.python.org/mailman/listinfo/matplotlib-users)\n mailing list: \n- [Announcement](https://mail.python.org/mailman/listinfo/matplotlib-announce)\n mailing list: \n- [Development](https://mail.python.org/mailman/listinfo/matplotlib-devel)\n mailing list: \n\n[Gitter](https://gitter.im/matplotlib/matplotlib) is for coordinating\ndevelopment and asking questions directly related to contributing to\nmatplotlib.\n\n## Citing Matplotlib\n\nIf Matplotlib contributes to a project that leads to publication, please\nacknowledge this by citing Matplotlib.\n\n[A ready-made citation\nentry](https://matplotlib.org/stable/users/project/citing.html) is\navailable.\n" }, @@ -60,18 +57,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=22) "https://matplotlib.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "PSF" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-matplotlib_unsigned_tarball b/.snapshots/TestParse-matplotlib_unsigned_tarball index 6aca69b..f100a54 100644 --- a/.snapshots/TestParse-matplotlib_unsigned_tarball +++ b/.snapshots/TestParse-matplotlib_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -26,9 +26,6 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=48) "Topic :: Scientific/Engineering :: Visualization" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3641) "[![PyPi](https://img.shields.io/pypi/v/matplotlib)](https://pypi.org/project/matplotlib/)\n[![Conda](https://img.shields.io/conda/vn/conda-forge/matplotlib)](https://anaconda.org/conda-forge/matplotlib)\n[![Downloads](https://img.shields.io/pypi/dm/matplotlib)](https://pypi.org/project/matplotlib)\n[![NUMFocus](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](https://numfocus.org)\n\n[![Discourse help forum](https://img.shields.io/badge/help_forum-discourse-blue.svg)](https://discourse.matplotlib.org)\n[![Gitter](https://badges.gitter.im/matplotlib/matplotlib.svg)](https://gitter.im/matplotlib/matplotlib)\n[![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/matplotlib/matplotlib/issues)\n[![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://matplotlib.org/stable/devel/index.html)\n\n[![GitHub actions status](https://github.com/matplotlib/matplotlib/workflows/Tests/badge.svg)](https://github.com/matplotlib/matplotlib/actions?query=workflow%3ATests)\n[![Azure pipelines status](https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=main)](https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=main)\n[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=main&svg=true)](https://ci.appveyor.com/project/matplotlib/matplotlib)\n[![Codecov status](https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=main&service=github)](https://app.codecov.io/gh/matplotlib/matplotlib)\n\n![Matplotlib logotype](https://matplotlib.org/_static/logo2.svg)\n\nMatplotlib is a comprehensive library for creating static, animated, and\ninteractive visualizations in Python.\n\nCheck out our [home page](https://matplotlib.org/) for more information.\n\n![image](https://matplotlib.org/_static/readme_preview.png)\n\nMatplotlib produces publication-quality figures in a variety of hardcopy\nformats and interactive environments across platforms. Matplotlib can be\nused in Python scripts, Python/IPython shells, web application servers,\nand various graphical user interface toolkits.\n\n## Install\n\nSee the [install\ndocumentation](https://matplotlib.org/stable/users/installing/index.html),\nwhich is generated from `/doc/users/installing/index.rst`\n\n## Contribute\n\nYou've discovered a bug or something else you want to change — excellent!\n\nYou've worked out a way to fix it — even better!\n\nYou want to tell us about it — best of all!\n\nStart at the [contributing\nguide](https://matplotlib.org/devdocs/devel/contributing.html)!\n\n## Contact\n\n[Discourse](https://discourse.matplotlib.org/) is the discussion forum\nfor general questions and discussions and our recommended starting\npoint.\n\nOur active mailing lists (which are mirrored on Discourse) are:\n\n- [Users](https://mail.python.org/mailman/listinfo/matplotlib-users)\n mailing list: \n- [Announcement](https://mail.python.org/mailman/listinfo/matplotlib-announce)\n mailing list: \n- [Development](https://mail.python.org/mailman/listinfo/matplotlib-devel)\n mailing list: \n\n[Gitter](https://gitter.im/matplotlib/matplotlib) is for coordinating\ndevelopment and asking questions directly related to contributing to\nmatplotlib.\n\n## Citing Matplotlib\n\nIf Matplotlib contributes to a project that leads to publication, please\nacknowledge this by citing Matplotlib.\n\n[A ready-made citation\nentry](https://matplotlib.org/stable/users/project/citing.html) is\navailable.\n" }, @@ -60,18 +57,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=22) "https://matplotlib.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "PSF" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -95,7 +83,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=12) { (string) (len=16) "contourpy>=1.0.1", diff --git a/.snapshots/TestParse-matplotlib_unsigned_wheel b/.snapshots/TestParse-matplotlib_unsigned_wheel index adc3f6d..8d85851 100644 --- a/.snapshots/TestParse-matplotlib_unsigned_wheel +++ b/.snapshots/TestParse-matplotlib_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=24) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -26,9 +26,6 @@ (string) (len=38) "Programming Language :: Python :: 3.12", (string) (len=48) "Topic :: Scientific/Engineering :: Visualization" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=3641) "[![PyPi](https://img.shields.io/pypi/v/matplotlib)](https://pypi.org/project/matplotlib/)\n[![Conda](https://img.shields.io/conda/vn/conda-forge/matplotlib)](https://anaconda.org/conda-forge/matplotlib)\n[![Downloads](https://img.shields.io/pypi/dm/matplotlib)](https://pypi.org/project/matplotlib)\n[![NUMFocus](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](https://numfocus.org)\n\n[![Discourse help forum](https://img.shields.io/badge/help_forum-discourse-blue.svg)](https://discourse.matplotlib.org)\n[![Gitter](https://badges.gitter.im/matplotlib/matplotlib.svg)](https://gitter.im/matplotlib/matplotlib)\n[![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/matplotlib/matplotlib/issues)\n[![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://matplotlib.org/stable/devel/index.html)\n\n[![GitHub actions status](https://github.com/matplotlib/matplotlib/workflows/Tests/badge.svg)](https://github.com/matplotlib/matplotlib/actions?query=workflow%3ATests)\n[![Azure pipelines status](https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=main)](https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=main)\n[![AppVeyor status](https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=main&svg=true)](https://ci.appveyor.com/project/matplotlib/matplotlib)\n[![Codecov status](https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=main&service=github)](https://app.codecov.io/gh/matplotlib/matplotlib)\n\n![Matplotlib logotype](https://matplotlib.org/_static/logo2.svg)\n\nMatplotlib is a comprehensive library for creating static, animated, and\ninteractive visualizations in Python.\n\nCheck out our [home page](https://matplotlib.org/) for more information.\n\n![image](https://matplotlib.org/_static/readme_preview.png)\n\nMatplotlib produces publication-quality figures in a variety of hardcopy\nformats and interactive environments across platforms. Matplotlib can be\nused in Python scripts, Python/IPython shells, web application servers,\nand various graphical user interface toolkits.\n\n## Install\n\nSee the [install\ndocumentation](https://matplotlib.org/stable/users/installing/index.html),\nwhich is generated from `/doc/users/installing/index.rst`\n\n## Contribute\n\nYou've discovered a bug or something else you want to change — excellent!\n\nYou've worked out a way to fix it — even better!\n\nYou want to tell us about it — best of all!\n\nStart at the [contributing\nguide](https://matplotlib.org/devdocs/devel/contributing.html)!\n\n## Contact\n\n[Discourse](https://discourse.matplotlib.org/) is the discussion forum\nfor general questions and discussions and our recommended starting\npoint.\n\nOur active mailing lists (which are mirrored on Discourse) are:\n\n- [Users](https://mail.python.org/mailman/listinfo/matplotlib-users)\n mailing list: \n- [Announcement](https://mail.python.org/mailman/listinfo/matplotlib-announce)\n mailing list: \n- [Development](https://mail.python.org/mailman/listinfo/matplotlib-devel)\n mailing list: \n\n[Gitter](https://gitter.im/matplotlib/matplotlib) is for coordinating\ndevelopment and asking questions directly related to contributing to\nmatplotlib.\n\n## Citing Matplotlib\n\nIf Matplotlib contributes to a project that leads to publication, please\nacknowledge this by citing Matplotlib.\n\n[A ready-made citation\nentry](https://matplotlib.org/stable/users/project/citing.html) is\navailable.\n" }, @@ -60,18 +57,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=22) "https://matplotlib.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "PSF" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-pytest_signed_tarball b/.snapshots/TestParse-pytest_signed_tarball index ad52383..4563d85 100644 --- a/.snapshots/TestParse-pytest_signed_tarball +++ b/.snapshots/TestParse-pytest_signed_tarball @@ -1,14 +1,11 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, (string) (len=6) "author": ([]string) (len=1) { (string) (len=112) "Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others" }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -31,18 +28,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=5628) ".. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nDue to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial),\n `nose `_ test suites out of the box\n\n- Python 3.7+ or PyPy3\n\n- Rich plugin architecture, with over 850+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -50,17 +41,11 @@ (string) (len=34) "https://docs.pytest.org/en/latest/" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=13) "test,unittest" + (string) (len=14) "test, unittest" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -90,7 +75,7 @@ (string) (len=7) "testing" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=16) { (string) (len=9) "iniconfig", diff --git a/.snapshots/TestParse-pytest_signed_wheel b/.snapshots/TestParse-pytest_signed_wheel index 72bd32a..126f544 100644 --- a/.snapshots/TestParse-pytest_signed_wheel +++ b/.snapshots/TestParse-pytest_signed_wheel @@ -1,14 +1,11 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, (string) (len=6) "author": ([]string) (len=1) { (string) (len=112) "Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others" }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -31,18 +28,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=5628) ".. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nDue to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial),\n `nose `_ test suites out of the box\n\n- Python 3.7+ or PyPy3\n\n- Rich plugin architecture, with over 850+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -50,17 +41,11 @@ (string) (len=34) "https://docs.pytest.org/en/latest/" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=13) "test,unittest" + (string) (len=14) "test, unittest" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-pytest_unsigned_tarball b/.snapshots/TestParse-pytest_unsigned_tarball index cdf8252..d591cc3 100644 --- a/.snapshots/TestParse-pytest_unsigned_tarball +++ b/.snapshots/TestParse-pytest_unsigned_tarball @@ -1,14 +1,11 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, (string) (len=6) "author": ([]string) (len=1) { (string) (len=112) "Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others" }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -31,18 +28,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=5628) ".. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nDue to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial),\n `nose `_ test suites out of the box\n\n- Python 3.7+ or PyPy3\n\n- Rich plugin architecture, with over 850+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=5) "sdist" }, @@ -50,17 +41,11 @@ (string) (len=34) "https://docs.pytest.org/en/latest/" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=13) "test,unittest" + (string) (len=14) "test, unittest" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -90,7 +75,7 @@ (string) (len=7) "testing" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "requires_dist": ([]string) (len=16) { (string) (len=9) "iniconfig", diff --git a/.snapshots/TestParse-pytest_unsigned_wheel b/.snapshots/TestParse-pytest_unsigned_wheel index e6814d0..50556e6 100644 --- a/.snapshots/TestParse-pytest_unsigned_wheel +++ b/.snapshots/TestParse-pytest_unsigned_wheel @@ -1,14 +1,11 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=28) { + Metadata: (map[string][]string) (len=23) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, (string) (len=6) "author": ([]string) (len=1) { (string) (len=112) "Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others" }, - (string) (len=12) "author_email": ([]string) (len=1) { - (string) "" - }, (string) (len=17) "blake2_256_digest": ([]string) (len=1) { (string) (len=24) "blake2_256_digest exists" }, @@ -31,18 +28,12 @@ (string) (len=40) "Topic :: Software Development :: Testing", (string) (len=18) "Topic :: Utilities" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=5628) ".. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg\n :target: https://docs.pytest.org/en/stable/\n :align: center\n :height: 200\n :alt: pytest\n\n\n------\n\n.. image:: https://img.shields.io/pypi/v/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pytest.svg\n :target: https://anaconda.org/conda-forge/pytest\n\n.. image:: https://img.shields.io/pypi/pyversions/pytest.svg\n :target: https://pypi.org/project/pytest/\n\n.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/pytest-dev/pytest\n :alt: Code coverage Status\n\n.. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg\n :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest\n\n.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg\n :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main\n :alt: pre-commit.ci status\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg\n :target: https://www.codetriage.com/pytest-dev/pytest\n\n.. image:: https://readthedocs.org/projects/pytest/badge/?version=latest\n :target: https://pytest.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Discord-pytest--dev-blue\n :target: https://discord.com/invite/pytest-dev\n :alt: Discord\n\n.. image:: https://img.shields.io/badge/Libera%20chat-%23pytest-orange\n :target: https://web.libera.chat/#pytest\n :alt: Libera chat\n\n\nThe ``pytest`` framework makes it easy to write small tests, yet\nscales to support complex functional testing for applications and libraries.\n\nAn example of a simple test:\n\n.. code-block:: python\n\n # content of test_sample.py\n def inc(x):\n return x + 1\n\n\n def test_answer():\n assert inc(3) == 5\n\n\nTo execute it::\n\n $ pytest\n ============================= test session starts =============================\n collected 1 items\n\n test_sample.py F\n\n ================================== FAILURES ===================================\n _________________________________ test_answer _________________________________\n\n def test_answer():\n > assert inc(3) == 5\n E assert 4 == 5\n E + where 4 = inc(3)\n\n test_sample.py:5: AssertionError\n ========================== 1 failed in 0.04 seconds ===========================\n\n\nDue to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples.\n\n\nFeatures\n--------\n\n- Detailed info on failing `assert statements `_ (no need to remember ``self.assert*`` names)\n\n- `Auto-discovery\n `_\n of test modules and functions\n\n- `Modular fixtures `_ for\n managing small or parametrized long-lived test resources\n\n- Can run `unittest `_ (or trial),\n `nose `_ test suites out of the box\n\n- Python 3.7+ or PyPy3\n\n- Rich plugin architecture, with over 850+ `external plugins `_ and thriving community\n\n\nDocumentation\n-------------\n\nFor full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/stable/.\n\n\nBugs/Requests\n-------------\n\nPlease use the `GitHub issue tracker `_ to submit bugs or request features.\n\n\nChangelog\n---------\n\nConsult the `Changelog `__ page for fixes and enhancements of each version.\n\n\nSupport pytest\n--------------\n\n`Open Collective`_ is an online funding platform for open and transparent communities.\nIt provides tools to raise money and share your finances in full transparency.\n\nIt is the platform of choice for individuals and companies that want to make one-time or\nmonthly donations directly to the project.\n\nSee more details in the `pytest collective`_.\n\n.. _Open Collective: https://opencollective.com\n.. _pytest collective: https://opencollective.com/pytest\n\n\npytest for enterprise\n---------------------\n\nAvailable as part of the Tidelift Subscription.\n\nThe maintainers of pytest and thousands of other packages are working with Tidelift to deliver commercial support and\nmaintenance for the open source dependencies you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.\n\n`Learn more. `_\n\nSecurity\n^^^^^^^^\n\npytest has never been associated with a security vulnerability, but in any case, to report a\nsecurity vulnerability please use the `Tidelift security contact `_.\nTidelift will coordinate the fix and disclosure.\n\n\nLicense\n-------\n\nCopyright Holger Krekel and others, 2004.\n\nDistributed under the terms of the `MIT`_ license, pytest is free and open source software.\n\n.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE\n" }, (string) (len=24) "description_content_type": ([]string) (len=1) { (string) (len=10) "text/x-rst" }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=8) "filetype": ([]string) (len=1) { (string) (len=11) "bdist_wheel" }, @@ -50,17 +41,11 @@ (string) (len=34) "https://docs.pytest.org/en/latest/" }, (string) (len=8) "keywords": ([]string) (len=1) { - (string) (len=13) "test,unittest" + (string) (len=14) "test, unittest" }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "MIT" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, diff --git a/.snapshots/TestParse-python-certifi_signed_tarball b/.snapshots/TestParse-python-certifi_signed_tarball index 49b4136..90cea39 100644 --- a/.snapshots/TestParse-python-certifi_signed_tarball +++ b/.snapshots/TestParse-python-certifi_signed_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -25,18 +25,9 @@ (string) (len=37) "Programming Language :: Python :: 3.2", (string) (len=37) "Programming Language :: Python :: 3.3" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=552) "Certifi: Python SSL Certificates\n================================\n\nThis installable Python package contains a CA Bundle that you can reference\nin your Python code. This is useful for verifying HTTP requests, for example.\n\nThis is the same CA Bundle which ships with the Requests codebase, and is\nderived from Mozilla Firefox's canonical set.\n\n\nUsage\n-----\n\nTo reference the installed CA Bundle, you can use the built-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem'\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=7) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -52,18 +43,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=26) "http://python-requests.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "ISC" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -77,10 +59,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" - }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" diff --git a/.snapshots/TestParse-python-certifi_signed_wheel b/.snapshots/TestParse-python-certifi_signed_wheel index b4c9aac..b32039e 100644 --- a/.snapshots/TestParse-python-certifi_signed_wheel +++ b/.snapshots/TestParse-python-certifi_signed_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -25,18 +25,9 @@ (string) (len=37) "Programming Language :: Python :: 3.2", (string) (len=37) "Programming Language :: Python :: 3.3" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=552) "Certifi: Python SSL Certificates\n================================\n\nThis installable Python package contains a CA Bundle that you can reference\nin your Python code. This is useful for verifying HTTP requests, for example.\n\nThis is the same CA Bundle which ships with the Requests codebase, and is\nderived from Mozilla Firefox's canonical set.\n\n\nUsage\n-----\n\nTo reference the installed CA Bundle, you can use the built-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem'\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=7) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -52,18 +43,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=26) "http://python-requests.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "ISC" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -79,9 +61,6 @@ (string) (len=9) "pyversion": ([]string) (len=1) { (string) (len=7) "py2.py3" }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" - }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" }, diff --git a/.snapshots/TestParse-python-certifi_unsigned_tarball b/.snapshots/TestParse-python-certifi_unsigned_tarball index 9577255..f7696a1 100644 --- a/.snapshots/TestParse-python-certifi_unsigned_tarball +++ b/.snapshots/TestParse-python-certifi_unsigned_tarball @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -25,18 +25,9 @@ (string) (len=37) "Programming Language :: Python :: 3.2", (string) (len=37) "Programming Language :: Python :: 3.3" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=552) "Certifi: Python SSL Certificates\n================================\n\nThis installable Python package contains a CA Bundle that you can reference\nin your Python code. This is useful for verifying HTTP requests, for example.\n\nThis is the same CA Bundle which ships with the Requests codebase, and is\nderived from Mozilla Firefox's canonical set.\n\n\nUsage\n-----\n\nTo reference the installed CA Bundle, you can use the built-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem'\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=7) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -52,18 +43,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=26) "http://python-requests.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "ISC" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -77,10 +59,7 @@ (string) (len=1) "1" }, (string) (len=9) "pyversion": ([]string) (len=1) { - (string) "" - }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" + (string) (len=6) "source" }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" diff --git a/.snapshots/TestParse-python-certifi_unsigned_wheel b/.snapshots/TestParse-python-certifi_unsigned_wheel index 8a5c798..e790745 100644 --- a/.snapshots/TestParse-python-certifi_unsigned_wheel +++ b/.snapshots/TestParse-python-certifi_unsigned_wheel @@ -1,5 +1,5 @@ (parse_test.ParserData) { - Metadata: (map[string][]string) (len=25) { + Metadata: (map[string][]string) (len=18) { (string) (len=7) ":action": ([]string) (len=1) { (string) (len=11) "file_upload" }, @@ -25,18 +25,9 @@ (string) (len=37) "Programming Language :: Python :: 3.2", (string) (len=37) "Programming Language :: Python :: 3.3" }, - (string) (len=7) "comment": ([]string) (len=1) { - (string) "" - }, (string) (len=11) "description": ([]string) (len=1) { (string) (len=552) "Certifi: Python SSL Certificates\n================================\n\nThis installable Python package contains a CA Bundle that you can reference\nin your Python code. This is useful for verifying HTTP requests, for example.\n\nThis is the same CA Bundle which ships with the Requests codebase, and is\nderived from Mozilla Firefox's canonical set.\n\n\nUsage\n-----\n\nTo reference the installed CA Bundle, you can use the built-in function::\n\n >>> import certifi\n\n >>> certifi.where()\n '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem'\n\nEnjoy!\n" }, - (string) (len=24) "description_content_type": ([]string) (len=1) { - (string) "" - }, - (string) (len=12) "download_url": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "dynamic": ([]string) (len=7) { (string) (len=6) "author", (string) (len=12) "author-email", @@ -52,18 +43,9 @@ (string) (len=9) "home_page": ([]string) (len=1) { (string) (len=26) "http://python-requests.org" }, - (string) (len=8) "keywords": ([]string) (len=1) { - (string) "" - }, (string) (len=7) "license": ([]string) (len=1) { (string) (len=3) "ISC" }, - (string) (len=10) "maintainer": ([]string) (len=1) { - (string) "" - }, - (string) (len=16) "maintainer_email": ([]string) (len=1) { - (string) "" - }, (string) (len=10) "md5_digest": ([]string) (len=1) { (string) (len=17) "md5_digest exists" }, @@ -79,9 +61,6 @@ (string) (len=9) "pyversion": ([]string) (len=1) { (string) (len=7) "py2.py3" }, - (string) (len=15) "requires_python": ([]string) (len=1) { - (string) "" - }, (string) (len=13) "sha256_digest": ([]string) (len=1) { (string) (len=20) "sha256_digest exists" }, diff --git a/internal/distributions/distribution.go b/internal/distributions/distribution.go index 7c16433..1cb73e0 100644 --- a/internal/distributions/distribution.go +++ b/internal/distributions/distribution.go @@ -213,6 +213,11 @@ func (bd *BaseDistribution) Parse(data []byte) error { return err } } else if headerValues[0] != "UNKNOWN" { + // Manipulate the keywords so there are spaces in between to match Twine output + if headerAttr.AttrName == "keywords"{ + headerValues[0] = strings.Join(strings.Split(headerValues[0], ","), ", ") + } + err := bd.setJSONValue(headerAttr.AttrName, headerValues[0]) if err != nil { return err diff --git a/internal/distributions/metadata.go b/internal/distributions/metadata.go index 8ffa5f4..cd3d213 100644 --- a/internal/distributions/metadata.go +++ b/internal/distributions/metadata.go @@ -81,7 +81,7 @@ func NewDistributionMetadata(filename string) (Distribution, string, string, err case "bdist_wheel", "bdist_wininst": pythonVersion = metadata.GetPythonVersion() default: - pythonVersion = "" + pythonVersion = "source" // Updated in twine 6.1.0 } return metadata, pythonVersion, fileType, nil diff --git a/types/types.go b/types/types.go index 9d4ba7f..675df95 100644 --- a/types/types.go +++ b/types/types.go @@ -62,26 +62,9 @@ func (pf *PackageFile) MetadataMap() map[string][]string { delete(result, key) } - allowedBlankValues := []string{ - "author", - "author_email", - "comment", - "download_url", - "home_page", - "keywords", - "license", - "maintainer", - "pyversion", - "description_content_type", - "maintainer_email", - "requires_python", - } // remove any keys that are an empty value, unless twine expects them result = lo.OmitBy(result, func(key string, value []string) bool { - if lo.Contains(allowedBlankValues, key) { - return false - } return value == nil || len(value) == 1 && (value[0] == "" || value[0] == "") })