pyUSPTO 0.4.4__tar.gz → 0.5.0__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 (146) hide show
  1. pyuspto-0.5.0/.github/workflows/codeql.yml +99 -0
  2. {pyuspto-0.4.4 → pyuspto-0.5.0}/.readthedocs.yaml +1 -1
  3. {pyuspto-0.4.4 → pyuspto-0.5.0}/CHANGELOG.md +113 -1
  4. {pyuspto-0.4.4 → pyuspto-0.5.0}/PKG-INFO +1 -1
  5. pyuspto-0.5.0/docs/source/api/clients/enriched_citations.rst +7 -0
  6. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/index.rst +1 -0
  7. pyuspto-0.5.0/docs/source/api/models/enriched_citations.rst +7 -0
  8. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/index.rst +1 -0
  9. pyuspto-0.5.0/docs/source/examples/enriched_citations.rst +6 -0
  10. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/index.rst +1 -0
  11. pyuspto-0.5.0/examples/bulk_data_example.py +133 -0
  12. pyuspto-0.5.0/examples/enriched_citations_example.py +132 -0
  13. {pyuspto-0.4.4 → pyuspto-0.5.0}/examples/error_handling_example.py +31 -25
  14. pyuspto-0.5.0/examples/ifw_example.py +121 -0
  15. pyuspto-0.5.0/examples/patent_data_example.py +310 -0
  16. pyuspto-0.5.0/examples/petition_decisions_example.py +237 -0
  17. pyuspto-0.5.0/examples/ptab_appeals_example.py +179 -0
  18. pyuspto-0.5.0/examples/ptab_interferences_example.py +217 -0
  19. pyuspto-0.5.0/examples/ptab_trials_example.py +141 -0
  20. {pyuspto-0.4.4 → pyuspto-0.5.0}/requirements-dev.txt +5 -9
  21. {pyuspto-0.4.4 → pyuspto-0.5.0}/requirements.txt +1 -1
  22. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/__init__.py +27 -3
  23. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/__init__.py +2 -0
  24. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/base.py +305 -114
  25. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/bulk_data.py +4 -9
  26. pyuspto-0.5.0/src/pyUSPTO/clients/enriched_citations.py +254 -0
  27. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/patent_data.py +30 -41
  28. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/petition_decisions.py +14 -21
  29. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/ptab_appeals.py +5 -9
  30. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/ptab_interferences.py +5 -9
  31. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/clients/ptab_trials.py +11 -15
  32. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/config.py +16 -9
  33. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/__init__.py +11 -0
  34. pyuspto-0.5.0/src/pyUSPTO/models/enriched_citations.py +354 -0
  35. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/patent_data.py +13 -13
  36. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/petition_decisions.py +6 -9
  37. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/ptab.py +0 -15
  38. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/PKG-INFO +1 -1
  39. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/SOURCES.txt +10 -0
  40. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_base.py +389 -89
  41. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_bulk_data_clients.py +3 -3
  42. pyuspto-0.5.0/tests/clients/test_enriched_citation_clients.py +456 -0
  43. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_patent_data_clients.py +347 -320
  44. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_petition_decision_clients.py +130 -112
  45. pyuspto-0.5.0/tests/integration/test_enriched_citations_integration.py +242 -0
  46. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_patent_data_integration.py +15 -15
  47. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_petition_decisions_integration.py +23 -23
  48. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_ptab_appeals_integration.py +18 -14
  49. pyuspto-0.5.0/tests/models/test_enriched_citation_models.py +420 -0
  50. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/test_petition_decision_models.py +8 -10
  51. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_config.py +7 -0
  52. pyuspto-0.4.4/examples/bulk_data_example.py +0 -190
  53. pyuspto-0.4.4/examples/ifw_example.py +0 -120
  54. pyuspto-0.4.4/examples/patent_data_example.py +0 -337
  55. pyuspto-0.4.4/examples/petition_decisions_example.py +0 -302
  56. pyuspto-0.4.4/examples/ptab_appeals_example.py +0 -261
  57. pyuspto-0.4.4/examples/ptab_interferences_example.py +0 -289
  58. pyuspto-0.4.4/examples/ptab_trials_example.py +0 -197
  59. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  60. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  61. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/ISSUE_TEMPLATE/documentation-updates.yml +0 -0
  62. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  63. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  64. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/dependabot.yml +0 -0
  65. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/workflows/publish-docs.yaml +0 -0
  66. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/workflows/publish-to-test-pypi.yml +0 -0
  67. {pyuspto-0.4.4 → pyuspto-0.5.0}/.github/workflows/python-tests.yml +0 -0
  68. {pyuspto-0.4.4 → pyuspto-0.5.0}/.gitignore +0 -0
  69. {pyuspto-0.4.4 → pyuspto-0.5.0}/ADVANCED.md +0 -0
  70. {pyuspto-0.4.4 → pyuspto-0.5.0}/CODE_OF_CONDUCT.md +0 -0
  71. {pyuspto-0.4.4 → pyuspto-0.5.0}/CONTRIBUTING.md +0 -0
  72. {pyuspto-0.4.4 → pyuspto-0.5.0}/LICENSE +0 -0
  73. {pyuspto-0.4.4 → pyuspto-0.5.0}/README.md +0 -0
  74. {pyuspto-0.4.4 → pyuspto-0.5.0}/_version.pyi +0 -0
  75. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/Makefile +0 -0
  76. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/_static/.gitkeep +0 -0
  77. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/advanced.rst +0 -0
  78. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/bulk_data.rst +0 -0
  79. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/patent_data.rst +0 -0
  80. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/petition_decisions.rst +0 -0
  81. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/ptab_appeals.rst +0 -0
  82. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/ptab_interferences.rst +0 -0
  83. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/clients/ptab_trials.rst +0 -0
  84. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/config/config.rst +0 -0
  85. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/config/http_config.rst +0 -0
  86. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/config/index.rst +0 -0
  87. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/exceptions.rst +0 -0
  88. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/index.rst +0 -0
  89. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/base.rst +0 -0
  90. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/bulk_data.rst +0 -0
  91. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/patent_data.rst +0 -0
  92. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/petition_decisions.rst +0 -0
  93. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/ptab.rst +0 -0
  94. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/models/utils.rst +0 -0
  95. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/api/warnings.rst +0 -0
  96. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/conf.py +0 -0
  97. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/configuration.rst +0 -0
  98. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/development.rst +0 -0
  99. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/bulk_data.rst +0 -0
  100. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/ifw_example.rst +0 -0
  101. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/patent_data.rst +0 -0
  102. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/petition_decisions.rst +0 -0
  103. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/ptab_appeals.rst +0 -0
  104. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/ptab_interferences.rst +0 -0
  105. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/examples/ptab_trials.rst +0 -0
  106. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/index.rst +0 -0
  107. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/installation.rst +0 -0
  108. {pyuspto-0.4.4 → pyuspto-0.5.0}/docs/source/quickstart.rst +0 -0
  109. {pyuspto-0.4.4 → pyuspto-0.5.0}/pyUSPTO.code-workspace +0 -0
  110. {pyuspto-0.4.4 → pyuspto-0.5.0}/pyproject.toml +0 -0
  111. {pyuspto-0.4.4 → pyuspto-0.5.0}/setup.cfg +0 -0
  112. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/exceptions.py +0 -0
  113. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/http_config.py +0 -0
  114. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/base.py +0 -0
  115. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/bulk_data.py +0 -0
  116. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/models/utils.py +0 -0
  117. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/py.typed +0 -0
  118. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/utils/__init__.py +0 -0
  119. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO/warnings.py +0 -0
  120. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/dependency_links.txt +0 -0
  121. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/requires.txt +0 -0
  122. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/top_level.txt +0 -0
  123. {pyuspto-0.4.4 → pyuspto-0.5.0}/src/pyUSPTO.egg-info/zip-safe +0 -0
  124. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/__init__.py +0 -0
  125. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/__init__.py +0 -0
  126. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_ptab_appeals_client.py +0 -0
  127. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_ptab_interferences_client.py +0 -0
  128. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/clients/test_ptab_trials_client.py +0 -0
  129. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/conftest.py +0 -0
  130. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/__init__.py +0 -0
  131. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/conftest.py +0 -0
  132. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_bulk_data_integration.py +0 -0
  133. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_ptab_interferences_integration.py +0 -0
  134. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/integration/test_ptab_trials_integration.py +0 -0
  135. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/__init__.py +0 -0
  136. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/test_bulk_data_models.py +0 -0
  137. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/test_patent_data_models.py +0 -0
  138. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/test_ptab_models.py +0 -0
  139. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/models/test_utils.py +0 -0
  140. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_edge_cases.py +0 -0
  141. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_exceptions.py +0 -0
  142. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_http_config.py +0 -0
  143. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_init.py +0 -0
  144. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/test_version.py +0 -0
  145. {pyuspto-0.4.4 → pyuspto-0.5.0}/tests/utils/__init__.py +0 -0
  146. {pyuspto-0.4.4 → pyuspto-0.5.0}/tox.ini +0 -0
