pyUSPTO 0.5.4__tar.gz → 0.5.6__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 (172) hide show
  1. pyuspto-0.5.6/.devcontainer/devcontainer-lock.json +19 -0
  2. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/codeql.yml +1 -1
  3. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/publish-docs.yaml +2 -2
  4. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/publish-to-test-pypi.yml +2 -2
  5. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/python-tests.yml +5 -5
  6. {pyuspto-0.5.4 → pyuspto-0.5.6}/CHANGELOG.md +50 -1
  7. {pyuspto-0.5.4 → pyuspto-0.5.6}/PKG-INFO +1 -1
  8. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/patent_data_example.py +28 -0
  9. {pyuspto-0.5.4 → pyuspto-0.5.6}/requirements-dev.txt +15 -15
  10. {pyuspto-0.5.4 → pyuspto-0.5.6}/requirements.txt +4 -4
  11. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/__init__.py +2 -1
  12. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/patent_data.py +199 -0
  13. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/PKG-INFO +1 -1
  14. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/SOURCES.txt +2 -0
  15. pyuspto-0.5.6/src/pyUSPTO.egg-info/scm_file_list.json +165 -0
  16. pyuspto-0.5.6/src/pyUSPTO.egg-info/scm_version.json +8 -0
  17. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_patent_data_clients.py +185 -0
  18. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_patent_data_integration.py +60 -0
  19. pyuspto-0.5.4/.devcontainer/devcontainer-lock.json +0 -14
  20. {pyuspto-0.5.4 → pyuspto-0.5.6}/.devcontainer/devcontainer.json +0 -0
  21. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  22. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
  24. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  25. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  26. {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/dependabot.yml +0 -0
  27. {pyuspto-0.5.4 → pyuspto-0.5.6}/.gitignore +0 -0
  28. {pyuspto-0.5.4 → pyuspto-0.5.6}/.readthedocs.yaml +0 -0
  29. {pyuspto-0.5.4 → pyuspto-0.5.6}/ADVANCED.md +0 -0
  30. {pyuspto-0.5.4 → pyuspto-0.5.6}/CODE_OF_CONDUCT.md +0 -0
  31. {pyuspto-0.5.4 → pyuspto-0.5.6}/CONTRIBUTING.md +0 -0
  32. {pyuspto-0.5.4 → pyuspto-0.5.6}/LICENSE +0 -0
  33. {pyuspto-0.5.4 → pyuspto-0.5.6}/README.md +0 -0
  34. {pyuspto-0.5.4 → pyuspto-0.5.6}/_version.pyi +0 -0
  35. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/Makefile +0 -0
  36. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/_static/.gitkeep +0 -0
  37. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/about.rst +0 -0
  38. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/advanced.rst +0 -0
  39. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/bulk_data.rst +0 -0
  40. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/enriched_citations.rst +0 -0
  41. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/index.rst +0 -0
  42. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_actions.rst +0 -0
  43. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_citations.rst +0 -0
  44. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_rejections.rst +0 -0
  45. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/patent_data.rst +0 -0
  46. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/petition_decisions.rst +0 -0
  47. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_appeals.rst +0 -0
  48. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_interferences.rst +0 -0
  49. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_trials.rst +0 -0
  50. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/config.rst +0 -0
  51. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/http_config.rst +0 -0
  52. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/index.rst +0 -0
  53. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/exceptions.rst +0 -0
  54. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/index.rst +0 -0
  55. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/base.rst +0 -0
  56. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/bulk_data.rst +0 -0
  57. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/enriched_citations.rst +0 -0
  58. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/index.rst +0 -0
  59. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_actions.rst +0 -0
  60. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_citations.rst +0 -0
  61. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_rejections.rst +0 -0
  62. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/patent_data.rst +0 -0
  63. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/petition_decisions.rst +0 -0
  64. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/ptab.rst +0 -0
  65. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/utils.rst +0 -0
  66. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/warnings.rst +0 -0
  67. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/conf.py +0 -0
  68. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/configuration.rst +0 -0
  69. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/development.rst +0 -0
  70. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/bulk_data.rst +0 -0
  71. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/enriched_citations.rst +0 -0
  72. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ifw_example.rst +0 -0
  73. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/index.rst +0 -0
  74. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_actions.rst +0 -0
  75. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_citations.rst +0 -0
  76. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_rejections.rst +0 -0
  77. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/patent_data.rst +0 -0
  78. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/petition_decisions.rst +0 -0
  79. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_appeals.rst +0 -0
  80. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_interferences.rst +0 -0
  81. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_trials.rst +0 -0
  82. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/index.rst +0 -0
  83. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/installation.rst +0 -0
  84. {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/quickstart.rst +0 -0
  85. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/bulk_data_example.py +0 -0
  86. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/enriched_citations_example.py +0 -0
  87. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/error_handling_example.py +0 -0
  88. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ifw_example.py +0 -0
  89. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_actions_example.py +0 -0
  90. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_citations_example.py +0 -0
  91. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_rejections_example.py +0 -0
  92. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/petition_decisions_example.py +0 -0
  93. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_appeals_example.py +0 -0
  94. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_interferences_example.py +0 -0
  95. {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_trials_example.py +0 -0
  96. {pyuspto-0.5.4 → pyuspto-0.5.6}/pyUSPTO.code-workspace +0 -0
  97. {pyuspto-0.5.4 → pyuspto-0.5.6}/pyproject.toml +0 -0
  98. {pyuspto-0.5.4 → pyuspto-0.5.6}/setup.cfg +0 -0
  99. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/__init__.py +0 -0
  100. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/base.py +0 -0
  101. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/bulk_data.py +0 -0
  102. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/enriched_citations.py +0 -0
  103. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_actions.py +0 -0
  104. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_citations.py +0 -0
  105. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_rejections.py +0 -0
  106. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/petition_decisions.py +0 -0
  107. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_appeals.py +0 -0
  108. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_interferences.py +0 -0
  109. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_trials.py +0 -0
  110. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/config.py +0 -0
  111. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/exceptions.py +0 -0
  112. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/http_config.py +0 -0
  113. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/__init__.py +0 -0
  114. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/base.py +0 -0
  115. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/bulk_data.py +0 -0
  116. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/enriched_citations.py +0 -0
  117. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_actions.py +0 -0
  118. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_citations.py +0 -0
  119. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_rejections.py +0 -0
  120. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/patent_data.py +0 -0
  121. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/petition_decisions.py +0 -0
  122. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/ptab.py +0 -0
  123. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/utils.py +0 -0
  124. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/py.typed +0 -0
  125. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/utils/__init__.py +0 -0
  126. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/warnings.py +0 -0
  127. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
  128. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/requires.txt +0 -0
  129. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/top_level.txt +0 -0
  130. {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/zip-safe +0 -0
  131. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/__init__.py +0 -0
  132. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/__init__.py +0 -0
  133. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_base.py +0 -0
  134. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_bulk_data_clients.py +0 -0
  135. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_enriched_citation_clients.py +0 -0
  136. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_actions_clients.py +0 -0
  137. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_citations_clients.py +0 -0
  138. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_rejections_clients.py +0 -0
  139. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_petition_decision_clients.py +0 -0
  140. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_appeals_client.py +0 -0
  141. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_interferences_client.py +0 -0
  142. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_trials_client.py +0 -0
  143. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/conftest.py +0 -0
  144. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/__init__.py +0 -0
  145. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/conftest.py +0 -0
  146. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_bulk_data_integration.py +0 -0
  147. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_enriched_citations_integration.py +0 -0
  148. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_actions_integration.py +0 -0
  149. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_citations_integration.py +0 -0
  150. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_rejections_integration.py +0 -0
  151. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_petition_decisions_integration.py +0 -0
  152. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_appeals_integration.py +0 -0
  153. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_interferences_integration.py +0 -0
  154. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_trials_integration.py +0 -0
  155. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/__init__.py +0 -0
  156. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_bulk_data_models.py +0 -0
  157. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_enriched_citation_models.py +0 -0
  158. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_actions_models.py +0 -0
  159. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_citations_models.py +0 -0
  160. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_rejections_models.py +0 -0
  161. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_patent_data_models.py +0 -0
  162. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_petition_decision_models.py +0 -0
  163. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_ptab_models.py +0 -0
  164. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_utils.py +0 -0
  165. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_config.py +0 -0
  166. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_edge_cases.py +0 -0
  167. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_exceptions.py +0 -0
  168. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_http_config.py +0 -0
  169. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_init.py +0 -0
  170. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_version.py +0 -0
  171. {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/utils/__init__.py +0 -0
  172. {pyuspto-0.5.4 → pyuspto-0.5.6}/tox.ini +0 -0
@@ -0,0 +1,19 @@
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:2": {
9
+ "version": "2.1.0",
10
+ "resolved": "ghcr.io/devcontainers/features/node@sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857",
11
+ "integrity": "sha256:586c9a6f7dd40bd3ba2cd41e7f2f88dcc31fbe5d1442afcbf07ffbc66b686857"
12
+ },
13
+ "ghcr.io/devcontainers/features/powershell:2.0.2": {
14
+ "version": "2.0.2",
15
+ "resolved": "ghcr.io/devcontainers/features/powershell@sha256:82ea3880c5706ac3963f1b5e940a7f5871835393a5472f80008148b995d58d61",
16
+ "integrity": "sha256:82ea3880c5706ac3963f1b5e940a7f5871835393a5472f80008148b995d58d61"
17
+ }
18
+ }
19
+ }
@@ -55,7 +55,7 @@ jobs:
55
55
  # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
56
56
  steps:
57
57
  - name: Checkout repository
58
- uses: actions/checkout@v6
58
+ uses: actions/checkout@v7
59
59
 
60
60
  # Add any setup steps before running the `github/codeql-action/init` action.
61
61
  # This includes steps like installing compilers or runtimes (`actions/setup-node`
@@ -15,9 +15,9 @@ jobs:
15
15
  name: Build documentation
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v6
18
+ - uses: actions/checkout@v7
19
19
  - name: Set up Python
20
- uses: actions/setup-python@v6
20
+ uses: actions/setup-python@v7
21
21
  with:
22
22
  python-version: "3.14"
23
23
  - name: Install dependencies
@@ -16,11 +16,11 @@ jobs:
16
16
  runs-on: ubuntu-latest
17
17
 
18
18
  steps:
19
- - uses: actions/checkout@v6
19
+ - uses: actions/checkout@v7
20
20
  with:
21
21
  persist-credentials: false
22
22
  - name: Set up Python
23
- uses: actions/setup-python@v6
23
+ uses: actions/setup-python@v7
24
24
  with:
25
25
  python-version: "3.x"
26
26
  - name: Install pypa/build
@@ -14,10 +14,10 @@ jobs:
14
14
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
15
15
 
16
16
  steps:
17
- - uses: actions/checkout@v6
17
+ - uses: actions/checkout@v7
18
18
 
19
19
  - name: Set up Python ${{ matrix.python-version }}
20
- uses: actions/setup-python@v6
20
+ uses: actions/setup-python@v7
21
21
  with:
22
22
  python-version: ${{ matrix.python-version }}
23
23
 
@@ -32,7 +32,7 @@ jobs:
32
32
  pytest tests/ --cov=src/pyUSPTO
33
33
 
34
34
  - name: Upload coverage report
35
- uses: codecov/codecov-action@v6
35
+ uses: codecov/codecov-action@v7
36
36
  with:
37
37
  fail_ci_if_error: false
38
38
 
@@ -40,10 +40,10 @@ jobs:
40
40
  runs-on: ubuntu-latest
41
41
 
42
42
  steps:
43
- - uses: actions/checkout@v6
43
+ - uses: actions/checkout@v7
44
44
 
45
45
  - name: Set up Python
46
- uses: actions/setup-python@v6
46
+ uses: actions/setup-python@v7
47
47
  with:
48
48
  python-version: "3.14"
49
49
 
@@ -5,16 +5,65 @@ 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]
8
+ ## [0.5.5] - 2026-07-22
9
+
10
+ ### Added
11
+
12
+ - `PatentDataClient.get_firm_portfolio(customer_numbers, ...)` — helper that searches a law firm's portfolio across one or more USPTO Customer Numbers. Builds a single Lucene `OR` query, applies a named field preset by default, and returns a `PatentDataResponse`. Pairs with `get_application_metadata` / `get_application_by_number` for per-application drill-down.
13
+ - `FIELD_PRESETS` constant (exported from `pyUSPTO`) — three named field sets for `get_firm_portfolio`'s `fields` argument: `"minimal"` (8 firm-internal identifiers), `"portfolio"` (16 fields for status + deadline derivation, default), and `"full_meta"` (uses the API's `applicationMetaData` shorthand for the entire 27-key metadata object, ~7.5× payload reduction vs. the un-fielded default).
14
+ - Multi-value `customer_number_q` and `status_code_q` on `search_applications` and `get_search_results` — accept a single value or a list; lists are OR-joined as `field:(a OR b)`.
15
+ - New `status_date_from_q` / `status_date_to_q` on `search_applications` and `get_search_results` — date-range filters against `applicationMetaData.applicationStatusDate`, mirroring the existing `filing_date` and `grant_date` range params. Useful for bounding the deadline-coming-due horizon.
16
+
17
+ ## [0.5.4] - 2026-05-27
9
18
 
