From ac33104c32cbce87301a55a63215dbe1b21c4bd7 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 13 Mar 2026 23:35:02 -0400 Subject: [PATCH 01/41] Bump to Ubuntu 24.04 for RTD builds --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 7409274..03c3c3f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -7,7 +7,7 @@ version: 2 # Build and VM configuration build: - os: 'ubuntu-22.04' + os: 'ubuntu-24.04' tools: python: '3.13' From cb53f5ca1c79aa8bbb4686e3efc9722edbc7a5f1 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 13 Mar 2026 23:35:16 -0400 Subject: [PATCH 02/41] Freshen links into Sphinx source --- doc/source/index.rst | 2 +- doc/source/syntax.rst | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/source/index.rst b/doc/source/index.rst index d07d5be..114e9d7 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -11,7 +11,7 @@ Welcome to sphobjinv! When documentation is built using, e.g., Sphinx's :obj:`~sphinx.builders.html.StandaloneHTMLBuilder`, an inventory of the named objects in the documentation set `is dumped -`__ +`__ to a file called |objects.inv| in the html build directory. (One common location is, |cour|\ doc/build/html\ |/cour|, though the exact location will vary depending on the details of how Sphinx is configured.) This file is read by |isphx| when diff --git a/doc/source/syntax.rst b/doc/source/syntax.rst index ab51b11..0bbb877 100644 --- a/doc/source/syntax.rst +++ b/doc/source/syntax.rst @@ -27,7 +27,7 @@ data line. ---- **The first line** `must be exactly -`__: +`__: .. code-block:: none @@ -36,7 +36,7 @@ data line. ---- **The second and third lines** `must obey -`__ +`__ the template: .. code-block:: none @@ -56,7 +56,7 @@ the |isphx| cross-references: ---- **The fourth line** `must contain -`__ +`__ the string ``zlib`` somewhere within it, but for consistency it should be exactly: .. code-block:: none @@ -67,7 +67,7 @@ the string ``zlib`` somewhere within it, but for consistency it should be exactl **All remaining lines** of the file are the objects data, each laid out in the `following syntax -`__: +`__: .. code-block:: none @@ -132,7 +132,7 @@ the string ``zlib`` somewhere within it, but for consistency it should be exactl ``{priority}`` Flag for `placement in search results - `__. Most will be ``1`` (standard priority) or + `__. Most will be ``1`` (standard priority) or ``-1`` (omit from results) for documentation built by Sphinx; values of ``0`` (higher priority) or ``2`` (lower priority) may also occur. @@ -217,11 +217,11 @@ size of the inventory file: `__," the portion following the ``#`` symbol) and the tail of the anchor is identical to |{name}|_, that tail is `replaced - `__ + `__ with ``$``. |br| |br| #. If |{dispname}|_ is identical to |{name}|_, it is `stored - `__ + `__ as ``-``. Thus, a standard |isphx| reference to this method would take the form: @@ -271,11 +271,11 @@ as in :obj:`This is join! `: .. |prio_js_search| replace:: here -.. _prio_js_search: https://github.com/sphinx-doc/sphinx/blob/ac3f74a3e0fbb326f73989a16dfa369e072064ca/sphinx/themes/basic/static/searchtools.js#L28-L46 +.. _prio_js_search: https://github.com/sphinx-doc/sphinx/blob/e552f8429c3039bc0649a7da82bdfa0df3273c3d/sphinx/themes/basic/static/searchtools.js#L21-L39 .. |prio_py_search| replace:: here -.. _prio_py_search: https://github.com/sphinx-doc/sphinx/blob/ac3f74a3e0fbb326f73989a16dfa369e072064ca/sphinx/search/__init__.py#L344-L345 +.. _prio_py_search: https://github.com/sphinx-doc/sphinx/blob/e552f8429c3039bc0649a7da82bdfa0df3273c3d/sphinx/search/__init__.py#L377-L378 .. |sphinx_uri_issue| replace:: sphinx-doc/sphinx#7096 @@ -297,4 +297,4 @@ as in :obj:`This is join! `: .. _rst-directive-option: https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#directive-rst-directive-option -.. _parsing regex: https://github.com/sphinx-doc/sphinx/blob/ac3f74a3e0fbb326f73989a16dfa369e072064ca/sphinx/util/inventory.py#L134-L135 +.. _parsing regex: https://github.com/sphinx-doc/sphinx/blob/e552f8429c3039bc0649a7da82bdfa0df3273c3d/sphinx/util/inventory.py#L115-L119 From fd037642c183a79000ec1488aa934b1923e241da Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 13 Mar 2026 23:39:35 -0400 Subject: [PATCH 03/41] Update numpy example in README --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 8aef5f0..3bf36e7 100644 --- a/README.md +++ b/README.md @@ -84,31 +84,31 @@ cross-reference the `linspace` function from numpy (see [here][numpy linspace]): ```none -$ sphobjinv suggest https://numpy.org/doc/1.26/reference/index.html linspace -su +$ sphobjinv suggest https://numpy.org/doc/2.4/reference/index.html linspace -su -Attempting https://numpy.org/doc/1.26/reference/index.html ... +Attempting https://numpy.org/doc/2.4/reference/index.html ... ... no recognized inventory. -Attempting "https://numpy.org/doc/1.26/reference/index.html/objects.inv" ... +Attempting "https://numpy.org/doc/2.4/reference/index.html/objects.inv" ... ... HTTP error: 404 Not Found. -Attempting "https://numpy.org/doc/1.26/reference/objects.inv" ... +Attempting "https://numpy.org/doc/2.4/reference/objects.inv" ... ... HTTP error: 404 Not Found. -Attempting "https://numpy.org/doc/1.26/objects.inv" ... +Attempting "https://numpy.org/doc/2.4/objects.inv" ... ... inventory found. ----------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------- The intersphinx_mapping for this docset is LIKELY: - (https://numpy.org/doc/1.26/, None) + (https://numpy.org/doc/2.4/, None) ----------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------- Project: NumPy -Version: 1.26 +Version: 2.4 -8152 objects in inventory. +8456 objects in inventory. ----------------------------------------------------------------------------------- +----------------------------------------------------------------------------------------------------------- 8 results found at/above current threshold of 75. From f188bcc436ce33ba810fc3e334f1081914ac2c0c Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 14 Mar 2026 00:36:35 -0400 Subject: [PATCH 04/41] Freshen/update some docs bits --- doc/source/_static/mouseover_example.png | Bin 48977 -> 21672 bytes doc/source/customfile.rst | 2 +- doc/source/index.rst | 2 ++ doc/source/syntax.rst | 6 +++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/source/_static/mouseover_example.png b/doc/source/_static/mouseover_example.png index eef34b44b1ea27405ffc3e8b61f4e2509e786483..7e60477449668af89e2f5e27643320d90706e1e0 100644 GIT binary patch literal 21672 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 Bk3s+d literal 48977 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 St3llW0000`__) + * Fedora: ``python-sphobjinv`` (`info `__) * Gentoo: ``dev-python/sphobjinv`` (`info `__) diff --git a/doc/source/syntax.rst b/doc/source/syntax.rst index 0bbb877..0b0f57e 100644 --- a/doc/source/syntax.rst +++ b/doc/source/syntax.rst @@ -5,8 +5,8 @@ Sphinx objects.inv v2 Syntax After decompression, "version 2" Sphinx |objects.inv| files follow a syntax that, to the best of this author's ability to determine, is not included in the -Sphinx documentation. The below syntax is believed to be accurate as of May 2024 -(Sphinx v7.3.7). It is based on inspection of |objects.inv| files "in the +Sphinx documentation. The below syntax is believed to be accurate as of March 2026 +(Sphinx v9.1.0). It is based on inspection of |objects.inv| files "in the wild" and of the Sphinx inventory object `parsing regex`_. Based upon a quick ``git diff`` of the `Sphinx repository @@ -194,7 +194,7 @@ of cross-references from other documentation source. **For illustration**, the following is the entry for the :meth:`join() ` method of the :class:`str` class in the -Python 3.12 |objects.inv|, broken out field-by-field: +Python 3.14 |objects.inv|, broken out field-by-field: .. code-block:: none From 86ca3214c389a047e61b6eb63790da0b08e4f543 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 00:57:17 -0400 Subject: [PATCH 05/41] Bump package to 2.4.dev0 and update README example --- README.md | 14 ++++++-------- src/sphobjinv/version.py | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3bf36e7..14bf93f 100644 --- a/README.md +++ b/README.md @@ -42,26 +42,24 @@ For internal cross-references, locate `objects.inv` within `build/html`: ```none $ sphobjinv suggest doc/build/html/objects.inv as_rst -st 58 ------------------------------------------------- +----------------------------------------------------------------------------------------------------------- Cannot infer intersphinx_mapping from a local objects.inv. ------------------------------------------------- +----------------------------------------------------------------------------------------------------------- Project: sphobjinv -Version: 2.3 - -220 objects in inventory. +Version: 2.4 ------------------------------------------------- +151 objects in inventory. -11 results found at/above current threshold of 58. +----------------------------------------------------------------------------------------------------------- +10 results found at/above current threshold of 58. Name Score --------------------------------------------------- ------- :py:property:`sphobjinv.data.SuperDataObj.as_rst` 60 -:py:class:`sphobjinv.cli.parser.PrsConst` 59 :py:class:`sphobjinv.data.DataFields` 59 :py:class:`sphobjinv.data.DataObjBytes` 59 :py:class:`sphobjinv.data.DataObjStr` 59 diff --git a/src/sphobjinv/version.py b/src/sphobjinv/version.py index 3840d8c..ac087af 100644 --- a/src/sphobjinv/version.py +++ b/src/sphobjinv/version.py @@ -29,4 +29,4 @@ """ -__version__ = "2.3.2.dev0" +__version__ = "2.4.dev0" From 40109b0ac963509a13c4a5717761d728cf475c83 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 17:25:54 -0400 Subject: [PATCH 06/41] Specify Python 3.13 for black, and blacken --- pyproject.toml | 1 + src/sphobjinv/re.py | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0ad2588..adeec1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ namespaces = false version = {attr = "sphobjinv.version.__version__"} [tool.black] +target-version = ["py313"] line-length = 88 include = ''' ( diff --git a/src/sphobjinv/re.py b/src/sphobjinv/re.py index dfe4c9e..017a181 100644 --- a/src/sphobjinv/re.py +++ b/src/sphobjinv/re.py @@ -45,9 +45,7 @@ [#][ ]Project:[ ] # Preamble (?P<{HF.Project.value}>.*?) # Lazy rest of line is project name \r?$ # Ignore possible CR at EOL - """.encode( - encoding="utf-8" - ), + """.encode(encoding="utf-8"), re.M | re.X, ) @@ -58,9 +56,7 @@ [#][ ]Version:[ ] # Preamble (?P<{HF.Version.value}>.*?) # Lazy rest of line is version \r?$ # Ignore possible CR at EOL - """.encode( - encoding="utf-8" - ), + """.encode(encoding="utf-8"), re.M | re.X, ) From 2a0ebba683d81068a636395f5b80422fd16fa928 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 17:26:05 -0400 Subject: [PATCH 07/41] Bump minimum jsonschema to v3.1.1 --- pyproject.toml | 2 +- tox.ini | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index adeec1b..2f37d8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ requires-python = ">=3.10" dependencies = [ "attrs>=19.2", "certifi", - "jsonschema>=3.0", + "jsonschema>=3.1.1", ] dynamic = ["version", "readme"] diff --git a/tox.ini b/tox.ini index b0366da..8ada057 100644 --- a/tox.ini +++ b/tox.ini @@ -11,11 +11,13 @@ envlist= # Scan attrs versions py313-sphx_latest-attrs_{19_2,19_3,20_3,21_3,22_2,23_2,24_3,dev}-jsch_latest # Scan jsonschema versions - py313-sphx_latest-attrs_latest-jsch_{3_0,3_x,4_0,4_8,4_14,4_20,dev} + py313-sphx_latest-attrs_latest-jsch_{3_1_1,3_x,4_0,4_8,4_14,4_20,dev} # Earliest supported Python and lib versions all together - py310-sphx_1_6_x-attrs_19_2-jsch_3_0 + py310-sphx_1_6_x-attrs_19_2-jsch_3_1_1 # Spot matrix of early Python, Sphinx, attrs versions py3{10,11}-sphx_{1,2}_x-attrs_{19,20}_2-jsch_latest + # Test the new-earliest jsonschema version that started failing in 3.13 + py3{10,11,12,13,14}-sphx_latest-attrs_latest-jsch_3_1_1 # Test the specific Sphinx threshold cases where behavior changed py313-sphx_{2_3_1,2_4_0,3_2_1,3_3_0,3_4_0,8_1_3,8_2_0}-attrs_latest-jsch_latest # Simple 'does the sdist install' check @@ -63,7 +65,7 @@ deps= attrs_latest: attrs attrs_dev: git+https://github.com/python-attrs/attrs - jsch_3_0: jsonschema==3.0 + jsch_3_1_1: jsonschema==3.1.1 jsch_3_x: jsonschema<4 jsch_4_0: jsonschema<4.1 jsch_4_8: jsonschema<4.9 From ade2a2069e8cfea160ccbb055a91ca063dcf3c37 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 20:25:22 -0400 Subject: [PATCH 08/41] Update sphinx and attrs invs --- tests/resource/objects_attrs.inv | Bin 1434 -> 1838 bytes tests/resource/objects_attrs_22_1.inv | Bin 0 -> 1434 bytes tests/resource/objects_sphinx.inv | Bin 14192 -> 17616 bytes tests/resource/objects_sphinx_6_0b.inv | Bin 0 -> 14192 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/resource/objects_attrs_22_1.inv create mode 100644 tests/resource/objects_sphinx_6_0b.inv diff --git a/tests/resource/objects_attrs.inv b/tests/resource/objects_attrs.inv index 85189bdf1858248a4f6b3eead8acdc496c072967..7c5a9b0a8c39d9e1c978f5e68bce2409a0dbb340 100644 GIT binary patch delta 1746 zcmV;@1}*uT3$6~3Is-K>G?6_zf2CN>a@#f#zVj(K(_HCkueo#-MUFj9Y)|YY(-Q_F zAqis$U;)Usa_ZCc!TKa!{E*@wB!IodA@qH__*v}k2duTs>*M>qs1A(ezvj561%|<^ zo!+xw+;H(OFETs0fPd)vpo!s>3@erYHlVcFyZfh`+q+K&Sz(RC!0$vVe=7Jb--rma zXpf)C)IK?T@XH(2fPnlh@7ah7_FkkvoP@m0v`p0il1 zT}I!k;4egKBF`FXK|Ss@F13(nr_ewe-itd(MByZ-Pqi2x>nH%cEvzb9YD3%{c&Xvn za72J%QN}{`p=Kl!Y!(>@e=YYlIw;Dwk?>~ARl?n?$cFOBsgoDMUShFtC8-T0Wils{ zy=AJsYIj0kivzD#QVJV(Epj4&BCU*lek2=wV0ytM!PW7R=u~$B17lCuQv4*momi@$ zNqWf3JmcqW-g2ceFK14?&mQ}Lb6VKdDVvT`olMdvy(}?fc+JQRe-C}?*!sg!?*xAm z;+`c(?U*~Z|BYkLg~pmxv%@HC!~5G%!m7CYZlNj#i{f+fhO)%8<{4(S>`;*;H&>LW zkZefDVYfshdEn>;GYZ{{h%E#=90{cBIGm})$Q92x{6U*wj{{4hOr1dbSd&Qmv9Ou@ z2fW1i@g5>q+@DXJe~S@x8Wn7g`%~!PI%RrKAdytl_^E#N0&u!DO(0#}EFNzbA3m=P z8@CIaV*xD}%bV55`G!8P7T;HB@%jGlf6V6F-Mke|cH;@8tLyu(%lSS*Ma}2_xq3_^ zOz32GHxn#B&UJtmY?iBjrAcntYxafxB(l>32gog?)xc#hKV zmuy^C=5ZEg6VFKNO9n3M<_HUCH1Q?&1UL(M|>59cdZ1NEsk zdM43l(ct4UeuECH)FC4oDWbRWM7YAdLMa}g43Qd9SW8?u44Hde*HKl!OQgy;tCC1t zk_gvmo*$hAryM2XU2Q>Plg3l1^kpH5mkLi?z14U`foe*my&)EJC%YWj=~NDsvb58Q zZxOpBf0^b)#fD~0bET{Il_m{FS{f6E=_Tf)S)yFu-s+o5IinU!K+V@Va9 zMi<_WdVKqxb;L|>P3F~PupYDg@}RWX7XvpfYv9OmErI^TW&<)Wf6n;w4Ydzm15vE#VZlB^$mf;-z>hGV-|GAa zjQ^euk-a%hSqa$ijak$zZuhofwU14ff9&6LiV{Nss!%NjEK46_tc~eKOJCaW{K0)w zm@-_^NB?%TbT=eBovvSX=U{DUzi*)V4+^*9pz{xcG9qgR{aALen&f{nQyJ0USsVHQQ(8cKAf57%$ zKsP!O?)9-~esG??xHi@WJ~wrzJ1INhfcHFqg8H-+&{UYxWouL>AcMY8^4cXeW1i=~ zvRcv?*yo}x6KD4B!C~{o32U}u!6-H--C4zjt#UrbasEhI2ir+?|-uY0LB^4h%0zy@Bjb+ delta 1339 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 literal 0 HcmV?d00001 diff --git a/tests/resource/objects_sphinx.inv b/tests/resource/objects_sphinx.inv index ed2fe5b49dea079c6de5789bf7e6d5695944f23b..7a4f085be3d3b5c8ebc6785883e7cba494a58a76 100644 GIT binary patch literal 17616 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 literal 14192 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 G(=kkTBdzKH diff --git a/tests/resource/objects_sphinx_6_0b.inv b/tests/resource/objects_sphinx_6_0b.inv new file mode 100644 index 0000000000000000000000000000000000000000..ed2fe5b49dea079c6de5789bf7e6d5695944f23b GIT binary patch literal 14192 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 G(=kkTBdzKH literal 0 HcmV?d00001 From 2014ccf6ef60a73fe28643a6d4d332bb6e784f65 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 20:50:47 -0400 Subject: [PATCH 09/41] Update JSON and TXT attrs invs, too --- tests/resource/objects_attrs.json | 2 +- tests/resource/objects_attrs.txt | 121 +++++++++++++++++++++--------- 2 files changed, 87 insertions(+), 36 deletions(-) diff --git a/tests/resource/objects_attrs.json b/tests/resource/objects_attrs.json index b114431..d0ad36c 100644 --- a/tests/resource/objects_attrs.json +++ b/tests/resource/objects_attrs.json @@ -1 +1 @@ -{"project": "attrs", "version": "22.1", "count": 129, "0": {"name": "attr", "domain": "py", "role": "module", "priority": "0", "uri": "index.html#module-$", "dispname": "-"}, "1": {"name": "attr.VersionInfo", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "2": {"name": "attr._make.Attribute", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.Attribute", "dispname": "-"}, "3": {"name": "attr._make.Factory", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.Factory", "dispname": "-"}, "4": {"name": "attr._version_info.VersionInfo", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attr.VersionInfo", "dispname": "-"}, "5": {"name": "attr.asdict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "6": {"name": "attr.assoc", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "7": {"name": "attr.astuple", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "8": {"name": "attr.attr.NOTHING", "domain": "py", "role": "data", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "9": {"name": "attr.attr.cmp_using", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "10": {"name": "attr.attr.evolve", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "11": {"name": "attr.attr.fields", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "12": {"name": "attr.attr.fields_dict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "13": {"name": "attr.attr.filters.exclude", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "14": {"name": "attr.attr.filters.include", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "15": {"name": "attr.attr.has", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "16": {"name": "attr.attr.resolve_types", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "17": {"name": "attr.attr.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "18": {"name": "attr.attrs.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "19": {"name": "attr.attrs.mutable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "20": {"name": "attr.attrs.setters.NO_OP", "domain": "py", "role": "data", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "21": {"name": "attr.define", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "22": {"name": "attr.exceptions.AttrsAttributeNotFoundError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.AttrsAttributeNotFoundError", "dispname": "-"}, "23": {"name": "attr.exceptions.DefaultAlreadySetError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.DefaultAlreadySetError", "dispname": "-"}, "24": {"name": "attr.exceptions.FrozenAttributeError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenAttributeError", "dispname": "-"}, "25": {"name": "attr.exceptions.FrozenError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenError", "dispname": "-"}, "26": {"name": "attr.exceptions.FrozenInstanceError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenInstanceError", "dispname": "-"}, "27": {"name": "attr.exceptions.NotAnAttrsClassError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.NotAnAttrsClassError", "dispname": "-"}, "28": {"name": "attr.exceptions.NotCallableError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.NotCallableError", "dispname": "-"}, "29": {"name": "attr.exceptions.PythonTooOldError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.PythonTooOldError", "dispname": "-"}, "30": {"name": "attr.exceptions.UnannotatedAttributeError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.UnannotatedAttributeError", "dispname": "-"}, "31": {"name": "attr.field", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "32": {"name": "attr.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "33": {"name": "attr.get_run_validators", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "34": {"name": "attr.ib", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "35": {"name": "attr.mutable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "36": {"name": "attr.s", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "37": {"name": "attr.set_run_validators", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "38": {"name": "attrs", "domain": "py", "role": "module", "priority": "0", "uri": "index.html#module-$", "dispname": "-"}, "39": {"name": "attrs.Attribute", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "40": {"name": "attrs.Attribute.evolve", "domain": "py", "role": "method", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "41": {"name": "attrs.Factory", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "42": {"name": "attrs.NOTHING", "domain": "py", "role": "data", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "43": {"name": "attrs.asdict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "44": {"name": "attrs.astuple", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "45": {"name": "attrs.cmp_using", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "46": {"name": "attrs.converters.default_if_none", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "47": {"name": "attrs.converters.optional", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "48": {"name": "attrs.converters.pipe", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "49": {"name": "attrs.converters.to_bool", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "50": {"name": "attrs.define", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "51": {"name": "attrs.evolve", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "52": {"name": "attrs.exceptions.AttrsAttributeNotFoundError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "53": {"name": "attrs.exceptions.DefaultAlreadySetError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "54": {"name": "attrs.exceptions.FrozenAttributeError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "55": {"name": "attrs.exceptions.FrozenError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "56": {"name": "attrs.exceptions.FrozenInstanceError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "57": {"name": "attrs.exceptions.NotAnAttrsClassError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "58": {"name": "attrs.exceptions.NotCallableError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "59": {"name": "attrs.exceptions.PythonTooOldError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "60": {"name": "attrs.exceptions.UnannotatedAttributeError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "61": {"name": "attrs.field", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "62": {"name": "attrs.fields", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "63": {"name": "attrs.fields_dict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "64": {"name": "attrs.filters.exclude", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "65": {"name": "attrs.filters.include", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "66": {"name": "attrs.has", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "67": {"name": "attrs.make_class", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "68": {"name": "attrs.resolve_types", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "69": {"name": "attrs.setters.convert", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "70": {"name": "attrs.setters.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "71": {"name": "attrs.setters.pipe", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "72": {"name": "attrs.setters.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "73": {"name": "attrs.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "74": {"name": "attrs.validators.and_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "75": {"name": "attrs.validators.deep_iterable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "76": {"name": "attrs.validators.deep_mapping", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "77": {"name": "attrs.validators.disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "78": {"name": "attrs.validators.ge", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "79": {"name": "attrs.validators.get_disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "80": {"name": "attrs.validators.gt", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "81": {"name": "attrs.validators.in_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "82": {"name": "attrs.validators.instance_of", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "83": {"name": "attrs.validators.is_callable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "84": {"name": "attrs.validators.le", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "85": {"name": "attrs.validators.lt", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "86": {"name": "attrs.validators.matches_re", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "87": {"name": "attrs.validators.max_len", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "88": {"name": "attrs.validators.min_len", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "89": {"name": "attrs.validators.optional", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "90": {"name": "attrs.validators.provides", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "91": {"name": "attrs.validators.set_disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "92": {"name": "api", "domain": "std", "role": "doc", "priority": "-1", "uri": "api.html", "dispname": "API Reference"}, "93": {"name": "api_setters", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#api-setters", "dispname": "Setters"}, "94": {"name": "api_validators", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#api-validators", "dispname": "Validators"}, "95": {"name": "asdict", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#$", "dispname": "Converting to Collections Types"}, "96": {"name": "changelog", "domain": "std", "role": "doc", "priority": "-1", "uri": "changelog.html", "dispname": "Changelog"}, "97": {"name": "comparison", "domain": "std", "role": "doc", "priority": "-1", "uri": "comparison.html", "dispname": "Comparison"}, "98": {"name": "converters", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Converters"}, "99": {"name": "custom-comparison", "domain": "std", "role": "label", "priority": "-1", "uri": "comparison.html#$", "dispname": "Customization"}, "100": {"name": "dict classes", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-dict-classes", "dispname": "-"}, "101": {"name": "dunder methods", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-dunder-methods", "dispname": "-"}, "102": {"name": "examples", "domain": "std", "role": "doc", "priority": "-1", "uri": "examples.html", "dispname": "attrs by Example"}, "103": {"name": "examples_validators", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#examples-validators", "dispname": "Validators"}, "104": {"name": "extending", "domain": "std", "role": "doc", "priority": "-1", "uri": "extending.html", "dispname": "Extending"}, "105": {"name": "extending_metadata", "domain": "std", "role": "label", "priority": "-1", "uri": "extending.html#extending-metadata", "dispname": "Metadata"}, "106": {"name": "genindex", "domain": "std", "role": "label", "priority": "-1", "uri": "genindex.html", "dispname": "Index"}, "107": {"name": "glossary", "domain": "std", "role": "doc", "priority": "-1", "uri": "glossary.html", "dispname": "Glossary"}, "108": {"name": "hashing", "domain": "std", "role": "doc", "priority": "-1", "uri": "hashing.html", "dispname": "Hashing"}, "109": {"name": "helpers", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#$", "dispname": "Helpers"}, "110": {"name": "how", "domain": "std", "role": "label", "priority": "-1", "uri": "how-does-it-work.html#$", "dispname": "How Does It Work?"}, "111": {"name": "how-does-it-work", "domain": "std", "role": "doc", "priority": "-1", "uri": "how-does-it-work.html", "dispname": "How Does It Work?"}, "112": {"name": "how-frozen", "domain": "std", "role": "label", "priority": "-1", "uri": "how-does-it-work.html#$", "dispname": "Immutability"}, "113": {"name": "index", "domain": "std", "role": "doc", "priority": "-1", "uri": "index.html", "dispname": "attrs: Classes Without Boilerplate"}, "114": {"name": "init", "domain": "std", "role": "doc", "priority": "-1", "uri": "init.html", "dispname": "Initialization"}, "115": {"name": "license", "domain": "std", "role": "doc", "priority": "-1", "uri": "license.html", "dispname": "License and Credits"}, "116": {"name": "metadata", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#$", "dispname": "Metadata"}, "117": {"name": "modindex", "domain": "std", "role": "label", "priority": "-1", "uri": "py-modindex.html", "dispname": "Module Index"}, "118": {"name": "names", "domain": "std", "role": "doc", "priority": "-1", "uri": "names.html", "dispname": "On The Core API Names"}, "119": {"name": "overview", "domain": "std", "role": "doc", "priority": "-1", "uri": "overview.html", "dispname": "Overview"}, "120": {"name": "philosophy", "domain": "std", "role": "label", "priority": "-1", "uri": "overview.html#$", "dispname": "Philosophy"}, "121": {"name": "py-modindex", "domain": "std", "role": "label", "priority": "-1", "uri": "py-modindex.html", "dispname": "Python Module Index"}, "122": {"name": "search", "domain": "std", "role": "label", "priority": "-1", "uri": "search.html", "dispname": "Search Page"}, "123": {"name": "slotted classes", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-slotted-classes", "dispname": "-"}, "124": {"name": "transform-fields", "domain": "std", "role": "label", "priority": "-1", "uri": "extending.html#$", "dispname": "Automatic Field Transformation and Modification"}, "125": {"name": "types", "domain": "std", "role": "doc", "priority": "-1", "uri": "types.html", "dispname": "Type Annotations"}, "126": {"name": "validators", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Validators"}, "127": {"name": "version-info", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#$", "dispname": "-"}, "128": {"name": "why", "domain": "std", "role": "doc", "priority": "-1", "uri": "why.html", "dispname": "Why not\u2026"}} \ No newline at end of file +{"project": "attrs", "version": "25.4", "count": 180, "0": {"name": "attr", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "1": {"name": "attr.Attribute", "domain": "py", "role": "class", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "2": {"name": "attr.NOTHING", "domain": "py", "role": "data", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "3": {"name": "attr.VersionInfo", "domain": "py", "role": "class", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "4": {"name": "attr._make.Attribute", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.Attribute", "dispname": "-"}, "5": {"name": "attr._make.ClassProps", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.ClassProps", "dispname": "-"}, "6": {"name": "attr._make.ClassProps.Hashability", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.ClassProps.Hashability", "dispname": "-"}, "7": {"name": "attr._make.ClassProps.KeywordOnly", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.ClassProps.KeywordOnly", "dispname": "-"}, "8": {"name": "attr._make.Converter", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.Converter", "dispname": "-"}, "9": {"name": "attr._make.Factory", "domain": "py", "role": "class", "priority": "-1", "uri": "api.html#attrs.Factory", "dispname": "-"}, "10": {"name": "attr._version_info.VersionInfo", "domain": "py", "role": "class", "priority": "-1", "uri": "api-attr.html#attr.VersionInfo", "dispname": "-"}, "11": {"name": "attr.asdict", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "12": {"name": "attr.assoc", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "13": {"name": "attr.astuple", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "14": {"name": "attr.attrs", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "15": {"name": "attr.cmp_using", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "16": {"name": "attr.converters", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "17": {"name": "attr.define", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "18": {"name": "attr.evolve", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "19": {"name": "attr.exceptions", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "20": {"name": "attr.exceptions.AttrsAttributeNotFoundError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.AttrsAttributeNotFoundError", "dispname": "-"}, "21": {"name": "attr.exceptions.DefaultAlreadySetError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.DefaultAlreadySetError", "dispname": "-"}, "22": {"name": "attr.exceptions.FrozenAttributeError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenAttributeError", "dispname": "-"}, "23": {"name": "attr.exceptions.FrozenError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenError", "dispname": "-"}, "24": {"name": "attr.exceptions.FrozenInstanceError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.FrozenInstanceError", "dispname": "-"}, "25": {"name": "attr.exceptions.NotAnAttrsClassError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.NotAnAttrsClassError", "dispname": "-"}, "26": {"name": "attr.exceptions.NotCallableError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.NotCallableError", "dispname": "-"}, "27": {"name": "attr.exceptions.PythonTooOldError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.PythonTooOldError", "dispname": "-"}, "28": {"name": "attr.exceptions.UnannotatedAttributeError", "domain": "py", "role": "exception", "priority": "-1", "uri": "api.html#attrs.exceptions.UnannotatedAttributeError", "dispname": "-"}, "29": {"name": "attr.field", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "30": {"name": "attr.fields", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "31": {"name": "attr.fields_dict", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "32": {"name": "attr.filters", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "33": {"name": "attr.filters.exclude", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "34": {"name": "attr.filters.include", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "35": {"name": "attr.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "36": {"name": "attr.get_run_validators", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "37": {"name": "attr.has", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "38": {"name": "attr.ib", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "39": {"name": "attr.make_class", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "40": {"name": "attr.mutable", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "41": {"name": "attr.resolve_types", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "42": {"name": "attr.s", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "43": {"name": "attr.set_run_validators", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "44": {"name": "attr.setters", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "45": {"name": "attr.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api-attr.html#$", "dispname": "-"}, "46": {"name": "attr.validators", "domain": "py", "role": "module", "priority": "0", "uri": "api-attr.html#module-$", "dispname": "-"}, "47": {"name": "attrs", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "48": {"name": "attrs.Attribute", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "49": {"name": "attrs.Attribute.evolve", "domain": "py", "role": "method", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "50": {"name": "attrs.ClassProps", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "51": {"name": "attrs.ClassProps.Hashability", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "52": {"name": "attrs.ClassProps.Hashability.HASHABLE", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "53": {"name": "attrs.ClassProps.Hashability.HASHABLE_CACHED", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "54": {"name": "attrs.ClassProps.Hashability.LEAVE_ALONE", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "55": {"name": "attrs.ClassProps.Hashability.UNHASHABLE", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "56": {"name": "attrs.ClassProps.KeywordOnly", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "57": {"name": "attrs.ClassProps.KeywordOnly.FORCE", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "58": {"name": "attrs.ClassProps.KeywordOnly.NO", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "59": {"name": "attrs.ClassProps.KeywordOnly.YES", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "60": {"name": "attrs.ClassProps.added_eq", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "61": {"name": "attrs.ClassProps.added_init", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "62": {"name": "attrs.ClassProps.added_match_args", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "63": {"name": "attrs.ClassProps.added_ordering", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "64": {"name": "attrs.ClassProps.added_pickling", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "65": {"name": "attrs.ClassProps.added_repr", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "66": {"name": "attrs.ClassProps.added_str", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "67": {"name": "attrs.ClassProps.collected_fields_by_mro", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "68": {"name": "attrs.ClassProps.field_transformer", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "69": {"name": "attrs.ClassProps.has_weakref_slot", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "70": {"name": "attrs.ClassProps.hashability", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "71": {"name": "attrs.ClassProps.is_exception", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "72": {"name": "attrs.ClassProps.is_frozen", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "73": {"name": "attrs.ClassProps.is_slotted", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "74": {"name": "attrs.ClassProps.kw_only", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "75": {"name": "attrs.ClassProps.on_setattr_hook", "domain": "py", "role": "attribute", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "76": {"name": "attrs.Converter", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "77": {"name": "attrs.Factory", "domain": "py", "role": "class", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "78": {"name": "attrs.NOTHING", "domain": "py", "role": "data", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "79": {"name": "attrs.asdict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "80": {"name": "attrs.astuple", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "81": {"name": "attrs.cmp_using", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "82": {"name": "attrs.converters", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "83": {"name": "attrs.converters.default_if_none", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "84": {"name": "attrs.converters.optional", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "85": {"name": "attrs.converters.pipe", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "86": {"name": "attrs.converters.to_bool", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "87": {"name": "attrs.define", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "88": {"name": "attrs.evolve", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "89": {"name": "attrs.exceptions", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "90": {"name": "attrs.exceptions.AttrsAttributeNotFoundError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "91": {"name": "attrs.exceptions.DefaultAlreadySetError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "92": {"name": "attrs.exceptions.FrozenAttributeError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "93": {"name": "attrs.exceptions.FrozenError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "94": {"name": "attrs.exceptions.FrozenInstanceError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "95": {"name": "attrs.exceptions.NotAnAttrsClassError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "96": {"name": "attrs.exceptions.NotCallableError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "97": {"name": "attrs.exceptions.PythonTooOldError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "98": {"name": "attrs.exceptions.UnannotatedAttributeError", "domain": "py", "role": "exception", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "99": {"name": "attrs.field", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "100": {"name": "attrs.fields", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "101": {"name": "attrs.fields_dict", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "102": {"name": "attrs.filters", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "103": {"name": "attrs.filters.exclude", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "104": {"name": "attrs.filters.include", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "105": {"name": "attrs.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "106": {"name": "attrs.has", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "107": {"name": "attrs.inspect", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "108": {"name": "attrs.make_class", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "109": {"name": "attrs.mutable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "110": {"name": "attrs.resolve_types", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "111": {"name": "attrs.setters", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "112": {"name": "attrs.setters.NO_OP", "domain": "py", "role": "data", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "113": {"name": "attrs.setters.convert", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "114": {"name": "attrs.setters.frozen", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "115": {"name": "attrs.setters.pipe", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "116": {"name": "attrs.setters.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "117": {"name": "attrs.validate", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "118": {"name": "attrs.validators", "domain": "py", "role": "module", "priority": "0", "uri": "api.html#module-$", "dispname": "-"}, "119": {"name": "attrs.validators.and_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "120": {"name": "attrs.validators.deep_iterable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "121": {"name": "attrs.validators.deep_mapping", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "122": {"name": "attrs.validators.disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "123": {"name": "attrs.validators.ge", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "124": {"name": "attrs.validators.get_disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "125": {"name": "attrs.validators.gt", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "126": {"name": "attrs.validators.in_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "127": {"name": "attrs.validators.instance_of", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "128": {"name": "attrs.validators.is_callable", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "129": {"name": "attrs.validators.le", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "130": {"name": "attrs.validators.lt", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "131": {"name": "attrs.validators.matches_re", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "132": {"name": "attrs.validators.max_len", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "133": {"name": "attrs.validators.min_len", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "134": {"name": "attrs.validators.not_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "135": {"name": "attrs.validators.optional", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "136": {"name": "attrs.validators.or_", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "137": {"name": "attrs.validators.set_disabled", "domain": "py", "role": "function", "priority": "1", "uri": "api.html#$", "dispname": "-"}, "138": {"name": "api", "domain": "std", "role": "doc", "priority": "-1", "uri": "api.html", "dispname": "API Reference"}, "139": {"name": "api-attr", "domain": "std", "role": "doc", "priority": "-1", "uri": "api-attr.html", "dispname": "API Reference for the attr Namespace"}, "140": {"name": "api-validators", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#$", "dispname": "Validators"}, "141": {"name": "api_setters", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#api-setters", "dispname": "Setters"}, "142": {"name": "asdict", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#$", "dispname": "Converting to Collections Types"}, "143": {"name": "attribute", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-$", "dispname": "-"}, "144": {"name": "changelog", "domain": "std", "role": "doc", "priority": "-1", "uri": "changelog.html", "dispname": "Changelog"}, "145": {"name": "comparison", "domain": "std", "role": "doc", "priority": "-1", "uri": "comparison.html", "dispname": "Comparison"}, "146": {"name": "converters", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Converters"}, "147": {"name": "custom-comparison", "domain": "std", "role": "label", "priority": "-1", "uri": "comparison.html#$", "dispname": "Customization"}, "148": {"name": "defaults", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Defaults"}, "149": {"name": "dict classes", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-dict-classes", "dispname": "-"}, "150": {"name": "dunder methods", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-dunder-methods", "dispname": "-"}, "151": {"name": "examples", "domain": "std", "role": "doc", "priority": "-1", "uri": "examples.html", "dispname": "attrs by Example"}, "152": {"name": "examples-validators", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#$", "dispname": "Validators"}, "153": {"name": "extending", "domain": "std", "role": "doc", "priority": "-1", "uri": "extending.html", "dispname": "Extending"}, "154": {"name": "extending-metadata", "domain": "std", "role": "label", "priority": "-1", "uri": "extending.html#$", "dispname": "Metadata"}, "155": {"name": "field", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-$", "dispname": "-"}, "156": {"name": "genindex", "domain": "std", "role": "label", "priority": "-1", "uri": "genindex.html", "dispname": "Index"}, "157": {"name": "glossary", "domain": "std", "role": "doc", "priority": "-1", "uri": "glossary.html", "dispname": "Glossary"}, "158": {"name": "hashing", "domain": "std", "role": "doc", "priority": "-1", "uri": "hashing.html", "dispname": "Hashing"}, "159": {"name": "helpers", "domain": "std", "role": "label", "priority": "-1", "uri": "api.html#$", "dispname": "Helpers"}, "160": {"name": "how", "domain": "std", "role": "label", "priority": "-1", "uri": "how-does-it-work.html#$", "dispname": "How Does It Work?"}, "161": {"name": "how-does-it-work", "domain": "std", "role": "doc", "priority": "-1", "uri": "how-does-it-work.html", "dispname": "How Does It Work?"}, "162": {"name": "how-frozen", "domain": "std", "role": "label", "priority": "-1", "uri": "how-does-it-work.html#$", "dispname": "Immutability"}, "163": {"name": "how-slotted-cached_property", "domain": "std", "role": "label", "priority": "-1", "uri": "how-does-it-work.html#how-slotted-cached-property", "dispname": "Cached Properties on Slotted Classes"}, "164": {"name": "index", "domain": "std", "role": "doc", "priority": "-1", "uri": "index.html", "dispname": "attrs: Classes Without Boilerplate"}, "165": {"name": "init", "domain": "std", "role": "doc", "priority": "-1", "uri": "init.html", "dispname": "Initialization"}, "166": {"name": "init-subclass", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "attrs and __init_subclass__"}, "167": {"name": "license", "domain": "std", "role": "doc", "priority": "-1", "uri": "license.html", "dispname": "License and Credits"}, "168": {"name": "metadata", "domain": "std", "role": "label", "priority": "-1", "uri": "examples.html#$", "dispname": "Metadata"}, "169": {"name": "modindex", "domain": "std", "role": "label", "priority": "-1", "uri": "py-modindex.html", "dispname": "Module Index"}, "170": {"name": "names", "domain": "std", "role": "doc", "priority": "-1", "uri": "names.html", "dispname": "On The Core API Names"}, "171": {"name": "overview", "domain": "std", "role": "doc", "priority": "-1", "uri": "overview.html", "dispname": "Overview"}, "172": {"name": "private-attributes", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Private Attributes and Aliases"}, "173": {"name": "py-modindex", "domain": "std", "role": "label", "priority": "-1", "uri": "py-modindex.html", "dispname": "Python Module Index"}, "174": {"name": "search", "domain": "std", "role": "label", "priority": "-1", "uri": "search.html", "dispname": "Search Page"}, "175": {"name": "slotted classes", "domain": "std", "role": "term", "priority": "-1", "uri": "glossary.html#term-slotted-classes", "dispname": "-"}, "176": {"name": "transform-fields", "domain": "std", "role": "label", "priority": "-1", "uri": "extending.html#$", "dispname": "Automatic Field Transformation and Modification"}, "177": {"name": "types", "domain": "std", "role": "doc", "priority": "-1", "uri": "types.html", "dispname": "Type Annotations"}, "178": {"name": "validators", "domain": "std", "role": "label", "priority": "-1", "uri": "init.html#$", "dispname": "Validators"}, "179": {"name": "why", "domain": "std", "role": "doc", "priority": "-1", "uri": "why.html", "dispname": "Why not\u2026"}} \ No newline at end of file diff --git a/tests/resource/objects_attrs.txt b/tests/resource/objects_attrs.txt index 50cf946..a81d296 100644 --- a/tests/resource/objects_attrs.txt +++ b/tests/resource/objects_attrs.txt @@ -1,29 +1,27 @@ # Sphinx inventory version 2 # Project: attrs -# Version: 22.1 +# Version: 25.4 # The remainder of this file is compressed using zlib. -attr py:module 0 index.html#module-$ - -attr.VersionInfo py:class 1 api.html#$ - +attr py:module 0 api-attr.html#module-$ - +attr.Attribute py:class 1 api-attr.html#$ - +attr.NOTHING py:data 1 api-attr.html#$ - +attr.VersionInfo py:class 1 api-attr.html#$ - attr._make.Attribute py:class -1 api.html#attrs.Attribute - +attr._make.ClassProps py:class -1 api.html#attrs.ClassProps - +attr._make.ClassProps.Hashability py:class -1 api.html#attrs.ClassProps.Hashability - +attr._make.ClassProps.KeywordOnly py:class -1 api.html#attrs.ClassProps.KeywordOnly - +attr._make.Converter py:class -1 api.html#attrs.Converter - attr._make.Factory py:class -1 api.html#attrs.Factory - -attr._version_info.VersionInfo py:class -1 api.html#attr.VersionInfo - -attr.asdict py:function 1 api.html#$ - -attr.assoc py:function 1 api.html#$ - -attr.astuple py:function 1 api.html#$ - -attr.attr.NOTHING py:data 1 api.html#$ - -attr.attr.cmp_using py:function 1 api.html#$ - -attr.attr.evolve py:function 1 api.html#$ - -attr.attr.fields py:function 1 api.html#$ - -attr.attr.fields_dict py:function 1 api.html#$ - -attr.attr.filters.exclude py:function 1 api.html#$ - -attr.attr.filters.include py:function 1 api.html#$ - -attr.attr.has py:function 1 api.html#$ - -attr.attr.resolve_types py:function 1 api.html#$ - -attr.attr.validate py:function 1 api.html#$ - -attr.attrs.frozen py:function 1 api.html#$ - -attr.attrs.mutable py:function 1 api.html#$ - -attr.attrs.setters.NO_OP py:data 1 api.html#$ - -attr.define py:function 1 api.html#$ - +attr._version_info.VersionInfo py:class -1 api-attr.html#attr.VersionInfo - +attr.asdict py:function 1 api-attr.html#$ - +attr.assoc py:function 1 api-attr.html#$ - +attr.astuple py:function 1 api-attr.html#$ - +attr.attrs py:function 1 api-attr.html#$ - +attr.cmp_using py:function 1 api-attr.html#$ - +attr.converters py:module 0 api-attr.html#module-$ - +attr.define py:function 1 api-attr.html#$ - +attr.evolve py:function 1 api-attr.html#$ - +attr.exceptions py:module 0 api-attr.html#module-$ - attr.exceptions.AttrsAttributeNotFoundError py:exception -1 api.html#attrs.exceptions.AttrsAttributeNotFoundError - attr.exceptions.DefaultAlreadySetError py:exception -1 api.html#attrs.exceptions.DefaultAlreadySetError - attr.exceptions.FrozenAttributeError py:exception -1 api.html#attrs.exceptions.FrozenAttributeError - @@ -33,27 +31,67 @@ attr.exceptions.NotAnAttrsClassError py:exception -1 api.html#attrs.exceptions.N attr.exceptions.NotCallableError py:exception -1 api.html#attrs.exceptions.NotCallableError - attr.exceptions.PythonTooOldError py:exception -1 api.html#attrs.exceptions.PythonTooOldError - attr.exceptions.UnannotatedAttributeError py:exception -1 api.html#attrs.exceptions.UnannotatedAttributeError - -attr.field py:function 1 api.html#$ - -attr.frozen py:function 1 api.html#$ - -attr.get_run_validators py:function 1 api.html#$ - -attr.ib py:function 1 api.html#$ - -attr.mutable py:function 1 api.html#$ - -attr.s py:function 1 api.html#$ - -attr.set_run_validators py:function 1 api.html#$ - -attrs py:module 0 index.html#module-$ - +attr.field py:function 1 api-attr.html#$ - +attr.fields py:function 1 api-attr.html#$ - +attr.fields_dict py:function 1 api-attr.html#$ - +attr.filters py:module 0 api-attr.html#module-$ - +attr.filters.exclude py:function 1 api-attr.html#$ - +attr.filters.include py:function 1 api-attr.html#$ - +attr.frozen py:function 1 api-attr.html#$ - +attr.get_run_validators py:function 1 api-attr.html#$ - +attr.has py:function 1 api-attr.html#$ - +attr.ib py:function 1 api-attr.html#$ - +attr.make_class py:function 1 api-attr.html#$ - +attr.mutable py:function 1 api-attr.html#$ - +attr.resolve_types py:function 1 api-attr.html#$ - +attr.s py:function 1 api-attr.html#$ - +attr.set_run_validators py:function 1 api-attr.html#$ - +attr.setters py:module 0 api-attr.html#module-$ - +attr.validate py:function 1 api-attr.html#$ - +attr.validators py:module 0 api-attr.html#module-$ - +attrs py:module 0 api.html#module-$ - attrs.Attribute py:class 1 api.html#$ - attrs.Attribute.evolve py:method 1 api.html#$ - +attrs.ClassProps py:class 1 api.html#$ - +attrs.ClassProps.Hashability py:class 1 api.html#$ - +attrs.ClassProps.Hashability.HASHABLE py:attribute 1 api.html#$ - +attrs.ClassProps.Hashability.HASHABLE_CACHED py:attribute 1 api.html#$ - +attrs.ClassProps.Hashability.LEAVE_ALONE py:attribute 1 api.html#$ - +attrs.ClassProps.Hashability.UNHASHABLE py:attribute 1 api.html#$ - +attrs.ClassProps.KeywordOnly py:class 1 api.html#$ - +attrs.ClassProps.KeywordOnly.FORCE py:attribute 1 api.html#$ - +attrs.ClassProps.KeywordOnly.NO py:attribute 1 api.html#$ - +attrs.ClassProps.KeywordOnly.YES py:attribute 1 api.html#$ - +attrs.ClassProps.added_eq py:attribute 1 api.html#$ - +attrs.ClassProps.added_init py:attribute 1 api.html#$ - +attrs.ClassProps.added_match_args py:attribute 1 api.html#$ - +attrs.ClassProps.added_ordering py:attribute 1 api.html#$ - +attrs.ClassProps.added_pickling py:attribute 1 api.html#$ - +attrs.ClassProps.added_repr py:attribute 1 api.html#$ - +attrs.ClassProps.added_str py:attribute 1 api.html#$ - +attrs.ClassProps.collected_fields_by_mro py:attribute 1 api.html#$ - +attrs.ClassProps.field_transformer py:attribute 1 api.html#$ - +attrs.ClassProps.has_weakref_slot py:attribute 1 api.html#$ - +attrs.ClassProps.hashability py:attribute 1 api.html#$ - +attrs.ClassProps.is_exception py:attribute 1 api.html#$ - +attrs.ClassProps.is_frozen py:attribute 1 api.html#$ - +attrs.ClassProps.is_slotted py:attribute 1 api.html#$ - +attrs.ClassProps.kw_only py:attribute 1 api.html#$ - +attrs.ClassProps.on_setattr_hook py:attribute 1 api.html#$ - +attrs.Converter py:class 1 api.html#$ - attrs.Factory py:class 1 api.html#$ - attrs.NOTHING py:data 1 api.html#$ - attrs.asdict py:function 1 api.html#$ - attrs.astuple py:function 1 api.html#$ - attrs.cmp_using py:function 1 api.html#$ - +attrs.converters py:module 0 api.html#module-$ - attrs.converters.default_if_none py:function 1 api.html#$ - attrs.converters.optional py:function 1 api.html#$ - attrs.converters.pipe py:function 1 api.html#$ - attrs.converters.to_bool py:function 1 api.html#$ - attrs.define py:function 1 api.html#$ - attrs.evolve py:function 1 api.html#$ - +attrs.exceptions py:module 0 api.html#module-$ - attrs.exceptions.AttrsAttributeNotFoundError py:exception 1 api.html#$ - attrs.exceptions.DefaultAlreadySetError py:exception 1 api.html#$ - attrs.exceptions.FrozenAttributeError py:exception 1 api.html#$ - @@ -66,16 +104,23 @@ attrs.exceptions.UnannotatedAttributeError py:exception 1 api.html#$ - attrs.field py:function 1 api.html#$ - attrs.fields py:function 1 api.html#$ - attrs.fields_dict py:function 1 api.html#$ - +attrs.filters py:module 0 api.html#module-$ - attrs.filters.exclude py:function 1 api.html#$ - attrs.filters.include py:function 1 api.html#$ - +attrs.frozen py:function 1 api.html#$ - attrs.has py:function 1 api.html#$ - +attrs.inspect py:function 1 api.html#$ - attrs.make_class py:function 1 api.html#$ - +attrs.mutable py:function 1 api.html#$ - attrs.resolve_types py:function 1 api.html#$ - +attrs.setters py:module 0 api.html#module-$ - +attrs.setters.NO_OP py:data 1 api.html#$ - attrs.setters.convert py:function 1 api.html#$ - attrs.setters.frozen py:function 1 api.html#$ - attrs.setters.pipe py:function 1 api.html#$ - attrs.setters.validate py:function 1 api.html#$ - attrs.validate py:function 1 api.html#$ - +attrs.validators py:module 0 api.html#module-$ - attrs.validators.and_ py:function 1 api.html#$ - attrs.validators.deep_iterable py:function 1 api.html#$ - attrs.validators.deep_mapping py:function 1 api.html#$ - @@ -91,23 +136,28 @@ attrs.validators.lt py:function 1 api.html#$ - attrs.validators.matches_re py:function 1 api.html#$ - attrs.validators.max_len py:function 1 api.html#$ - attrs.validators.min_len py:function 1 api.html#$ - +attrs.validators.not_ py:function 1 api.html#$ - attrs.validators.optional py:function 1 api.html#$ - -attrs.validators.provides py:function 1 api.html#$ - +attrs.validators.or_ py:function 1 api.html#$ - attrs.validators.set_disabled py:function 1 api.html#$ - api std:doc -1 api.html API Reference +api-attr std:doc -1 api-attr.html API Reference for the attr Namespace +api-validators std:label -1 api.html#$ Validators api_setters std:label -1 api.html#api-setters Setters -api_validators std:label -1 api.html#api-validators Validators asdict std:label -1 examples.html#$ Converting to Collections Types +attribute std:term -1 glossary.html#term-$ - changelog std:doc -1 changelog.html Changelog comparison std:doc -1 comparison.html Comparison converters std:label -1 init.html#$ Converters custom-comparison std:label -1 comparison.html#$ Customization +defaults std:label -1 init.html#$ Defaults dict classes std:term -1 glossary.html#term-dict-classes - dunder methods std:term -1 glossary.html#term-dunder-methods - examples std:doc -1 examples.html attrs by Example -examples_validators std:label -1 examples.html#examples-validators Validators +examples-validators std:label -1 examples.html#$ Validators extending std:doc -1 extending.html Extending -extending_metadata std:label -1 extending.html#extending-metadata Metadata +extending-metadata std:label -1 extending.html#$ Metadata +field std:term -1 glossary.html#term-$ - genindex std:label -1 genindex.html Index glossary std:doc -1 glossary.html Glossary hashing std:doc -1 hashing.html Hashing @@ -115,19 +165,20 @@ helpers std:label -1 api.html#$ Helpers how std:label -1 how-does-it-work.html#$ How Does It Work? how-does-it-work std:doc -1 how-does-it-work.html How Does It Work? how-frozen std:label -1 how-does-it-work.html#$ Immutability +how-slotted-cached_property std:label -1 how-does-it-work.html#how-slotted-cached-property Cached Properties on Slotted Classes index std:doc -1 index.html attrs: Classes Without Boilerplate init std:doc -1 init.html Initialization +init-subclass std:label -1 init.html#$ attrs and __init_subclass__ license std:doc -1 license.html License and Credits metadata std:label -1 examples.html#$ Metadata modindex std:label -1 py-modindex.html Module Index names std:doc -1 names.html On The Core API Names overview std:doc -1 overview.html Overview -philosophy std:label -1 overview.html#$ Philosophy +private-attributes std:label -1 init.html#$ Private Attributes and Aliases py-modindex std:label -1 py-modindex.html Python Module Index search std:label -1 search.html Search Page slotted classes std:term -1 glossary.html#term-slotted-classes - transform-fields std:label -1 extending.html#$ Automatic Field Transformation and Modification types std:doc -1 types.html Type Annotations validators std:label -1 init.html#$ Validators -version-info std:label -1 api.html#$ - why std:doc -1 why.html Why not… From 77613b239e8b8c02b988e84adbf5e2063200911d Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 21:03:54 -0400 Subject: [PATCH 10/41] Update test checks to match new attrs inventory --- tests/conftest.py | 4 ++-- tests/test_api_good.py | 4 ++-- tests/test_cli.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 19db681..7402f2f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -310,8 +310,8 @@ def func(inv, source_type): """ assert inv.project == "attrs" - assert inv.version == "22.1" - assert inv.count == 129 + assert inv.version == "25.4" + assert inv.count == 180 assert inv.source_type return func diff --git a/tests/test_api_good.py b/tests/test_api_good.py index 8193306..9e9d57c 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -452,8 +452,8 @@ def test_api_inventory_toosmallflatdict_importbutignore(self, res_dec): def test_api_inventory_namesuggest(self, res_cmp, check): """Confirm object name suggestion is nominally working on a specific object.""" - rst = ":py:function:`attr.attr.evolve`" - idx = 10 + rst = ":py:function:`attr.evolve`" + idx = 18 inv = soi.Inventory(str(res_cmp)) diff --git a/tests/test_cli.py b/tests/test_cli.py index 8dd367e..adffa6b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -355,7 +355,7 @@ def test_cli_suggest_withindex(self, run_cmdline_test, res_cmp): """Confirm with_index suggest works.""" with stdio_mgr() as (in_, out_, err_): run_cmdline_test(["suggest", res_cmp, "instance", "-it", "50"]) - assert re.search("^.*instance_of\\S*\\s+82\\s*$", out_.getvalue(), re.M) + assert re.search("^.*instance_of\\S*\\s+127\\s*$", out_.getvalue(), re.M) @pytest.mark.timeout(CLI_TEST_TIMEOUT) def test_cli_suggest_withscore(self, run_cmdline_test, res_cmp): @@ -373,7 +373,7 @@ def test_cli_suggest_withscoreandindex(self, run_cmdline_test, res_cmp): @pytest.mark.parametrize( ["inp", "flags", "nlines"], - [("", "-at", 129), ("y\n", "-t", 130), ("n\n", "-t", 1)], + [("", "-at", 180), ("y\n", "-t", 181), ("n\n", "-t", 1)], ) # Extra line for input() query in the "y\n" case @pytest.mark.timeout(CLI_TEST_TIMEOUT) def test_cli_suggest_long_list(self, inp, flags, nlines, run_cmdline_test, res_cmp): From 7a763584178f7f84c8af2cc3a6a864e81c81a244 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 21:10:52 -0400 Subject: [PATCH 11/41] Update README doctest examples --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14bf93f..5ae5a01 100644 --- a/README.md +++ b/README.md @@ -152,13 +152,13 @@ inventory creation/modification: >>> import sphobjinv as soi >>> inv = soi.Inventory('doc/build/html/objects.inv') >>> print(inv) - + >>> inv.project 'sphobjinv' >>> inv.version -'2.3' +'2.4' >>> inv.objects[0] -DataObjStr(name='sphobjinv.cli.convert', domain='py', role='module', priority='0', uri='cli/implementation/convert.html#module-$', dispname='-') +DataObjStr(name='sphobjinv.data', domain='py', role='module', priority='0', uri='api/data.html#module-$', dispname='-') ``` From 573c2555e8051efb4f2a49bc9151d826f608ae83 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 21:38:17 -0400 Subject: [PATCH 12/41] Update Pepy badge link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ae5a01..b5313ea 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ under a [Creative Commons Attribution 4.0 International License][cc-by 4.0] [mit license]: https://opensource.org/licenses/MIT [numpy linspace]: https://numpy.org/doc/1.26/reference/generated/numpy.linspace.html [pepy badge]: https://pepy.tech/badge/sphobjinv/month -[pepy link target]: https://pepy.tech/projects/sphobjinv?timeRange=threeMonths&category=version&includeCIDownloads=true&granularity=daily&viewType=chart&versions=2.0.*%2C2.1.*%2C2.2.*%2C2.3.* +[pepy link target]: https://pepy.tech/projects/sphobjinv?timeRange=threeMonths&category=version&includeCIDownloads=true&granularity=daily&versions=2.3.*%2C2.4* [pypi badge]: https://img.shields.io/pypi/v/sphobjinv.svg?logo=pypi] [pypi link target]: https://pypi.org/project/sphobjinv [python versions badge]: https://img.shields.io/pypi/pyversions/sphobjinv.svg?logo=python From 1297e6c2249b00b92e992d4efbc8ca640d4b1471 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 21:38:44 -0400 Subject: [PATCH 13/41] Reset and refactor version override in setup.py --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f172d29..0061532 100644 --- a/setup.py +++ b/setup.py @@ -9,13 +9,13 @@ exec(Path("src", "sphobjinv", "version.py").read_text(encoding="utf-8"), exec_ns) __version__ = exec_ns["__version__"] -version_override = "2.3.1.2" +version_override = None def readme(): content = Path("README.md").read_text(encoding="utf-8") - new_ver = version_override if version_override else __version__ + new_ver = version_override or __version__ # Helper function def content_update(content, pattern, sub): From 7ae75a1cbd585f3cf7e72202afc1a23ecad92360 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 15 Mar 2026 21:39:07 -0400 Subject: [PATCH 14/41] Update copyright statements and year ranges --- LICENSE.txt | 2 +- README.md | 2 +- doc/source/conf.py | 2 +- src/sphobjinv/__init__.py | 2 +- src/sphobjinv/__main__.py | 2 +- src/sphobjinv/_vendored/__init__.py | 2 +- src/sphobjinv/_vendored/fuzzywuzzy/__init__.py | 2 +- src/sphobjinv/cli/__init__.py | 2 +- src/sphobjinv/cli/convert.py | 2 +- src/sphobjinv/cli/core.py | 2 +- src/sphobjinv/cli/load.py | 2 +- src/sphobjinv/cli/parser.py | 4 ++-- src/sphobjinv/cli/paths.py | 2 +- src/sphobjinv/cli/suggest.py | 2 +- src/sphobjinv/cli/ui.py | 2 +- src/sphobjinv/cli/write.py | 2 +- src/sphobjinv/data.py | 2 +- src/sphobjinv/enum.py | 2 +- src/sphobjinv/error.py | 2 +- src/sphobjinv/fileops.py | 2 +- src/sphobjinv/inventory.py | 2 +- src/sphobjinv/re.py | 2 +- src/sphobjinv/schema.py | 2 +- src/sphobjinv/version.py | 4 ++-- src/sphobjinv/zlib.py | 2 +- tests/conftest.py | 2 +- tests/enum.py | 2 +- tests/fixtures_http.py | 2 +- tests/test_api_fail.py | 2 +- tests/test_api_good.py | 2 +- tests/test_api_good_nonlocal.py | 2 +- tests/test_cli.py | 2 +- tests/test_cli_nonlocal.py | 2 +- tests/test_cli_textconv.py | 2 +- tests/test_fixture.py | 2 +- tests/test_flake8_ext.py | 2 +- tests/test_intersphinx.py | 2 +- tests/test_valid_objects.py | 2 +- 38 files changed, 40 insertions(+), 40 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index e892de6..8afcbd7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2025 Brian Skinn and community contributors +Copyright (c) 2016-2026 Brian Skinn and community contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index b5313ea..6a3e885 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ Available on [PyPI][pypi link target] (`pip install sphobjinv`). Source on [GitHub][github repo]. Bug reports and feature requests are welcomed at the [Issues][github issue tracker] page there. -Copyright (c) Brian Skinn 2016-2025 +Copyright (c) 2016-2026 Brian Skinn and community contributors The `sphobjinv` documentation (including docstrings and README) is licensed under a [Creative Commons Attribution 4.0 International License][cc-by 4.0] diff --git a/doc/source/conf.py b/doc/source/conf.py index 5abed10..c9a2932 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -21,7 +21,7 @@ # -- Project information ----------------------------------------------------- project = "sphobjinv" -copyright = "2016-2025, Brian Skinn" +copyright = "2016-2026, Brian Skinn and community contributors" author = "Brian Skinn" # The full version for `release`, including alpha/beta/rc tags diff --git a/src/sphobjinv/__init__.py b/src/sphobjinv/__init__.py index 0e141f9..e46dd28 100644 --- a/src/sphobjinv/__init__.py +++ b/src/sphobjinv/__init__.py @@ -10,7 +10,7 @@ 17 May 2016 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/__main__.py b/src/sphobjinv/__main__.py index 6e30775..d063bb2 100644 --- a/src/sphobjinv/__main__.py +++ b/src/sphobjinv/__main__.py @@ -10,7 +10,7 @@ 15 May 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/_vendored/__init__.py b/src/sphobjinv/_vendored/__init__.py index 36ba019..b5f7e17 100644 --- a/src/sphobjinv/_vendored/__init__.py +++ b/src/sphobjinv/_vendored/__init__.py @@ -12,7 +12,7 @@ 11 Dec 2021 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/_vendored/fuzzywuzzy/__init__.py b/src/sphobjinv/_vendored/fuzzywuzzy/__init__.py index ff3129d..f88ee54 100644 --- a/src/sphobjinv/_vendored/fuzzywuzzy/__init__.py +++ b/src/sphobjinv/_vendored/fuzzywuzzy/__init__.py @@ -25,7 +25,7 @@ 11 Dec 2021 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/__init__.py b/src/sphobjinv/cli/__init__.py index 357e6e8..d7b267b 100644 --- a/src/sphobjinv/cli/__init__.py +++ b/src/sphobjinv/cli/__init__.py @@ -10,7 +10,7 @@ 15 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/convert.py b/src/sphobjinv/cli/convert.py index 1a342d6..829f1c7 100644 --- a/src/sphobjinv/cli/convert.py +++ b/src/sphobjinv/cli/convert.py @@ -10,7 +10,7 @@ 20 Oct 2022 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/core.py b/src/sphobjinv/cli/core.py index 9130f99..3fbc6d1 100644 --- a/src/sphobjinv/cli/core.py +++ b/src/sphobjinv/cli/core.py @@ -10,7 +10,7 @@ 15 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/load.py b/src/sphobjinv/cli/load.py index 3240575..07032c9 100644 --- a/src/sphobjinv/cli/load.py +++ b/src/sphobjinv/cli/load.py @@ -10,7 +10,7 @@ 17 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/parser.py b/src/sphobjinv/cli/parser.py index 19727e1..224bd59 100644 --- a/src/sphobjinv/cli/parser.py +++ b/src/sphobjinv/cli/parser.py @@ -10,7 +10,7 @@ 15 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv @@ -44,7 +44,7 @@ class PrsConst: #: Version &c. output blurb VER_TXT = ( - f"\nsphobjinv v{__version__}\n\nCopyright (c) Brian Skinn 2016-2025\n" + f"\nsphobjinv v{__version__}\n\nCopyright (c) 2016-2026 Brian Skinn and community contributors\n" "License: The MIT License\n\n" "Bug reports & feature requests:" " https://github.com/bskinn/sphobjinv\n" diff --git a/src/sphobjinv/cli/paths.py b/src/sphobjinv/cli/paths.py index de9bfc2..1ce9581 100644 --- a/src/sphobjinv/cli/paths.py +++ b/src/sphobjinv/cli/paths.py @@ -10,7 +10,7 @@ 19 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/suggest.py b/src/sphobjinv/cli/suggest.py index 1fb7dd5..865dd4a 100644 --- a/src/sphobjinv/cli/suggest.py +++ b/src/sphobjinv/cli/suggest.py @@ -10,7 +10,7 @@ 20 Oct 2022 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/ui.py b/src/sphobjinv/cli/ui.py index 2ab2290..a886880 100644 --- a/src/sphobjinv/cli/ui.py +++ b/src/sphobjinv/cli/ui.py @@ -10,7 +10,7 @@ 19 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/cli/write.py b/src/sphobjinv/cli/write.py index f7f0816..b9a9930 100644 --- a/src/sphobjinv/cli/write.py +++ b/src/sphobjinv/cli/write.py @@ -10,7 +10,7 @@ 19 Nov 2020 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/data.py b/src/sphobjinv/data.py index 10a6c7d..76cade5 100644 --- a/src/sphobjinv/data.py +++ b/src/sphobjinv/data.py @@ -10,7 +10,7 @@ 7 Nov 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/enum.py b/src/sphobjinv/enum.py index d046dc9..3fa4fcd 100644 --- a/src/sphobjinv/enum.py +++ b/src/sphobjinv/enum.py @@ -10,7 +10,7 @@ 4 May 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/error.py b/src/sphobjinv/error.py index 3742230..ba07b20 100644 --- a/src/sphobjinv/error.py +++ b/src/sphobjinv/error.py @@ -10,7 +10,7 @@ 5 Nov 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/fileops.py b/src/sphobjinv/fileops.py index feba9da..e30c4b4 100644 --- a/src/sphobjinv/fileops.py +++ b/src/sphobjinv/fileops.py @@ -10,7 +10,7 @@ 5 Nov 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/inventory.py b/src/sphobjinv/inventory.py index 33c685e..d56c712 100644 --- a/src/sphobjinv/inventory.py +++ b/src/sphobjinv/inventory.py @@ -10,7 +10,7 @@ 7 Dec 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/re.py b/src/sphobjinv/re.py index 017a181..e42ab29 100644 --- a/src/sphobjinv/re.py +++ b/src/sphobjinv/re.py @@ -10,7 +10,7 @@ 5 Nov 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/schema.py b/src/sphobjinv/schema.py index b609b04..2cc54d2 100644 --- a/src/sphobjinv/schema.py +++ b/src/sphobjinv/schema.py @@ -11,7 +11,7 @@ 7 Dec 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/src/sphobjinv/version.py b/src/sphobjinv/version.py index ac087af..00369de 100644 --- a/src/sphobjinv/version.py +++ b/src/sphobjinv/version.py @@ -10,7 +10,7 @@ 18 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv @@ -29,4 +29,4 @@ """ -__version__ = "2.4.dev0" +__version__ = "2.4" diff --git a/src/sphobjinv/zlib.py b/src/sphobjinv/zlib.py index 649d54c..34dfe6a 100644 --- a/src/sphobjinv/zlib.py +++ b/src/sphobjinv/zlib.py @@ -10,7 +10,7 @@ 5 Nov 2017 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/conftest.py b/tests/conftest.py index 7402f2f..937fa43 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/enum.py b/tests/enum.py index 685d240..0c1b975 100644 --- a/tests/enum.py +++ b/tests/enum.py @@ -10,7 +10,7 @@ 22 Dec 2025 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/fixtures_http.py b/tests/fixtures_http.py index 27abe55..694d523 100644 --- a/tests/fixtures_http.py +++ b/tests/fixtures_http.py @@ -10,7 +10,7 @@ 24 Dec 2025 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_api_fail.py b/tests/test_api_fail.py index d77088f..786ca49 100644 --- a/tests/test_api_fail.py +++ b/tests/test_api_fail.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_api_good.py b/tests/test_api_good.py index 9e9d57c..7ce5918 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_api_good_nonlocal.py b/tests/test_api_good_nonlocal.py index eec4073..5d267f9 100644 --- a/tests/test_api_good_nonlocal.py +++ b/tests/test_api_good_nonlocal.py @@ -10,7 +10,7 @@ 21 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_cli.py b/tests/test_cli.py index adffa6b..06ade7e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_cli_nonlocal.py b/tests/test_cli_nonlocal.py index f074e86..064733f 100644 --- a/tests/test_cli_nonlocal.py +++ b/tests/test_cli_nonlocal.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_cli_textconv.py b/tests/test_cli_textconv.py index 3ad39cc..f08356f 100644 --- a/tests/test_cli_textconv.py +++ b/tests/test_cli_textconv.py @@ -10,7 +10,7 @@ 22 Dec 2025 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_fixture.py b/tests/test_fixture.py index a48cb98..0760ddf 100644 --- a/tests/test_fixture.py +++ b/tests/test_fixture.py @@ -10,7 +10,7 @@ 20 Mar 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_flake8_ext.py b/tests/test_flake8_ext.py index 8604d12..ddc5933 100644 --- a/tests/test_flake8_ext.py +++ b/tests/test_flake8_ext.py @@ -10,7 +10,7 @@ 27 Apr 2019 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py index 4096c0c..7d72739 100644 --- a/tests/test_intersphinx.py +++ b/tests/test_intersphinx.py @@ -10,7 +10,7 @@ 21 Jun 2022 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv diff --git a/tests/test_valid_objects.py b/tests/test_valid_objects.py index 6367dde..b934394 100644 --- a/tests/test_valid_objects.py +++ b/tests/test_valid_objects.py @@ -10,7 +10,7 @@ 13 Feb 2021 **Copyright** - \(c) Brian Skinn 2016-2025 + \(c) 2016-2026 Brian Skinn and community contributors **Source Repository** https://github.com/bskinn/sphobjinv From f9582a94cc0b48f4297d15efb699b307cb08e08c Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Thu, 19 Mar 2026 22:26:49 -0400 Subject: [PATCH 15/41] Modernize package license metadata --- pyproject.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2f37d8e..1ed6313 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,11 +8,10 @@ requires = [ [project] name = "sphobjinv" description = "Sphinx objects.inv Inspection/Manipulation Tool" -license = {text = "MIT License"} +license = "MIT" +license-files = ["LICENSE.txt"] authors = [{name = "Brian Skinn", email = "brian.skinn@gmail.com"}] classifiers = [ - "License :: OSI Approved", - "License :: OSI Approved :: MIT License", "Natural Language :: English", "Environment :: Console", "Framework :: Sphinx", @@ -57,7 +56,6 @@ sphobjinv-textconv = "sphobjinv.cli.core:main_textconv" [tool.setuptools] package-dir = {"" = "src"} platforms = ["any"] -license-files = ["LICENSE.txt"] include-package-data = false [tool.setuptools.packages.find] From 454328ae31a4642ed1544fc2143dd774fcb4f505 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Thu, 19 Mar 2026 23:04:56 -0400 Subject: [PATCH 16/41] Substitute in 2.4 for ##VER## tags --- doc/source/cli/index.rst | 2 +- doc/source/cli/textconv.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/cli/index.rst b/doc/source/cli/index.rst index 2d26cc0..952f11d 100644 --- a/doc/source/cli/index.rst +++ b/doc/source/cli/index.rst @@ -12,7 +12,7 @@ The primary CLI for |soi| is implemented using two subcommands of the - ``sphobjinv suggest`` (:doc:`docs page `), which provides suggestions for objects in an inventory matching a desired search term. -As of v##VER##, |soi| also provides an auxiliary entrypoint, +As of v2.4, |soi| also provides an auxiliary entrypoint, ``sphobjinv-textconv`` (:doc:`docs page `), which takes one required argument: a path to a file on disk. This entrypoint attempts to instantiate an |Inventory| with this file and emit its plaintext contents to |stdout| with no diff --git a/doc/source/cli/textconv.rst b/doc/source/cli/textconv.rst index fd13a37..2baa429 100644 --- a/doc/source/cli/textconv.rst +++ b/doc/source/cli/textconv.rst @@ -82,4 +82,4 @@ will render correctly in ReadTheDocs builds): Display brief package version information and exit. -.. versionadded:: ##VER## +.. versionadded:: 2.4 From cdf1ee43ccf2e27041069c6d450fa5e355cbee8f Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Thu, 19 Mar 2026 23:10:31 -0400 Subject: [PATCH 17/41] Apply version and date to CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e79336..b46b88b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows an extension of fourth number represents an administrative maintenance release with no code changes. -### *Unreleased* +### [2.4] - 2026-03-19 #### Added From 19bcd72dd7651de22270a8c26a96f84cb94c3006 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 20 Mar 2026 00:01:49 -0400 Subject: [PATCH 18/41] Update CONTRIBUTING.md --- CONTRIBUTING.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c51c3a5..e73bd72 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,6 +122,10 @@ flag: $ pytest --nonloc ``` +Most of these nonlocal tests now use an ephemeral local web server instead of +reaching out to the web, and so should run even without network access and +should just run faster in general. + When putting together a PR, at minimum, please add/augment the test suite as necessary to maintain 100% test coverage. To the extent possible, please go beyond this and add tests that check potential edge cases, bad/malformed/invalid @@ -141,15 +145,15 @@ project, it is **not** set up to be an everyday test runner. Instead, its purpose for testing is to execute an extensive matrix of test environments checking for the compatibility of different Python and dependency versions. You can run it if you want, but you'll need working versions of all of Python 3.10 -through 3.14 installed and on `PATH` as `python3.10`, `python3.11`, etc. The -nonlocal test suite is run for each `tox` environment, so it's best to use at -most two parallel sub-processes to avoid oversaturating your network bandwidth; -e.g.: +through 3.14 installed and on `PATH` as `python3.10`, `python3.11`, etc., as +well as free-threaded versions for Python 3.13 onward as `python3.13t`, etc. The +test matrix can be accelerated by using `tox`'s parallel execution mode; e.g.: ```bash $ tox -rp2 ``` + ## Code Autoformatting The project is set up with a `tox` environment to blacken the codebase; run with: @@ -244,20 +248,17 @@ with `make linkcheck`. ## Continuous Integration -Both Github Actions and Azure Pipelines are set up for the project, and should -run on any forks of the repository. +Github Actions workflows are set up for the project, and should run on any forks +of the repository. Note that the CI runs differently on draft versus non-draft +PRs: on draft PRs, the only workflow that runs runs tests on Windows and Linux +with one Python version; whereas on non-draft PRs, a complete test matrix of +platforms and Python versions is run, as well as doctests and linting checks. Github Actions runs the test suite on Linux for Python 3.10 through 3.14, as well as the `flake8` lints and the Sphinx doctests. By default, the Github Actions will run on all commits, but the workflows can be skipped per-commit by including `[skip ci]` in the commit message. -The Azure Pipelines CI runs an extensive matrix of cross-platform and -cross-Python-version tests, as well as numerous other checks. Due to its length, -it is configured to run only on release branches and PRs to `main` or `stable`. -The Azure Pipelines workflows now [also obey `[skip ci]` -directives](https://learn.microsoft.com/en-us/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#skipping-ci-for-individual-pushes). - ## CHANGELOG From 1f852e81506d49bee9ed1d5cd5771999bc38f56f Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 20 Mar 2026 00:08:24 -0400 Subject: [PATCH 19/41] Bump release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b46b88b..320098e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows an extension of fourth number represents an administrative maintenance release with no code changes. -### [2.4] - 2026-03-19 +### [2.4] - 2026-03-20 #### Added From 13376fc55341498bd105ea95af92400822f09c26 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 20 Mar 2026 00:12:50 -0400 Subject: [PATCH 20/41] Fix line length in parser.py --- src/sphobjinv/cli/parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sphobjinv/cli/parser.py b/src/sphobjinv/cli/parser.py index 224bd59..44e1a1a 100644 --- a/src/sphobjinv/cli/parser.py +++ b/src/sphobjinv/cli/parser.py @@ -44,7 +44,8 @@ class PrsConst: #: Version &c. output blurb VER_TXT = ( - f"\nsphobjinv v{__version__}\n\nCopyright (c) 2016-2026 Brian Skinn and community contributors\n" + f"\nsphobjinv v{__version__}\n\n" + "Copyright (c) 2016-2026 Brian Skinn and community contributors\n" "License: The MIT License\n\n" "Bug reports & feature requests:" " https://github.com/bskinn/sphobjinv\n" From 085356e31ca2979b5b6ea333b75e08fe636b0250 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 20 Mar 2026 00:16:13 -0400 Subject: [PATCH 21/41] Update attrs versions in doctests --- doc/source/api_usage.rst | 16 ++++++++-------- doc/source/cli/convert.rst | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/source/api_usage.rst b/doc/source/api_usage.rst index 8e6e097..bef6fc6 100644 --- a/doc/source/api_usage.rst +++ b/doc/source/api_usage.rst @@ -17,9 +17,9 @@ Inspecting the contents of an existing inventory is handled entirely by the >>> inv = soi.Inventory('objects_attrs.inv') >>> print(inv) - + >>> inv.version - '22.1' + '25.4' >>> inv.count 129 @@ -56,10 +56,10 @@ inventories, as |bytes|: >>> inv2 = soi.Inventory(inv.data_file()) >>> print(inv2) - + >>> inv3 = soi.Inventory(soi.compress(inv.data_file())) >>> print(inv3) - + Remote |objects.inv| files can also be retrieved via URL, with the *url* keyword argument: @@ -67,7 +67,7 @@ Remote |objects.inv| files can also be retrieved via URL, with the *url* keyword >>> inv4 = soi.Inventory(url='https://github.com/bskinn/sphobjinv/raw/main/tests/resource/objects_attrs.inv') >>> print(inv4) - + Comparing Inventories --------------------- @@ -156,7 +156,7 @@ the plaintext |objects.inv| format **as** |bytes| via :meth:`~sphobjinv.inventor >>> print(*inv.data_file().splitlines()[:6], sep='\n') b'# Sphinx inventory version 2' b'# Project: attrs' - b'# Version: 22.1' + b'# Version: 25.4' b'# The remainder of this file is compressed using zlib.' b'attr py:module 0 index.html#module-$ -' b'attr.VersionInfo py:class 1 api.html#$ -' @@ -202,7 +202,7 @@ To export plaintext: >>> print(*Path('objects_attrs.txt').read_text().splitlines()[:6], sep='\n') # Sphinx inventory version 2 # Project: attrs - # Version: 22.1 + # Version: 25.4 # The remainder of this file is compressed using zlib. attr py:module 0 index.html#module-$ - attr.VersionInfo py:class 1 api.html#$ - @@ -216,7 +216,7 @@ For zlib-compressed: >>> print(*Path('objects_attrs_new.inv').read_bytes().splitlines()[:4], sep='\n') b'# Sphinx inventory version 2' b'# Project: attrs' - b'# Version: 22.1' + b'# Version: 25.4' b'# The remainder of this file is compressed using zlib.' >>> print(Path('objects_attrs_new.inv').read_bytes().splitlines()[6][:10]) b'\xbf\x86\x8fL49\xc4\x91\xb8\x8c' diff --git a/doc/source/cli/convert.rst b/doc/source/cli/convert.rst index f387193..2f49e38 100644 --- a/doc/source/cli/convert.rst +++ b/doc/source/cli/convert.rst @@ -32,7 +32,7 @@ Basic file conversion to the default output filename is straightforward: >>> print(file_head('objects_attrs.txt', head=6)) # Sphinx inventory version 2 # Project: attrs - # Version: 22.1 + # Version: 25.4 # The remainder of this file is compressed using zlib. attr py:module 0 index.html#module-$ - attr.VersionInfo py:class 1 api.html#$ - @@ -76,7 +76,7 @@ indicated URL): >>> print(file_head('objects.txt', head=6)) # Sphinx inventory version 2 # Project: attrs - # Version: 22.1 + # Version: 25.4 # The remainder of this file is compressed using zlib. attr py:module 0 index.html#module-$ - attr.VersionInfo py:class 1 api.html#$ - @@ -135,7 +135,7 @@ If processing of JSON files by API URL is desirable, please >>> cli_run('sphobjinv co plain objects_attrs.inv -') # Sphinx inventory version 2 # Project: attrs - # Version: 22.1 + # Version: 25.4 # The remainder of this file is compressed using zlib. attr py:module 0 index.html#module-$ - attr.VersionInfo py:class 1 api.html#$ - From 83acf02d83f975f0d2dee60ff6020b38b0cef4cd Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Fri, 20 Mar 2026 00:20:04 -0400 Subject: [PATCH 22/41] Bump checkout/setup-python actions versions and de-persist creds Closes #322 --- .github/workflows/all_core_tests.yml | 6 ++++-- .github/workflows/ready_doctest.yml | 6 ++++-- .github/workflows/ready_linting.yml | 12 ++++++++---- .github/workflows/ready_test_matrix.yml | 6 ++++-- .github/workflows/ready_test_nonloc.yml | 6 ++++-- .github/workflows/release_check_sdist.yml | 6 ++++-- .github/workflows/release_doc_warnings.yml | 6 ++++-- .github/workflows/release_enusre_no_ver_markers.yml | 2 ++ .github/workflows/release_flake8_noqa_nofail.yml | 6 ++++-- .github/workflows/release_readme_doctest.yml | 6 ++++-- .github/workflows/release_test_file_coverage.yml | 6 ++++-- 11 files changed, 46 insertions(+), 22 deletions(-) diff --git a/.github/workflows/all_core_tests.yml b/.github/workflows/all_core_tests.yml index 9693596..33e0749 100644 --- a/.github/workflows/all_core_tests.yml +++ b/.github/workflows/all_core_tests.yml @@ -19,10 +19,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_doctest.yml b/.github/workflows/ready_doctest.yml index a5fc4dd..cb3b304 100644 --- a/.github/workflows/ready_doctest.yml +++ b/.github/workflows/ready_doctest.yml @@ -22,10 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_linting.yml b/.github/workflows/ready_linting.yml index 0e1cb68..08e9fa9 100644 --- a/.github/workflows/ready_linting.yml +++ b/.github/workflows/ready_linting.yml @@ -22,10 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' @@ -50,10 +52,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_test_matrix.yml b/.github/workflows/ready_test_matrix.yml index be3136b..f013c86 100644 --- a/.github/workflows/ready_test_matrix.yml +++ b/.github/workflows/ready_test_matrix.yml @@ -29,10 +29,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.py }} cache: 'pip' diff --git a/.github/workflows/ready_test_nonloc.yml b/.github/workflows/ready_test_nonloc.yml index 9a7d0d7..8bfd830 100644 --- a/.github/workflows/ready_test_nonloc.yml +++ b/.github/workflows/ready_test_nonloc.yml @@ -25,10 +25,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_check_sdist.yml b/.github/workflows/release_check_sdist.yml index bc2ac33..e8e7598 100644 --- a/.github/workflows/release_check_sdist.yml +++ b/.github/workflows/release_check_sdist.yml @@ -21,10 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_doc_warnings.yml b/.github/workflows/release_doc_warnings.yml index 2cb09b1..82addcd 100644 --- a/.github/workflows/release_doc_warnings.yml +++ b/.github/workflows/release_doc_warnings.yml @@ -21,10 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_enusre_no_ver_markers.yml b/.github/workflows/release_enusre_no_ver_markers.yml index 446bd55..24f6744 100644 --- a/.github/workflows/release_enusre_no_ver_markers.yml +++ b/.github/workflows/release_enusre_no_ver_markers.yml @@ -22,6 +22,8 @@ jobs: steps: - name: Check out repo uses: actions/checkout@v6 + with: + persist-credentials: false - name: Error if any markers found run: | diff --git a/.github/workflows/release_flake8_noqa_nofail.yml b/.github/workflows/release_flake8_noqa_nofail.yml index 249ed3b..0fdcde5 100644 --- a/.github/workflows/release_flake8_noqa_nofail.yml +++ b/.github/workflows/release_flake8_noqa_nofail.yml @@ -21,10 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_readme_doctest.yml b/.github/workflows/release_readme_doctest.yml index 9327fce..056a97a 100644 --- a/.github/workflows/release_readme_doctest.yml +++ b/.github/workflows/release_readme_doctest.yml @@ -21,10 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_test_file_coverage.yml b/.github/workflows/release_test_file_coverage.yml index d3bd545..5dd7beb 100644 --- a/.github/workflows/release_test_file_coverage.yml +++ b/.github/workflows/release_test_file_coverage.yml @@ -21,10 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.13' cache: 'pip' From 12076095aa01c29ddb2cbc2d9d6aeee99b7a5e95 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 21:46:18 -0400 Subject: [PATCH 23/41] Pin actions to SHAs --- .github/workflows/all_core_tests.yml | 4 ++-- .github/workflows/ready_doctest.yml | 4 ++-- .github/workflows/ready_linting.yml | 8 ++++---- .github/workflows/ready_test_matrix.yml | 4 ++-- .github/workflows/ready_test_nonloc.yml | 4 ++-- .github/workflows/release_check_sdist.yml | 4 ++-- .github/workflows/release_doc_warnings.yml | 4 ++-- .github/workflows/release_enusre_no_ver_markers.yml | 2 +- .github/workflows/release_flake8_noqa_nofail.yml | 4 ++-- .github/workflows/release_readme_doctest.yml | 4 ++-- .github/workflows/release_test_file_coverage.yml | 4 ++-- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/all_core_tests.yml b/.github/workflows/all_core_tests.yml index 33e0749..a521cdb 100644 --- a/.github/workflows/all_core_tests.yml +++ b/.github/workflows/all_core_tests.yml @@ -19,12 +19,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_doctest.yml b/.github/workflows/ready_doctest.yml index cb3b304..f2ae5c2 100644 --- a/.github/workflows/ready_doctest.yml +++ b/.github/workflows/ready_doctest.yml @@ -22,12 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_linting.yml b/.github/workflows/ready_linting.yml index 08e9fa9..1896ba7 100644 --- a/.github/workflows/ready_linting.yml +++ b/.github/workflows/ready_linting.yml @@ -22,12 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' @@ -52,12 +52,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_test_matrix.yml b/.github/workflows/ready_test_matrix.yml index f013c86..b8d3410 100644 --- a/.github/workflows/ready_test_matrix.yml +++ b/.github/workflows/ready_test_matrix.yml @@ -29,12 +29,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: ${{ matrix.py }} cache: 'pip' diff --git a/.github/workflows/ready_test_nonloc.yml b/.github/workflows/ready_test_nonloc.yml index 8bfd830..3117354 100644 --- a/.github/workflows/ready_test_nonloc.yml +++ b/.github/workflows/ready_test_nonloc.yml @@ -25,12 +25,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_check_sdist.yml b/.github/workflows/release_check_sdist.yml index e8e7598..2d4fe8d 100644 --- a/.github/workflows/release_check_sdist.yml +++ b/.github/workflows/release_check_sdist.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_doc_warnings.yml b/.github/workflows/release_doc_warnings.yml index 82addcd..fe4105e 100644 --- a/.github/workflows/release_doc_warnings.yml +++ b/.github/workflows/release_doc_warnings.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_enusre_no_ver_markers.yml b/.github/workflows/release_enusre_no_ver_markers.yml index 24f6744..e7efbd7 100644 --- a/.github/workflows/release_enusre_no_ver_markers.yml +++ b/.github/workflows/release_enusre_no_ver_markers.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false diff --git a/.github/workflows/release_flake8_noqa_nofail.yml b/.github/workflows/release_flake8_noqa_nofail.yml index 0fdcde5..731f502 100644 --- a/.github/workflows/release_flake8_noqa_nofail.yml +++ b/.github/workflows/release_flake8_noqa_nofail.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_readme_doctest.yml b/.github/workflows/release_readme_doctest.yml index 056a97a..c195cf1 100644 --- a/.github/workflows/release_readme_doctest.yml +++ b/.github/workflows/release_readme_doctest.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_test_file_coverage.yml b/.github/workflows/release_test_file_coverage.yml index 5dd7beb..727ebdf 100644 --- a/.github/workflows/release_test_file_coverage.yml +++ b/.github/workflows/release_test_file_coverage.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@v6 + uses: actions/checkout@0c366fd6a with: persist-credentials: false - name: Install Python - uses: actions/setup-python@v6 + uses: actions/setup-python@28f2168f4d9 with: python-version: '3.13' cache: 'pip' From 432603e7913082fec649f4ac5f47b1c8b0c7df52 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 21:48:19 -0400 Subject: [PATCH 24/41] Update actions to full SHA refs --- .github/workflows/all_core_tests.yml | 4 ++-- .github/workflows/ready_doctest.yml | 4 ++-- .github/workflows/ready_linting.yml | 8 ++++---- .github/workflows/ready_test_matrix.yml | 4 ++-- .github/workflows/ready_test_nonloc.yml | 4 ++-- .github/workflows/release_check_sdist.yml | 4 ++-- .github/workflows/release_doc_warnings.yml | 4 ++-- .github/workflows/release_enusre_no_ver_markers.yml | 2 +- .github/workflows/release_flake8_noqa_nofail.yml | 4 ++-- .github/workflows/release_readme_doctest.yml | 4 ++-- .github/workflows/release_test_file_coverage.yml | 4 ++-- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/all_core_tests.yml b/.github/workflows/all_core_tests.yml index a521cdb..686676a 100644 --- a/.github/workflows/all_core_tests.yml +++ b/.github/workflows/all_core_tests.yml @@ -19,12 +19,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_doctest.yml b/.github/workflows/ready_doctest.yml index f2ae5c2..73519dd 100644 --- a/.github/workflows/ready_doctest.yml +++ b/.github/workflows/ready_doctest.yml @@ -22,12 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_linting.yml b/.github/workflows/ready_linting.yml index 1896ba7..427d684 100644 --- a/.github/workflows/ready_linting.yml +++ b/.github/workflows/ready_linting.yml @@ -22,12 +22,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' @@ -52,12 +52,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/ready_test_matrix.yml b/.github/workflows/ready_test_matrix.yml index b8d3410..dda2f27 100644 --- a/.github/workflows/ready_test_matrix.yml +++ b/.github/workflows/ready_test_matrix.yml @@ -29,12 +29,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: ${{ matrix.py }} cache: 'pip' diff --git a/.github/workflows/ready_test_nonloc.yml b/.github/workflows/ready_test_nonloc.yml index 3117354..e434d72 100644 --- a/.github/workflows/ready_test_nonloc.yml +++ b/.github/workflows/ready_test_nonloc.yml @@ -25,12 +25,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_check_sdist.yml b/.github/workflows/release_check_sdist.yml index 2d4fe8d..35e2505 100644 --- a/.github/workflows/release_check_sdist.yml +++ b/.github/workflows/release_check_sdist.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_doc_warnings.yml b/.github/workflows/release_doc_warnings.yml index fe4105e..f3e33c0 100644 --- a/.github/workflows/release_doc_warnings.yml +++ b/.github/workflows/release_doc_warnings.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_enusre_no_ver_markers.yml b/.github/workflows/release_enusre_no_ver_markers.yml index e7efbd7..da49997 100644 --- a/.github/workflows/release_enusre_no_ver_markers.yml +++ b/.github/workflows/release_enusre_no_ver_markers.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false diff --git a/.github/workflows/release_flake8_noqa_nofail.yml b/.github/workflows/release_flake8_noqa_nofail.yml index 731f502..16d9993 100644 --- a/.github/workflows/release_flake8_noqa_nofail.yml +++ b/.github/workflows/release_flake8_noqa_nofail.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_readme_doctest.yml b/.github/workflows/release_readme_doctest.yml index c195cf1..4a690a0 100644 --- a/.github/workflows/release_readme_doctest.yml +++ b/.github/workflows/release_readme_doctest.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' diff --git a/.github/workflows/release_test_file_coverage.yml b/.github/workflows/release_test_file_coverage.yml index 727ebdf..52c3dad 100644 --- a/.github/workflows/release_test_file_coverage.yml +++ b/.github/workflows/release_test_file_coverage.yml @@ -21,12 +21,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@0c366fd6a + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 with: persist-credentials: false - name: Install Python - uses: actions/setup-python@28f2168f4d9 + uses: actions/setup-python@28f2168f4d98ee0445e3c6321f6e6616c83dd5ec with: python-version: '3.13' cache: 'pip' From a5db0c1c55e0e9e51fcf90820b285591e9482b75 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 22:26:30 -0400 Subject: [PATCH 25/41] Update doctests to new attrs version --- doc/source/api_usage.rst | 40 +++++++++++++++++++------------------- doc/source/cli/convert.rst | 13 +++++++------ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/doc/source/api_usage.rst b/doc/source/api_usage.rst index bef6fc6..b8f236a 100644 --- a/doc/source/api_usage.rst +++ b/doc/source/api_usage.rst @@ -17,11 +17,11 @@ Inspecting the contents of an existing inventory is handled entirely by the >>> inv = soi.Inventory('objects_attrs.inv') >>> print(inv) - + >>> inv.version '25.4' >>> inv.count - 129 + 180 The location of the inventory file to import can also be provided as a :class:`pathlib.Path`, instead of as a string: @@ -38,16 +38,16 @@ a |list| in the :attr:`~sphobjinv.inventory.Inventory.objects` attribute: .. doctest:: api_inspect >>> len(inv.objects) - 129 + 180 >>> dobj = inv.objects[0] >>> dobj - DataObjStr(name='attr', domain='py', role='module', priority='0', uri='index.html#module-$', dispname='-') + DataObjStr(name='attr', domain='py', role='module', priority='0', uri='api-attr.html#module-$', dispname='-') >>> dobj.name 'attr' >>> dobj.domain 'py' - >>> [d.name for d in inv.objects if 'validator' in d.uri] - ['api_validators', 'examples_validators'] + >>> [d.name for d in inv.objects if 'validator' in d.name][:2] + ['attr.get_run_validators', 'attr.set_run_validators'] :class:`~sphobjinv.inventory.Inventory` objects can also import from plaintext or zlib-compressed inventories, as |bytes|: @@ -56,10 +56,10 @@ inventories, as |bytes|: >>> inv2 = soi.Inventory(inv.data_file()) >>> print(inv2) - + >>> inv3 = soi.Inventory(soi.compress(inv.data_file())) >>> print(inv3) - + Remote |objects.inv| files can also be retrieved via URL, with the *url* keyword argument: @@ -67,7 +67,7 @@ Remote |objects.inv| files can also be retrieved via URL, with the *url* keyword >>> inv4 = soi.Inventory(url='https://github.com/bskinn/sphobjinv/raw/main/tests/resource/objects_attrs.inv') >>> print(inv4) - + Comparing Inventories --------------------- @@ -118,7 +118,7 @@ The :class:`~sphobjinv.data.DataObjStr` instances can be edited in place: >>> inv = soi.Inventory('objects_attrs.inv') >>> inv.objects[0] - DataObjStr(name='attr', domain='py', role='module', priority='0', uri='index.html#module-$', dispname='-') + DataObjStr(name='attr', domain='py', role='module', priority='0', uri='api-attr.html#module-$', dispname='-') >>> inv.objects[0].uri = 'attribute.html' >>> inv.objects[0] DataObjStr(name='attr', domain='py', role='module', priority='0', uri='attribute.html', dispname='-') @@ -130,7 +130,7 @@ New instances can be easily created either by direct instantiation, or by >>> inv.objects.append(inv.objects[0].evolve(name='attr.Generator', uri='generator.html')) >>> inv.count - 130 + 181 >>> inv.objects[-1] DataObjStr(name='attr.Generator', domain='py', role='module', priority='0', uri='generator.html', dispname='-') @@ -141,7 +141,7 @@ The other attributes of the :class:`~sphobjinv.inventory.Inventory` instance can >>> inv.project = 'not_attrs' >>> inv.version = '0.1' >>> print(inv) - + Formatting Inventory Contents @@ -158,8 +158,8 @@ the plaintext |objects.inv| format **as** |bytes| via :meth:`~sphobjinv.inventor b'# Project: attrs' b'# Version: 25.4' b'# The remainder of this file is compressed using zlib.' - b'attr py:module 0 index.html#module-$ -' - b'attr.VersionInfo py:class 1 api.html#$ -' + b'attr py:module 0 api-attr.html#module-$ -' + b'attr.Attribute py:class 1 api-attr.html#$ -' This method makes use of the :meth:`DataObjStr.data_line ` method to format each of the object information lines. @@ -171,11 +171,11 @@ If desired, the :ref:`shorthand ` used for the .. doctest:: api_formatting >>> print(*inv.data_file(expand=True).splitlines()[4:6], sep='\n') - b'attr py:module 0 index.html#module-attr attr' - b'attr.VersionInfo py:class 1 api.html#attr.VersionInfo attr.VersionInfo' + b'attr py:module 0 api-attr.html#module-attr attr' + b'attr.Attribute py:class 1 api-attr.html#attr.Attribute attr.Attribute' >>> do = inv.objects[0] >>> do.data_line(expand=True) - 'attr py:module 0 index.html#module-attr attr' + 'attr py:module 0 api-attr.html#module-attr attr' Exporting an Inventory @@ -204,8 +204,8 @@ To export plaintext: # Project: attrs # Version: 25.4 # The remainder of this file is compressed using zlib. - attr py:module 0 index.html#module-$ - - attr.VersionInfo py:class 1 api.html#$ - + attr py:module 0 api-attr.html#module-$ - + attr.Attribute py:class 1 api-attr.html#$ - For zlib-compressed: @@ -219,7 +219,7 @@ For zlib-compressed: b'# Version: 25.4' b'# The remainder of this file is compressed using zlib.' >>> print(Path('objects_attrs_new.inv').read_bytes().splitlines()[6][:10]) - b'\xbf\x86\x8fL49\xc4\x91\xb8\x8c' + b"$e2'\x92\xbde\xaa\xbdj" For JSON: diff --git a/doc/source/cli/convert.rst b/doc/source/cli/convert.rst index 2f49e38..7220276 100644 --- a/doc/source/cli/convert.rst +++ b/doc/source/cli/convert.rst @@ -34,8 +34,8 @@ Basic file conversion to the default output filename is straightforward: # Project: attrs # Version: 25.4 # The remainder of this file is compressed using zlib. - attr py:module 0 index.html#module-$ - - attr.VersionInfo py:class 1 api.html#$ - + attr py:module 0 api-attr.html#module-$ - + attr.Attribute py:class 1 api-attr.html#$ - A different target filename can be specified, to avoid overwriting an existing file: @@ -76,7 +76,7 @@ indicated URL): >>> print(file_head('objects.txt', head=6)) # Sphinx inventory version 2 # Project: attrs - # Version: 25.4 + # Version: ... # The remainder of this file is compressed using zlib. attr py:module 0 index.html#module-$ - attr.VersionInfo py:class 1 api.html#$ - @@ -137,9 +137,10 @@ If processing of JSON files by API URL is desirable, please # Project: attrs # Version: 25.4 # The remainder of this file is compressed using zlib. - attr py:module 0 index.html#module-$ - - attr.VersionInfo py:class 1 api.html#$ - - attr._make.Attribute py:class -1 api.html#attrs.Attribute - + attr py:module 0 api-attr.html#module-$ - + attr.Attribute py:class 1 api-attr.html#$ - + attr.NOTHING py:data 1 api-attr.html#$ - + attr.VersionInfo py:class 1 api-attr.html#$ - ... From 44ccac6584ba025d3e485f43c3f616630a85c04d Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 22:35:30 -0400 Subject: [PATCH 26/41] Update test-tests with new attrs content --- tests/test_api_good.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_api_good.py b/tests/test_api_good.py index 7ce5918..a6c4102 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -115,19 +115,19 @@ def test_api_decompress(self, path_fxn, scratch_path, misc_info, decomp_cmp_test soi.DataFields.Domain: b"py", soi.DataFields.Role: b"module", soi.DataFields.Priority: b"0", - soi.DataFields.URI: b"index.html#module-$", + soi.DataFields.URI: b"api-attr.html#module-$", soi.DataFields.DispName: b"-", }, ], [ -3, { # slots std:label -1 examples.html#$ Slots - soi.DataFields.Name: b"validators", + soi.DataFields.Name: b"types", soi.DataFields.Domain: b"std", - soi.DataFields.Role: b"label", + soi.DataFields.Role: b"doc", soi.DataFields.Priority: b"-1", - soi.DataFields.URI: b"init.html#$", - soi.DataFields.DispName: b"Validators", + soi.DataFields.URI: b"types.html", + soi.DataFields.DispName: b"Type Annotations", }, ], ), @@ -136,7 +136,7 @@ def test_api_data_regex(self, element, datadict, bytes_txt, misc_info): """Confirm the regex for loading data lines is working properly.""" # Prelim approximate check to be sure we're working with the # correct file/data. - assert len(soi.re.pb_data.findall(bytes_txt)) == 129 + assert len(soi.re.pb_data.findall(bytes_txt)) == 180 mchs = list(soi.re.pb_data.finditer(bytes_txt)) @@ -448,7 +448,7 @@ def test_api_inventory_toosmallflatdict_importbutignore(self, res_dec): inv2 = soi.Inventory(d, count_error=False) # 128 (one less than 129) b/c the loop continues past missing elements - assert inv2.count == 128 + assert inv2.count == 179 def test_api_inventory_namesuggest(self, res_cmp, check): """Confirm object name suggestion is nominally working on a specific object.""" From 24677038a5c50d0beea8836f1a8ed083d5f37e9b Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 23:29:26 -0400 Subject: [PATCH 27/41] Fix Sphinx inv objects check for multiple sphinx inventories Pattern match, not just substring --- tests/test_api_good.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/test_api_good.py b/tests/test_api_good.py index a6c4102..7945b57 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -584,7 +584,25 @@ def test_api_inventory_matches_sphinx_ifile( original_ifile_data ), fname - elif "sphinx.inv" in fname: # pragma: no cover + elif re.search(r"sphinx.*[.]inv", fname): # pragma: no cover + soi_names = [o.name for o in inv.objects] + ifile_names = list( + itt.chain.from_iterable( + list(original_ifile_data[k].keys()) for k in original_ifile_data + ) + ) + # There is the same set of unique names in the sphobjinv Inventory + # as in the Sphinx IFile imported data ... + assert set(soi_names) == set(ifile_names), fname + + # ... but there are duplicate names in each ... + assert inv.count > len(set(soi_names)), fname + assert sphinx_ifile_data_count(original_ifile_data) > len( + set(ifile_names) + ), fname + + # ... and there are always four more items in the sphobjinv Inventory + # than in the IFile data. assert inv.count == 4 + sphinx_ifile_data_count(original_ifile_data), fname else: From 440c68588143fa990ffec5a17301cc0e5fd47f3e Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 23:39:14 -0400 Subject: [PATCH 28/41] Refine sphinx inv filter The old one doesn't have the mismatch --- tests/test_api_good.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api_good.py b/tests/test_api_good.py index 7945b57..3d4d52c 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -584,7 +584,7 @@ def test_api_inventory_matches_sphinx_ifile( original_ifile_data ), fname - elif re.search(r"sphinx.*[.]inv", fname): # pragma: no cover + elif re.search(r"sphinx(|_6_0b)[.]inv", fname): # pragma: no cover soi_names = [o.name for o in inv.objects] ifile_names = list( itt.chain.from_iterable( From d2402afe6a15a94df9b411ec10529587baca61cf Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sat, 21 Mar 2026 23:59:17 -0400 Subject: [PATCH 29/41] Add missing newline in test_api_good.py --- tests/test_api_good.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_api_good.py b/tests/test_api_good.py index 3d4d52c..d746bff 100644 --- a/tests/test_api_good.py +++ b/tests/test_api_good.py @@ -591,6 +591,7 @@ def test_api_inventory_matches_sphinx_ifile( list(original_ifile_data[k].keys()) for k in original_ifile_data ) ) + # There is the same set of unique names in the sphobjinv Inventory # as in the Sphinx IFile imported data ... assert set(soi_names) == set(ifile_names), fname From 4bf131fdb4b4408cc76f8e7627dc35d3ae616663 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 22 Mar 2026 01:15:10 -0400 Subject: [PATCH 30/41] Remove flake8 extensions test Now that we're running flake8 with tox, the virtualenv can be de-synced with the linting environment, resulting in spurious test failure. Test was really always overkill anyways. --- .../workflows/release_test_file_coverage.yml | 4 +- tests/conftest.py | 3 - tests/test_flake8_ext.py | 73 ------------------- tox.ini | 1 - 4 files changed, 2 insertions(+), 79 deletions(-) delete mode 100644 tests/test_flake8_ext.py diff --git a/.github/workflows/release_test_file_coverage.yml b/.github/workflows/release_test_file_coverage.yml index 52c3dad..f2c4025 100644 --- a/.github/workflows/release_test_file_coverage.yml +++ b/.github/workflows/release_test_file_coverage.yml @@ -35,7 +35,7 @@ jobs: requirements-flake8.txt - name: Install CI requirements - run: pip install -r requirements-ci.txt -r requirements-flake8.txt + run: pip install -r requirements-ci.txt - name: Build docs & ensure scratch run: | @@ -44,7 +44,7 @@ jobs: mkdir scratch - name: Run pytest covering entire project tree - run: pytest --cov=. --nonloc --flake8_ext + run: pytest --cov=. --nonloc - name: Check 100% test code execution run: coverage report --include="tests/*" --fail-under=100 diff --git a/tests/conftest.py b/tests/conftest.py index 937fa43..f982e26 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -61,9 +61,6 @@ def pytest_addoption(parser): ), ) parser.addoption("--nonloc", action="store_true", help="Include nonlocal tests") - parser.addoption( - "--flake8_ext", action="store_true", help="Include flake8 extensions test" - ) @pytest.fixture(scope="session") diff --git a/tests/test_flake8_ext.py b/tests/test_flake8_ext.py deleted file mode 100644 index ddc5933..0000000 --- a/tests/test_flake8_ext.py +++ /dev/null @@ -1,73 +0,0 @@ -r"""*Test(s) to ensure full loading of flake8 extensions*. - -``sphobjinv`` is a toolkit for manipulation and inspection of -Sphinx |objects.inv| files. - -**Author** - Brian Skinn (brian.skinn@gmail.com) - -**File Created** - 27 Apr 2019 - -**Copyright** - \(c) 2016-2026 Brian Skinn and community contributors - -**Source Repository** - https://github.com/bskinn/sphobjinv - -**Documentation** - https://sphobjinv.readthedocs.io/en/stable - -**License** - Code: `MIT License`_ - - Docs & Docstrings: |CC BY 4.0|_ - - See |license_txt|_ for full license terms. - -**Members** - -""" - -import re -import subprocess as sp # noqa: S404 -import sys -from pathlib import Path - -import pytest - -pytestmark = [pytest.mark.flake8_ext] - - -@pytest.fixture(scope="module", autouse=True) -def skip_if_no_flake8_ext(pytestconfig): - """Skip test if --flake8_ext not provided. - - Auto-applied to all functions in module. - - """ - if not pytestconfig.getoption("--flake8_ext"): - pytest.skip("'--flake8_ext' not specified") # pragma: no cover - - -@pytest.mark.skipif( - sys.version_info < (3, 6), - reason="Some flake8 extensions require Python 3.6 or later", -) -def test_flake8_version_output(check): - """Confirm that all desired plugins actually report as loaded.""" - p_pkgname = re.compile("^[0-9a-z_-]+", re.I) - plugins = Path("requirements-flake8.txt").read_text().splitlines()[1:] - plugins = [p_pkgname.search(p).group(0) for p in plugins] - - # This is fragile if anything ends up not having a prefix that needs - # stripping - plugins = [p.partition("flake8-")[-1] for p in plugins] - - flake8_ver_output = sp.check_output( # noqa: S607,S603 - ["flake8", "--version"], universal_newlines=True - ) # noqa: S607,S603 - - for p in plugins: - with check(msg=p): - assert p in flake8_ver_output.replace("_", "-").replace("\n", "") diff --git a/tox.ini b/tox.ini index 8ada057..fe6d9d6 100644 --- a/tox.ini +++ b/tox.ini @@ -162,7 +162,6 @@ markers = intersphinx: Tests on intersphinx-related functionality fixture: Trivial tests for test suite fixtures testall: Tests that use *all* objects_xyz.inv files in tests/resource, if --testall is specified - flake8_ext: Test checking that all desired plugins are active first: Inherited marker from `pytest-ordering` timeout: Inherited marker from `pytest-timeout` From 3c40df2aad401fab7d9ad2d6ef5114beba9f1f78 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 22 Mar 2026 01:15:55 -0400 Subject: [PATCH 31/41] Add some pragma: no cover Some for windows; some for paths that are only reached when tests fail. --- tests/conftest.py | 8 ++++---- tests/fixtures_http.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f982e26..26dae3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -155,7 +155,7 @@ def scratch_path(tmp_path, res_path, misc_info, is_win, unix2dos): # With the conversion of resources/objects_attrs.txt to Unix EOLs in order to # provide for a Unix-testable sdist, on Windows systems this resource needs # to be converted to DOS EOLs for consistency. - if is_win: + if is_win: # pragma: no cover win_path = tmp_path / f"{scr_base}{misc_info.Extensions.DEC.value}" win_path.write_bytes(unix2dos(win_path.read_bytes())) @@ -217,7 +217,7 @@ def func(path): """Perform the 'live' inventory load test.""" try: sphinx_ifile_load(path) - except Exception as e: # noqa: PIE786 + except Exception as e: # noqa: PIE786 pragma: no cover # An exception here is a failing test, not a test error. pytest.fail(e) @@ -262,7 +262,7 @@ def func(arglist, *, command=CLICommand.Core, expect=0): # , suffix=None): except SystemExit as e: retcode = e.args[0] ok = True - else: + else: # pragma: no cover ok = False # Do all pytesty stuff outside monkeypatch context @@ -284,7 +284,7 @@ def func(path): res_bytes = Path(misc_info.res_decomp_path).read_bytes() tgt_bytes = Path(path).read_bytes() # .replace(b"\r\n", b"\n") - if is_win: + if is_win: # pragma: no cover # Have to explicitly convert these newlines, now that the # tests/resource/objects_attrs.txt file is marked 'binary' in # .gitattributes diff --git a/tests/fixtures_http.py b/tests/fixtures_http.py index 694d523..7627db4 100644 --- a/tests/fixtures_http.py +++ b/tests/fixtures_http.py @@ -94,7 +94,7 @@ def resource_http_base_url() -> Generator[str, None, None]: """Provide base URL of HTTP server exposing tests/resource/*.""" # noqa: RST213 resource_dir = Path(__file__).resolve().parent / "resource" - if not resource_dir.is_dir(): + if not resource_dir.is_dir(): # pragma: no cover raise RuntimeError( f"Expected test resource directory not found: {resource_dir}" ) @@ -119,7 +119,7 @@ def resource_url(resource_http_base_url: str) -> Callable[[str], str]: def _calc_path(rel_path: str) -> str: """Calculate the full test-resource URL from a relative URL.""" # Prevent escaping the resource directory. - if ".." in Path(rel_path).parts: + if ".." in Path(rel_path).parts: # pragma: no cover raise ValueError("Path must not contain '..'") # Ensure consistent URL path separators. From b49356bbe8cf787a1fd64cb24ec99b4e6022a380 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 22 Mar 2026 01:16:02 -0400 Subject: [PATCH 32/41] Don't cover setup.py --- .coveragerc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.coveragerc b/.coveragerc index d3b3b11..9cac3c1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -5,6 +5,8 @@ source = omit = # Don't worry about covering vendored libraries src/sphobjinv/_vendored/* + # Not part of the test suite + setup.py [report] exclude_lines = From 40ed2d7eeb772fa1eaf9ee4f496b4abdd47301c5 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 22 Mar 2026 01:16:24 -0400 Subject: [PATCH 33/41] Remove obsolete fixture for doc scratch No longer needed now that we've pulled out the README shell doctests --- tests/conftest.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 26dae3b..ffd9fdf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -162,14 +162,6 @@ def scratch_path(tmp_path, res_path, misc_info, is_win, unix2dos): yield tmp_path -@pytest.fixture(scope="session") -def ensure_doc_scratch(): - """Ensure doc/scratch dir exists, for README shell examples.""" - (Path(__file__).resolve().parent.parent / "doc" / "scratch").mkdir( - parents=True, exist_ok=True - ) - - @pytest.fixture(scope="session") def bytes_txt(misc_info, res_path): """Load and return the contents of the example objects_attrs.txt as bytes.""" From d3bcb832bcc8087186cc6bced8e266f6fd72baf5 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Sun, 22 Mar 2026 01:19:50 -0400 Subject: [PATCH 34/41] Update CHANGELOG --- CHANGELOG.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 320098e..693a5e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows an extension of fourth number represents an administrative maintenance release with no code changes. -### [2.4] - 2026-03-20 +### [2.4] - 2026-03-22 #### Added @@ -21,6 +21,18 @@ changes. #### Tests + * Remove flake8_ext test file and machinery ([#336]). + * pytest environment now can easily de-sync from the flake8 environment + since flake8 is running in tox now. + * It was really always over-cautious, too. + + * Exclude `setup.py` from coverage ([#336]). + * Necessary due to a change in coverage.py behavior, maybe? + * Definitely is not expected to run during execution of the test suite. + + * Remove unused `ensure_doc_scratch` fixture from `conftest.py` ([#336]). + * Obsolete now that the README shell examples aren't doctested. + * Add 3.13t and 3.14t to `tox` test matrix ([#333]). * Also add report of the current GIL status to the `tox` env output. @@ -55,6 +67,9 @@ changes. #### Internal + * Pin Actions versions to SHAs and de-persist credentials ([#)336]. + * Closes [#322]. + * Add Actions workflow to error on a non-draft release branch if any `#VER#` markers remain in docs source ([#331]). @@ -81,6 +96,9 @@ changes. #### Documentation + * Update Sphinx, attrs, Python, etc. content to freshen and to match the new + inventories in the test resources ([#336]). + * Dynamically retrieve the current values of `PrsConst.SUGGEST_CONFIRM_LENGTH` and `PrsConst.DEF_THRESH` to define their replaces in `conf.py` ([#331]). @@ -785,7 +803,9 @@ changes. [#315]: https://github.com/bskinn/sphobjinv/pull/315 [#316]: https://github.com/bskinn/sphobjinv/pull/316 [#320]: https://github.com/bskinn/sphobjinv/pull/320 +[#322]: https://github.com/bskinn/sphobjinv/issues/322 [#325]: https://github.com/bskinn/sphobjinv/pull/325 [#327]: https://github.com/bskinn/sphobjinv/pull/327 [#331]: https://github.com/bskinn/sphobjinv/pull/331 [#333]: https://github.com/bskinn/sphobjinv/pull/333 +[#336]: https://github.com/bskinn/sphobjinv/pull/336 From ae31b9d6e3ae75dd2738f3030301024499454c56 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:25:11 -0400 Subject: [PATCH 35/41] Add 'build' tox env --- tox.ini | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tox.ini b/tox.ini index fe6d9d6..47857a0 100644 --- a/tox.ini +++ b/tox.ini @@ -152,6 +152,16 @@ commands= python -Werror -c "import sphobjinv" deps= +[testenv:build] +skip_install=True +description=Build sdist and wheel +deps= + build + twine +commands= + python -m build + twine check dist/* + [pytest] markers = local: Tests not requiring Internet access From 77ae00bf170a28573776d12f77d4ede695d323fe Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:29:09 -0400 Subject: [PATCH 36/41] Remove superfluous packages from req'ts files They'll be pulled in by the -e . --- requirements-ci.txt | 3 --- requirements-dev.txt | 4 ---- 2 files changed, 7 deletions(-) diff --git a/requirements-ci.txt b/requirements-ci.txt index 3342964..68da258 100644 --- a/requirements-ci.txt +++ b/requirements-ci.txt @@ -1,8 +1,5 @@ -attrs>=19.2 -certifi coverage dictdiffer -jsonschema md-toc pytest>=4.4.0 pytest-check>=1.1.2 diff --git a/requirements-dev.txt b/requirements-dev.txt index 5070a9a..df2e9b9 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,9 +1,5 @@ -attrs>=19.2 -build -certifi coverage dictdiffer -jsonschema md-toc pytest>=4.4.0 pytest-check>=1.1.2 From 823f452a9cf834af7088231f97fa262fc9e826d9 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:37:48 -0400 Subject: [PATCH 37/41] Add tests/resource/objects_pdfminer* to MANIFEST.in Otherwise the sdist-install-and-test job warns during the docs build, since it won't have that inventory available. < 1kB, so should negligibly affect sdist size. --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 0acd465..51cd741 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,7 +8,7 @@ include doc/make.bat doc/Makefile graft tests prune tests/resource -include tests/resource/objects_attrs* tests/resource/objects_sarge* +include tests/resource/objects_attrs* tests/resource/objects_sarge* tests/resource/objects_pdfminer* global-exclude __pycache__/* prune **/*.egg-info From c841682551ad22b3450a9d8d250a0cf63ae04e36 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:46:24 -0400 Subject: [PATCH 38/41] Fix to correct reST italics in textconv.rst --- doc/source/cli/textconv.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/cli/textconv.rst b/doc/source/cli/textconv.rst index 2baa429..b01c7b9 100644 --- a/doc/source/cli/textconv.rst +++ b/doc/source/cli/textconv.rst @@ -38,7 +38,7 @@ Ultimately, a textconv requires three things: *.inv diff=objects_inv With |sphobjinv-textconv| configured in this fashion as a textconv for Sphinx -inventory files, the following should all yield _nearly_ the same output. +inventory files, the following should all yield *nearly* the same output. Using ``sphobjinv convert``: From d42583c2335fde0771c4754cc25cc79b3b990ca6 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:47:06 -0400 Subject: [PATCH 39/41] Update CHANGELOG & fix typo --- CHANGELOG.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 693a5e6..e46e835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,7 +67,19 @@ changes. #### Internal - * Pin Actions versions to SHAs and de-persist credentials ([#)336]. + * Convert `build` call into a `tox` env and remove `build` from + `requirements-dev.txt` ([#336]). + + * Remove redundant packages from `requirements-dev.txt` and + `requirements-ci.txt` that are pulled in by the `-e .` line ([#336]). + + * Add `tests/resource/objects_pdfminer*` to `MANIFEST.in`, to make that + inventory available to the docs build in the sdist unpack-and-test workflow + job ([#336]). + * Otherwise the docs job emits a warning. Not fatal, but better to have a + clean build. + + * Pin Actions versions to SHAs and de-persist credentials ([#336]). * Closes [#322]. * Add Actions workflow to error on a non-draft release branch if any `#VER#` From f4a2a2815d6225ac34817b96668305ee739ba9f8 Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 00:51:13 -0400 Subject: [PATCH 40/41] Bump v2.4 date in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e46e835..a90a49a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project follows an extension of fourth number represents an administrative maintenance release with no code changes. -### [2.4] - 2026-03-22 +### [2.4] - 2026-03-23 #### Added From 74337b1dfb55f4ff1fe7d596ac59e94914a9fe3b Mon Sep 17 00:00:00 2001 From: Brian Skinn Date: Mon, 23 Mar 2026 01:07:17 -0400 Subject: [PATCH 41/41] Bump to next dev version --- src/sphobjinv/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sphobjinv/version.py b/src/sphobjinv/version.py index 00369de..b961ad1 100644 --- a/src/sphobjinv/version.py +++ b/src/sphobjinv/version.py @@ -29,4 +29,4 @@ """ -__version__ = "2.4" +__version__ = "2.4.1.dev0"