Skip to content
Merged

Wip #84

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a956f20
docs: fix model names and add missing warning category
dpieski Jan 12, 2026
6fb41aa
Fix pypi typo
dpieski Jan 12, 2026
0b1eb4e
Update docstring
dpieski Jan 12, 2026
243526d
refactor: centralize session management in USPTOConfig
dpieski Jan 12, 2026
cc1d51a
Update tests to check config lifecycle
dpieski Jan 12, 2026
56d0b52
update documentation of include_raw_data
dpieski Jan 12, 2026
6e170fc
fix: prevent path traversal in archive extraction
dpieski Jan 14, 2026
f81de3b
Update docstrings
dpieski Feb 23, 2026
a862a95
docs: fix model names and add missing warning category
dpieski Jan 12, 2026
5ef2a3b
Fix pypi typo
dpieski Jan 12, 2026
7eb39b8
Update docstring
dpieski Jan 12, 2026
70a3a95
refactor: centralize session management in USPTOConfig
dpieski Jan 12, 2026
2415021
Update tests to check config lifecycle
dpieski Jan 12, 2026
78892a3
update documentation of include_raw_data
dpieski Jan 12, 2026
57e5e3f
fix: prevent path traversal in archive extraction
dpieski Jan 14, 2026
cad3742
Update docstrings
dpieski Feb 23, 2026
d31d827
Merge branch 'wip' of https://github.com/DunlapCoddingPC/pyUSPTO into…
dpieski Feb 23, 2026
5fd243b
Update docstring
dpieski Jan 12, 2026
745576c
Merge branch 'wip' of https://github.com/DunlapCoddingPC/pyUSPTO into…
dpieski Feb 23, 2026
f9c1e30
document that extraction shouldnt be default
dpieski Feb 23, 2026
0d64e3c
Fix #79
dpieski Feb 23, 2026
8783e4b
fix: change FileData.file_date to datetime type
dpieski Feb 23, 2026
0b3dacc
Merge branch 'main' into wip
dpieski Feb 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ADVANCED.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ if response.raw_data:
- Raw data is stored in the `raw_data` attribute of response objects
- This increases memory usage as both parsed and raw data are kept
- Only enable when needed for debugging - disable for better performance
- All response models support `raw_data` when this flag is enabled
- Response models support `raw_data` when this flag is enabled (except StatusCodeSearchResponse)

**Example: Debugging a missing field**

Expand Down Expand Up @@ -180,6 +180,7 @@ All warnings inherit from `USPTODataWarning`:
- `USPTOBooleanParseWarning`: Y/N boolean string parsing failures
- `USPTOTimezoneWarning`: Timezone-related issues
- `USPTOEnumParseWarning`: Enum value parsing failures
- `USPTODataMismatchWarning`: API returns data with different identifier than requested

**Controlling Warnings**

Expand All @@ -190,7 +191,8 @@ from pyUSPTO.warnings import (
USPTODateParseWarning,
USPTOBooleanParseWarning,
USPTOTimezoneWarning,
USPTOEnumParseWarning
USPTOEnumParseWarning,
USPTODataMismatchWarning
)

