pyUSPTO 0.4.0__tar.gz → 0.4.1__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.4.0 → pyuspto-0.4.1}/ADVANCED.md +70 -10
- {pyuspto-0.4.0 → pyuspto-0.4.1}/PKG-INFO +60 -93
- {pyuspto-0.4.0 → pyuspto-0.4.1}/README.md +59 -92
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/base.py +29 -10
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/patent_data.py +1 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/config.py +1 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/http_config.py +6 -3
- pyuspto-0.4.1/src/pyUSPTO/utils/__init__.py +4 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/PKG-INFO +60 -93
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/SOURCES.txt +1 -3
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_base.py +213 -1
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_config.py +10 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_http_config.py +3 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tox.ini +5 -1
- pyuspto-0.4.0/src/pyUSPTO/utils/__init__.py +0 -11
- pyuspto-0.4.0/src/pyUSPTO/utils/http.py +0 -50
- pyuspto-0.4.0/tests/utils/test_http.py +0 -73
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/dependabot.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/publish-docs.yaml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/publish-to-test-pypi.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/python-tests.yml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.gitignore +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/.readthedocs.yaml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/CHANGELOG.md +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/CODE_OF_CONDUCT.md +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/CONTRIBUTING.md +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/LICENSE +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/_version.pyi +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/Makefile +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/_static/.gitkeep +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/advanced.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/bulk_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/patent_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/petition_decisions.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_appeals.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_interferences.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_trials.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/config.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/http_config.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/exceptions.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/base.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/bulk_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/patent_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/petition_decisions.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/ptab.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/utils.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/warnings.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/conf.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/configuration.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/development.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/bulk_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ifw_example.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/patent_data.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/petition_decisions.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_appeals.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_interferences.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_trials.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/index.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/installation.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/quickstart.rst +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/bulk_data_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/error_handling_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ifw_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/patent_data_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/petition_decisions_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_appeals_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_interferences_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_trials_example.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/pyUSPTO.code-workspace +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/pyproject.toml +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/requirements-dev.txt +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/requirements.txt +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/setup.cfg +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/bulk_data.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/petition_decisions.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_appeals.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_interferences.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_trials.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/exceptions.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/base.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/bulk_data.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/patent_data.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/petition_decisions.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/ptab.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/utils.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/py.typed +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/warnings.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/requires.txt +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/top_level.txt +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/zip-safe +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_bulk_data_clients.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_patent_data_clients.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_petition_decision_clients.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_appeals_client.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_interferences_client.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_trials_client.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/conftest.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/conftest.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_bulk_data_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_patent_data_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_petition_decisions_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_appeals_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_interferences_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_trials_integration.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/__init__.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_bulk_data_models.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_patent_data_models.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_petition_decision_models.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_ptab_models.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_utils.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_edge_cases.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_exceptions.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_init.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_version.py +0 -0
- {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/utils/__init__.py +0 -0
|
@@ -31,7 +31,28 @@ config = USPTOConfig(
|
|
|
31
31
|
client = PatentDataClient(config=config)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
## Session Lifecycle
|
|
35
|
+
|
|
36
|
+
`USPTOConfig` manages an underlying `requests.Session`. For short-lived scripts this is cleaned up automatically, but for long-running applications or tests you may close it explicitly:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from pyUSPTO import PatentDataClient, USPTOConfig
|
|
40
|
+
|
|
41
|
+
# Option 1: Context manager
|
|
42
|
+
with USPTOConfig(api_key="your_key") as config:
|
|
43
|
+
client = PatentDataClient(config=config)
|
|
44
|
+
response = client.search_applications(limit=1)
|
|
45
|
+
|
|
46
|
+
# Option 2: Explicit close
|
|
47
|
+
config = USPTOConfig(api_key="your_key")
|
|
48
|
+
try:
|
|
49
|
+
client = PatentDataClient(config=config)
|
|
50
|
+
response = client.search_applications(limit=1)
|
|
51
|
+
finally:
|
|
52
|
+
config.close()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## HTTP Configuration via Environment Variables
|
|
35
56
|
|
|
36
57
|
```bash
|
|
37
58
|
export USPTO_REQUEST_TIMEOUT=60.0 # Read timeout
|
|
@@ -75,24 +96,32 @@ All clients support configuration via environment variables. This is the recomme
|
|
|
75
96
|
| `USPTO_PATENT_DATA_BASE_URL` | Base URL for Patent Data API | `https://api.uspto.gov` |
|
|
76
97
|
| `USPTO_PETITION_DECISIONS_BASE_URL` | Base URL for Petition Decisions API | `https://api.uspto.gov` |
|
|
77
98
|
| `USPTO_PTAB_BASE_URL` | Base URL for PTAB APIs | `https://api.uspto.gov` |
|
|
78
|
-
|
|
99
|
+
|
|
100
|
+
> [!NOTE]
|
|
101
|
+
> The base URL variables are provided in case the USPTO introduces alternate environments (e.g., a development or testing endpoint) in the future. Currently there are no such endpoints, and these defaults should not be changed.
|
|
79
102
|
|
|
80
103
|
### HTTP Transport Configuration
|
|
81
104
|
|
|
82
|
-
| Environment Variable
|
|
83
|
-
|
|
|
84
|
-
| `USPTO_REQUEST_TIMEOUT`
|
|
85
|
-
| `USPTO_CONNECT_TIMEOUT`
|
|
86
|
-
| `USPTO_MAX_RETRIES`
|
|
87
|
-
| `USPTO_BACKOFF_FACTOR`
|
|
88
|
-
| `USPTO_POOL_CONNECTIONS`
|
|
89
|
-
| `USPTO_POOL_MAXSIZE`
|
|
105
|
+
| Environment Variable | Description | Default |
|
|
106
|
+
| ----------------------------- | ------------------------------------------ | --------------- |
|
|
107
|
+
| `USPTO_REQUEST_TIMEOUT` | Read timeout in seconds | `30.0` |
|
|
108
|
+
| `USPTO_CONNECT_TIMEOUT` | Connection timeout in seconds | `10.0` |
|
|
109
|
+
| `USPTO_MAX_RETRIES` | Maximum number of retry attempts | `3` |
|
|
110
|
+
| `USPTO_BACKOFF_FACTOR` | Exponential backoff multiplier for retries | `2.0` |
|
|
111
|
+
| `USPTO_POOL_CONNECTIONS` | Number of connection pools to cache | `10` |
|
|
112
|
+
| `USPTO_POOL_MAXSIZE` | Maximum connections per pool | `10` |
|
|
113
|
+
| `USPTO_DOWNLOAD_CHUNK_SIZE` | Chunk size in bytes for file downloads | `8192` |
|
|
114
|
+
| `USPTO_MAX_EXTRACT_SIZE` | Maximum bytes to extract from archives | None (no limit) |
|
|
90
115
|
|
|
91
116
|
### Example: Configuration
|
|
92
117
|
|
|
93
118
|
```bash
|
|
94
119
|
# API Configuration
|
|
95
120
|
export USPTO_API_KEY="your_api_key"
|
|
121
|
+
export USPTO_BULK_DATA_BASE_URL="https://api.uspto.gov"
|
|
122
|
+
export USPTO_PATENT_DATA_BASE_URL="https://api.uspto.gov"
|
|
123
|
+
export USPTO_PETITION_DECISIONS_BASE_URL="https://api.uspto.gov"
|
|
124
|
+
export USPTO_PTAB_BASE_URL="https://api.uspto.gov"
|
|
96
125
|
|
|
97
126
|
# Increase timeouts for large downloads
|
|
98
127
|
export USPTO_REQUEST_TIMEOUT=120.0
|
|
@@ -108,6 +137,9 @@ export USPTO_POOL_MAXSIZE=20
|
|
|
108
137
|
|
|
109
138
|
# Larger chunk size for faster downloads
|
|
110
139
|
export USPTO_DOWNLOAD_CHUNK_SIZE=65536
|
|
140
|
+
|
|
141
|
+
# Limit total bytes extracted from archives
|
|
142
|
+
export USPTO_MAX_EXTRACT_SIZE=10737418240
|
|
111
143
|
```
|
|
112
144
|
|
|
113
145
|
## Debugging with Raw Data Preservation
|
|
@@ -212,3 +244,31 @@ warnings.filterwarnings('always', category=USPTODataWarning)
|
|
|
212
244
|
```
|
|
213
245
|
|
|
214
246
|
The library's permissive parsing philosophy returns `None` for fields that cannot be parsed, allowing you to retrieve partial data even when some fields have issues. Warnings inform you when this happens without stopping execution.
|
|
247
|
+
|
|
248
|
+
## Archive Extraction Safety
|
|
249
|
+
|
|
250
|
+
Download methods that accept `extract=True` (e.g., `BulkDataClient.download_file`) automatically extract archive files (tar.gz, zip). The extraction includes the following protections:
|
|
251
|
+
|
|
252
|
+
- **Path traversal protection**: Archive members with paths that resolve outside the extraction directory are rejected.
|
|
253
|
+
- **Size limits**: Set `max_extract_size` on `HTTPConfig` to cap the total bytes extracted, protecting against zip bombs or file system size limitations.
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
from pyUSPTO import USPTOConfig, HTTPConfig, BulkDataClient
|
|
257
|
+
|
|
258
|
+
http_config = HTTPConfig(
|
|
259
|
+
max_extract_size=10 * 1024 * 1024 * 1024 # 10 GB
|
|
260
|
+
)
|
|
261
|
+
config = USPTOConfig(api_key="your_key", http_config=http_config)
|
|
262
|
+
client = BulkDataClient(config=config)
|
|
263
|
+
|
|
264
|
+
# Extraction will raise ValueError if total extracted size exceeds 10 GB
|
|
265
|
+
client.download_file(product_file, destination="/tmp", extract=True)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Or via environment variable:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
export USPTO_MAX_EXTRACT_SIZE=10737418240 # 10 GB
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
By default, `extract` is `False` on `BulkDataClient.download_file` and there is no size limit.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyUSPTO
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
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
|
|
@@ -70,7 +70,7 @@ A Python client library for interacting with the United Stated Patent and Tradem
|
|
|
70
70
|
This package provides clients for interacting with the USPTO Bulk Data API, Patent Data API, Final Petition Decisions API, and PTAB (Patent Trial and Appeal Board) APIs.
|
|
71
71
|
|
|
72
72
|
> [!IMPORTANT]
|
|
73
|
-
> The USPTO is in the process of moving their API. This package is only concerned with the new API. The [old API](https://developer.uspto.gov/)
|
|
73
|
+
> The USPTO is in the process of moving their Developer API. This package is only concerned with the new API. The [old API](https://developer.uspto.gov/) was officially retired at the end of 2025; however, some products have not yet been fully transitioned to the Open Data Portal API. The USPTO expects the remaining products to be transitioned to the Open Data Portal in early 2026.
|
|
74
74
|
|
|
75
75
|
## Quick Start
|
|
76
76
|
|
|
@@ -97,33 +97,12 @@ print(f"Found {results.count} applications")
|
|
|
97
97
|
|
|
98
98
|
## Configuration
|
|
99
99
|
|
|
100
|
-
All clients require a `USPTOConfig` object
|
|
100
|
+
All clients require a `USPTOConfig` object. You can create one from environment variables (recommended) or by passing the API key directly.
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```python
|
|
105
|
-
from pyUSPTO import (
|
|
106
|
-
BulkDataClient,
|
|
107
|
-
PatentDataClient,
|
|
108
|
-
FinalPetitionDecisionsClient,
|
|
109
|
-
PTABTrialsClient,
|
|
110
|
-
PTABAppealsClient,
|
|
111
|
-
PTABInterferencesClient
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
from pyUSPTO.config import USPTOConfig
|
|
115
|
-
|
|
116
|
-
config = USPTOConfig(api_key="your_api_key_here")
|
|
117
|
-
|
|
118
|
-
patent_client = PatentDataClient(config=config)
|
|
119
|
-
bulk_client = BulkDataClient(config=config)
|
|
120
|
-
petition_client = FinalPetitionDecisionsClient(config=config)
|
|
121
|
-
trials_client = PTABTrialsClient(config=config)
|
|
122
|
-
appeals_client = PTABAppealsClient(config=config)
|
|
123
|
-
interferences_client = PTABInterferencesClient(config=config)
|
|
124
|
-
```
|
|
102
|
+
> [!TIP]
|
|
103
|
+
> `USPTOConfig` manages an underlying HTTP session. For long-running applications, use it as a context manager (`with USPTOConfig(...) as config:`) or call `config.close()` when done. See [ADVANCED.md](ADVANCED.md#session-lifecycle) for details.
|
|
125
104
|
|
|
126
|
-
###
|
|
105
|
+
### Environment Variables (Recommended)
|
|
127
106
|
|
|
128
107
|
Set the environment variable in your shell:
|
|
129
108
|
|
|
@@ -140,9 +119,9 @@ from pyUSPTO import (
|
|
|
140
119
|
FinalPetitionDecisionsClient,
|
|
141
120
|
PTABTrialsClient,
|
|
142
121
|
PTABAppealsClient,
|
|
143
|
-
PTABInterferencesClient
|
|
122
|
+
PTABInterferencesClient,
|
|
123
|
+
USPTOConfig,
|
|
144
124
|
)
|
|
145
|
-
from pyUSPTO.config import USPTOConfig
|
|
146
125
|
|
|
147
126
|
# Load configuration from environment
|
|
148
127
|
config = USPTOConfig.from_env()
|
|
@@ -155,7 +134,17 @@ appeals_client = PTABAppealsClient(config=config)
|
|
|
155
134
|
interferences_client = PTABInterferencesClient(config=config)
|
|
156
135
|
```
|
|
157
136
|
|
|
158
|
-
|
|
137
|
+
### Direct API Key
|
|
138
|
+
|
|
139
|
+
Alternatively, you can pass your API key directly when creating the config:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from pyUSPTO import USPTOConfig
|
|
143
|
+
|
|
144
|
+
config = USPTOConfig(api_key="your_api_key_here")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Client Usage Examples
|
|
159
148
|
|
|
160
149
|
> [!TIP]
|
|
161
150
|
> For comprehensive examples with detailed explanations, see the [`examples/`](examples/) directory.
|
|
@@ -163,7 +152,7 @@ interferences_client = PTABInterferencesClient(config=config)
|
|
|
163
152
|
### Patent Data API
|
|
164
153
|
|
|
165
154
|
```python
|
|
166
|
-
from pyUSPTO import PatentDataClient
|
|
155
|
+
from pyUSPTO import PatentDataClient, USPTOConfig
|
|
167
156
|
|
|
168
157
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
169
158
|
client = PatentDataClient(config=config)
|
|
@@ -178,12 +167,47 @@ if app.application_meta_data:
|
|
|
178
167
|
print(f"Title: {app.application_meta_data.invention_title}")
|
|
179
168
|
```
|
|
180
169
|
|
|
170
|
+
`PatentDataClient` also provides convenience methods for common lookups:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
# Look up a patent wrapper by any identifier type (you must use keyword names).
|
|
174
|
+
wrapper = client.get_IFW_metadata(application_number="18/045,436")
|
|
175
|
+
wrapper = client.get_IFW_metadata(patent_number="11,234,567")
|
|
176
|
+
wrapper = client.get_IFW_metadata(publication_number="2023/0012345")
|
|
177
|
+
wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US24/12345")
|
|
178
|
+
|
|
179
|
+
# Look up USPTO status codes
|
|
180
|
+
status_codes = client.get_status_codes()
|
|
181
|
+
```
|
|
182
|
+
|
|
181
183
|
See [`examples/patent_data_example.py`](examples/patent_data_example.py) for detailed examples including downloading documents and publications.
|
|
182
184
|
|
|
185
|
+
### Bulk Data API
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from pyUSPTO import BulkDataClient, USPTOConfig
|
|
189
|
+
|
|
190
|
+
config = USPTOConfig(api_key="your_api_key_here")
|
|
191
|
+
client = BulkDataClient(config=config)
|
|
192
|
+
|
|
193
|
+
# Search for bulk data products
|
|
194
|
+
response = client.search_products(query="patent", limit=5)
|
|
195
|
+
print(f"Found {response.count} products matching 'patent'")
|
|
196
|
+
|
|
197
|
+
for product in response.bulk_data_product_bag:
|
|
198
|
+
print(f" {product.product_title_text} ({product.product_identifier})")
|
|
199
|
+
|
|
200
|
+
# Get a specific product with its files
|
|
201
|
+
product = client.get_product_by_id("PTGRXML", include_files=True, latest=True)
|
|
202
|
+
print(f"Product: {product.product_title_text}")
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
See [`examples/bulk_data_example.py`](examples/bulk_data_example.py) for detailed examples including file downloads and archive extraction.
|
|
206
|
+
|
|
183
207
|
### Final Petition Decisions API
|
|
184
208
|
|
|
185
209
|
```python
|
|
186
|
-
from pyUSPTO import FinalPetitionDecisionsClient
|
|
210
|
+
from pyUSPTO import FinalPetitionDecisionsClient, USPTOConfig
|
|
187
211
|
|
|
188
212
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
189
213
|
client = FinalPetitionDecisionsClient(config=config)
|
|
@@ -207,7 +231,7 @@ See [`examples/petition_decisions_example.py`](examples/petition_decisions_examp
|
|
|
207
231
|
### PTAB Trials API
|
|
208
232
|
|
|
209
233
|
```python
|
|
210
|
-
from pyUSPTO import PTABTrialsClient
|
|
234
|
+
from pyUSPTO import PTABTrialsClient, USPTOConfig
|
|
211
235
|
|
|
212
236
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
213
237
|
client = PTABTrialsClient(config=config)
|
|
@@ -235,7 +259,7 @@ See [`examples/ptab_trials_example.py`](examples/ptab_trials_example.py) for det
|
|
|
235
259
|
### PTAB Appeals API
|
|
236
260
|
|
|
237
261
|
```python
|
|
238
|
-
from pyUSPTO import PTABAppealsClient
|
|
262
|
+
from pyUSPTO import PTABAppealsClient, USPTOConfig
|
|
239
263
|
|
|
240
264
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
241
265
|
client = PTABAppealsClient(config=config)
|
|
@@ -255,7 +279,7 @@ See [`examples/ptab_appeals_example.py`](examples/ptab_appeals_example.py) for d
|
|
|
255
279
|
### PTAB Interferences API
|
|
256
280
|
|
|
257
281
|
```python
|
|
258
|
-
from pyUSPTO import PTABInterferencesClient
|
|
282
|
+
from pyUSPTO import PTABInterferencesClient, USPTOConfig
|
|
259
283
|
|
|
260
284
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
261
285
|
client = PTABInterferencesClient(config=config)
|
|
@@ -276,64 +300,7 @@ Full documentation may be found on [Read the Docs](https://pyuspto.readthedocs.i
|
|
|
276
300
|
|
|
277
301
|
## Data Models
|
|
278
302
|
|
|
279
|
-
The library uses Python dataclasses to represent API responses. All data models include type annotations
|
|
280
|
-
|
|
281
|
-
#### Bulk Data API
|
|
282
|
-
|
|
283
|
-
- `BulkDataResponse`: Top-level response from the API
|
|
284
|
-
- `BulkDataProduct`: Information about a specific product
|
|
285
|
-
- `ProductFileBag`: Container for file data elements
|
|
286
|
-
- `FileData`: Information about an individual file
|
|
287
|
-
|
|
288
|
-
#### Patent Data API
|
|
289
|
-
|
|
290
|
-
- `PatentDataResponse`: Top-level response from the API
|
|
291
|
-
- `PatentFileWrapper`: Information about a patent application
|
|
292
|
-
- `ApplicationMetaData`: Metadata about a patent application
|
|
293
|
-
- `Person`, `Applicant`, `Inventor`, `Attorney`: Person-related data classes
|
|
294
|
-
- `Assignment`, `Assignor`, `Assignee`: Assignment-related data classes
|
|
295
|
-
- `Continuity`, `ParentContinuity`, `ChildContinuity`: Continuity-related data classes
|
|
296
|
-
- `PatentTermAdjustmentData`: Patent term adjustment information
|
|
297
|
-
- `DocumentBag`, `EntityStatus`, `RecordAttorney`: Additional data classes for patent data
|
|
298
|
-
- And many more specialized classes for different aspects of patent data
|
|
299
|
-
|
|
300
|
-
#### Final Petition Decisions API
|
|
301
|
-
|
|
302
|
-
- `PetitionDecisionResponse`: Top-level response from the API
|
|
303
|
-
- `PetitionDecision`: Complete information about a petition decision
|
|
304
|
-
- `PetitionDecisionDocument`: Document associated with a petition decision
|
|
305
|
-
- `DecisionTypeCode`: Enum for petition decision types
|
|
306
|
-
- `DocumentDirectionCategory`: Enum for document direction categories
|
|
307
|
-
|
|
308
|
-
#### PTAB Trials API
|
|
309
|
-
|
|
310
|
-
- `PTABTrialProceedingResponse`: Top-level response from the API
|
|
311
|
-
- `PTABTrialProceeding`: Information about a PTAB trial proceeding (IPR, PGR, CBM, DER)
|
|
312
|
-
- `PTABTrialDocumentResponse`: Response containing trial documents
|
|
313
|
-
- `PTABTrialDocument`: Document associated with a trial proceeding
|
|
314
|
-
- `TrialDecisionData`: Decision information for a trial proceeding
|
|
315
|
-
- `TrialDocumentData`: Document metadata for trial documents
|
|
316
|
-
- `TrialMetaData`: Trial metadata and status information
|
|
317
|
-
- `RegularPetitionerData`, `RespondentData`, `DerivationPetitionerData`: Party data for different trial types
|
|
318
|
-
|
|
319
|
-
#### PTAB Appeals API
|
|
320
|
-
|
|
321
|
-
- `PTABAppealResponse`: Top-level response from the API
|
|
322
|
-
- `PTABAppealDecision`: Ex parte appeal decision information
|
|
323
|
-
- `AppellantData`: Appellant information and application details
|
|
324
|
-
- `AppealMetaData`: Appeal metadata and filing information
|
|
325
|
-
- `AppealDocumentData`: Document and decision details
|
|
326
|
-
|
|
327
|
-
#### PTAB Interferences API
|
|
328
|
-
|
|
329
|
-
- `PTABInterferenceResponse`: Top-level response from the API
|
|
330
|
-
- `PTABInterferenceDecision`: Interference proceeding decision information
|
|
331
|
-
- `SeniorPartyData`, `JuniorPartyData`, `AdditionalPartyData`: Party data classes
|
|
332
|
-
- `InterferenceMetaData`: Interference metadata and status information
|
|
333
|
-
- `InterferenceDocumentData`: Document and outcome details
|
|
334
|
-
- `DecisionData`: Decision information for interference proceedings
|
|
335
|
-
|
|
336
|
-
For a complete list of all data models, see the [API Reference docuentation](https://pyuspto.readthedocs.io/en/latest/api/models/index.html).
|
|
303
|
+
The library uses Python dataclasses to represent API responses. All data models include type annotations and are fully compatible with static type checkers. For a complete list of all data models, see the [API Reference documentation](https://pyuspto.readthedocs.io/en/latest/api/models/index.html).
|
|
337
304
|
|
|
338
305
|
## Advanced Topics
|
|
339
306
|
|
|
@@ -10,7 +10,7 @@ A Python client library for interacting with the United Stated Patent and Tradem
|
|
|
10
10
|
This package provides clients for interacting with the USPTO Bulk Data API, Patent Data API, Final Petition Decisions API, and PTAB (Patent Trial and Appeal Board) APIs.
|
|
11
11
|
|
|
12
12
|
> [!IMPORTANT]
|
|
13
|
-
> The USPTO is in the process of moving their API. This package is only concerned with the new API. The [old API](https://developer.uspto.gov/)
|
|
13
|
+
> The USPTO is in the process of moving their Developer API. This package is only concerned with the new API. The [old API](https://developer.uspto.gov/) was officially retired at the end of 2025; however, some products have not yet been fully transitioned to the Open Data Portal API. The USPTO expects the remaining products to be transitioned to the Open Data Portal in early 2026.
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
@@ -37,33 +37,12 @@ print(f"Found {results.count} applications")
|
|
|
37
37
|
|
|
38
38
|
## Configuration
|
|
39
39
|
|
|
40
|
-
All clients require a `USPTOConfig` object
|
|
40
|
+
All clients require a `USPTOConfig` object. You can create one from environment variables (recommended) or by passing the API key directly.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
from pyUSPTO import (
|
|
46
|
-
BulkDataClient,
|
|
47
|
-
PatentDataClient,
|
|
48
|
-
FinalPetitionDecisionsClient,
|
|
49
|
-
PTABTrialsClient,
|
|
50
|
-
PTABAppealsClient,
|
|
51
|
-
PTABInterferencesClient
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
from pyUSPTO.config import USPTOConfig
|
|
55
|
-
|
|
56
|
-
config = USPTOConfig(api_key="your_api_key_here")
|
|
57
|
-
|
|
58
|
-
patent_client = PatentDataClient(config=config)
|
|
59
|
-
bulk_client = BulkDataClient(config=config)
|
|
60
|
-
petition_client = FinalPetitionDecisionsClient(config=config)
|
|
61
|
-
trials_client = PTABTrialsClient(config=config)
|
|
62
|
-
appeals_client = PTABAppealsClient(config=config)
|
|
63
|
-
interferences_client = PTABInterferencesClient(config=config)
|
|
64
|
-
```
|
|
42
|
+
> [!TIP]
|
|
43
|
+
> `USPTOConfig` manages an underlying HTTP session. For long-running applications, use it as a context manager (`with USPTOConfig(...) as config:`) or call `config.close()` when done. See [ADVANCED.md](ADVANCED.md#session-lifecycle) for details.
|
|
65
44
|
|
|
66
|
-
###
|
|
45
|
+
### Environment Variables (Recommended)
|
|
67
46
|
|
|
68
47
|
Set the environment variable in your shell:
|
|
69
48
|
|
|
@@ -80,9 +59,9 @@ from pyUSPTO import (
|
|
|
80
59
|
FinalPetitionDecisionsClient,
|
|
81
60
|
PTABTrialsClient,
|
|
82
61
|
PTABAppealsClient,
|
|
83
|
-
PTABInterferencesClient
|
|
62
|
+
PTABInterferencesClient,
|
|
63
|
+
USPTOConfig,
|
|
84
64
|
)
|
|
85
|
-
from pyUSPTO.config import USPTOConfig
|
|
86
65
|
|
|
87
66
|
# Load configuration from environment
|
|
88
67
|
config = USPTOConfig.from_env()
|
|
@@ -95,7 +74,17 @@ appeals_client = PTABAppealsClient(config=config)
|
|
|
95
74
|
interferences_client = PTABInterferencesClient(config=config)
|
|
96
75
|
```
|
|
97
76
|
|
|
98
|
-
|
|
77
|
+
### Direct API Key
|
|
78
|
+
|
|
79
|
+
Alternatively, you can pass your API key directly when creating the config:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from pyUSPTO import USPTOConfig
|
|
83
|
+
|
|
84
|
+
config = USPTOConfig(api_key="your_api_key_here")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Client Usage Examples
|
|
99
88
|
|
|
100
89
|
> [!TIP]
|
|
101
90
|
> For comprehensive examples with detailed explanations, see the [`examples/`](examples/) directory.
|
|
@@ -103,7 +92,7 @@ interferences_client = PTABInterferencesClient(config=config)
|
|
|
103
92
|
### Patent Data API
|
|
104
93
|
|
|
105
94
|
```python
|
|
106
|
-
from pyUSPTO import PatentDataClient
|
|
95
|
+
from pyUSPTO import PatentDataClient, USPTOConfig
|
|
107
96
|
|
|
108
97
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
109
98
|
client = PatentDataClient(config=config)
|
|
@@ -118,12 +107,47 @@ if app.application_meta_data:
|
|
|
118
107
|
print(f"Title: {app.application_meta_data.invention_title}")
|
|
119
108
|
```
|
|
120
109
|
|
|
110
|
+
`PatentDataClient` also provides convenience methods for common lookups:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Look up a patent wrapper by any identifier type (you must use keyword names).
|
|
114
|
+
wrapper = client.get_IFW_metadata(application_number="18/045,436")
|
|
115
|
+
wrapper = client.get_IFW_metadata(patent_number="11,234,567")
|
|
116
|
+
wrapper = client.get_IFW_metadata(publication_number="2023/0012345")
|
|
117
|
+
wrapper = client.get_IFW_metadata(PCT_app_number="PCT/US24/12345")
|
|
118
|
+
|
|
119
|
+
# Look up USPTO status codes
|
|
120
|
+
status_codes = client.get_status_codes()
|
|
121
|
+
```
|
|
122
|
+
|
|
121
123
|
See [`examples/patent_data_example.py`](examples/patent_data_example.py) for detailed examples including downloading documents and publications.
|
|
122
124
|
|
|
125
|
+
### Bulk Data API
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from pyUSPTO import BulkDataClient, USPTOConfig
|
|
129
|
+
|
|
130
|
+
config = USPTOConfig(api_key="your_api_key_here")
|
|
131
|
+
client = BulkDataClient(config=config)
|
|
132
|
+
|
|
133
|
+
# Search for bulk data products
|
|
134
|
+
response = client.search_products(query="patent", limit=5)
|
|
135
|
+
print(f"Found {response.count} products matching 'patent'")
|
|
136
|
+
|
|
137
|
+
for product in response.bulk_data_product_bag:
|
|
138
|
+
print(f" {product.product_title_text} ({product.product_identifier})")
|
|
139
|
+
|
|
140
|
+
# Get a specific product with its files
|
|
141
|
+
product = client.get_product_by_id("PTGRXML", include_files=True, latest=True)
|
|
142
|
+
print(f"Product: {product.product_title_text}")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [`examples/bulk_data_example.py`](examples/bulk_data_example.py) for detailed examples including file downloads and archive extraction.
|
|
146
|
+
|
|
123
147
|
### Final Petition Decisions API
|
|
124
148
|
|
|
125
149
|
```python
|
|
126
|
-
from pyUSPTO import FinalPetitionDecisionsClient
|
|
150
|
+
from pyUSPTO import FinalPetitionDecisionsClient, USPTOConfig
|
|
127
151
|
|
|
128
152
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
129
153
|
client = FinalPetitionDecisionsClient(config=config)
|
|
@@ -147,7 +171,7 @@ See [`examples/petition_decisions_example.py`](examples/petition_decisions_examp
|
|
|
147
171
|
### PTAB Trials API
|
|
148
172
|
|
|
149
173
|
```python
|
|
150
|
-
from pyUSPTO import PTABTrialsClient
|
|
174
|
+
from pyUSPTO import PTABTrialsClient, USPTOConfig
|
|
151
175
|
|
|
152
176
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
153
177
|
client = PTABTrialsClient(config=config)
|
|
@@ -175,7 +199,7 @@ See [`examples/ptab_trials_example.py`](examples/ptab_trials_example.py) for det
|
|
|
175
199
|
### PTAB Appeals API
|
|
176
200
|
|
|
177
201
|
```python
|
|
178
|
-
from pyUSPTO import PTABAppealsClient
|
|
202
|
+
from pyUSPTO import PTABAppealsClient, USPTOConfig
|
|
179
203
|
|
|
180
204
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
181
205
|
client = PTABAppealsClient(config=config)
|
|
@@ -195,7 +219,7 @@ See [`examples/ptab_appeals_example.py`](examples/ptab_appeals_example.py) for d
|
|
|
195
219
|
### PTAB Interferences API
|
|
196
220
|
|
|
197
221
|
```python
|
|
198
|
-
from pyUSPTO import PTABInterferencesClient
|
|
222
|
+
from pyUSPTO import PTABInterferencesClient, USPTOConfig
|
|
199
223
|
|
|
200
224
|
config = USPTOConfig(api_key="your_api_key_here")
|
|
201
225
|
client = PTABInterferencesClient(config=config)
|
|
@@ -216,64 +240,7 @@ Full documentation may be found on [Read the Docs](https://pyuspto.readthedocs.i
|
|
|
216
240
|
|
|
217
241
|
## Data Models
|
|
218
242
|
|
|
219
|
-
The library uses Python dataclasses to represent API responses. All data models include type annotations
|
|
220
|
-
|
|
221
|
-
#### Bulk Data API
|
|
222
|
-
|
|
223
|
-
- `BulkDataResponse`: Top-level response from the API
|
|
224
|
-
- `BulkDataProduct`: Information about a specific product
|
|
225
|
-
- `ProductFileBag`: Container for file data elements
|
|
226
|
-
- `FileData`: Information about an individual file
|
|
227
|
-
|
|
228
|
-
#### Patent Data API
|
|
229
|
-
|
|
230
|
-
- `PatentDataResponse`: Top-level response from the API
|
|
231
|
-
- `PatentFileWrapper`: Information about a patent application
|
|
232
|
-
- `ApplicationMetaData`: Metadata about a patent application
|
|
233
|
-
- `Person`, `Applicant`, `Inventor`, `Attorney`: Person-related data classes
|
|
234
|
-
- `Assignment`, `Assignor`, `Assignee`: Assignment-related data classes
|
|
235
|
-
- `Continuity`, `ParentContinuity`, `ChildContinuity`: Continuity-related data classes
|
|
236
|
-
- `PatentTermAdjustmentData`: Patent term adjustment information
|
|
237
|
-
- `DocumentBag`, `EntityStatus`, `RecordAttorney`: Additional data classes for patent data
|
|
238
|
-
- And many more specialized classes for different aspects of patent data
|
|
239
|
-
|
|
240
|
-
#### Final Petition Decisions API
|
|
241
|
-
|
|
242
|
-
- `PetitionDecisionResponse`: Top-level response from the API
|
|
243
|
-
- `PetitionDecision`: Complete information about a petition decision
|
|
244
|
-
- `PetitionDecisionDocument`: Document associated with a petition decision
|
|
245
|
-
- `DecisionTypeCode`: Enum for petition decision types
|
|
246
|
-
- `DocumentDirectionCategory`: Enum for document direction categories
|
|
247
|
-
|
|
248
|
-
#### PTAB Trials API
|
|
249
|
-
|
|
250
|
-
- `PTABTrialProceedingResponse`: Top-level response from the API
|
|
251
|
-
- `PTABTrialProceeding`: Information about a PTAB trial proceeding (IPR, PGR, CBM, DER)
|
|
252
|
-
- `PTABTrialDocumentResponse`: Response containing trial documents
|
|
253
|
-
- `PTABTrialDocument`: Document associated with a trial proceeding
|
|
254
|
-
- `TrialDecisionData`: Decision information for a trial proceeding
|
|
255
|
-
- `TrialDocumentData`: Document metadata for trial documents
|
|
256
|
-
- `TrialMetaData`: Trial metadata and status information
|
|
257
|
-
- `RegularPetitionerData`, `RespondentData`, `DerivationPetitionerData`: Party data for different trial types
|
|
258
|
-
|
|
259
|
-
#### PTAB Appeals API
|
|
260
|
-
|
|
261
|
-
- `PTABAppealResponse`: Top-level response from the API
|
|
262
|
-
- `PTABAppealDecision`: Ex parte appeal decision information
|
|
263
|
-
- `AppellantData`: Appellant information and application details
|
|
264
|
-
- `AppealMetaData`: Appeal metadata and filing information
|
|
265
|
-
- `AppealDocumentData`: Document and decision details
|
|
266
|
-
|
|
267
|
-
#### PTAB Interferences API
|
|
268
|
-
|
|
269
|
-
- `PTABInterferenceResponse`: Top-level response from the API
|
|
270
|
-
- `PTABInterferenceDecision`: Interference proceeding decision information
|
|
271
|
-
- `SeniorPartyData`, `JuniorPartyData`, `AdditionalPartyData`: Party data classes
|
|
272
|
-
- `InterferenceMetaData`: Interference metadata and status information
|
|
273
|
-
- `InterferenceDocumentData`: Document and outcome details
|
|
274
|
-
- `DecisionData`: Decision information for interference proceedings
|
|
275
|
-
|
|
276
|
-
For a complete list of all data models, see the [API Reference docuentation](https://pyuspto.readthedocs.io/en/latest/api/models/index.html).
|
|
243
|
+
The library uses Python dataclasses to represent API responses. All data models include type annotations and are fully compatible with static type checkers. For a complete list of all data models, see the [API Reference documentation](https://pyuspto.readthedocs.io/en/latest/api/models/index.html).
|
|
277
244
|
|
|
278
245
|
## Advanced Topics
|
|
279
246
|
|
|
@@ -562,12 +562,18 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
562
562
|
else:
|
|
563
563
|
filename = "download"
|
|
564
564
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
else
|
|
570
|
-
|
|
565
|
+
filename = Path(filename).name
|
|
566
|
+
if not filename or filename in (".", ".."):
|
|
567
|
+
filename = "download"
|
|
568
|
+
|
|
569
|
+
dest_path = Path(destination) if destination else Path.cwd()
|
|
570
|
+
dest_path.mkdir(parents=True, exist_ok=True)
|
|
571
|
+
final_path = dest_path / filename
|
|
572
|
+
|
|
573
|
+
if not self._is_safe_path(dest_path, final_path):
|
|
574
|
+
raise ValueError(
|
|
575
|
+
f"Filename {filename!r} resolves outside destination directory"
|
|
576
|
+
)
|
|
571
577
|
|
|
572
578
|
if final_path.exists() and not overwrite:
|
|
573
579
|
raise FileExistsError(f"File exists: {final_path}. Use overwrite=True")
|
|
@@ -642,9 +648,11 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
642
648
|
with tarfile.open(archive_path, "r:*") as tar:
|
|
643
649
|
# Extract members one by one with validation
|
|
644
650
|
for member in tar.getmembers():
|
|
645
|
-
# Skip directories
|
|
651
|
+
# Skip directories and symlinks
|
|
646
652
|
if member.isdir():
|
|
647
653
|
continue
|
|
654
|
+
if member.issym() or member.islnk():
|
|
655
|
+
continue
|
|
648
656
|
|
|
649
657
|
# Path traversal check
|
|
650
658
|
member_path = extract_to / member.name
|
|
@@ -670,9 +678,11 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
670
678
|
with zipfile.ZipFile(archive_path, "r") as zip_ref:
|
|
671
679
|
# Extract members one by one with validation
|
|
672
680
|
for zip_info in zip_ref.infolist():
|
|
673
|
-
# Skip directories
|
|
681
|
+
# Skip directories and symlinks
|
|
674
682
|
if zip_info.is_dir():
|
|
675
683
|
continue
|
|
684
|
+
if (zip_info.external_attr >> 16) & 0o170000 == 0o120000:
|
|
685
|
+
continue
|
|
676
686
|
|
|
677
687
|
# Path traversal check
|
|
678
688
|
member_path = extract_to / zip_info.filename
|
|
@@ -714,6 +724,10 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
714
724
|
) -> str:
|
|
715
725
|
"""Download file and auto-extract if it's an archive.
|
|
716
726
|
|
|
727
|
+
Archives are extracted with path traversal protection. Extraction size
|
|
728
|
+
can be limited via ``http_config.max_extract_size`` to guard against
|
|
729
|
+
zip bombs.
|
|
730
|
+
|
|
717
731
|
Args:
|
|
718
732
|
url: URL to download
|
|
719
733
|
destination: Directory to save/extract to
|
|
@@ -726,7 +740,8 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
726
740
|
Raises:
|
|
727
741
|
TypeError: If response is not a valid Response object
|
|
728
742
|
FileExistsError: If file exists and overwrite is False
|
|
729
|
-
ValueError: If downloaded file is not a valid archive when extraction
|
|
743
|
+
ValueError: If downloaded file is not a valid archive when extraction
|
|
744
|
+
attempted, or if extraction exceeds max_extract_size
|
|
730
745
|
"""
|
|
731
746
|
import tarfile
|
|
732
747
|
import zipfile
|
|
@@ -743,7 +758,11 @@ class BaseUSPTOClient(Generic[T]):
|
|
|
743
758
|
)
|
|
744
759
|
|
|
745
760
|
if is_archive:
|
|
746
|
-
return self._extract_archive(
|
|
761
|
+
return self._extract_archive(
|
|
762
|
+
path_obj,
|
|
763
|
+
remove_archive=True,
|
|
764
|
+
max_size=self.http_config.max_extract_size,
|
|
765
|
+
)
|
|
747
766
|
else:
|
|
748
767
|
return downloaded_path
|
|
749
768
|
|