10
19
  ### Changed
11
20
 
12
21
  - **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.
22
+ - `USPTOConfig` now applies user > env > default precedence uniformly across all fields. Previously only `api_key` fell back to its environment variable; base URLs and `HTTPConfig` ignored env in the constructor. Env reading is consolidated in an internal `_env_values()` helper shared by `__init__` and `from_env`.
13
23
 
14
24
  ### Deprecated
15
25
 
16
26
  - `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
27
 
28
+ ### Fixed
29
+
30
+ - `USPTO_API_KEY=""` was stored as `""` instead of `None`, breaking `is None` checks. Empty-string constructor arguments are now treated as no-value and fall back to env.
31
+
32
+ ## [0.5.3] - 2026-05-13
33
+
34
+ ### Changed
35
+
36
+ - Maintenance release: dependency updates only (including urllib3 v2.7.0 security update); no library code changes.
37
+
38
+ ## [0.5.2] - 2026-04-16
39
+
40
+ ### Added
41
+
42
+ - `PatentDataClient.stream_document(document, format)` — returns a streaming `requests.Response` the caller consumes via `iter_content()` or `iter_lines()`. Accepts the same `format` argument (`DocumentMimeType` enum or MIME string) as `download_document` and raises the same `FormatNotAvailableError` on an unavailable format. The returned response is the caller's responsibility — use as a context manager or call `.close()` when finished.
43
+ - Streaming download example in `examples/patent_data_example.py`
44
+ - Bulk Data product identifier reference table in the documentation
45
+
46
+ ### Changed
47
+
48
+ - `stream_document` and `download_document` now share format resolution through an internal `_resolve_document_format` helper, so both methods raise identical errors for missing formats or missing download URLs. No changes to existing `download_document` behavior.
49
+
50
+ ## [0.5.1] - 2026-03-30
51
+
52
+ ### Added
53
+
54
+ - `OAActionsClient` — Office Action Text Retrieval API (v1): full-text office action documents including body text and structured section data (§101/102/103/112 rejections, citations, etc.)
55
+ - `OARejectionsClient` — Office Action Rejections API (v2): rejection-level records with rejection type indicators (`hasRej101/102/103/112/DP`), claim arrays, and examiner classification metadata
56
+ - `OACitationsClient` — Office Action Citations API: enriched citation records from office actions including cited document identifiers, legal section codes, and examiner-cited indicators
57
+ - Config and environment variable support for the three new base URLs (`USPTO_OA_ACTIONS_BASE_URL`, `USPTO_OA_REJECTIONS_BASE_URL`, `USPTO_OA_CITATIONS_BASE_URL`)
58
+
59
+ ## [0.5.0] - 2026-03-27
60
+
61
+ ### Added
62
+
63
+ - `EnrichedCitationsClient` for the USPTO Enriched Cited Reference Metadata API (v3) — citation data extracted from patent office actions using AI/NLP, including citation category codes (X/Y/A/etc.), passage locations in the prior art, rejected claims, and examiner vs. applicant citation indicators
64
+ - Client methods: `search_citations()` (POST-based search with convenience parameters), `paginate_citations()` (auto-paginating iterator), and `get_fields()`
65
+ - Models: `EnrichedCitation` (21 fields), `EnrichedCitationResponse`, `EnrichedCitationFieldsResponse`
66
+
18
67
  ## [0.4.5] - 2026-03-11
19
68
 
20
69
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyUSPTO
3
- Version: 0.5.4
3
+ Version: 0.5.6
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
@@ -315,3 +315,31 @@ print(
315
315
  )
316
316
  for code_obj in status_code_response.status_code_bag:
317
317
  print(f" - Code: {code_obj.code}, Description: {code_obj.description}")
318
+
319
+ print("-" * 40)
320
+ print("Example 9: Firm portfolio across multiple Customer Numbers")
321
+ print("-" * 40)
322
+
323
+ # get_firm_portfolio builds one Lucene OR query across all provided Customer
324
+ # Numbers, applies the "portfolio" field preset by default, and returns a
325
+ # PatentDataResponse. Combine with status_date_from to bound the deadline
326
+ # horizon ("show me cases whose status changed since X").
327
+ from collections import Counter
328
+
329
+ portfolio_response = client.get_firm_portfolio(
330
+ customer_numbers=[30589, 174793],
331
+ status_date_from="2025-01-01",
332
+ sort="applicationMetaData.applicationStatusDate desc",
333
+ limit=25,
334
+ )
335
+ print(f"Total matching applications across both Customer Numbers: {portfolio_response.count}")
336
+
337
+ status_counter: Counter[str] = Counter()
338
+ for wrapper in portfolio_response.patent_file_wrapper_data_bag:
339
+ meta = wrapper.application_meta_data
340
+ if meta and meta.application_status_code is not None:
341
+ status_counter[str(meta.application_status_code)] += 1
342
+
343
+ print("Status-code tally for the page:")
344
+ for code, n in status_counter.most_common():
345
+ print(f" {code}: {n}")
@@ -8,22 +8,22 @@ alabaster==1.0.0
8
8
  # via sphinx
9
9
  babel==2.18.0
10
10
  # via sphinx
11
- certifi==2026.5.20
11
+ certifi==2026.7.22
12
12
  # via requests
13
- charset-normalizer==3.4.7
13
+ charset-normalizer==3.5.1
14
14
  # via requests
15
15
  colorama==0.4.6
16
16
  # via
17
17
  # pytest
18
18
  # sphinx
19
- coverage==7.14.1
19
+ coverage==7.15.4
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.16
26
+ idna==3.19
27
27
  # via requests
28
28
  imagesize==2.0.0
29
29
  # via sphinx
@@ -33,7 +33,7 @@ jinja2==3.1.6
33
33
  # via
34
34
  # myst-parser
35
35
  # sphinx
36
- librt==0.11.0
36
+ librt==0.15.0
37
37
  # via mypy
38
38
  markdown-it-py==4.2.0
39
39
  # via
@@ -45,13 +45,13 @@ 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==2.1.0
48
+ mypy==2.3.1
49
49
  # via pyuspto
50
50
  mypy-extensions==1.1.0
51
51
  # via mypy
52
52
  myst-parser==5.1.0
53
53
  # via pyuspto
54
- packaging==26.2
54
+ packaging==26.3
55
55
  # via
56
56
  # pytest
57
57
  # sphinx
@@ -61,11 +61,11 @@ pluggy==1.6.0
61
61
  # via
62
62
  # pytest
63
63
  # pytest-cov
64
- pygments==2.20.0
64
+ pygments==2.21.0
65
65
  # via
66
66
  # pytest
67
67
  # sphinx
68
- pytest==9.0.3
68
+ pytest==9.1.1
69
69
  # via
70
70
  # pytest-cov
71
71
  # pytest-mock
@@ -83,9 +83,9 @@ requests==2.34.2
83
83
  # sphinx
84
84
  roman-numerals==4.1.0
85
85
  # via sphinx
86
- ruff==0.15.14
86
+ ruff==0.16.4
87
87
  # via pyuspto
88
- snowballstemmer==3.1.0
88
+ snowballstemmer==3.1.1
89
89
  # via sphinx
90
90
  sphinx==9.1.0
91
91
  # via
@@ -95,7 +95,7 @@ sphinx==9.1.0
95
95
  # sphinx-copybutton
96
96
  # sphinx-rtd-theme
97
97
  # sphinxcontrib-jquery
98
- sphinx-autodoc-typehints==3.10.2
98
+ sphinx-autodoc-typehints==3.13.2
99
99
  # via pyuspto
100
100
  sphinx-copybutton==0.5.2
101
101
  # via pyuspto
@@ -115,13 +115,13 @@ 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.20260518
118
+ types-requests==2.33.0.20260712
119
119
  # via pyuspto
120
- typing-extensions==4.15.0
120
+ typing-extensions==4.16.0
121
121
  # via
122
122
  # mypy
123
123
  # pyuspto
124
- tzdata==2026.2
124
+ tzdata==2026.3
125
125
  # via
126
126
  # pyUSPTO (pyproject.toml)
127
127
  # pyuspto
@@ -4,15 +4,15 @@
4
4
  #
5
5
  # pip-compile --output-file=requirements.txt --strip-extras pyproject.toml
6
6
  #
7
- certifi==2026.5.20
7
+ certifi==2026.7.22
8
8
  # via requests
9
- charset-normalizer==3.4.7
9
+ charset-normalizer==3.5.1
10
10
  # via requests
11
- idna==3.16
11
+ idna==3.19
12
12
  # via requests
13
13
  requests==2.34.2
14
14
  # via pyUSPTO (pyproject.toml)
15
- tzdata==2026.2
15
+ tzdata==2026.3
16
16
  # via pyUSPTO (pyproject.toml)
17
17
  urllib3==2.7.0
18
18
  # via
@@ -16,7 +16,7 @@ from pyUSPTO.clients.enriched_citations import EnrichedCitationsClient
16
16
  from pyUSPTO.clients.oa_actions import OAActionsClient
17
17
  from pyUSPTO.clients.oa_citations import OACitationsClient
18
18
  from pyUSPTO.clients.oa_rejections import OARejectionsClient
19
- from pyUSPTO.clients.patent_data import PatentDataClient
19
+ from pyUSPTO.clients.patent_data import FIELD_PRESETS, PatentDataClient
20
20
  from pyUSPTO.clients.petition_decisions import FinalPetitionDecisionsClient
21
21
  from pyUSPTO.clients.ptab_appeals import PTABAppealsClient
22
22
  from pyUSPTO.clients.ptab_interferences import PTABInterferencesClient
@@ -138,6 +138,7 @@ __all__ = [
138
138
  "FileData",
139
139
  # Patent Data API
140
140
  "PatentDataClient",
141
+ "FIELD_PRESETS",
141
142
  "ApplicationContinuityData",
142
143
  "PatentDataResponse",
143
144
  "PatentFileWrapper",
@@ -39,6 +39,57 @@ from pyUSPTO.models.patent_data import (
39
39
  from pyUSPTO.warnings import USPTODataMismatchWarning
40
40
 
41
41
 
42
+ def _or_clause(field: str, value: int | str | list[int | str]) -> str:
43
+ """Build a Lucene clause for a single value or a list of values.
44
+
45
+ Single value → ``field:val``. List → ``field:(v1 OR v2 ...)``.
46
+ """
47
+ if isinstance(value, list):
48
+ return f"{field}:({' OR '.join(str(v) for v in value)})"
49
+ return f"{field}:{value}"
50
+
51
+
52
+ FIELD_PRESETS: dict[str, list[str]] = {
53
+ "minimal": [
54
+ "applicationNumberText",
55
+ "applicationMetaData.customerNumber",
56
+ "applicationMetaData.applicationStatusCode",
57
+ "applicationMetaData.applicationStatusDate",
58
+ "applicationMetaData.filingDate",
59
+ "applicationMetaData.firstApplicantName",
60
+ "applicationMetaData.firstInventorName",
61
+ "applicationMetaData.docketNumber",
62
+ ],
63
+ "portfolio": [
64
+ "applicationNumberText",
65
+ "applicationMetaData.customerNumber",
66
+ "applicationMetaData.applicationStatusCode",
67
+ "applicationMetaData.applicationStatusDescriptionText",
68
+ "applicationMetaData.applicationStatusDate",
69
+ "applicationMetaData.filingDate",
70
+ "applicationMetaData.effectiveFilingDate",
71
+ "applicationMetaData.patentNumber",
72
+ "applicationMetaData.grantDate",
73
+ "applicationMetaData.inventionTitle",
74
+ "applicationMetaData.firstApplicantName",
75
+ "applicationMetaData.firstInventorName",
76
+ "applicationMetaData.docketNumber",
77
+ "applicationMetaData.examinerNameText",
78
+ "applicationMetaData.applicationTypeCode",
79
+ "applicationMetaData.applicationTypeLabelName",
80
+ ],
81
+ # ``full_meta`` uses the USPTO API's top-level shorthand: passing
82
+ # ``applicationMetaData`` returns the entire 27-key object.
83
+ # ``applicationNumberText`` is added explicitly because it lives at the
84
+ # wrapper top level (outside applicationMetaData) and would otherwise be
85
+ # stripped. Payload is roughly 7.5x smaller than the un-fielded default.
86
+ "full_meta": [
87
+ "applicationNumberText",
88
+ "applicationMetaData",
89
+ ],
90
+ }
91
+
92
+
42
93
  class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
43
94
  """Client for interacting with the USPTO Patent Data API."""
44
95
 
@@ -267,10 +318,14 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
267
318
  inventor_name_q: str | None = None,
268
319
  applicant_name_q: str | None = None,
269
320
  assignee_name_q: str | None = None,
321
+ customer_number_q: int | str | list[int | str] | None = None,
322
+ status_code_q: int | str | list[int | str] | None = None,
270
323
  filing_date_from_q: str | None = None,
271
324
  filing_date_to_q: str | None = None,
272
325
  grant_date_from_q: str | None = None,
273
326
  grant_date_to_q: str | None = None,
327
+ status_date_from_q: str | None = None,
328
+ status_date_to_q: str | None = None,
274
329
  classification_q: str | None = None,
275
330
  earliestPublicationNumber_q: str | None = None,
276
331
  pctPublicationNumber_q: str | None = None,
@@ -279,6 +334,11 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
279
334
  """Search for patent applications.
280
335
 
281
336
  Can perform a GET request based on OpenAPI query parameters or a POST request if post_body is specified.
337
+
338
+ ``customer_number_q`` and ``status_code_q`` accept a single value or a list;
339
+ a list builds a Lucene ``field:(a OR b)`` clause. ``status_date_from_q`` /
340
+ ``status_date_to_q`` follow the same date-range pattern as
341
+ ``filing_date_from_q`` / ``filing_date_to_q``.
282
342
  """
283
343
  endpoint = self.ENDPOINTS["search_applications"]
284
344
 
@@ -325,6 +385,18 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
325
385
  else assignee_name_q
326
386
  )
327
387
  q_parts.append(f"assignmentBag.assigneeBag.assigneeNameText:{v}")
388
+ if customer_number_q is not None:
389
+ q_parts.append(
390
+ _or_clause(
391
+ "applicationMetaData.customerNumber", customer_number_q
392
+ )
393
+ )
394
+ if status_code_q is not None:
395
+ q_parts.append(
396
+ _or_clause(
397
+ "applicationMetaData.applicationStatusCode", status_code_q
398
+ )
399
+ )
328
400
  if classification_q:
329
401
  v = (
330
402
  f'"{classification_q}"'
@@ -364,6 +436,19 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
364
436
  elif grant_date_to_q:
365
437
  q_parts.append(f"applicationMetaData.grantDate:<={grant_date_to_q}")
366
438
 
439
+ if status_date_from_q and status_date_to_q:
440
+ q_parts.append(
441
+ f"applicationMetaData.applicationStatusDate:[{status_date_from_q} TO {status_date_to_q}]"
442
+ )
443
+ elif status_date_from_q:
444
+ q_parts.append(
445
+ f"applicationMetaData.applicationStatusDate:>={status_date_from_q}"
446
+ )
447
+ elif status_date_to_q:
448
+ q_parts.append(
449
+ f"applicationMetaData.applicationStatusDate:<={status_date_to_q}"
450
+ )
451
+
367
452
  if q_parts:
368
453
  final_q = " AND ".join(q_parts)
369
454
 
@@ -409,10 +494,14 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
409
494
  inventor_name_q: str | None = None,
410
495
  applicant_name_q: str | None = None,
411
496
  assignee_name_q: str | None = None,
497
+ customer_number_q: int | str | list[int | str] | None = None,
498
+ status_code_q: int | str | list[int | str] | None = None,
412
499
  filing_date_from_q: str | None = None,
413
500
  filing_date_to_q: str | None = None,
414
501
  grant_date_from_q: str | None = None,
415
502
  grant_date_to_q: str | None = None,
503
+ status_date_from_q: str | None = None,
504
+ status_date_to_q: str | None = None,
416
505
  classification_q: str | None = None,
417
506
  additional_query_params: dict[str, Any] | None = None,
418
507
  ) -> list[ApplicationMetaData]:
@@ -468,6 +557,18 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
468
557
  else assignee_name_q
469
558
  )
470
559
  q_parts.append(f"assignmentBag.assigneeBag.assigneeNameText:{v}")
560
+ if customer_number_q is not None:
561
+ q_parts.append(
562
+ _or_clause(
563
+ "applicationMetaData.customerNumber", customer_number_q
564
+ )
565
+ )
566
+ if status_code_q is not None:
567
+ q_parts.append(
568
+ _or_clause(
569
+ "applicationMetaData.applicationStatusCode", status_code_q
570
+ )
571
+ )
471
572
  if classification_q:
472
573
  v = (
473
574
  f'"{classification_q}"'
@@ -500,6 +601,19 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
500
601
  elif grant_date_to_q:
501
602
  q_parts.append(f"applicationMetaData.grantDate:<={grant_date_to_q}")
502
603
 
604
+ if status_date_from_q and status_date_to_q:
605
+ q_parts.append(
606
+ f"applicationMetaData.applicationStatusDate:[{status_date_from_q} TO {status_date_to_q}]"
607
+ )
608
+ elif status_date_from_q:
609
+ q_parts.append(
610
+ f"applicationMetaData.applicationStatusDate:>={status_date_from_q}"
611
+ )
612
+ elif status_date_to_q:
613
+ q_parts.append(
614
+ f"applicationMetaData.applicationStatusDate:<={status_date_to_q}"
615
+ )
616
+
503
617
  if q_parts:
504
618
  final_q = " AND ".join(q_parts)
505
619
 
@@ -924,6 +1038,91 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
924
1038
  **kwargs,
925
1039
  )
926
1040
 
1041
+ def get_firm_portfolio(
1042
+ self,
1043
+ customer_numbers: list[int | str],
1044
+ status_codes: list[int | str] | None = None,
1045
+ status_date_from: str | None = None,
1046
+ status_date_to: str | None = None,
1047
+ filing_date_from: str | None = None,
1048
+ filing_date_to: str | None = None,
1049
+ fields: str | list[str] = "portfolio",
1050
+ sort: str | None = None,
1051
+ offset: int | None = 0,
1052
+ limit: int | None = 25,
1053
+ ) -> PatentDataResponse:
1054
+ """Search a law firm's portfolio across one or more USPTO Customer Numbers.
1055
+
1056
+ A USPTO Customer Number identifies a registered practitioner or firm's
1057
+ correspondence group. Firms typically have multiple Customer Numbers
1058
+ (small firms ~10; large firms 30+), so this helper accepts a list and
1059
+ builds a single Lucene ``OR`` query.
1060
+
1061
+ For per-application drill-down, see the drill hierarchy:
1062
+
1063
+ 1. ``get_firm_portfolio(...)`` — firm-wide list with ``minimal`` /
1064
+ ``portfolio`` / ``full_meta`` field presets.
1065
+ 2. ``get_application_metadata(app_number)`` — one application, full
1066
+ ``ApplicationMetaData`` (same shape as one ``full_meta`` row).
1067
+ 3. ``get_application_by_number(app_number)`` — one application, full
1068
+ ``PatentFileWrapper`` including wrapper-level bags (assignment,
1069
+ continuity, transactions, attorney of record, foreign priority,
1070
+ event data).
1071
+
1072
+ Args:
1073
+ customer_numbers: Non-empty list of Customer Numbers (ints or strings).
1074
+ status_codes: Optional filter to specific application status codes
1075
+ (single value or list). Useful for narrowing to "moving" cases
1076
+ such as non-final / final Office Actions.
1077
+ status_date_from: Lower bound (inclusive) on
1078
+ ``applicationMetaData.applicationStatusDate``, e.g. ``"2025-01-01"``.
1079
+ Pair with a sort like ``"applicationMetaData.applicationStatusDate desc"``
1080
+ to surface cases whose deadline is coming due.
1081
+ status_date_to: Upper bound on the status date.
1082
+ filing_date_from: Lower bound on ``applicationMetaData.filingDate``.
1083
+ filing_date_to: Upper bound on the filing date.
1084
+ fields: Polymorphic. A preset name from :data:`FIELD_PRESETS`
1085
+ (``"minimal"``, ``"portfolio"``, or ``"full_meta"``), a list of
1086
+ dotted field paths, or a comma-joined string. Defaults to
1087
+ ``"portfolio"``. Power users wanting bulk full metadata can pass
1088
+ ``"applicationMetaData,applicationNumberText"`` directly — the
1089
+ API accepts ``applicationMetaData`` as a shorthand for the
1090
+ entire 27-key object.
1091
+ sort: Optional Lucene sort string. No default; a common choice is
1092
+ ``"applicationMetaData.applicationStatusDate desc"``.
1093
+ offset: Pagination offset.
1094
+ limit: Page size.
1095
+
1096
+ Returns:
1097
+ PatentDataResponse: The same response shape as
1098
+ :meth:`search_applications`. Pagination is the caller's responsibility.
1099
+
1100
+ Raises:
1101
+ ValueError: If ``customer_numbers`` is empty.
1102
+ """
1103
+ if not customer_numbers:
1104
+ raise ValueError("customer_numbers must be a non-empty list")
1105
+
1106
+ if isinstance(fields, str) and fields in FIELD_PRESETS:
1107
+ resolved_fields: str = ",".join(FIELD_PRESETS[fields])
1108
+ elif isinstance(fields, list):
1109
+ resolved_fields = ",".join(fields)
1110
+ else:
1111
+ resolved_fields = fields
1112
+
1113
+ return self.search_applications(
1114
+ customer_number_q=list(customer_numbers),
1115
+ status_code_q=list(status_codes) if status_codes else None,
1116
+ status_date_from_q=status_date_from,
1117
+ status_date_to_q=status_date_to,
1118
+ filing_date_from_q=filing_date_from,
1119
+ filing_date_to_q=filing_date_to,
1120
+ fields=resolved_fields,
1121
+ sort=sort,
1122
+ offset=offset,
1123
+ limit=limit,
1124
+ )
1125
+
927
1126
  def get_status_codes(
928
1127
  self, params: dict[str, Any] | None = None
929
1128
  ) -> StatusCodeSearchResponse:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyUSPTO
3
- Version: 0.5.4
3
+ Version: 0.5.6
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
@@ -96,6 +96,8 @@ src/pyUSPTO.egg-info/PKG-INFO
96
96
  src/pyUSPTO.egg-info/SOURCES.txt
97
97
  src/pyUSPTO.egg-info/dependency_links.txt
98
98
  src/pyUSPTO.egg-info/requires.txt
99
+ src/pyUSPTO.egg-info/scm_file_list.json
100
+ src/pyUSPTO.egg-info/scm_version.json
99
101
  src/pyUSPTO.egg-info/top_level.txt
100
102
  src/pyUSPTO.egg-info/zip-safe
101
103
  src/pyUSPTO/clients/__init__.py