# Suppress all pyUSPTO data warnings
Expand Down
71 changes: 29 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ pip install pyUSPTO
> You must have an API key for the [USPTO Open Data Portal API](https://data.uspto.gov/myodp/landing).

```python
from pyUSPTO import PatentDataClient
from pyUSPTO import PatentDataClient, USPTOConfig

# Initialize with your API key
client = PatentDataClient(api_key="your_api_key_here")
# Initialize with config
config = USPTOConfig(api_key="your_api_key_here")
client = PatentDataClient(config=config)

# Search for patent applications
results = client.search_applications(inventor_name_q="Smith", limit=10)
Expand All @@ -36,32 +37,9 @@ print(f"Found {results.count} applications")

## Configuration

All clients can be configured using one of three methods:

### Method 1: Direct API Key Initialization

> [!NOTE]
> This method is convenient for quick scripts but not recommended. Consider using environment variables instead.

```python
from pyUSPTO import (
BulkDataClient,
PatentDataClient,
FinalPetitionDecisionsClient,
PTABTrialsClient,
PTABAppealsClient,
PTABInterferencesClient
)

patent_client = PatentDataClient(api_key="your_api_key_here")
bulk_client = BulkDataClient(api_key="your_api_key_here")
petition_client = FinalPetitionDecisionsClient(api_key="your_api_key_here")
trials_client = PTABTrialsClient(api_key="your_api_key_here")
appeals_client = PTABAppealsClient(api_key="your_api_key_here")
interferences_client = PTABInterferencesClient(api_key="your_api_key_here")
```
All clients require a `USPTOConfig` object for configuration. There are two methods:

### Method 2: Using USPTOConfig
### Method 1: Using USPTOConfig

```python
from pyUSPTO import (
Expand All @@ -85,7 +63,7 @@ appeals_client = PTABAppealsClient(config=config)
interferences_client = PTABInterferencesClient(config=config)
```

### Method 3: Environment Variables (Recommended)
### Method 2: Environment Variables (Recommended)

Set the environment variable in your shell:

Expand Down Expand Up @@ -127,7 +105,8 @@ interferences_client = PTABInterferencesClient(config=config)
```python
from pyUSPTO import PatentDataClient

client = PatentDataClient(api_key="your_api_key_here")
config = USPTOConfig(api_key="your_api_key_here")
client = PatentDataClient(config=config)

# Search for applications by inventor name
response = client.search_applications(inventor_name_q="Smith", limit=2)
Expand All @@ -146,7 +125,8 @@ See [`examples/patent_data_example.py`](examples/patent_data_example.py) for det
```python
from pyUSPTO import FinalPetitionDecisionsClient

client = FinalPetitionDecisionsClient(api_key="your_api_key_here")
config = USPTOConfig(api_key="your_api_key_here")
client = FinalPetitionDecisionsClient(config=config)

# Search for petition decisions
response = client.search_decisions(
Expand All @@ -169,7 +149,8 @@ See [`examples/petition_decisions_example.py`](examples/petition_decisions_examp
```python
from pyUSPTO import PTABTrialsClient

client = PTABTrialsClient(api_key="your_api_key_here")
config = USPTOConfig(api_key="your_api_key_here")
client = PTABTrialsClient(config=config)

# Search for IPR proceedings
response = client.search_proceedings(
Expand All @@ -196,7 +177,8 @@ See [`examples/ptab_trials_example.py`](examples/ptab_trials_example.py) for det
```python
from pyUSPTO import PTABAppealsClient

client = PTABAppealsClient(api_key="your_api_key_here")
config = USPTOConfig(api_key="your_api_key_here")
client = PTABAppealsClient(config=config)

# Search for appeal decisions
response = client.search_decisions(
Expand All @@ -215,7 +197,8 @@ See [`examples/ptab_appeals_example.py`](examples/ptab_appeals_example.py) for d
```python
from pyUSPTO import PTABInterferencesClient

client = PTABInterferencesClient(api_key="your_api_key_here")
config = USPTOConfig(api_key="your_api_key_here")
client = PTABInterferencesClient(config=config)

# Search for interference decisions
response = client.search_decisions(
Expand Down Expand Up @@ -247,46 +230,50 @@ The library uses Python dataclasses to represent API responses. All data models
- `PatentDataResponse`: Top-level response from the API
- `PatentFileWrapper`: Information about a patent application
- `ApplicationMetaData`: Metadata about a patent application
- `Address`: Represents an address in the patent data
- `Person`, `Applicant`, `Inventor`, `Attorney`: Person-related data classes
- `Assignment`, `Assignor`, `Assignee`: Assignment-related data classes
- `Continuity`, `ParentContinuity`, `ChildContinuity`: Continuity-related data classes
- `PatentTermAdjustmentData`: Patent term adjustment information
- `DocumentBag`, `EntityStatus`, `RecordAttorney`: Additional data classes for patent data
- And many more specialized classes for different aspects of patent data

#### Final Petition Decisions API

- `PetitionDecisionResponse`: Top-level response from the API
- `PetitionDecision`: Complete information about a petition decision
- `PetitionDecisionDocument`: Document associated with a petition decision
- `DocumentDownloadOption`: Download options for petition documents
- `DecisionTypeCode`: Enum for petition decision types
- `DocumentDirectionCategory`: Enum for document direction categories

#### PTAB Trials API

- `PTABTrialProceedingResponse`: Top-level response from the API
- `PTABTrialProceeding`: Information about a PTAB trial proceeding (IPR, PGR, CBM, DER)
- `PTABTrialDocumentResponse`: Response containing trial documents
- `PTABTrialDocument`: Document associated with a trial proceeding
- `PTABTrialDecision`: Decision information for a trial proceeding
- `TrialDecisionData`: Decision information for a trial proceeding
- `TrialDocumentData`: Document metadata for trial documents
- `TrialMetaData`: Trial metadata and status information
- `RegularPetitionerData`, `RespondentData`, `DerivationPetitionerData`: Party data for different trial types
- `PTABTrialMetaData`: Trial metadata and status information

#### PTAB Appeals API

- `PTABAppealResponse`: Top-level response from the API
- `PTABAppealDecision`: Ex parte appeal decision information
- `AppellantData`: Appellant information and application details
- `PTABAppealMetaData`: Appeal metadata and filing information
- `PTABAppealDocumentData`: Document and decision details
- `AppealMetaData`: Appeal metadata and filing information
- `AppealDocumentData`: Document and decision details

#### PTAB Interferences API

- `PTABInterferenceResponse`: Top-level response from the API
- `PTABInterferenceDecision`: Interference proceeding decision information
- `SeniorPartyData`, `JuniorPartyData`, `AdditionalPartyData`: Party data classes
- `PTABInterferenceMetaData`: Interference metadata and status information
- `PTABInterferenceDocumentData`: Document and outcome details
- `InterferenceMetaData`: Interference metadata and status information
- `InterferenceDocumentData`: Document and outcome details
- `DecisionData`: Decision information for interference proceedings

For a complete list of all data models, see the [API Reference docuentation](https://pyuspto.readthedocs.io/en/latest/api/models/index.html).

## Advanced Topics

Expand Down
15 changes: 5 additions & 10 deletions examples/bulk_data_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Example usage of the BulkDataClient.
"""Example usage of pyUSPTO for the BulkDataClient.

This example demonstrates how to use the BulkDataClient to interact with the USPTO Bulk Data API.
It shows how to search for products, retrieve product details, and download files.
Expand Down Expand Up @@ -37,18 +37,13 @@ def format_size(size_bytes: int | float) -> str:
# Client Initialization Methods
# ============================================================================

# Method 1: Initialize with API key directly
print("Method 1: Initialize with direct API key")
api_key = "YOUR_API_KEY_HERE" # Replace with your actual API key
client = BulkDataClient(api_key=api_key)

# Method 2: Initialize with USPTOConfig object
print("\nMethod 2: Initialize with USPTOConfig")
# Method 1: Initialize with USPTOConfig object
print("\nMethod 1: Initialize with USPTOConfig")
config = USPTOConfig(api_key="YOUR_API_KEY_HERE")
client = BulkDataClient(config=config)

# Method 3: Initialize from environment variables (recommended)
print("\nMethod 3: Initialize from environment variables")
# Method 2: Initialize from environment variables (recommended)
print("\nMethod 2: Initialize from environment variables")
os.environ["USPTO_API_KEY"] = "YOUR_API_KEY_HERE" # Set this outside your script
config_from_env = USPTOConfig.from_env()
client = BulkDataClient(config=config_from_env)
Expand Down
5 changes: 3 additions & 2 deletions examples/error_handling_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@

# Initialize client
api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
client = PatentDataClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = PatentDataClient(config=config)

# Example 1: Handle authentication errors
print("Example 1: Authentication errors")
try:
# This will fail with invalid API key
bad_client = PatentDataClient(api_key="invalid_key")
bad_client = PatentDataClient(config=config)
bad_client.search_applications(limit=1)
except USPTOApiAuthError as e:
print(f"Authentication failed: {e}")
Expand Down
5 changes: 3 additions & 2 deletions examples/ifw_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
import os

from pyUSPTO.clients.patent_data import PatentDataClient
from pyUSPTO.config import USPTOConfig

api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
if api_key == "YOUR_API_KEY_HERE":
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)

client = PatentDataClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = PatentDataClient(config=config)


print("\nBeginning API requests with configured client:")
Expand Down
8 changes: 5 additions & 3 deletions examples/patent_data_example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Example usage of the uspto_api module for patent data.
"""Example usage of the pyUSPTO module for patent data.

This example demonstrates how to use the PatentDataClient to interact with the USPTO Patent Data API.
It shows how to retrieve patent applications, search for patents by various criteria, and access
Expand All @@ -9,17 +9,19 @@
import os

from pyUSPTO.clients.patent_data import PatentDataClient
from pyUSPTO.config import USPTOConfig
from pyUSPTO.models.patent_data import ApplicationContinuityData

# --- Initialization ---
# Initialize the client with API key from ENV Var.
print("Initialize with direct API key")
print("Initialize with config")
api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
if api_key == "YOUR_API_KEY_HERE":
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)
client = PatentDataClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = PatentDataClient(config=config)

DEST_PATH = "./download-example"

Expand Down
4 changes: 3 additions & 1 deletion examples/petition_decisions_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os

from pyUSPTO.clients import FinalPetitionDecisionsClient
from pyUSPTO.config import USPTOConfig
from pyUSPTO.models.petition_decisions import PetitionDecisionDownloadResponse

# --- Initialization ---
Expand All @@ -20,7 +21,8 @@
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)
client = FinalPetitionDecisionsClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = FinalPetitionDecisionsClient(config=config)

DEST_PATH = "./download-example"

Expand Down
4 changes: 3 additions & 1 deletion examples/ptab_appeals_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os

from pyUSPTO import PTABAppealsClient
from pyUSPTO.config import USPTOConfig

# --- Initialization ---
# Initialize the client with direct API key
Expand All @@ -19,7 +20,8 @@
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)
client = PTABAppealsClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = PTABAppealsClient(config=config)


print("\nBeginning PTAB Appeals API requests with configured client:")
Expand Down
4 changes: 3 additions & 1 deletion examples/ptab_interferences_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import os

from pyUSPTO import PTABInterferencesClient
from pyUSPTO.config import USPTOConfig

# --- Initialization ---
# Initialize the client with direct API key
Expand All @@ -20,7 +21,8 @@
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)
client = PTABInterferencesClient(api_key=api_key)
config = USPTOConfig(api_key=api_key)
client = PTABInterferencesClient(config=config)

print("\nBeginning PTAB Interferences API requests with configured client:")

Expand Down
5 changes: 4 additions & 1 deletion examples/ptab_trials_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import os

from pyUSPTO import PTABTrialsClient
from pyUSPTO.config import USPTOConfig

# --- Initialization ---
# Initialize the client with direct API key
Expand All @@ -23,7 +24,9 @@
raise ValueError(
"WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
)
client = PTABTrialsClient(api_key=api_key)

config = USPTOConfig(api_key=api_key)
client = PTABTrialsClient(config=config)

print("\nBeginning PTAB Trials API requests with configured client:")

Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pyUSPTO"
description = "A Modern Python client for accessing United Stated Patent and Trademark Office (USPTO) Open Data Portal (ODP) APIs."
description = "A Modern Python client for accessing the United States Patent and Trademark Office (USPTO) Open Data Portal (ODP) APIs."
authors = [
{ name = "Andrew Piechocki", email = "apiechocki@dunlapcodding.com" },
]
Expand Down Expand Up @@ -46,7 +46,7 @@ keywords = ["uspto", "patent", "odp", "client", "bulk data", "patent data"]
dependencies = [
"requests>=2.32.5",
"typing-extensions>=4.15.0; python_version < '3.11'",
"tzdata>=2025.2",
"tzdata>=2025.3",
]
dynamic = ["version"]

Expand All @@ -67,7 +67,7 @@ dev = [
"mypy>=1.19.0",
"types-requests>=2.32.4",
# Code quality and formatting
"ruff>=0.8.0",
"ruff>=0.15.0",
]

[project.urls]
Expand Down
Loading
Loading