pyUSPTO 0.6.0__tar.gz → 0.6.2__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.6.0 → pyuspto-0.6.2}/.github/workflows/publish-docs.yaml +1 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/workflows/python-tests.yml +1 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2}/CHANGELOG.md +33 -1
- {pyuspto-0.6.0/src/pyUSPTO.egg-info → pyuspto-0.6.2}/PKG-INFO +1 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/error_handling_example.py +2 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2}/requirements-dev.txt +12 -12
- {pyuspto-0.6.0 → pyuspto-0.6.2}/requirements.txt +2 -2
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/base.py +18 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/bulk_data.py +8 -4
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/enriched_citations.py +32 -35
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/oa_actions.py +26 -27
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/oa_citations.py +36 -31
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/oa_rejections.py +25 -25
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/patent_data.py +121 -335
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/petition_decisions.py +78 -97
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/ptab_appeals.py +34 -38
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/ptab_interferences.py +67 -49
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/ptab_trials.py +93 -109
- pyuspto-0.6.2/src/pyUSPTO/clients/query.py +288 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/exceptions.py +17 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2/src/pyUSPTO.egg-info}/PKG-INFO +1 -1
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/SOURCES.txt +2 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/scm_file_list.json +2 -0
- pyuspto-0.6.2/src/pyUSPTO.egg-info/scm_version.json +8 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_base.py +19 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_bulk_data_clients.py +56 -2
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_enriched_citation_clients.py +28 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_oa_actions_clients.py +63 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_oa_citations_clients.py +32 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_oa_rejections_clients.py +32 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_patent_data_clients.py +108 -8
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_petition_decision_clients.py +65 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_ptab_appeals_client.py +3 -3
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_ptab_interferences_client.py +9 -3
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/test_ptab_trials_client.py +5 -5
- pyuspto-0.6.2/tests/clients/test_query.py +148 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_enriched_citations_integration.py +26 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_oa_actions_integration.py +14 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_oa_citations_integration.py +13 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_oa_rejections_integration.py +13 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_patent_data_integration.py +83 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_petition_decisions_integration.py +13 -0
- pyuspto-0.6.2/tests/integration/test_ptab_appeals_integration.py +448 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_ptab_interferences_integration.py +14 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_ptab_trials_integration.py +14 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_exceptions.py +42 -0
- pyuspto-0.6.0/src/pyUSPTO.egg-info/scm_version.json +0 -8
- pyuspto-0.6.0/tests/integration/test_ptab_appeals_integration.py +0 -522
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.devcontainer/devcontainer-lock.json +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.devcontainer/devcontainer.json +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/dependabot.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/workflows/codeql.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.github/workflows/publish-to-test-pypi.yml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.gitignore +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/.readthedocs.yaml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/ADVANCED.md +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/CODE_OF_CONDUCT.md +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/CONTRIBUTING.md +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/LICENSE +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/README.md +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/_version.pyi +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/Makefile +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/_static/.gitkeep +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/about.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/advanced.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/bulk_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/enriched_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/oa_actions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/oa_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/oa_rejections.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/patent_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/petition_decisions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/ptab_appeals.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/ptab_interferences.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/clients/ptab_trials.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/config/config.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/config/http_config.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/config/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/exceptions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/base.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/bulk_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/enriched_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/oa_actions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/oa_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/oa_rejections.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/patent_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/petition_decisions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/ptab.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/models/utils.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/api/warnings.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/conf.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/configuration.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/development.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/bulk_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/enriched_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/ifw_example.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/oa_actions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/oa_citations.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/oa_rejections.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/patent_data.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/petition_decisions.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/ptab_appeals.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/ptab_interferences.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/examples/ptab_trials.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/index.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/installation.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/docs/source/quickstart.rst +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/bulk_data_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/enriched_citations_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/ifw_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/oa_actions_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/oa_citations_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/oa_rejections_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/patent_data_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/petition_decisions_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/ptab_appeals_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/ptab_interferences_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/examples/ptab_trials_example.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/pyUSPTO.code-workspace +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/pyproject.toml +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/setup.cfg +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/clients/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/config.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/http_config.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/base.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/bulk_data.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/enriched_citations.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/oa_actions.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/oa_citations.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/oa_rejections.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/patent_data.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/petition_decisions.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/ptab.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/models/utils.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/py.typed +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/utils/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO/warnings.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/requires.txt +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/top_level.txt +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/src/pyUSPTO.egg-info/zip-safe +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/clients/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/conftest.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/conftest.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/integration/test_bulk_data_integration.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_bulk_data_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_enriched_citation_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_oa_actions_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_oa_citations_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_oa_rejections_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_patent_data_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_petition_decision_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_ptab_models.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/models/test_utils.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_config.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_edge_cases.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_http_config.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_init.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/test_version.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tests/utils/__init__.py +0 -0
- {pyuspto-0.6.0 → pyuspto-0.6.2}/tox.ini +0 -0
|
@@ -5,7 +5,39 @@ 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
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `sanitize_application_number` now returns series-code input as 8 digits (`18/511,739` → `18511739`). Previously it kept the slash, so `get_application_by_number` and the other per-application methods requested `.../applications/18/511739`, which the API rejects with HTTP 403. This fixes every method that takes an application number, including `get_IFW_metadata(application_number=...)` and `get_IFW(application_number=...)`.
|
|
13
|
+
- A 403 response with the body `{"message":"Missing Authentication Token"}` now adds to its exception message that USPTO also returns this body when the requested URL path does not exist. It is still raised as `USPTOApiAuthError`.
|
|
14
|
+
- `error_handling_example.py` notes that a "Missing Authentication Token" error can also mean a bad URL path.
|
|
15
|
+
- Every client builds its convenience filters with one shared module, `pyUSPTO.clients.query`. `PTABTrialsClient` and `PTABInterferencesClient` no longer quote a single-word text value. Live, `trialStatusCategory:Instituted` and `trialStatusCategory:"Instituted"` both return 220 proceedings. `PTABInterferencesClient` also wraps each party-name filter's `OR` group in parentheses, which returned the same records as before in live checks.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- `application_number_q` (used by `search_applications` and `get_search_results`) now goes through `sanitize_application_number`, so `14/412875`, `14/412,875`, and `14412875` all match, and `PCT/US2025/047756` is sent as `PCTUS2025047756`. Previously the value was sent verbatim and `14/412875` matched nothing. Values containing `*`, and values the sanitizer rejects (such as range or `OR` expressions), are not sanitized.
|
|
20
|
+
- `application_number_q` values that are not a single application number (wildcards, `OR` and range expressions) are now sent inside parentheses, so the field applies to every term. Previously it applied only to the first term: `14412875 OR 10000000` searched `10000000` as free text and returned 3 applications instead of 1.
|
|
21
|
+
- The application-number filters on the other clients get the same cleanup as `application_number_q`, including the parentheses above: `PetitionDecisionsClient` (`application_number_q`), `PTABAppealsClient` (`application_number_text_q`), `PTABInterferencesClient` (`senior_party_application_number_q`, `junior_party_application_number_q`), `PTABTrialsClient.search_decisions` (`application_number_q`), and `patent_application_number_q` on `OAActionsClient`, `OACitationsClient`, `OARejectionsClient`, and `EnrichedCitationsClient`. Previously `17/765301` matched nothing in any of them, and `17/765,301` matched nothing in the office action and enriched citation APIs.
|
|
22
|
+
- Text filters (names, titles, categories, classifications) are quoted when the value contains whitespace or one of `+ - & | ! ( ) { } [ ] ^ " ~ : \ /`, and double quotes and backslashes inside the quotes are escaped. A single plain word, including one with a `*` or `?` wildcard, is sent unquoted. A wildcard value that also contains one of those characters (`Garcia-Lopez*`) is quoted, so its wildcard is searched as plain text. Live, quoted `"Garcia-Lopez*"` returns the same 119 applications as `"Garcia-Lopez"`, and the unquoted form, sent before this change, returned HTTP 404. Before, the filters that quoted at all did so only for a space (or, for `classification_q`, a slash), so `assignee_name_q="Smith-Kline"` was sent unquoted, and an inner quote broke the phrase: `inventor_name_q='Smith "John'` matched nothing and now matches. Applies to the convenience filters of every search client.
|
|
23
|
+
- Code filters (such as `patent_number_q`) send a value containing spaces inside parentheses, so the field applies to every term. `patent_number_q="10000000 OR 10000001"` returned 3 applications and now returns 2. Applies to the convenience filters of every search client.
|
|
24
|
+
- `PTABAppealsClient` `appellant_name_q`, `requestor_name_q`, and `decision_type_category_q` were never quoted and are now quoted under the rule above. A multi-word value searched every word after the first as free text: `appellant_name_q="Block, Inc."` returned 4303 decisions from 2025 instead of 1.
|
|
25
|
+
- The office action and enriched citation category filters are code filters under the rule above: `OAActionsClient` `access_level_category_q` and `application_type_category_q`, `action_type_category_q` on `OACitationsClient` and `OARejectionsClient`, and `EnrichedCitationsClient` `office_action_category_q`. Their values are single-word codes (`PUBLIC`, `REGULAR`, `rejected`, `CTNF`), so `office_action_category_q="CTNF OR CTFR"` is sent as `officeActionCategory:(CTNF OR CTFR)`, and the `OR` now applies to the field.
|
|
26
|
+
- `customer_number_q=[]` and `status_code_q=[]` raise `ValueError` instead of sending the malformed clause `field:()`. Dropping the filter instead would have run the search unfiltered.
|
|
27
|
+
- `OAActionsClient` `group_art_unit_number_q=""` adds no filter. It sent `groupArtUnitNumber:`.
|
|
28
|
+
- `PetitionDecisionsClient.get_decision_by_id`, `BulkDataClient.get_product_by_id`, and `BulkDataClient.download_file` (when the file has no download URI) now percent-encode the ID or file name in the URL path. Previously a `?` or `/` in the value changed the request; `get_decision_by_id("abc?x")` requested decision `abc`. A non-string ID, such as a `uuid.UUID`, still works as it did before.
|
|
29
|
+
- `PTABTrialsClient.search_decisions(document_type_description_q=...)` escapes double quotes and backslashes in the value. A `"` in the value closed the quoted search early and broke the query.
|
|
30
|
+
- `BulkDataClient.download_file(file_name=...)` uses `file_name` only as the local save name. When the file had no download URI, it also requested `file_name` from the server instead of the real file, so `download_file(file_data, file_name="custom.zip")` asked for `.../custom.zip`.
|
|
31
|
+
|
|
32
|
+
## [0.6.1] - 2026-10-27
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- `requirements.txt` pins `certifi` 2026.10.23 (was 2026.7.22).
|
|
37
|
+
- The lint job (ruff, mypy) and the docs workflow run on Python 3.15 (was 3.14).
|
|
38
|
+
- Development dependency updates: certifi 2026.10.23, coverage 7.17.0, pluggy 1.7.0, pytest 9.2.0, pytest-mock 3.17.0, ruff 0.17.3, sphinx 9.2.0, sphinx-autodoc-typehints 3.17.4, sphinxcontrib-jsmath 2.0.0.
|
|
39
|
+
|
|
40
|
+
## [0.6.0] - 2026-10-27
|
|
9
41
|
|
|
10
42
|
### Added
|
|
11
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyUSPTO
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
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
|
|
@@ -32,6 +32,7 @@ try:
|
|
|
32
32
|
except USPTOApiAuthError as e:
|
|
33
33
|
print(f"Authentication failed: {e}")
|
|
34
34
|
print("Check your API key and try again.")
|
|
35
|
+
print("A 'Missing Authentication Token' message can also mean a bad URL path.")
|
|
35
36
|
|
|
36
37
|
print("-" * 40)
|
|
37
38
|
print("Example 2: Not found errors")
|
|
@@ -95,7 +96,7 @@ try:
|
|
|
95
96
|
except USPTOApiRateLimitError:
|
|
96
97
|
print("Rate limited - wait and retry")
|
|
97
98
|
except USPTOApiAuthError:
|
|
98
|
-
print("Authentication failed - check API key")
|
|
99
|
+
print("Authentication failed - check API key or URL path")
|
|
99
100
|
except USPTOTimeout:
|
|
100
101
|
print("Request timed out - try again")
|
|
101
102
|
except USPTOConnectionError:
|
|
@@ -10,7 +10,7 @@ ast-serialize==0.13.1
|
|
|
10
10
|
# via mypy
|
|
11
11
|
babel==2.18.0
|
|
12
12
|
# via sphinx
|
|
13
|
-
certifi==2026.
|
|
13
|
+
certifi==2026.10.23
|
|
14
14
|
# via requests
|
|
15
15
|
charset-normalizer==3.5.2
|
|
16
16
|
# via requests
|
|
@@ -18,7 +18,7 @@ colorama==0.4.6
|
|
|
18
18
|
# via
|
|
19
19
|
# pytest
|
|
20
20
|
# sphinx
|
|
21
|
-
coverage==7.
|
|
21
|
+
coverage==7.17.0
|
|
22
22
|
# via pytest-cov
|
|
23
23
|
docutils==0.22.4
|
|
24
24
|
# via
|
|
@@ -47,7 +47,7 @@ mdit-py-plugins==0.6.1
|
|
|
47
47
|
# via myst-parser
|
|
48
48
|
mdurl==0.1.2
|
|
49
49
|
# via markdown-it-py
|
|
50
|
-
mypy==2.4.
|
|
50
|
+
mypy==2.4.1
|
|
51
51
|
# via pyUSPTO (pyproject.toml)
|
|
52
52
|
mypy-extensions==1.1.0
|
|
53
53
|
# via mypy
|
|
@@ -59,7 +59,7 @@ packaging==26.3
|
|
|
59
59
|
# sphinx
|
|
60
60
|
pathspec==1.1.1
|
|
61
61
|
# via mypy
|
|
62
|
-
pluggy==1.
|
|
62
|
+
pluggy==1.7.0
|
|
63
63
|
# via
|
|
64
64
|
# pytest
|
|
65
65
|
# pytest-cov
|
|
@@ -67,14 +67,14 @@ pygments==2.21.0
|
|
|
67
67
|
# via
|
|
68
68
|
# pytest
|
|
69
69
|
# sphinx
|
|
70
|
-
pytest==9.
|
|
70
|
+
pytest==9.2.0
|
|
71
71
|
# via
|
|
72
72
|
# pyUSPTO (pyproject.toml)
|
|
73
73
|
# pytest-cov
|
|
74
74
|
# pytest-mock
|
|
75
75
|
pytest-cov==7.1.0
|
|
76
76
|
# via pyUSPTO (pyproject.toml)
|
|
77
|
-
pytest-mock==3.
|
|
77
|
+
pytest-mock==3.17.0
|
|
78
78
|
# via pyUSPTO (pyproject.toml)
|
|
79
79
|
pyyaml==6.0.3
|
|
80
80
|
# via myst-parser
|
|
@@ -84,11 +84,11 @@ requests==2.34.2
|
|
|
84
84
|
# sphinx
|
|
85
85
|
roman-numerals==4.1.0
|
|
86
86
|
# via sphinx
|
|
87
|
-
ruff==0.17.
|
|
87
|
+
ruff==0.17.3
|
|
88
88
|
# via pyUSPTO (pyproject.toml)
|
|
89
89
|
snowballstemmer==3.1.1
|
|
90
90
|
# via sphinx
|
|
91
|
-
sphinx==9.
|
|
91
|
+
sphinx==9.2.0
|
|
92
92
|
# via
|
|
93
93
|
# myst-parser
|
|
94
94
|
# pyUSPTO (pyproject.toml)
|
|
@@ -96,7 +96,7 @@ sphinx==9.1.0
|
|
|
96
96
|
# sphinx-copybutton
|
|
97
97
|
# sphinx-rtd-theme
|
|
98
98
|
# sphinxcontrib-jquery
|
|
99
|
-
sphinx-autodoc-typehints==3.
|
|
99
|
+
sphinx-autodoc-typehints==3.17.4
|
|
100
100
|
# via pyUSPTO (pyproject.toml)
|
|
101
101
|
sphinx-copybutton==0.5.2
|
|
102
102
|
# via pyUSPTO (pyproject.toml)
|
|
@@ -110,17 +110,17 @@ sphinxcontrib-htmlhelp==2.1.0
|
|
|
110
110
|
# via sphinx
|
|
111
111
|
sphinxcontrib-jquery==4.1
|
|
112
112
|
# via sphinx-rtd-theme
|
|
113
|
-
sphinxcontrib-jsmath==
|
|
113
|
+
sphinxcontrib-jsmath==2.0.0
|
|
114
114
|
# via sphinx
|
|
115
115
|
sphinxcontrib-qthelp==2.0.0
|
|
116
116
|
# via sphinx
|
|
117
117
|
sphinxcontrib-serializinghtml==2.0.0
|
|
118
118
|
# via sphinx
|
|
119
|
-
types-requests==2.33.0.
|
|
119
|
+
types-requests==2.33.0.20261030
|
|
120
120
|
# via pyUSPTO (pyproject.toml)
|
|
121
121
|
typing-extensions==4.16.0
|
|
122
122
|
# via mypy
|
|
123
|
-
tzdata==2026.
|
|
123
|
+
tzdata==2026.6
|
|
124
124
|
# via pyUSPTO (pyproject.toml)
|
|
125
125
|
urllib3==2.8.0
|
|
126
126
|
# via
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#
|
|
5
5
|
# pip-compile --output-file=requirements.txt --strip-extras pyproject.toml
|
|
6
6
|
#
|
|
7
|
-
certifi==2026.
|
|
7
|
+
certifi==2026.10.23
|
|
8
8
|
# via requests
|
|
9
9
|
charset-normalizer==3.5.2
|
|
10
10
|
# via requests
|
|
@@ -12,7 +12,7 @@ idna==3.20
|
|
|
12
12
|
# via requests
|
|
13
13
|
requests==2.34.2
|
|
14
14
|
# via pyUSPTO (pyproject.toml)
|
|
15
|
-
tzdata==2026.
|
|
15
|
+
tzdata==2026.6
|
|
16
16
|
# via pyUSPTO (pyproject.toml)
|
|
17
17
|
urllib3==2.8.0
|
|
18
18
|
# via
|
|
@@ -14,6 +14,7 @@ from typing import (
|
|
|
14
14
|
TypeVar,
|
|
15
15
|
runtime_checkable,
|
|
16
16
|
)
|
|
17
|
+
from urllib.parse import quote
|
|
17
18
|
|
|
18
19
|
import requests
|
|
19
20
|
|
|
@@ -196,6 +197,23 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
196
197
|
base = custom_base_url if custom_base_url else self.base_url
|
|
197
198
|
return f"{base}/{endpoint.lstrip('/')}"
|
|
198
199
|
|
|
200
|
+
@staticmethod
|
|
201
|
+
def _quote_path_value(value: object) -> str:
|
|
202
|
+
"""Percent-encode a caller value for use as one URL path segment.
|
|
203
|
+
|
|
204
|
+
Every reserved character is encoded, including ``/``, ``?``, and
|
|
205
|
+
``#``, so the value cannot add path segments, a query string, or a
|
|
206
|
+
fragment to the request. A non-string value, such as a ``uuid.UUID``,
|
|
207
|
+
is formatted with ``str()`` first.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
value: The raw value, such as a record ID or file name.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
The encoded value.
|
|
214
|
+
"""
|
|
215
|
+
return quote(str(value), safe="")
|
|
216
|
+
|
|
199
217
|
def _execute_request(
|
|
200
218
|
self,
|
|
201
219
|
method: str,
|
|
@@ -92,7 +92,9 @@ class BulkDataClient(BaseUSPTOClient[BulkDataResponse]):
|
|
|
92
92
|
... latest=True
|
|
93
93
|
... )
|
|
94
94
|
"""
|
|
95
|
-
endpoint = self.ENDPOINTS["product_by_id"].format(
|
|
95
|
+
endpoint = self.ENDPOINTS["product_by_id"].format(
|
|
96
|
+
product_id=self._quote_path_value(product_id)
|
|
97
|
+
)
|
|
96
98
|
|
|
97
99
|
params = {}
|
|
98
100
|
if file_data_from_date:
|
|
@@ -147,7 +149,9 @@ class BulkDataClient(BaseUSPTOClient[BulkDataResponse]):
|
|
|
147
149
|
Args:
|
|
148
150
|
file_data: FileData object containing download info and product_identifier.
|
|
149
151
|
destination: Directory to save/extract to. Defaults to current directory.
|
|
150
|
-
file_name:
|
|
152
|
+
file_name: Name to save the file under locally. Defaults to
|
|
153
|
+
file_data.file_name. The download always requests
|
|
154
|
+
file_data.file_name from the server.
|
|
151
155
|
overwrite: Whether to overwrite existing files. Defaults to False.
|
|
152
156
|
extract: Whether to auto-extract archives. Defaults to False.
|
|
153
157
|
|
|
@@ -171,8 +175,8 @@ class BulkDataClient(BaseUSPTOClient[BulkDataResponse]):
|
|
|
171
175
|
download_url = file_data.file_download_uri
|
|
172
176
|
else:
|
|
173
177
|
endpoint = self.ENDPOINTS["download_file"].format(
|
|
174
|
-
productIdentifier=file_data.product_identifier,
|
|
175
|
-
fileName=
|
|
178
|
+
productIdentifier=self._quote_path_value(file_data.product_identifier),
|
|
179
|
+
fileName=self._quote_path_value(file_data.file_name),
|
|
176
180
|
)
|
|
177
181
|
download_url = f"{self.base_url}/{endpoint}"
|
|
178
182
|
|
|
@@ -9,6 +9,14 @@ from collections.abc import Iterator
|
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
11
|
from pyUSPTO.clients.base import BaseUSPTOClient
|
|
12
|
+
from pyUSPTO.clients.query import (
|
|
13
|
+
all_of,
|
|
14
|
+
application_number,
|
|
15
|
+
boolean,
|
|
16
|
+
date_range,
|
|
17
|
+
phrase,
|
|
18
|
+
term,
|
|
19
|
+
)
|
|
12
20
|
from pyUSPTO.config import USPTOConfig
|
|
13
21
|
from pyUSPTO.models.enriched_citations import (
|
|
14
22
|
EnrichedCitation,
|
|
@@ -84,6 +92,12 @@ class EnrichedCitationsClient(BaseUSPTOClient[EnrichedCitationResponse]):
|
|
|
84
92
|
You can provide either a direct post_body, a query string, or use convenience
|
|
85
93
|
parameters that will be automatically combined into a query.
|
|
86
94
|
|
|
95
|
+
``cited_document_identifier_q`` is quoted when it contains spaces or
|
|
96
|
+
special characters, with inner quotes escaped. The code filters
|
|
97
|
+
(office action and citation category codes, tech centers, art units)
|
|
98
|
+
wrap a value that contains spaces, such as ``"CTNF OR CTFR"``, in
|
|
99
|
+
parentheses, so the field applies to every term.
|
|
100
|
+
|
|
87
101
|
Args:
|
|
88
102
|
query: Direct query string in USPTO search syntax.
|
|
89
103
|
sort: Sort order for results.
|
|
@@ -92,6 +106,8 @@ class EnrichedCitationsClient(BaseUSPTOClient[EnrichedCitationResponse]):
|
|
|
92
106
|
post_body: Optional POST body for complex queries. When provided,
|
|
93
107
|
all other parameters are ignored.
|
|
94
108
|
patent_application_number_q: Filter by patent application number.
|
|
109
|
+
Any common form matches (``17/765,301``, ``17765301``). Write
|
|
110
|
+
each number in an ``OR`` or range expression as 8 digits.
|
|
95
111
|
cited_document_identifier_q: Filter by cited document identifier.
|
|
96
112
|
office_action_category_q: Filter by office action category (e.g., "CTNF").
|
|
97
113
|
citation_category_code_q: Filter by citation category code (e.g., "X", "Y").
|
|
@@ -141,41 +157,22 @@ class EnrichedCitationsClient(BaseUSPTOClient[EnrichedCitationResponse]):
|
|
|
141
157
|
# Build query from convenience parameters
|
|
142
158
|
final_q = query
|
|
143
159
|
if final_q is None:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if group_art_unit_number_q:
|
|
161
|
-
q_parts.append(f"groupArtUnitNumber:{group_art_unit_number_q}")
|
|
162
|
-
if examiner_cited_q is not None:
|
|
163
|
-
q_parts.append(
|
|
164
|
-
f"examinerCitedReferenceIndicator:{str(examiner_cited_q).lower()}"
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
# Handle office action date range
|
|
168
|
-
if office_action_date_from_q and office_action_date_to_q:
|
|
169
|
-
q_parts.append(
|
|
170
|
-
f"officeActionDate:[{office_action_date_from_q} TO {office_action_date_to_q}]"
|
|
171
|
-
)
|
|
172
|
-
elif office_action_date_from_q:
|
|
173
|
-
q_parts.append(f"officeActionDate:>={office_action_date_from_q}")
|
|
174
|
-
elif office_action_date_to_q:
|
|
175
|
-
q_parts.append(f"officeActionDate:<={office_action_date_to_q}")
|
|
176
|
-
|
|
177
|
-
if q_parts:
|
|
178
|
-
final_q = " AND ".join(q_parts)
|
|
160
|
+
final_q = all_of(
|
|
161
|
+
application_number(
|
|
162
|
+
"patentApplicationNumber", patent_application_number_q
|
|
163
|
+
),
|
|
164
|
+
phrase("citedDocumentIdentifier", cited_document_identifier_q),
|
|
165
|
+
term("officeActionCategory", office_action_category_q),
|
|
166
|
+
term("citationCategoryCode", citation_category_code_q),
|
|
167
|
+
term("techCenter", tech_center_q),
|
|
168
|
+
term("groupArtUnitNumber", group_art_unit_number_q),
|
|
169
|
+
boolean("examinerCitedReferenceIndicator", examiner_cited_q),
|
|
170
|
+
date_range(
|
|
171
|
+
"officeActionDate",
|
|
172
|
+
office_action_date_from_q,
|
|
173
|
+
office_action_date_to_q,
|
|
174
|
+
),
|
|
175
|
+
)
|
|
179
176
|
|
|
180
177
|
if final_q is not None:
|
|
181
178
|
body["criteria"] = final_q
|
|
@@ -10,6 +10,12 @@ from collections.abc import Iterator
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from pyUSPTO.clients.base import BaseUSPTOClient
|
|
13
|
+
from pyUSPTO.clients.query import (
|
|
14
|
+
all_of,
|
|
15
|
+
application_number,
|
|
16
|
+
date_range,
|
|
17
|
+
term,
|
|
18
|
+
)
|
|
13
19
|
from pyUSPTO.config import USPTOConfig
|
|
14
20
|
from pyUSPTO.models.oa_actions import (
|
|
15
21
|
OAActionsFieldsResponse,
|
|
@@ -77,6 +83,11 @@ class OAActionsClient(BaseUSPTOClient[OAActionsResponse]):
|
|
|
77
83
|
office action documents. You can provide either a direct post_body,
|
|
78
84
|
a criteria string, or use convenience parameters.
|
|
79
85
|
|
|
86
|
+
Every convenience filter is a code filter (document codes, categories,
|
|
87
|
+
tech centers, art units). A value that contains spaces, such as
|
|
88
|
+
``"rejected OR objected"``, is wrapped in parentheses, so the field
|
|
89
|
+
applies to every term.
|
|
90
|
+
|
|
80
91
|
Args:
|
|
81
92
|
criteria: Direct Solr query string (e.g., ``"patentApplicationNumber:14485382"``).
|
|
82
93
|
sort: Sort order for results (e.g., ``"submissionDate desc"``).
|
|
@@ -85,6 +96,8 @@ class OAActionsClient(BaseUSPTOClient[OAActionsResponse]):
|
|
|
85
96
|
post_body: Optional POST body dict for complex queries. When provided,
|
|
86
97
|
all other parameters are ignored.
|
|
87
98
|
patent_application_number_q: Filter by patent application number.
|
|
99
|
+
Any common form matches (``17/765,301``, ``17765301``). Write
|
|
100
|
+
each number in an ``OR`` or range expression as 8 digits.
|
|
88
101
|
legacy_document_code_identifier_q: Filter by document code (e.g., ``"CTNF"``, ``"NOA"``).
|
|
89
102
|
group_art_unit_number_q: Filter by group art unit number.
|
|
90
103
|
tech_center_q: Filter by technology center code.
|
|
@@ -132,33 +145,19 @@ class OAActionsClient(BaseUSPTOClient[OAActionsResponse]):
|
|
|
132
145
|
# Build criteria from convenience parameters
|
|
133
146
|
final_criteria = criteria
|
|
134
147
|
if final_criteria is None:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if application_type_category_q:
|
|
149
|
-
q_parts.append(f"applicationTypeCategory:{application_type_category_q}")
|
|
150
|
-
|
|
151
|
-
if submission_date_from_q and submission_date_to_q:
|
|
152
|
-
q_parts.append(
|
|
153
|
-
f"submissionDate:[{submission_date_from_q} TO {submission_date_to_q}]"
|
|
154
|
-
)
|
|
155
|
-
elif submission_date_from_q:
|
|
156
|
-
q_parts.append(f"submissionDate:>={submission_date_from_q}")
|
|
157
|
-
elif submission_date_to_q:
|
|
158
|
-
q_parts.append(f"submissionDate:<={submission_date_to_q}")
|
|
159
|
-
|
|
160
|
-
if q_parts:
|
|
161
|
-
final_criteria = " AND ".join(q_parts)
|
|
148
|
+
final_criteria = all_of(
|
|
149
|
+
application_number(
|
|
150
|
+
"patentApplicationNumber", patent_application_number_q
|
|
151
|
+
),
|
|
152
|
+
term("legacyDocumentCodeIdentifier", legacy_document_code_identifier_q),
|
|
153
|
+
term("groupArtUnitNumber", group_art_unit_number_q),
|
|
154
|
+
term("techCenter", tech_center_q),
|
|
155
|
+
term("accessLevelCategory", access_level_category_q),
|
|
156
|
+
term("applicationTypeCategory", application_type_category_q),
|
|
157
|
+
date_range(
|
|
158
|
+
"submissionDate", submission_date_from_q, submission_date_to_q
|
|
159
|
+
),
|
|
160
|
+
)
|
|
162
161
|
|
|
163
162
|
if final_criteria is not None:
|
|
164
163
|
body["criteria"] = final_criteria
|
|
@@ -10,6 +10,14 @@ from collections.abc import Iterator
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from pyUSPTO.clients.base import BaseUSPTOClient
|
|
13
|
+
from pyUSPTO.clients.query import (
|
|
14
|
+
all_of,
|
|
15
|
+
application_number,
|
|
16
|
+
boolean,
|
|
17
|
+
contains,
|
|
18
|
+
date_range,
|
|
19
|
+
term,
|
|
20
|
+
)
|
|
13
21
|
from pyUSPTO.config import USPTOConfig
|
|
14
22
|
from pyUSPTO.models.oa_citations import (
|
|
15
23
|
OACitationRecord,
|
|
@@ -79,6 +87,11 @@ class OACitationsClient(BaseUSPTOClient[OACitationsResponse]):
|
|
|
79
87
|
Office Action citation records. You can provide either a direct post_body,
|
|
80
88
|
a criteria string, or use convenience parameters.
|
|
81
89
|
|
|
90
|
+
Every convenience filter is a code filter (document codes, categories,
|
|
91
|
+
tech centers, art units). A value that contains spaces, such as
|
|
92
|
+
``"rejected OR objected"``, is wrapped in parentheses, so the field
|
|
93
|
+
applies to every term.
|
|
94
|
+
|
|
82
95
|
Args:
|
|
83
96
|
criteria: Direct Solr query string (e.g., ``"patentApplicationNumber:16845502"``).
|
|
84
97
|
sort: Sort order for results (e.g., ``"createDateTime desc"``).
|
|
@@ -87,6 +100,8 @@ class OACitationsClient(BaseUSPTOClient[OACitationsResponse]):
|
|
|
87
100
|
post_body: Optional POST body dict for complex queries. When provided,
|
|
88
101
|
all other parameters are ignored.
|
|
89
102
|
patent_application_number_q: Filter by patent application number.
|
|
103
|
+
Any common form matches (``17/765,301``, ``17765301``). Write
|
|
104
|
+
each number in an ``OR`` or range expression as 8 digits.
|
|
90
105
|
legal_section_code_q: Filter by legal section code (e.g., ``"101"``, ``"103"``).
|
|
91
106
|
action_type_category_q: Filter by action type (e.g., ``"rejected"``).
|
|
92
107
|
tech_center_q: Filter by technology center code.
|
|
@@ -137,37 +152,27 @@ class OACitationsClient(BaseUSPTOClient[OACitationsResponse]):
|
|
|
137
152
|
# Build criteria from convenience parameters
|
|
138
153
|
final_criteria = criteria
|
|
139
154
|
if final_criteria is None:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
q_parts.append(
|
|
162
|
-
f"createDateTime:[{create_date_time_from_q} TO {create_date_time_to_q}]"
|
|
163
|
-
)
|
|
164
|
-
elif create_date_time_from_q:
|
|
165
|
-
q_parts.append(f"createDateTime:>={create_date_time_from_q}")
|
|
166
|
-
elif create_date_time_to_q:
|
|
167
|
-
q_parts.append(f"createDateTime:<={create_date_time_to_q}")
|
|
168
|
-
|
|
169
|
-
if q_parts:
|
|
170
|
-
final_criteria = " AND ".join(q_parts)
|
|
155
|
+
final_criteria = all_of(
|
|
156
|
+
application_number(
|
|
157
|
+
"patentApplicationNumber", patent_application_number_q
|
|
158
|
+
),
|
|
159
|
+
contains("legalSectionCode", legal_section_code_q),
|
|
160
|
+
term("actionTypeCategory", action_type_category_q),
|
|
161
|
+
term("techCenter", tech_center_q),
|
|
162
|
+
term("workGroup", work_group_q),
|
|
163
|
+
term("groupArtUnitNumber", group_art_unit_number_q),
|
|
164
|
+
boolean(
|
|
165
|
+
"examinerCitedReferenceIndicator",
|
|
166
|
+
examiner_cited_reference_indicator_q,
|
|
167
|
+
),
|
|
168
|
+
boolean(
|
|
169
|
+
"applicantCitedExaminerReferenceIndicator",
|
|
170
|
+
applicant_cited_examiner_reference_indicator_q,
|
|
171
|
+
),
|
|
172
|
+
date_range(
|
|
173
|
+
"createDateTime", create_date_time_from_q, create_date_time_to_q
|
|
174
|
+
),
|
|
175
|
+
)
|
|
171
176
|
|
|
172
177
|
if final_criteria is not None:
|
|
173
178
|
body["criteria"] = final_criteria
|
|
@@ -10,6 +10,12 @@ from collections.abc import Iterator
|
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
12
|
from pyUSPTO.clients.base import BaseUSPTOClient
|
|
13
|
+
from pyUSPTO.clients.query import (
|
|
14
|
+
all_of,
|
|
15
|
+
application_number,
|
|
16
|
+
date_range,
|
|
17
|
+
term,
|
|
18
|
+
)
|
|
13
19
|
from pyUSPTO.config import USPTOConfig
|
|
14
20
|
from pyUSPTO.models.oa_rejections import (
|
|
15
21
|
OARejectionsFieldsResponse,
|
|
@@ -76,6 +82,11 @@ class OARejectionsClient(BaseUSPTOClient[OARejectionsResponse]):
|
|
|
76
82
|
office action rejection records. You can provide either a direct
|
|
77
83
|
post_body, a criteria string, or use convenience parameters.
|
|
78
84
|
|
|
85
|
+
Every convenience filter is a code filter (document codes, categories,
|
|
86
|
+
tech centers, art units). A value that contains spaces, such as
|
|
87
|
+
``"rejected OR objected"``, is wrapped in parentheses, so the field
|
|
88
|
+
applies to every term.
|
|
89
|
+
|
|
79
90
|
Args:
|
|
80
91
|
criteria: Direct Solr query string (e.g., ``"patentApplicationNumber:12190351"``).
|
|
81
92
|
sort: Sort order for results (e.g., ``"submissionDate desc"``).
|
|
@@ -84,6 +95,8 @@ class OARejectionsClient(BaseUSPTOClient[OARejectionsResponse]):
|
|
|
84
95
|
post_body: Optional POST body dict for complex queries. When provided,
|
|
85
96
|
all other parameters are ignored.
|
|
86
97
|
patent_application_number_q: Filter by patent application number.
|
|
98
|
+
Any common form matches (``17/765,301``, ``17765301``). Write
|
|
99
|
+
each number in an ``OR`` or range expression as 8 digits.
|
|
87
100
|
legacy_document_code_identifier_q: Filter by document code (e.g., ``"CTNF"``).
|
|
88
101
|
group_art_unit_number_q: Filter by group art unit number.
|
|
89
102
|
legal_section_code_q: Filter by legal section code.
|
|
@@ -130,31 +143,18 @@ class OARejectionsClient(BaseUSPTOClient[OARejectionsResponse]):
|
|
|
130
143
|
# Build criteria from convenience parameters
|
|
131
144
|
final_criteria = criteria
|
|
132
145
|
if final_criteria is None:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
q_parts.append(f"actionTypeCategory:{action_type_category_q}")
|
|
146
|
-
|
|
147
|
-
if submission_date_from_q and submission_date_to_q:
|
|
148
|
-
q_parts.append(
|
|
149
|
-
f"submissionDate:[{submission_date_from_q} TO {submission_date_to_q}]"
|
|
150
|
-
)
|
|
151
|
-
elif submission_date_from_q:
|
|
152
|
-
q_parts.append(f"submissionDate:>={submission_date_from_q}")
|
|
153
|
-
elif submission_date_to_q:
|
|
154
|
-
q_parts.append(f"submissionDate:<={submission_date_to_q}")
|
|
155
|
-
|
|
156
|
-
if q_parts:
|
|
157
|
-
final_criteria = " AND ".join(q_parts)
|
|
146
|
+
final_criteria = all_of(
|
|
147
|
+
application_number(
|
|
148
|
+
"patentApplicationNumber", patent_application_number_q
|
|
149
|
+
),
|
|
150
|
+
term("legacyDocumentCodeIdentifier", legacy_document_code_identifier_q),
|
|
151
|
+
term("groupArtUnitNumber", group_art_unit_number_q),
|
|
152
|
+
term("legalSectionCode", legal_section_code_q),
|
|
153
|
+
term("actionTypeCategory", action_type_category_q),
|
|
154
|
+
date_range(
|
|
155
|
+
"submissionDate", submission_date_from_q, submission_date_to_q
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
158
|
|
|
159
159
|
if final_criteria is not None:
|
|
160
160
|
body["criteria"] = final_criteria
|