pyUSPTO 0.5.2__tar.gz → 0.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. pyuspto-0.5.4/.devcontainer/devcontainer-lock.json +14 -0
  2. pyuspto-0.5.4/.devcontainer/devcontainer.json +33 -0
  3. {pyuspto-0.5.2 → pyuspto-0.5.4}/.gitignore +2 -0
  4. {pyuspto-0.5.2 → pyuspto-0.5.4}/CHANGELOG.md +10 -0
  5. {pyuspto-0.5.2 → pyuspto-0.5.4}/PKG-INFO +2 -2
  6. {pyuspto-0.5.2 → pyuspto-0.5.4}/README.md +1 -1
  7. {pyuspto-0.5.2 → pyuspto-0.5.4}/requirements-dev.txt +16 -16
  8. {pyuspto-0.5.2 → pyuspto-0.5.4}/requirements.txt +5 -5
  9. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/patent_data.py +32 -13
  10. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/config.py +79 -50
  11. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/patent_data.py +5 -1
  12. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/PKG-INFO +2 -2
  13. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/SOURCES.txt +2 -0
  14. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_base.py +9 -27
  15. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_oa_citations_clients.py +5 -14
  16. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_oa_rejections_clients.py +4 -4
  17. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_patent_data_clients.py +69 -8
  18. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_petition_decision_clients.py +1 -3
  19. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_oa_actions_integration.py +4 -12
  20. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_oa_citations_integration.py +4 -12
  21. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_oa_rejections_integration.py +3 -9
  22. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_patent_data_integration.py +6 -6
  23. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_petition_decisions_integration.py +9 -9
  24. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_ptab_appeals_integration.py +6 -6
  25. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_ptab_interferences_integration.py +13 -13
  26. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_ptab_trials_integration.py +12 -12
  27. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_bulk_data_models.py +12 -4
  28. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_enriched_citation_models.py +3 -9
  29. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_oa_actions_models.py +15 -3
  30. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_oa_citations_models.py +8 -20
  31. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_oa_rejections_models.py +2 -6
  32. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_edge_cases.py +1 -1
  33. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_init.py +3 -3
  34. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  35. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  36. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
  37. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  38. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  39. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/dependabot.yml +0 -0
  40. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/workflows/codeql.yml +0 -0
  41. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/workflows/publish-docs.yaml +0 -0
  42. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/workflows/publish-to-test-pypi.yml +0 -0
  43. {pyuspto-0.5.2 → pyuspto-0.5.4}/.github/workflows/python-tests.yml +0 -0
  44. {pyuspto-0.5.2 → pyuspto-0.5.4}/.readthedocs.yaml +0 -0
  45. {pyuspto-0.5.2 → pyuspto-0.5.4}/ADVANCED.md +0 -0
  46. {pyuspto-0.5.2 → pyuspto-0.5.4}/CODE_OF_CONDUCT.md +0 -0
  47. {pyuspto-0.5.2 → pyuspto-0.5.4}/CONTRIBUTING.md +0 -0
  48. {pyuspto-0.5.2 → pyuspto-0.5.4}/LICENSE +0 -0
  49. {pyuspto-0.5.2 → pyuspto-0.5.4}/_version.pyi +0 -0
  50. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/Makefile +0 -0
  51. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/_static/.gitkeep +0 -0
  52. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/about.rst +0 -0
  53. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/advanced.rst +0 -0
  54. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/bulk_data.rst +0 -0
  55. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/enriched_citations.rst +0 -0
  56. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/index.rst +0 -0
  57. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/oa_actions.rst +0 -0
  58. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/oa_citations.rst +0 -0
  59. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/oa_rejections.rst +0 -0
  60. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/patent_data.rst +0 -0
  61. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/petition_decisions.rst +0 -0
  62. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/ptab_appeals.rst +0 -0
  63. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/ptab_interferences.rst +0 -0
  64. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/clients/ptab_trials.rst +0 -0
  65. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/config/config.rst +0 -0
  66. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/config/http_config.rst +0 -0
  67. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/config/index.rst +0 -0
  68. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/exceptions.rst +0 -0
  69. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/index.rst +0 -0
  70. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/base.rst +0 -0
  71. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/bulk_data.rst +0 -0
  72. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/enriched_citations.rst +0 -0
  73. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/index.rst +0 -0
  74. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/oa_actions.rst +0 -0
  75. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/oa_citations.rst +0 -0
  76. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/oa_rejections.rst +0 -0
  77. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/patent_data.rst +0 -0
  78. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/petition_decisions.rst +0 -0
  79. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/ptab.rst +0 -0
  80. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/models/utils.rst +0 -0
  81. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/api/warnings.rst +0 -0
  82. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/conf.py +0 -0
  83. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/configuration.rst +0 -0
  84. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/development.rst +0 -0
  85. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/bulk_data.rst +0 -0
  86. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/enriched_citations.rst +0 -0
  87. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/ifw_example.rst +0 -0
  88. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/index.rst +0 -0
  89. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/oa_actions.rst +0 -0
  90. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/oa_citations.rst +0 -0
  91. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/oa_rejections.rst +0 -0
  92. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/patent_data.rst +0 -0
  93. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/petition_decisions.rst +0 -0
  94. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/ptab_appeals.rst +0 -0
  95. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/ptab_interferences.rst +0 -0
  96. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/examples/ptab_trials.rst +0 -0
  97. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/index.rst +0 -0
  98. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/installation.rst +0 -0
  99. {pyuspto-0.5.2 → pyuspto-0.5.4}/docs/source/quickstart.rst +0 -0
  100. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/bulk_data_example.py +0 -0
  101. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/enriched_citations_example.py +0 -0
  102. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/error_handling_example.py +0 -0
  103. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/ifw_example.py +0 -0
  104. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/oa_actions_example.py +0 -0
  105. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/oa_citations_example.py +0 -0
  106. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/oa_rejections_example.py +0 -0
  107. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/patent_data_example.py +0 -0
  108. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/petition_decisions_example.py +0 -0
  109. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/ptab_appeals_example.py +0 -0
  110. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/ptab_interferences_example.py +0 -0
  111. {pyuspto-0.5.2 → pyuspto-0.5.4}/examples/ptab_trials_example.py +0 -0
  112. {pyuspto-0.5.2 → pyuspto-0.5.4}/pyUSPTO.code-workspace +0 -0
  113. {pyuspto-0.5.2 → pyuspto-0.5.4}/pyproject.toml +0 -0
  114. {pyuspto-0.5.2 → pyuspto-0.5.4}/setup.cfg +0 -0
  115. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/__init__.py +0 -0
  116. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/__init__.py +0 -0
  117. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/base.py +0 -0
  118. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/bulk_data.py +0 -0
  119. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/enriched_citations.py +0 -0
  120. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/oa_actions.py +0 -0
  121. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/oa_citations.py +0 -0
  122. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/oa_rejections.py +0 -0
  123. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/petition_decisions.py +0 -0
  124. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/ptab_appeals.py +0 -0
  125. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/ptab_interferences.py +0 -0
  126. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/clients/ptab_trials.py +0 -0
  127. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/exceptions.py +0 -0
  128. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/http_config.py +0 -0
  129. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/__init__.py +0 -0
  130. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/base.py +0 -0
  131. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/bulk_data.py +0 -0
  132. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/enriched_citations.py +0 -0
  133. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/oa_actions.py +0 -0
  134. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/oa_citations.py +0 -0
  135. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/oa_rejections.py +0 -0
  136. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/petition_decisions.py +0 -0
  137. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/ptab.py +0 -0
  138. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/models/utils.py +0 -0
  139. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/py.typed +0 -0
  140. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/utils/__init__.py +0 -0
  141. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO/warnings.py +0 -0
  142. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
  143. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/requires.txt +0 -0
  144. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/top_level.txt +0 -0
  145. {pyuspto-0.5.2 → pyuspto-0.5.4}/src/pyUSPTO.egg-info/zip-safe +0 -0
  146. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/__init__.py +0 -0
  147. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/__init__.py +0 -0
  148. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_bulk_data_clients.py +0 -0
  149. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_enriched_citation_clients.py +0 -0
  150. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_oa_actions_clients.py +0 -0
  151. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_ptab_appeals_client.py +0 -0
  152. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_ptab_interferences_client.py +0 -0
  153. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/clients/test_ptab_trials_client.py +0 -0
  154. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/conftest.py +0 -0
  155. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/__init__.py +0 -0
  156. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/conftest.py +0 -0
  157. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_bulk_data_integration.py +0 -0
  158. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/integration/test_enriched_citations_integration.py +0 -0
  159. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/__init__.py +0 -0
  160. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_patent_data_models.py +0 -0
  161. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_petition_decision_models.py +0 -0
  162. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_ptab_models.py +0 -0
  163. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/models/test_utils.py +0 -0
  164. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_config.py +0 -0
  165. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_exceptions.py +0 -0
  166. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_http_config.py +0 -0
  167. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/test_version.py +0 -0
  168. {pyuspto-0.5.2 → pyuspto-0.5.4}/tests/utils/__init__.py +0 -0
  169. {pyuspto-0.5.2 → pyuspto-0.5.4}/tox.ini +0 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "features": {
3
+ "ghcr.io/devcontainers/features/git:1": {
4
+ "version": "1.3.5",
5
+ "resolved": "ghcr.io/devcontainers/features/git@sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251",
6
+ "integrity": "sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251"
7
+ },
8
+ "ghcr.io/devcontainers/features/node:1": {
9
+ "version": "1.7.1",
10
+ "resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6",
11
+ "integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "pyUSPTO",
3
+ "build": { "dockerfile": "Dockerfile" },
4
+ "features": {
5
+ "ghcr.io/devcontainers/features/git:1": {},
6
+ "ghcr.io/devcontainers/features/node:2": {},
7
+ "ghcr.io/devcontainers/features/powershell:2.0.2": {
8
+ "version": "latest"
9
+ }
10
+ },
11
+ "mounts": [
12
+ "source=pyuspto-claude-home,target=/home/vscode/.claude,type=volume"
13
+ ],
14
+ "postCreateCommand": "sudo chown vscode /home/vscode/.claude && touch /home/vscode/.claude/claude.json && ln -sf /home/vscode/.claude/claude.json /home/vscode/.claude.json && pip install -e \".[dev]\"",
15
+ "customizations": {
16
+ "vscode": {
17
+ "extensions": [
18
+ "ms-python.python",
19
+ "ms-python.mypy-type-checker",
20
+ "charliermarsh.ruff"
21
+ ],
22
+ "settings": {
23
+ "python.defaultInterpreterPath": "/usr/local/bin/python",
24
+ "python.testing.pytestEnabled": true,
25
+ "python.testing.pytestArgs": ["tests", "--ignore=tests/integration"]
26
+ }
27
+ }
28
+ },
29
+ "remoteEnv": {
30
+ "USPTO_API_KEY": "${localEnv:USPTO_API_KEY}",
31
+ "ENABLE_INTEGRATION_TESTS": "${localEnv:ENABLE_INTEGRATION_TESTS}"
32
+ }
33
+ }
@@ -22,3 +22,5 @@ run_integration_tests.py
22
22
  .plan.md
23
23
  CLAUDE.md
24
24
  docs/build/
25
+ .devcontainer/Dockerfile
26
+ .claude/skills/
@@ -5,6 +5,16 @@ All notable changes to the pyUSPTO package will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ### Changed
11
+
12
+ - **Breaking**: `sanitize_application_number` now emits the standardized 15-character PCT format (`PCT` + 2-char country + 4-digit year + 6-digit zero-padded serial, e.g. `PCTUS2024012345`) per USPTO ODP Release 3.6 (2026-04-10). Previously emitted a non-standard 12-character form (e.g. `PCTUS2412345`). Affects every endpoint that takes a PCT application number, including `get_pct`, `get_application_by_number`, and `get_IFW_metadata(PCT_app_number=...)`. 2-digit year inputs are expanded via a sliding window (YY≥78 → 19YY, else 20YY). Legacy 12-character PCT strings are no longer accepted as input.
13
+
14
+ ### Deprecated
15
+
16
+ - `Address.country_or_state_code` — USPTO ODP Release 3.6 removed `countryOrStateCode` from the Patent Assignment API response; the location data now lives in `geographicRegionCode` (already exposed as `Address.geographic_region_code`). The attribute remains for backward compatibility and will be `None` for responses from updated endpoints.
17
+
8
18
  ## [0.4.5] - 2026-03-11
9
19
 
10
20
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyUSPTO
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: A Modern Python client for accessing the United States Patent and Trademark Office (USPTO) Open Data Portal (ODP) APIs.
5
5
  Author-email: Andrew Piechocki <apiechocki@dunlapcodding.com>
6
6
  License-Expression: MIT
@@ -201,7 +201,7 @@ if app.application_meta_data:
201
201
  wrapper = client.get_IFW_metadata(application_number="18/045,436")
202
202
  wrapper = client.get_IFW_metadata(patent_number="11,234,567")
203
203
  wrapper = client.get_IFW_metadata(publication_number="2023/0012345")
204
- wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US24/12345")
204
+ wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US2024/012345")
205
205
 
206
206
  # Look up USPTO status codes
207
207
  status_codes = client.get_status_codes()
@@ -134,7 +134,7 @@ if app.application_meta_data:
134
134
  wrapper = client.get_IFW_metadata(application_number="18/045,436")
135
135
  wrapper = client.get_IFW_metadata(patent_number="11,234,567")
136
136
  wrapper = client.get_IFW_metadata(publication_number="2023/0012345")
137
- wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US24/12345")
137
+ wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US2024/012345")
138
138
 
139
139
  # Look up USPTO status codes
140
140
  status_codes = client.get_status_codes()
@@ -8,7 +8,7 @@ alabaster==1.0.0
8
8
  # via sphinx
9
9
  babel==2.18.0
10
10
  # via sphinx
11
- certifi==2026.2.25
11
+ certifi==2026.5.20
12
12
  # via requests
13
13
  charset-normalizer==3.4.7
14
14
  # via requests
@@ -16,14 +16,14 @@ colorama==0.4.6
16
16
  # via
17
17
  # pytest
18
18
  # sphinx
19
- coverage==7.13.5
19
+ coverage==7.14.1
20
20
  # via pytest-cov
21
21
  docutils==0.22.4
22
22
  # via
23
23
  # myst-parser
24
24
  # sphinx
25
25
  # sphinx-rtd-theme
26
- idna==3.11
26
+ idna==3.16
27
27
  # via requests
28
28
  imagesize==2.0.0
29
29
  # via sphinx
@@ -33,29 +33,29 @@ jinja2==3.1.6
33
33
  # via
34
34
  # myst-parser
35
35
  # sphinx
36
- librt==0.9.0
36
+ librt==0.11.0
37
37
  # via mypy
38
- markdown-it-py==4.0.0
38
+ markdown-it-py==4.2.0
39
39
  # via
40
40
  # mdit-py-plugins
41
41
  # myst-parser
42
42
  markupsafe==3.0.3
43
43
  # via jinja2
44
- mdit-py-plugins==0.5.0
44
+ mdit-py-plugins==0.6.1
45
45
  # via myst-parser
46
46
  mdurl==0.1.2
47
47
  # via markdown-it-py
48
- mypy==1.20.1
48
+ mypy==2.1.0
49
49
  # via pyuspto
50
50
  mypy-extensions==1.1.0
51
51
  # via mypy
52
- myst-parser==5.0.0
52
+ myst-parser==5.1.0
53
53
  # via pyuspto
54
- packaging==26.1
54
+ packaging==26.2
55
55
  # via
56
56
  # pytest
57
57
  # sphinx
58
- pathspec==1.0.4
58
+ pathspec==1.1.1
59
59
  # via mypy
60
60
  pluggy==1.6.0
61
61
  # via
@@ -76,16 +76,16 @@ pytest-mock==3.15.1
76
76
  # via pyuspto
77
77
  pyyaml==6.0.3
78
78
  # via myst-parser
79
- requests==2.33.1
79
+ requests==2.34.2
80
80
  # via
81
81
  # pyUSPTO (pyproject.toml)
82
82
  # pyuspto
83
83
  # sphinx
84
84
  roman-numerals==4.1.0
85
85
  # via sphinx
86
- ruff==0.15.11
86
+ ruff==0.15.14
87
87
  # via pyuspto
88
- snowballstemmer==3.0.1
88
+ snowballstemmer==3.1.0
89
89
  # via sphinx
90
90
  sphinx==9.1.0
91
91
  # via
@@ -115,17 +115,17 @@ sphinxcontrib-qthelp==2.0.0
115
115
  # via sphinx
116
116
  sphinxcontrib-serializinghtml==2.0.0
117
117
  # via sphinx
118
- types-requests==2.33.0.20260408
118
+ types-requests==2.33.0.20260518
119
119
  # via pyuspto
120
120
  typing-extensions==4.15.0
121
121
  # via
122
122
  # mypy
123
123
  # pyuspto
124
- tzdata==2026.1
124
+ tzdata==2026.2
125
125
  # via
126
126
  # pyUSPTO (pyproject.toml)
127
127
  # pyuspto
128
- urllib3==2.6.3
128
+ urllib3==2.7.0
129
129
  # via
130
130
  # requests
131
131
  # types-requests
@@ -4,17 +4,17 @@
4
4
  #
5
5
  # pip-compile --output-file=requirements.txt --strip-extras pyproject.toml
6
6
  #
7
- certifi==2026.2.25
7
+ certifi==2026.5.20
8
8
  # via requests
9
9
  charset-normalizer==3.4.7
10
10
  # via requests
11
- idna==3.11
11
+ idna==3.16
12
12
  # via requests
13
- requests==2.33.1
13
+ requests==2.34.2
14
14
  # via pyUSPTO (pyproject.toml)
15
- tzdata==2026.1
15
+ tzdata==2026.2
16
16
  # via pyUSPTO (pyproject.toml)
17
- urllib3==2.6.3
17
+ urllib3==2.7.0
18
18
  # via
19
19
  # pyUSPTO (pyproject.toml)
20
20
  # requests
@@ -93,7 +93,8 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
93
93
  Application numbers are either:
94
94
  - 8 digits (e.g., "16123456")
95
95
  - Series code format: 2 digits + "/" + 6 digits (e.g., "08/123456")
96
- - PCT format: "PCT/US2024/012345" → "PCTUS2412345"
96
+ - PCT format: "PCT/US2024/012345" → "PCTUS2024012345"
97
+ (standardized 15-character form per USPTO ODP Release 3.6, 2026-04-10)
97
98
 
98
99
  This method removes common separators (commas, spaces) while preserving
99
100
  the "/" in series code format.
@@ -103,7 +104,8 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
103
104
  spaces, or other formatting.
104
105
 
105
106
  Returns:
106
- str: Sanitized application number (either "NNNNNNNN" or "NN/NNNNNN").
107
+ str: Sanitized application number ("NNNNNNNN", "NN/NNNNNN", or
108
+ "PCT" + 2-char country + 4-digit year + 6-digit serial).
107
109
 
108
110
  Raises:
109
111
  ValueError: If the format is invalid.
@@ -117,19 +119,28 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
117
119
  "08/123456"
118
120
  >>> client.sanitize_application_number("08/123,456")
119
121
  "08/123456"
122
+ >>> client.sanitize_application_number("PCT/US2024/012345")
123
+ "PCTUS2024012345"
120
124
  """
121
125
  if not input_number or not input_number.strip():
122
126
  raise ValueError("Application number cannot be empty")
123
127
 
124
128
  raw = input_number.strip()
125
129
 
126
- # --- NEW: Handle PCT formats ---
127
- # Example: "PCT/US2024/012345" -> "PCTUS2412345"
130
+ # Handle PCT formats. Output is the standardized 15-char form:
131
+ # "PCT" + 2-char country + 4-digit year + 6-digit zero-padded serial.
132
+ # Example: "PCT/US2024/012345" -> "PCTUS2024012345"
128
133
  if raw.startswith("PCT"):
129
134
  parts = raw.split("/")
130
135
  if len(parts) == 1:
131
- # Already sanitized (e.g. "PCTUS0812705"), return as-is
132
- return raw
136
+ # No slashes — only accept input that is already in the 15-char form.
137
+ body = raw[3:]
138
+ if len(body) == 12 and body[:2].isalpha() and body[2:].isdigit():
139
+ return raw
140
+ raise ValueError(
141
+ f"Invalid PCT application format: {input_number}. "
142
+ "Expected PCT/CCYYYY/NNNNNN or PCTCCYYYYNNNNNN."
143
+ )
133
144
  if len(parts) != 3:
134
145
  raise ValueError(
135
146
  f"Invalid PCT application format: {input_number}. "
@@ -140,6 +151,10 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
140
151
 
141
152
  # country_year can be "US2024" or "US24"
142
153
  country = country_year[:2]
154
+ if len(country) != 2 or not country.isalpha():
155
+ raise ValueError(
156
+ f"Invalid PCT country code in: {country_year}. Expected 2 letters."
157
+ )
143
158
 
144
159
  year_part = country_year[2:]
145
160
  if not year_part.isdigit():
@@ -147,24 +162,28 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
147
162
  f"Invalid PCT year in: {country_year}. Must be digits."
148
163
  )
149
164
 
150
- # Normalize:
151
- # "2024" -> "24"
152
- # "24" -> "24"
165
+ # Normalize to 4-digit year. 2-digit input uses a sliding window
166
+ # tied to the PCT system's start year (1978): YY>=78 -> 19YY, else 20YY.
153
167
  if len(year_part) == 4:
154
- year = year_part[-2:]
155
- elif len(year_part) == 2:
156
168
  year = year_part
169
+ elif len(year_part) == 2:
170
+ yy = int(year_part)
171
+ year = f"19{year_part}" if yy >= 78 else f"20{year_part}"
157
172
  else:
158
173
  raise ValueError(
159
174
  f"Invalid PCT year length in: {country_year}. "
160
175
  "Expected CCYYYY or CCYY."
161
176
  )
162
177
 
163
- # Serial must be digits only
178
+ # Serial must be digits only, and fit in 6 digits.
164
179
  if not serial.isdigit():
165
180
  raise ValueError(f"Invalid PCT serial: {serial}. Must be numeric.")
181
+ if len(serial) > 6:
182
+ raise ValueError(
183
+ f"Invalid PCT serial: {serial}. Must be at most 6 digits."
184
+ )
166
185
 
167
- return f"PCT{country}{year}{serial.lstrip('0')}"
186
+ return f"PCT{country}{year}{serial.zfill(6)}"
168
187
 
169
188
  # Strip whitespace and remove commas/spaces
170
189
  cleaned = raw.replace(",", "").replace(" ", "")
@@ -5,7 +5,7 @@ including API keys, base URLs, and HTTP transport settings.
5
5
  """
6
6
 
7
7
  import os
8
- from typing import TYPE_CHECKING
8
+ from typing import TYPE_CHECKING, Any
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  import requests
@@ -15,6 +15,36 @@ from pyUSPTO.http_config import HTTPConfig
15
15
  DEFAULT_BASE_URL = "https://api.uspto.gov"
16
16
 
17
17
 
18
+ def _env_values() -> dict[str, Any]:
19
+ """Build a dict of config values from environment variables (or defaults)."""
20
+ return {
21
+ "api_key": os.environ.get("USPTO_API_KEY") or None,
22
+ "bulk_data_base_url": os.environ.get(
23
+ "USPTO_BULK_DATA_BASE_URL", DEFAULT_BASE_URL
24
+ ),
25
+ "patent_data_base_url": os.environ.get(
26
+ "USPTO_PATENT_DATA_BASE_URL", DEFAULT_BASE_URL
27
+ ),
28
+ "petition_decisions_base_url": os.environ.get(
29
+ "USPTO_PETITION_DECISIONS_BASE_URL", DEFAULT_BASE_URL
30
+ ),
31
+ "ptab_base_url": os.environ.get("USPTO_PTAB_BASE_URL", DEFAULT_BASE_URL),
32
+ "enriched_citations_base_url": os.environ.get(
33
+ "USPTO_ENRICHED_CITATIONS_BASE_URL", DEFAULT_BASE_URL
34
+ ),
35
+ "oa_actions_base_url": os.environ.get(
36
+ "USPTO_OA_ACTIONS_BASE_URL", DEFAULT_BASE_URL
37
+ ),
38
+ "oa_rejections_base_url": os.environ.get(
39
+ "USPTO_OA_REJECTIONS_BASE_URL", DEFAULT_BASE_URL
40
+ ),
41
+ "oa_citations_base_url": os.environ.get(
42
+ "USPTO_OA_CITATIONS_BASE_URL", DEFAULT_BASE_URL
43
+ ),
44
+ "http_config": HTTPConfig.from_env(),
45
+ }
46
+
47
+
18
48
  class USPTOConfig:
19
49
  """Configuration for USPTO API clients.
20
50
 
@@ -25,19 +55,22 @@ class USPTOConfig:
25
55
  def __init__(
26
56
  self,
27
57
  api_key: str | None = None,
28
- bulk_data_base_url: str = DEFAULT_BASE_URL,
29
- patent_data_base_url: str = DEFAULT_BASE_URL,
30
- petition_decisions_base_url: str = DEFAULT_BASE_URL,
31
- ptab_base_url: str = DEFAULT_BASE_URL,
32
- enriched_citations_base_url: str = DEFAULT_BASE_URL,
33
- oa_actions_base_url: str = DEFAULT_BASE_URL,
34
- oa_rejections_base_url: str = DEFAULT_BASE_URL,
35
- oa_citations_base_url: str = DEFAULT_BASE_URL,
58
+ bulk_data_base_url: str | None = None,
59
+ patent_data_base_url: str | None = None,
60
+ petition_decisions_base_url: str | None = None,
61
+ ptab_base_url: str | None = None,
62
+ enriched_citations_base_url: str | None = None,
63
+ oa_actions_base_url: str | None = None,
64
+ oa_rejections_base_url: str | None = None,
65
+ oa_citations_base_url: str | None = None,
36
66
  http_config: HTTPConfig | None = None,
37
67
  include_raw_data: bool = False,
38
68
  ):
39
69
  """Initialize the USPTOConfig.
40
70
 
71
+ Each field falls back to its environment variable (or the package
72
+ default) when the caller does not pass a value.
73
+
41
74
  Args:
42
75
  api_key: API key for authentication, defaults to USPTO_API_KEY environment variable
43
76
  bulk_data_base_url: Base URL for the Bulk Data API
@@ -51,21 +84,43 @@ class USPTOConfig:
51
84
  http_config: Optional HTTPConfig for request handling (uses defaults if None)
52
85
  include_raw_data: If True, store raw JSON in response objects for debugging (default: False)
53
86
  """
54
- # Use environment variable only if api_key is None, not if it's an empty string
55
- self.api_key = (
56
- api_key if api_key is not None else os.environ.get("USPTO_API_KEY")
87
+ env = _env_values()
88
+
89
+ self.api_key = api_key if api_key else env["api_key"]
90
+ self.bulk_data_base_url = (
91
+ bulk_data_base_url if bulk_data_base_url else env["bulk_data_base_url"]
92
+ )
93
+ self.patent_data_base_url = (
94
+ patent_data_base_url
95
+ if patent_data_base_url
96
+ else env["patent_data_base_url"]
97
+ )
98
+ self.petition_decisions_base_url = (
99
+ petition_decisions_base_url
100
+ if petition_decisions_base_url
101
+ else env["petition_decisions_base_url"]
57
102
  )
58
- self.bulk_data_base_url = bulk_data_base_url
59
- self.patent_data_base_url = patent_data_base_url
60
- self.petition_decisions_base_url = petition_decisions_base_url
61
- self.ptab_base_url = ptab_base_url
62
- self.enriched_citations_base_url = enriched_citations_base_url
63
- self.oa_actions_base_url = oa_actions_base_url
64
- self.oa_rejections_base_url = oa_rejections_base_url
65
- self.oa_citations_base_url = oa_citations_base_url
66
-
67
- # Use provided HTTPConfig or create default
68
- self.http_config = http_config if http_config is not None else HTTPConfig()
103
+ self.ptab_base_url = ptab_base_url if ptab_base_url else env["ptab_base_url"]
104
+ self.enriched_citations_base_url = (
105
+ enriched_citations_base_url
106
+ if enriched_citations_base_url
107
+ else env["enriched_citations_base_url"]
108
+ )
109
+ self.oa_actions_base_url = (
110
+ oa_actions_base_url if oa_actions_base_url else env["oa_actions_base_url"]
111
+ )
112
+ self.oa_rejections_base_url = (
113
+ oa_rejections_base_url
114
+ if oa_rejections_base_url
115
+ else env["oa_rejections_base_url"]
116
+ )
117
+ self.oa_citations_base_url = (
118
+ oa_citations_base_url
119
+ if oa_citations_base_url
120
+ else env["oa_citations_base_url"]
121
+ )
122
+
123
+ self.http_config = http_config if http_config else env["http_config"]
69
124
 
70
125
  # Control whether to include raw JSON data in response objects
71
126
  self.include_raw_data = include_raw_data
@@ -80,33 +135,7 @@ class USPTOConfig:
80
135
  Returns:
81
136
  USPTOConfig instance with values from environment
82
137
  """
83
- return cls(
84
- api_key=os.environ.get("USPTO_API_KEY"),
85
- bulk_data_base_url=os.environ.get(
86
- "USPTO_BULK_DATA_BASE_URL", DEFAULT_BASE_URL
87
- ),
88
- patent_data_base_url=os.environ.get(
89
- "USPTO_PATENT_DATA_BASE_URL", DEFAULT_BASE_URL
90
- ),
91
- petition_decisions_base_url=os.environ.get(
92
- "USPTO_PETITION_DECISIONS_BASE_URL", DEFAULT_BASE_URL
93
- ),
94
- ptab_base_url=os.environ.get("USPTO_PTAB_BASE_URL", DEFAULT_BASE_URL),
95
- enriched_citations_base_url=os.environ.get(
96
- "USPTO_ENRICHED_CITATIONS_BASE_URL", DEFAULT_BASE_URL
97
- ),
98
- oa_actions_base_url=os.environ.get(
99
- "USPTO_OA_ACTIONS_BASE_URL", DEFAULT_BASE_URL
100
- ),
101
- oa_rejections_base_url=os.environ.get(
102
- "USPTO_OA_REJECTIONS_BASE_URL", DEFAULT_BASE_URL
103
- ),
104
- oa_citations_base_url=os.environ.get(
105
- "USPTO_OA_CITATIONS_BASE_URL", DEFAULT_BASE_URL
106
- ),
107
- # Also read HTTP config from environment
108
- http_config=HTTPConfig.from_env(),
109
- )
138
+ return cls(**_env_values())
110
139
 
111
140
  @property
112
141
  def session(self) -> "requests.Session":
@@ -480,7 +480,11 @@ class Address:
480
480
  country_name: Full name of the country (e.g., "United States").
481
481
  postal_address_category: Category of the address (e.g., "MAILING_ADDRESS").
482
482
  correspondent_name_text: Name of the correspondent at this address.
483
- country_or_state_code: Country or state code.
483
+ country_or_state_code: Country or state code. Deprecated: USPTO ODP
484
+ Release 3.6 (2026-04-10) removed this field from the Patent
485
+ Assignment API response. Read ``geographic_region_code`` instead;
486
+ this attribute will be ``None`` for responses from updated
487
+ endpoints.
484
488
  ict_state_code: International code for the state/region (USPTO format).
485
489
  ict_country_code: International code for the country (USPTO format).
486
490
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyUSPTO
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary: A Modern Python client for accessing the United States Patent and Trademark Office (USPTO) Open Data Portal (ODP) APIs.
5
5
  Author-email: Andrew Piechocki <apiechocki@dunlapcodding.com>
6
6
  License-Expression: MIT
@@ -201,7 +201,7 @@ if app.application_meta_data:
201
201
  wrapper = client.get_IFW_metadata(application_number="18/045,436")
202
202
  wrapper = client.get_IFW_metadata(patent_number="11,234,567")
203
203
  wrapper = client.get_IFW_metadata(publication_number="2023/0012345")
204
- wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US24/12345")
204
+ wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US2024/012345")
205
205
 
206
206
  # Look up USPTO status codes
207
207
  status_codes = client.get_status_codes()
@@ -12,6 +12,8 @@ pyproject.toml
12
12
  requirements-dev.txt
13
13
  requirements.txt
14
14
  tox.ini
15
+ .devcontainer/devcontainer-lock.json
16
+ .devcontainer/devcontainer.json
15
17
  .github/PULL_REQUEST_TEMPLATE.md
16
18
  .github/dependabot.yml
17
19
  .github/ISSUE_TEMPLATE/bug-report.yml
@@ -1133,9 +1133,7 @@ class TestPaginateSolrResults:
1133
1133
 
1134
1134
  received_bodies: list[dict[str, Any]] = []
1135
1135
 
1136
- def mock_search(
1137
- post_body: dict[str, Any] | None = None, **kwargs: Any
1138
- ) -> Any:
1136
+ def mock_search(post_body: dict[str, Any] | None = None, **kwargs: Any) -> Any:
1139
1137
  if post_body:
1140
1138
  received_bodies.append(post_body.copy())
1141
1139
  start = post_body["start"] if post_body else 0
@@ -1183,9 +1181,7 @@ class TestPaginateSolrResults:
1183
1181
  test_client = TestClient(base_url="https://api.test.com")
1184
1182
  test_client.config._session = mock_session
1185
1183
 
1186
- with patch.object(
1187
- test_client, "search", wraps=test_client.search
1188
- ) as spy:
1184
+ with patch.object(test_client, "search", wraps=test_client.search) as spy:
1189
1185
  results = list(
1190
1186
  test_client.paginate_solr_results(
1191
1187
  method_name="search",
@@ -1198,9 +1194,7 @@ class TestPaginateSolrResults:
1198
1194
  assert results == ["doc1"]
1199
1195
  spy.assert_called_once_with(query="test", start=0, rows=10)
1200
1196
 
1201
- def test_paginate_solr_results_custom_rows(
1202
- self, mock_session: MagicMock
1203
- ) -> None:
1197
+ def test_paginate_solr_results_custom_rows(self, mock_session: MagicMock) -> None:
1204
1198
  """Test that rows is extracted from post_body and used as page size."""
1205
1199
  response = MagicMock()
1206
1200
  response.count = 1
@@ -1208,9 +1202,7 @@ class TestPaginateSolrResults:
1208
1202
 
1209
1203
  received_bodies: list[dict[str, Any]] = []
1210
1204
 
1211
- def mock_search(
1212
- post_body: dict[str, Any] | None = None, **kwargs: Any
1213
- ) -> Any:
1205
+ def mock_search(post_body: dict[str, Any] | None = None, **kwargs: Any) -> Any:
1214
1206
  if post_body:
1215
1207
  received_bodies.append(post_body.copy())
1216
1208
  return response
@@ -1231,9 +1223,7 @@ class TestPaginateSolrResults:
1231
1223
  assert received_bodies[0]["rows"] == 100
1232
1224
  assert received_bodies[0]["start"] == 0
1233
1225
 
1234
- def test_paginate_solr_results_default_rows(
1235
- self, mock_session: MagicMock
1236
- ) -> None:
1226
+ def test_paginate_solr_results_default_rows(self, mock_session: MagicMock) -> None:
1237
1227
  """Test that rows defaults to 25 when not specified."""
1238
1228
  response = MagicMock()
1239
1229
  response.count = 1
@@ -1241,9 +1231,7 @@ class TestPaginateSolrResults:
1241
1231
 
1242
1232
  received_bodies: list[dict[str, Any]] = []
1243
1233
 
1244
- def mock_search(
1245
- post_body: dict[str, Any] | None = None, **kwargs: Any
1246
- ) -> Any:
1234
+ def mock_search(post_body: dict[str, Any] | None = None, **kwargs: Any) -> Any:
1247
1235
  if post_body:
1248
1236
  received_bodies.append(post_body.copy())
1249
1237
  return response
@@ -1271,9 +1259,7 @@ class TestPaginateSolrResults:
1271
1259
 
1272
1260
  post_body = {"criteria": "test", "start": 10, "rows": 50}
1273
1261
 
1274
- with pytest.raises(
1275
- ValueError, match="Cannot specify 'start' in post_body"
1276
- ):
1262
+ with pytest.raises(ValueError, match="Cannot specify 'start' in post_body"):
1277
1263
  list(
1278
1264
  client.paginate_solr_results(
1279
1265
  method_name="search",
@@ -1289,9 +1275,7 @@ class TestPaginateSolrResults:
1289
1275
  client: BaseUSPTOClient[Any] = BaseUSPTOClient(base_url="https://api.test.com")
1290
1276
  client.config._session = mock_session
1291
1277
 
1292
- with pytest.raises(
1293
- ValueError, match="Cannot specify 'start' in kwargs"
1294
- ):
1278
+ with pytest.raises(ValueError, match="Cannot specify 'start' in kwargs"):
1295
1279
  list(
1296
1280
  client.paginate_solr_results(
1297
1281
  method_name="search",
@@ -1353,9 +1337,7 @@ class TestPaginateSolrResults:
1353
1337
 
1354
1338
  received_bodies: list[dict[str, Any]] = []
1355
1339
 
1356
- def mock_search(
1357
- post_body: dict[str, Any] | None = None, **kwargs: Any
1358
- ) -> Any:
1340
+ def mock_search(post_body: dict[str, Any] | None = None, **kwargs: Any) -> Any:
1359
1341
  if post_body:
1360
1342
  received_bodies.append(post_body.copy())
1361
1343
  return response