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.
- pyuspto-0.5.6/.devcontainer/devcontainer-lock.json +19 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/codeql.yml +1 -1
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/publish-docs.yaml +2 -2
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/publish-to-test-pypi.yml +2 -2
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/workflows/python-tests.yml +5 -5
- {pyuspto-0.5.4 → pyuspto-0.5.6}/CHANGELOG.md +50 -1
- {pyuspto-0.5.4 → pyuspto-0.5.6}/PKG-INFO +1 -1
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/patent_data_example.py +28 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/requirements-dev.txt +15 -15
- {pyuspto-0.5.4 → pyuspto-0.5.6}/requirements.txt +4 -4
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/__init__.py +2 -1
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/patent_data.py +199 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/PKG-INFO +1 -1
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/SOURCES.txt +2 -0
- pyuspto-0.5.6/src/pyUSPTO.egg-info/scm_file_list.json +165 -0
- pyuspto-0.5.6/src/pyUSPTO.egg-info/scm_version.json +8 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_patent_data_clients.py +185 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_patent_data_integration.py +60 -0
- pyuspto-0.5.4/.devcontainer/devcontainer-lock.json +0 -14
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.devcontainer/devcontainer.json +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.github/dependabot.yml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.gitignore +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/.readthedocs.yaml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/ADVANCED.md +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/CODE_OF_CONDUCT.md +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/CONTRIBUTING.md +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/LICENSE +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/README.md +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/_version.pyi +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/Makefile +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/_static/.gitkeep +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/about.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/advanced.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/bulk_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/enriched_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_actions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/oa_rejections.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/patent_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/petition_decisions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_appeals.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_interferences.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/clients/ptab_trials.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/config.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/http_config.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/config/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/exceptions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/base.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/bulk_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/enriched_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_actions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/oa_rejections.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/patent_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/petition_decisions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/ptab.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/models/utils.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/api/warnings.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/conf.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/configuration.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/development.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/bulk_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/enriched_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ifw_example.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_actions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_citations.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/oa_rejections.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/patent_data.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/petition_decisions.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_appeals.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_interferences.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/examples/ptab_trials.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/index.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/installation.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/docs/source/quickstart.rst +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/bulk_data_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/enriched_citations_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/error_handling_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ifw_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_actions_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_citations_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/oa_rejections_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/petition_decisions_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_appeals_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_interferences_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/examples/ptab_trials_example.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/pyUSPTO.code-workspace +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/pyproject.toml +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/setup.cfg +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/base.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/bulk_data.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/enriched_citations.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_actions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_citations.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/oa_rejections.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/petition_decisions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_appeals.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_interferences.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/clients/ptab_trials.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/config.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/exceptions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/http_config.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/base.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/bulk_data.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/enriched_citations.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_actions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_citations.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/oa_rejections.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/patent_data.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/petition_decisions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/ptab.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/models/utils.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/py.typed +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/utils/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO/warnings.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/requires.txt +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/top_level.txt +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/src/pyUSPTO.egg-info/zip-safe +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_base.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_bulk_data_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_enriched_citation_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_actions_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_citations_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_oa_rejections_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_petition_decision_clients.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_appeals_client.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_interferences_client.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/clients/test_ptab_trials_client.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/conftest.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/conftest.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_bulk_data_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_enriched_citations_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_actions_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_citations_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_oa_rejections_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_petition_decisions_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_appeals_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_interferences_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/integration/test_ptab_trials_integration.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/__init__.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_bulk_data_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_enriched_citation_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_actions_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_citations_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_oa_rejections_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_patent_data_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_petition_decision_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_ptab_models.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/models/test_utils.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_config.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_edge_cases.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_exceptions.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_http_config.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_init.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/test_version.py +0 -0
- {pyuspto-0.5.4 → pyuspto-0.5.6}/tests/utils/__init__.py +0 -0
- {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@
|
|
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@
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
19
|
- name: Set up Python
|
|
20
|
-
uses: actions/setup-python@
|
|
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@
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
20
|
with:
|
|
21
21
|
persist-credentials: false
|
|
22
22
|
- name: Set up Python
|
|
23
|
-
uses: actions/setup-python@
|
|
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@
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
18
|
|
|
19
19
|
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
-
uses: actions/setup-python@
|
|
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@
|
|
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@
|
|
43
|
+
- uses: actions/checkout@v7
|
|
44
44
|
|
|
45
45
|
- name: Set up Python
|
|
46
|
-
uses: actions/setup-python@
|
|
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
|
-
## [
|
|
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.
|
|
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.
|
|
11
|
+
certifi==2026.7.22
|
|
12
12
|
# via requests
|
|
13
|
-
charset-normalizer==3.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
64
|
+
pygments==2.21.0
|
|
65
65
|
# via
|
|
66
66
|
# pytest
|
|
67
67
|
# sphinx
|
|
68
|
-
pytest==9.
|
|
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.
|
|
86
|
+
ruff==0.16.4
|
|
87
87
|
# via pyuspto
|
|
88
|
-
snowballstemmer==3.1.
|
|
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.
|
|
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.
|
|
118
|
+
types-requests==2.33.0.20260712
|
|
119
119
|
# via pyuspto
|
|
120
|
-
typing-extensions==4.
|
|
120
|
+
typing-extensions==4.16.0
|
|
121
121
|
# via
|
|
122
122
|
# mypy
|
|
123
123
|
# pyuspto
|
|
124
|
-
tzdata==2026.
|
|
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.
|
|
7
|
+
certifi==2026.7.22
|
|
8
8
|
# via requests
|
|
9
|
-
charset-normalizer==3.
|
|
9
|
+
charset-normalizer==3.5.1
|
|
10
10
|
# via requests
|
|
11
|
-
idna==3.
|
|
11
|
+
idna==3.19
|
|
12
12
|
# via requests
|
|
13
13
|
requests==2.34.2
|
|
14
14
|
# via pyUSPTO (pyproject.toml)
|
|
15
|
-
tzdata==2026.
|
|
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.
|
|
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
|