@@ -0,0 +1,99 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL Advanced"
13
+
14
+ on:
15
+ push:
16
+ branches: [ "main" ]
17
+ pull_request:
18
+ branches: [ "main" ]
19
+ schedule:
20
+ - cron: '41 13 * * 2'
21
+
22
+ jobs:
23
+ analyze:
24
+ name: Analyze (${{ matrix.language }})
25
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
26
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
27
+ # - https://gh.io/supported-runners-and-hardware-resources
28
+ # - https://gh.io/using-larger-runners (GitHub.com only)
29
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
30
+ runs-on: ${{ 'ubuntu-latest' }}
31
+ permissions:
32
+ # required for all workflows
33
+ security-events: write
34
+
35
+ # required to fetch internal or private CodeQL packs
36
+ packages: read
37
+
38
+ # only required for workflows in private repositories
39
+ actions: read
40
+ contents: read
41
+
42
+ strategy:
43
+ fail-fast: false
44
+ matrix:
45
+ include:
46
+ - language: python
47
+ build-mode: none
48
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
49
+ # Use `c-cpp` to analyze code written in C, C++ or both
50
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
51
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
52
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
53
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
54
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
55
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
56
+ steps:
57
+ - name: Checkout repository
58
+ uses: actions/checkout@v6
59
+
60
+ # Add any setup steps before running the `github/codeql-action/init` action.
61
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
62
+ # or others). This is typically only required for manual builds.
63
+ # - name: Setup runtime (example)
64
+ # uses: actions/setup-example@v1
65
+
66
+ # Initializes the CodeQL tools for scanning.
67
+ - name: Initialize CodeQL
68
+ uses: github/codeql-action/init@v4
69
+ with:
70
+ languages: ${{ matrix.language }}
71
+ build-mode: ${{ matrix.build-mode }}
72
+ # If you wish to specify custom queries, you can do so here or in a config file.
73
+ # By default, queries listed here will override any specified in a config file.
74
+ # Prefix the list here with "+" to use these queries and those in the config file.
75
+
76
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
77
+ queries: security-and-quality
78
+
79
+ # If the analyze step fails for one of the languages you are analyzing with
80
+ # "We were unable to automatically build your code", modify the matrix above
81
+ # to set the build mode to "manual" for that language. Then modify this step
82
+ # to build your code.
83
+ # ℹ️ Command-line programs to run using the OS shell.
84
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
85
+ - name: Run manual build steps
86
+ if: matrix.build-mode == 'manual'
87
+ shell: bash
88
+ run: |
89
+ echo 'If you are using a "manual" build mode for one or more of the' \
90
+ 'languages you are analyzing, replace this with the commands to build' \
91
+ 'your code, for example:'
92
+ echo ' make bootstrap'
93
+ echo ' make release'
94
+ exit 1
95
+
96
+ - name: Perform CodeQL Analysis
97
+ uses: github/codeql-action/analyze@v4
98
+ with:
99
+ category: "/language:${{matrix.language}}"
@@ -7,7 +7,7 @@ version: 2
7
7
  build:
