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.
Files changed (132) hide show
  1. {pyuspto-0.4.0 → pyuspto-0.4.1}/ADVANCED.md +70 -10
  2. {pyuspto-0.4.0 → pyuspto-0.4.1}/PKG-INFO +60 -93
  3. {pyuspto-0.4.0 → pyuspto-0.4.1}/README.md +59 -92
  4. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/base.py +29 -10
  5. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/patent_data.py +1 -0
  6. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/config.py +1 -0
  7. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/http_config.py +6 -3
  8. pyuspto-0.4.1/src/pyUSPTO/utils/__init__.py +4 -0
  9. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/PKG-INFO +60 -93
  10. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/SOURCES.txt +1 -3
  11. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_base.py +213 -1
  12. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_config.py +10 -0
  13. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_http_config.py +3 -0
  14. {pyuspto-0.4.0 → pyuspto-0.4.1}/tox.ini +5 -1
  15. pyuspto-0.4.0/src/pyUSPTO/utils/__init__.py +0 -11
  16. pyuspto-0.4.0/src/pyUSPTO/utils/http.py +0 -50
  17. pyuspto-0.4.0/tests/utils/test_http.py +0 -73
  18. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  19. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
  21. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  22. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  23. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/dependabot.yml +0 -0
  24. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/publish-docs.yaml +0 -0
  25. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/publish-to-test-pypi.yml +0 -0
  26. {pyuspto-0.4.0 → pyuspto-0.4.1}/.github/workflows/python-tests.yml +0 -0
  27. {pyuspto-0.4.0 → pyuspto-0.4.1}/.gitignore +0 -0
  28. {pyuspto-0.4.0 → pyuspto-0.4.1}/.readthedocs.yaml +0 -0
  29. {pyuspto-0.4.0 → pyuspto-0.4.1}/CHANGELOG.md +0 -0
  30. {pyuspto-0.4.0 → pyuspto-0.4.1}/CODE_OF_CONDUCT.md +0 -0
  31. {pyuspto-0.4.0 → pyuspto-0.4.1}/CONTRIBUTING.md +0 -0
  32. {pyuspto-0.4.0 → pyuspto-0.4.1}/LICENSE +0 -0
  33. {pyuspto-0.4.0 → pyuspto-0.4.1}/_version.pyi +0 -0
  34. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/Makefile +0 -0
  35. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/_static/.gitkeep +0 -0
  36. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/advanced.rst +0 -0
  37. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/bulk_data.rst +0 -0
  38. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/index.rst +0 -0
  39. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/patent_data.rst +0 -0
  40. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/petition_decisions.rst +0 -0
  41. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_appeals.rst +0 -0
  42. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_interferences.rst +0 -0
  43. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/clients/ptab_trials.rst +0 -0
  44. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/config.rst +0 -0
  45. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/http_config.rst +0 -0
  46. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/config/index.rst +0 -0
  47. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/exceptions.rst +0 -0
  48. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/index.rst +0 -0
  49. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/base.rst +0 -0
  50. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/bulk_data.rst +0 -0
  51. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/index.rst +0 -0
  52. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/patent_data.rst +0 -0
  53. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/petition_decisions.rst +0 -0
  54. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/ptab.rst +0 -0
  55. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/models/utils.rst +0 -0
  56. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/api/warnings.rst +0 -0
  57. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/conf.py +0 -0
  58. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/configuration.rst +0 -0
  59. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/development.rst +0 -0
  60. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/bulk_data.rst +0 -0
  61. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ifw_example.rst +0 -0
  62. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/index.rst +0 -0
  63. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/patent_data.rst +0 -0
  64. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/petition_decisions.rst +0 -0
  65. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_appeals.rst +0 -0
  66. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_interferences.rst +0 -0
  67. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/examples/ptab_trials.rst +0 -0
  68. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/index.rst +0 -0
  69. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/installation.rst +0 -0
  70. {pyuspto-0.4.0 → pyuspto-0.4.1}/docs/source/quickstart.rst +0 -0
  71. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/bulk_data_example.py +0 -0
  72. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/error_handling_example.py +0 -0
  73. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ifw_example.py +0 -0
  74. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/patent_data_example.py +0 -0
  75. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/petition_decisions_example.py +0 -0
  76. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_appeals_example.py +0 -0
  77. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_interferences_example.py +0 -0
  78. {pyuspto-0.4.0 → pyuspto-0.4.1}/examples/ptab_trials_example.py +0 -0
  79. {pyuspto-0.4.0 → pyuspto-0.4.1}/pyUSPTO.code-workspace +0 -0
  80. {pyuspto-0.4.0 → pyuspto-0.4.1}/pyproject.toml +0 -0
  81. {pyuspto-0.4.0 → pyuspto-0.4.1}/requirements-dev.txt +0 -0
  82. {pyuspto-0.4.0 → pyuspto-0.4.1}/requirements.txt +0 -0
  83. {pyuspto-0.4.0 → pyuspto-0.4.1}/setup.cfg +0 -0
  84. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/__init__.py +0 -0
  85. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/__init__.py +0 -0
  86. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/bulk_data.py +0 -0
  87. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/petition_decisions.py +0 -0
  88. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_appeals.py +0 -0
  89. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_interferences.py +0 -0
  90. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/clients/ptab_trials.py +0 -0
  91. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/exceptions.py +0 -0
  92. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/__init__.py +0 -0
  93. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/base.py +0 -0
  94. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/bulk_data.py +0 -0
  95. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/patent_data.py +0 -0
  96. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/petition_decisions.py +0 -0
  97. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/ptab.py +0 -0
  98. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/models/utils.py +0 -0
  99. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/py.typed +0 -0
  100. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO/warnings.py +0 -0
  101. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
  102. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/requires.txt +0 -0
  103. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/top_level.txt +0 -0
  104. {pyuspto-0.4.0 → pyuspto-0.4.1}/src/pyUSPTO.egg-info/zip-safe +0 -0
  105. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/__init__.py +0 -0
  106. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/__init__.py +0 -0
  107. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_bulk_data_clients.py +0 -0
  108. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_patent_data_clients.py +0 -0
  109. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_petition_decision_clients.py +0 -0
  110. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_appeals_client.py +0 -0
  111. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_interferences_client.py +0 -0
  112. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/clients/test_ptab_trials_client.py +0 -0
  113. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/conftest.py +0 -0
  114. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/__init__.py +0 -0
  115. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/conftest.py +0 -0
  116. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_bulk_data_integration.py +0 -0
  117. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_patent_data_integration.py +0 -0
  118. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_petition_decisions_integration.py +0 -0
  119. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_appeals_integration.py +0 -0
  120. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_interferences_integration.py +0 -0
  121. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/integration/test_ptab_trials_integration.py +0 -0
  122. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/__init__.py +0 -0
  123. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_bulk_data_models.py +0 -0
  124. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_patent_data_models.py +0 -0
  125. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_petition_decision_models.py +0 -0
  126. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_ptab_models.py +0 -0
  127. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/models/test_utils.py +0 -0
  128. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_edge_cases.py +0 -0
  129. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_exceptions.py +0 -0
  130. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_init.py +0 -0
  131. {pyuspto-0.4.0 → pyuspto-0.4.1}/tests/test_version.py +0 -0
  132. {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
- Configure HTTP settings via environment variables:
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
- | `USPTO_DOWNLOAD_CHUNK_SIZE` | Chunk size in bytes for file downloads | `8192` |
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 | Description | Default |
83
- | -------------------------- | ------------------------------------------ | -------- |
84
- | `USPTO_REQUEST_TIMEOUT` | Read timeout in seconds | `30.0` |
85
- | `USPTO_CONNECT_TIMEOUT` | Connection timeout in seconds | `10.0` |
86
- | `USPTO_MAX_RETRIES` | Maximum number of retry attempts | `3` |
87
- | `USPTO_BACKOFF_FACTOR` | Exponential backoff multiplier for retries | `2.0` |
88
- | `USPTO_POOL_CONNECTIONS` | Number of connection pools to cache | `10` |
89
- | `USPTO_POOL_MAXSIZE` | Maximum connections per pool | `10` |
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.0
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/) will be retired at the end of 2025.
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 for configuration. There are two methods:
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
- ### Method 1: Using USPTOConfig
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
- ### Method 2: Environment Variables (Recommended)
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
- ## API Usage Examples
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 for attributes and methods, making them fully compatible with static type checkers.
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/) will be retired at the end of 2025.
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 for configuration. There are two methods:
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
- ### Method 1: Using USPTOConfig
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
- ### Method 2: Environment Variables (Recommended)
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
- ## API Usage Examples
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 for attributes and methods, making them fully compatible with static type checkers.
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
- if destination:
566
- dest_path = Path(destination)
567
- dest_path.mkdir(parents=True, exist_ok=True)
568
- final_path = dest_path / filename
569
- else:
570
- final_path = Path.cwd() / filename
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 attempted
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(path_obj, remove_archive=True)
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
 
@@ -1005,6 +1005,7 @@ class PatentDataClient(BaseUSPTOClient[PatentDataResponse]):
1005
1005
 
1006
1006
  def get_IFW_metadata(
1007
1007
  self,
1008
+ *,
1008
1009
  application_number: str | None = None,
1009
1010
  publication_number: str | None = None,
1010
1011
  patent_number: str | None = None,
@@ -124,6 +124,7 @@ class USPTOConfig:
124
124
  total=self.http_config.max_retries,
125
125
  backoff_factor=self.http_config.backoff_factor,
126
126
  status_forcelist=self.http_config.retry_status_codes,
127
+ allowed_methods={"GET", "POST"},
127
128
  )
128
129
 
129
130
  # Configure connection pooling