8
8
  os: ubuntu-24.04
9
9
  tools:
10
- python: "3.10"
10
+ python: "3.14"
11
11
 
12
12
  # Build documentation in the "docs/" directory with Sphinx
13
13
  sphinx:
@@ -5,7 +5,119 @@ All notable changes to the pyUSPTO package will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.3.0] - TBD
8
+ ## [0.4.5] - 2026-03-11
9
+
10
+ ### Changed
11
+
12
+ - **Refactor**: Split `_make_request` into three typed request methods:
13
+ - `_get_model` — returns parsed model `T`
14
+ - `_get_json` — returns `dict[str, Any]`
15
+ - `_stream_request` — returns `requests.Response`
16
+ - Removed all `assert isinstance` runtime checks and `# type: ignore` annotations at 28 call sites
17
+ - `DocumentBag`, `StatusCodeSearchResponse`, and `PetitionDecisionDownloadResponse` now conform to `FromDictProtocol` (`include_raw_data` parameter added to `from_dict`)
18
+
19
+ ### Fixed
20
+
21
+ - PTAB appeals integration test query (`Appeal` → `REGULAR` for `applicationTypeCategory`)
22
+ - Read the Docs build: updated Python from 3.10 to 3.14 to satisfy `myst-parser>=3.11` requirement
23
+
24
+ ## [0.4.4] - 2026-03-08
25
+
26
+ ### Added
27
+
28
+ - `get_patent(patent_number)` — lookup `PatentFileWrapper` by granted patent number
29
+ - `get_publication(publication_number)` — lookup by publication number
30
+ - `get_pct(pct_number)` — lookup by PCT application or publication number (auto-detected)
31
+
32
+ ### Fixed
33
+
34
+ - `sanitize_application_number` now strips leading zeros from PCT serial numbers
35
+
36
+ ## [0.4.3] - 2026-03-05
37
+
38
+ ### Added
39
+
40
+ - `get_IFW` method for bulk downloading all documents in an application's IFW
41
+ - `IFWResult` model with document map and optional ZIP output
42
+ - `get_IFW_metadata` now populates `document_bag` on the returned `PatentFileWrapper`
43
+ - Example: searching CPC codes (#102)
44
+
45
+ ### Fixed
46
+
47
+ - Auto-quote `classification_q` values containing spaces or slashes (#101)
48
+ - Missing `typing_extensions` dependency
49
+ - CI refactor to exclude dev requirements from install
50
+
51
+ ## [0.4.2] - 2026-02-26
52
+
53
+ ### Fixed
54
+
55
+ - Quote multi-word values in query convenience parameters
56
+
57
+ ## [0.4.1] - 2026-02-25
58
+
59
+ ### Added
60
+
61
+ - Download path validation and zip-bomb protection
62
+ - Sanitize download filenames to prevent path traversal
63
+ - Skip symlinks during archive extraction
64
+ - Session lifecycle and extraction safety documentation
65
+
66
+ ### Changed
67
+
68
+ - Enable retries for POST requests
69
+ - Remove unused `utils.http` module and `ALLOWED_METHODS`
70
+ - Enforce keyword-only arguments in `get_IFW_metadata`
71
+ - Optimize tox deps and enable parallel
72
+
73
+ ## [0.4.0] - 2026-02-23
74
+
75
+ ### Changed
76
+
77
+ - **Refactor**: Centralize session management in `USPTOConfig`
78
+ - `FileData.file_date` changed to `datetime` type
79
+
80
+ ### Fixed
81
+
82
+ - Prevent path traversal in archive extraction
83
+ - Fix #79
84
+
85
+ ## [0.3.4] - 2026-01-11
86
+
87
+ ### Added
88
+
89
+ - JSON parsing error handling
90
+ - Pagination validation
91
+ - Documentation for HTTP method restrictions and `include_raw_data` flag
92
+
93
+ ### Changed
94
+
95
+ - Aligned backoff factor default
96
+
97
+ ## [0.3.3] - 2026-01-08
98
+
99
+ ### Changed
100
+
101
+ - Bulk data client refactor (#40)
102
+
103
+ ## [0.3.2] - 2025-12-31
104
+
105
+ ### Changed
106
+
107
+ - Refactor downloads (#35)
108
+ - Configurable download chunk size
109
+ - Session sharing across clients
110
+
111
+ ## [0.3.1] - 2025-12-15
112
+
113
+ ### Added
114
+
115
+ - `paginate_decisions` POST support
116
+ - Configurable download chunk size
117
+ - Session sharing across clients
118
+ - Bulk data endpoint updates
119
+
120
+ ## [0.3.0] - 2025-12-09
9
121
 
10
122
  ### Added
11
123
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyUSPTO
3
- Version: 0.4.4
3
+ Version: 0.5.0
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
@@ -0,0 +1,7 @@
1
+ Enriched Citations Client
2
+ =========================
3
+
4
+ .. automodule:: pyUSPTO.clients.enriched_citations
5
+ :members:
6
+ :undoc-members:
7
+ :show-inheritance:
@@ -5,6 +5,7 @@ Clients
5
5
  :maxdepth: 2
6
6
 
7
7
  bulk_data
8
+ enriched_citations
8
9
  patent_data
9
10
  petition_decisions
10
11
  ptab_appeals
@@ -0,0 +1,7 @@
1
+ Enriched Citations
2
+ ==================
3
+
4
+ .. automodule:: pyUSPTO.models.enriched_citations
5
+ :members:
6
+ :undoc-members:
7
+ :show-inheritance:
@@ -6,6 +6,7 @@ Models
6
6
 
7
7
  base
8
8
  bulk_data
9
+ enriched_citations
9
10
  patent_data
10
11
  petition_decisions
11
12
  ptab
@@ -0,0 +1,6 @@
1
+ Enriched Citations Example
2
+ ==========================
3
+
4
+ .. literalinclude:: ../../../examples/enriched_citations_example.py
5
+ :language: python
6
+ :linenos:
@@ -5,6 +5,7 @@ Examples
5
5
  :maxdepth: 2
6
6
 
7
7
  bulk_data
8
+ enriched_citations
8
9
  patent_data
9
10
  ifw_example
10
11
  petition_decisions
@@ -0,0 +1,133 @@
1
+ """Example usage of pyUSPTO for bulk data products.
2
+
3
+ Demonstrates the BulkDataClient for searching products, listing files,
4
+ and downloading bulk data archives.
5
+ """
6
+
7
+ import os
8
+
9
+ from pyUSPTO import BulkDataClient, FileData, USPTOConfig
10
+
11
+ DEST_PATH = "./notes/download-example"
12
+
13
+
14
+ def format_size(size_bytes: int | float) -> str:
15
+ """Format a size in bytes to a human-readable string (KB, MB, GB, etc.)."""
16
+ if size_bytes == 0:
17
+ return "0 B"
18
+
19
+ size_names = ["B", "KB", "MB", "GB", "TB", "PB"]
20
+ i = 0
21
+ while size_bytes >= 1024 and i < len(size_names) - 1:
22
+ size_bytes /= 1024
23
+ i += 1
24
+
25
+ return f"{size_bytes:.2f} {size_names[i]}"
26
+
27
+
28
+ # --- Client Initialization ---
29
+ api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
30
+ if api_key == "YOUR_API_KEY_HERE":
31
+ raise ValueError(
32
+ "API key is not set. Set the USPTO_API_KEY environment variable."
33
+ )
34
+ config = USPTOConfig(api_key=api_key)
35
+ client = BulkDataClient(config=config)
36
+
37
+ print("-" * 40)
38
+ print("Example 1: Search for products")
39
+ print("-" * 40)
40
+
41
+ response = client.search_products(query="patent", limit=5)
42
+ print(f"Found {response.count} products matching 'patent'")
43
+
44
+ for product in response.bulk_data_product_bag:
45
+ print(f"\n Product: {product.product_title_text}")
46
+ print(f" ID: {product.product_identifier}")
47
+ print(f" Description: {product.product_description_text[:100]}...")
48
+ print(f" Total files: {product.product_file_total_quantity}")
49
+ print(f" Total size: {format_size(product.product_total_file_size)}")
50
+
51
+ print("-" * 40)
52
+ print("Example 2: Paginate through products")
53
+ print("-" * 40)
54
+
55
+ max_items = 20
56
+ count = 0
57
+ for product in client.paginate_products(query="trademark", limit=10):
58
+ count += 1
59
+ print(f" {count}. {product.product_title_text} ({product.product_identifier})")
60
+ if count >= max_items:
61
+ print(f" ... (stopping at {max_items} products)")
62
+ break
63
+
64
+ print("-" * 40)
65
+ print("Example 3: Get product by ID")
66
+ print("-" * 40)
67
+
68
+ product_id = "PTGRXML" # Patent Grant Full-Text Data (No Images) - XML
69
+ product = client.get_product_by_id(product_id, include_files=True, latest=True)
70
+
71
+ print(f"Product: {product.product_title_text}")
72
+ print(f"Description: {product.product_description_text}")
73
+ print(f"Frequency: {product.product_frequency_text}")
74
+ print(f"Labels: {product.product_label_array_text}")
75
+ print(f"Categories: {product.product_dataset_category_array_text}")
76
+ print(f"Date range: {product.product_from_date} to {product.product_to_date}")
77
+
78
+ print("-" * 40)
79
+ print("Example 4: List files for a product")
80
+ print("-" * 40)
81
+
82
+ if product.product_file_bag and product.product_file_bag.file_data_bag:
83
+ print(f"Found {len(product.product_file_bag.file_data_bag)} file(s):")
84
+
85
+ for file_data in product.product_file_bag.file_data_bag:
86
+ print(f"\n File: {file_data.file_name}")
87
+ print(f" Size: {format_size(file_data.file_size)}")
88
+ print(f" Type: {file_data.file_type_text}")
89
+ print(
90
+ f" Data range: {file_data.file_data_from_date} to {file_data.file_data_to_date}"
91
+ )
92
+ print(f" Released: {file_data.file_release_date}")
93
+ print(f" Download URI: {file_data.file_download_uri}")
94
+ else:
95
+ print("No files found for this product")
96
+
97
+ print("-" * 40)
98
+ print("Example 5: Download a file (with extraction)")
99
+ print("-" * 40)
100
+
101
+ min_file: FileData | None = None
102
+ last_bytes: float = float("inf")
103
+
104
+ if product.product_file_bag and product.product_file_bag.file_data_bag:
105
+ for file_data in product.product_file_bag.file_data_bag:
106
+ if file_data.file_size < last_bytes:
107
+ last_bytes = file_data.file_size
108
+ min_file = file_data
109
+
110
+ if min_file:
111
+ print(f"Downloading smallest file: {min_file.file_name}")
112
+ print(f"Size: {format_size(min_file.file_size)}")
113
+
114
+ downloaded_path = client.download_file(
115
+ file_data=min_file,
116
+ destination=DEST_PATH,
117
+ overwrite=True,
118
+ extract=True,
119
+ )
120
+ print(f"Downloaded to {downloaded_path}")
121
+
122
+ print("-" * 40)
123
+ print("Example 6: Download without extraction")
124
+ print("-" * 40)
125
+
126
+ if product.product_file_bag and product.product_file_bag.file_data_bag and min_file:
127
+ downloaded_path = client.download_file(
128
+ file_data=min_file,
129
+ destination=DEST_PATH,
130
+ overwrite=True,
131
+ extract=False,
132
+ )
133
+ print(f"Archive saved to {downloaded_path}")
@@ -0,0 +1,132 @@
1
+ """Example usage of pyUSPTO for Enriched Cited Reference Metadata.
2
+
3
+ Demonstrates the EnrichedCitationsClient for searching citation data
4
+ extracted from patent office actions, filtering by various criteria,
5
+ and paginating through results.
6
+ """
7
+
8
+ import os
9
+
10
+ from pyUSPTO import EnrichedCitationsClient, USPTOConfig
11
+
12
+ # --- Client Initialization ---
13
+ api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
14
+ if api_key == "YOUR_API_KEY_HERE":
15
+ raise ValueError(
16
+ "API key is not set. Set the USPTO_API_KEY environment variable."
17
+ )
18
+ config = USPTOConfig(api_key=api_key)
19
+ client = EnrichedCitationsClient(config=config)
20
+
21
+ print("-" * 40)
22
+ print("Example 1: Search by application number")
23
+ print("-" * 40)
24
+
25
+ response = client.search_citations(patent_application_number_q="15061308")
26
+ print(f"Found {response.num_found} citations for application 15061308.")
27
+ for citation in response.docs[:5]:
28
+ print(f"\n Cited Document: {citation.cited_document_identifier}")
29
+ print(f" Category Code: {citation.citation_category_code}")
30
+ print(f" Office Action Date: {citation.office_action_date}")
31
+ print(f" Office Action Type: {citation.office_action_category}")
32
+ if citation.examiner_cited_reference_indicator:
33
+ print(" Cited by: Examiner")
34
+ if citation.passage_location_text:
35
+ print(f" Passages: {citation.passage_location_text}")
36
+
37
+ print("-" * 40)
38
+ print("Example 2: Search by tech center and citation category")
39
+ print("-" * 40)
40
+
41
+ response = client.search_citations(
42
+ tech_center_q="2800",
43
+ citation_category_code_q="X",
44
+ rows=5,
45
+ )
46
+ print(f"Found {response.num_found} 'X' citations in tech center 2800.")
47
+ for citation in response.docs:
48
+ print(
49
+ f" App {citation.patent_application_number}: "
50
+ f"{citation.cited_document_identifier} "
51
+ f"(claims: {citation.related_claim_number_text})"
52
+ )
53
+
54
+ print("-" * 40)
55
+ print("Example 3: Search by date range")
56
+ print("-" * 40)
57
+
58
+ response = client.search_citations(
59
+ office_action_date_from_q="2019-01-01",
60
+ office_action_date_to_q="2019-12-31",
61
+ rows=5,
62
+ )
63
+ print(f"Found {response.num_found} citations from 2019.")
64
+
65
+ print("-" * 40)
66
+ print("Example 4: Combined filters")
67
+ print("-" * 40)
68
+
69
+ response = client.search_citations(
70
+ tech_center_q="2800",
71
+ citation_category_code_q="Y",
72
+ examiner_cited_q=True,
73
+ rows=5,
74
+ )
75
+ print(
76
+ f"Found {response.num_found} examiner-cited 'Y' citations in tech center 2800."
77
+ )
78
+ for citation in response.docs:
79
+ print(
80
+ f" App {citation.patent_application_number}: "
81
+ f"{citation.cited_document_identifier} "
82
+ f"(art unit: {citation.group_art_unit_number})"
83
+ )
84
+
85
+ print("-" * 40)
86
+ print("Example 5: Search with sort")
87
+ print("-" * 40)
88
+
89
+ response = client.search_citations(
90
+ tech_center_q="2800",
91
+ sort="officeActionDate desc",
92
+ rows=5,
93
+ )
94
+ print(f"Found {response.num_found} citations, sorted by date descending.")
95
+ for citation in response.docs:
96
+ print(f" {citation.office_action_date}: {citation.cited_document_identifier}")
97
+
98
+ print("-" * 40)
99
+ print("Example 6: Search by cited document identifier")
100
+ print("-" * 40)
101
+
102
+ response = client.search_citations(
103
+ cited_document_identifier_q="US 20190165601 A1",
104
+ rows=5,
105
+ )
106
+ print(f"Found {response.num_found} citations of US 20190165601 A1.")
107
+
108
+ print("-" * 40)
109
+ print("Example 7: Paginate through results")
110
+ print("-" * 40)
111
+
112
+ max_items = 30
113
+ count = 0
114
+ for citation in client.paginate_citations(
115
+ tech_center_q="2800", rows=10
116
+ ):
117
+ count += 1
118
+ if count >= max_items:
119
+ print(f" ... (stopping at {max_items} items)")
120
+ break
121
+
122
+ print(f"Retrieved {count} citations via pagination")
123
+
124
+ print("-" * 40)
125
+ print("Example 8: Get available fields")
126
+ print("-" * 40)
127
+
128
+ fields_response = client.get_fields()
129
+ print(f"API Status: {fields_response.api_status}")
130
+ print(f"Field Count: {fields_response.field_count}")
131
+ print(f"Fields: {fields_response.fields}")
132
+ print(f"Last Updated: {fields_response.last_data_updated_date}")
@@ -1,64 +1,68 @@
1
- """Error handling example for pyUSPTO.
1
+ """Example usage of pyUSPTO for error handling patterns.
2
2
 
3
- This example demonstrates how to handle common errors when using the USPTO API clients.
3
+ Demonstrates how to handle common errors when using the USPTO API clients.
4
4
  """
5
5
 
6
6
  import os
7
7
  import time
8
8
 
9
- from pyUSPTO.clients import PatentDataClient
10
- from pyUSPTO.config import USPTOConfig
11
- from pyUSPTO.exceptions import (
9
+ from pyUSPTO import (
10
+ HTTPConfig,
11
+ PatentDataClient,
12
12
  USPTOApiAuthError,
13
13
  USPTOApiNotFoundError,
14
14
  USPTOApiRateLimitError,
15
+ USPTOConfig,
15
16
  USPTOConnectionError,
16
17
  USPTOTimeout,
17
18
  )
18
- from pyUSPTO.http_config import HTTPConfig
19
19
 
20
- # Initialize client
20
+ # --- Client Initialization ---
21
21
  api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
22
22
  config = USPTOConfig(api_key=api_key)
23
23
  client = PatentDataClient(config=config)
24
24
 
25
- # Example 1: Handle authentication errors
25
+ print("-" * 40)
26
26
  print("Example 1: Authentication errors")
27
+ print("-" * 40)
28
+
27
29
  try:
28
- # This will fail with invalid API key
29
30
  bad_client = PatentDataClient(config=config)
30
31
  bad_client.search_applications(limit=1)
31
32
  except USPTOApiAuthError as e:
32
33
  print(f"Authentication failed: {e}")
33
34
  print("Check your API key and try again.")
34
35
 
35
- # Example 2: Handle not found errors
36
- print("\nExample 2: Not found errors")
36
+ print("-" * 40)
37
+ print("Example 2: Not found errors")
38
+ print("-" * 40)
39
+
37
40
  try:
38
- # Try to get a non-existent application
39
41
  client.get_application_by_number("99999999")
40
42
  except USPTOApiNotFoundError as e:
41
43
  print(f"Resource not found: {e}")
42
44
  print("The application number may be invalid or not in the system.")
43
45
 
44
- # Example 3: Handle rate limiting with retry
45
- print("\nExample 3: Rate limiting")
46
+ print("-" * 40)
47
+ print("Example 3: Rate limiting")
48
+ print("-" * 40)
49
+
46
50
  try:
47
- # If you hit rate limits, the API returns 429
48
51
  results = client.search_applications(limit=100)
49
52
  print(f"Retrieved {results.count} results")
50
53
  except USPTOApiRateLimitError as e:
51
54
  print(f"Rate limit exceeded: {e}")
52
55
  print("Waiting 60 seconds before retry...")
53
56
  time.sleep(60)
54
- # Retry the request
55
57
  results = client.search_applications(limit=100)
56
58
  print(f"Retry successful: {results.count} results")
57
59
 
58
- # Example 4: Handle timeouts with custom configuration
59
- print("\nExample 4: Timeout handling")
60
+ print("-" * 40)
61
+ print("Example 4: Timeout handling")
62
+ print("-" * 40)
63
+
60
64
  # Configure shorter timeout for demonstration
61
- http_config = HTTPConfig(timeout=1) # Very short timeout
65
+ http_config = HTTPConfig(timeout=1)
62
66
  config = USPTOConfig(api_key=api_key, http_config=http_config)
63
67
  timeout_client = PatentDataClient(config=config)
64
68
 
@@ -68,17 +72,20 @@ except USPTOTimeout as e:
68
72
  print(f"Request timed out: {e}")
69
73
  print("Consider increasing timeout or checking network connection.")
70
74
 
71
- # Example 5: Handle connection errors
72
- print("\nExample 5: Connection errors")
75
+ print("-" * 40)
76
+ print("Example 5: Connection errors")
77
+ print("-" * 40)
78
+
73
79
  try:
74
- # This might fail due to network issues
75
80
  client.search_applications(limit=10)
76
81
  except USPTOConnectionError as e:
77
82
  print(f"Connection error: {e}")
78
83
  print("Check your network connection and try again.")
79
84
 
80
- # Example 6: Catch-all for unexpected errors
81
- print("\nExample 6: General error handling")
85
+ print("-" * 40)
86
+ print("Example 6: General error handling")
87
+ print("-" * 40)
88
+
82
89
  try:
83
90
  results = client.search_applications(patent_number_q="10000000", limit=5)
84
91
  if results.count > 0:
@@ -94,5 +101,4 @@ except USPTOTimeout:
94
101
  except USPTOConnectionError:
95
102
  print("Connection failed - check network")
96
103
  except Exception as e:
97
- # Catch any other unexpected errors
98
104
  print(f"Unexpected error: {e}")