edgarparser-sdk 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/PKG-INFO +10 -5
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/README.md +9 -4
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/pyproject.toml +2 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/src/edgarparser/__init__.py +1 -1
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/src/edgarparser/_manifest.py +8 -20
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/src/edgarparser/client.py +9 -30
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/test_client.py +7 -9
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/test_import.py +1 -1
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/test_manifest_alignment.py +0 -1
- edgarparser_sdk-0.1.2/tests/test_packaging.py +71 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/test_request_core.py +1 -1
- edgarparser_sdk-0.1.0/tests/test_packaging.py +0 -44
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/.gitignore +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/LICENSE +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/examples/filing_search.py +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/examples/financials.py +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/examples/metric_series.py +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/src/edgarparser/errors.py +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/src/edgarparser/py.typed +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/conftest.py +0 -0
- {edgarparser_sdk-0.1.0 → edgarparser_sdk-0.1.2}/tests/test_endpoint_methods.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: edgarparser-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Python SDK for the hosted EdgarParser SEC filings API
|
|
5
5
|
Project-URL: Homepage, https://www.edgarparser.com
|
|
6
6
|
Project-URL: Documentation, https://docs.edgarparser.com
|
|
@@ -23,6 +23,10 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
Python SDK for the hosted EdgarParser API.
|
|
25
25
|
|
|
26
|
+
**Status:** Living reference
|
|
27
|
+
**Current authority:** `packages/edgarparser/src/edgarparser/` (`client.py`, `__init__.py`, `_manifest.py`) and `packages/edgarparser/pyproject.toml`
|
|
28
|
+
**Last verified:** 2026-07-29
|
|
29
|
+
|
|
26
30
|
```bash
|
|
27
31
|
pip install edgarparser-sdk
|
|
28
32
|
```
|
|
@@ -36,9 +40,9 @@ print(client)
|
|
|
36
40
|
|
|
37
41
|
## Status
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
`edgarparser-sdk` is published on PyPI as the first-party Python client for the
|
|
44
|
+
hosted EdgarParser API. The package exports `EdgarClient`, typed SDK errors,
|
|
45
|
+
and the v1 hosted-API endpoint methods listed below.
|
|
42
46
|
|
|
43
47
|
## Package Boundary
|
|
44
48
|
|
|
@@ -71,7 +75,8 @@ from edgarparser import EdgarClient
|
|
|
71
75
|
client = EdgarClient()
|
|
72
76
|
```
|
|
73
77
|
|
|
74
|
-
|
|
78
|
+
Default `base_url` is `https://www.edgarparser.com`. Override it for staging
|
|
79
|
+
or local API testing:
|
|
75
80
|
|
|
76
81
|
```python
|
|
77
82
|
client = EdgarClient(api_key="edgar_...", base_url="http://127.0.0.1:8000")
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Python SDK for the hosted EdgarParser API.
|
|
4
4
|
|
|
5
|
+
**Status:** Living reference
|
|
6
|
+
**Current authority:** `packages/edgarparser/src/edgarparser/` (`client.py`, `__init__.py`, `_manifest.py`) and `packages/edgarparser/pyproject.toml`
|
|
7
|
+
**Last verified:** 2026-07-29
|
|
8
|
+
|
|
5
9
|
```bash
|
|
6
10
|
pip install edgarparser-sdk
|
|
7
11
|
```
|
|
@@ -15,9 +19,9 @@ print(client)
|
|
|
15
19
|
|
|
16
20
|
## Status
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
`edgarparser-sdk` is published on PyPI as the first-party Python client for the
|
|
23
|
+
hosted EdgarParser API. The package exports `EdgarClient`, typed SDK errors,
|
|
24
|
+
and the v1 hosted-API endpoint methods listed below.
|
|
21
25
|
|
|
22
26
|
## Package Boundary
|
|
23
27
|
|
|
@@ -50,7 +54,8 @@ from edgarparser import EdgarClient
|
|
|
50
54
|
client = EdgarClient()
|
|
51
55
|
```
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
Default `base_url` is `https://www.edgarparser.com`. Override it for staging
|
|
58
|
+
or local API testing:
|
|
54
59
|
|
|
55
60
|
```python
|
|
56
61
|
client = EdgarClient(api_key="edgar_...", base_url="http://127.0.0.1:8000")
|
|
@@ -33,9 +33,11 @@ dev = [
|
|
|
33
33
|
path = "src/edgarparser/__init__.py"
|
|
34
34
|
|
|
35
35
|
[tool.hatch.build.targets.wheel]
|
|
36
|
+
core-metadata-version = "2.4"
|
|
36
37
|
packages = ["src/edgarparser"]
|
|
37
38
|
|
|
38
39
|
[tool.hatch.build.targets.sdist]
|
|
40
|
+
core-metadata-version = "2.4"
|
|
39
41
|
include = [
|
|
40
42
|
"src/edgarparser/",
|
|
41
43
|
"examples/",
|
|
@@ -12,7 +12,6 @@ class SDKMethodSpec:
|
|
|
12
12
|
api_method: str
|
|
13
13
|
api_path: str
|
|
14
14
|
contract_version: str
|
|
15
|
-
schema_fingerprint: str
|
|
16
15
|
required_params: tuple[str, ...] = ()
|
|
17
16
|
optional_params: tuple[str, ...] = ()
|
|
18
17
|
path_params: tuple[str, ...] = ()
|
|
@@ -25,8 +24,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
25
24
|
tool_name="get_financials",
|
|
26
25
|
api_method="GET",
|
|
27
26
|
api_path="/api/financials",
|
|
28
|
-
contract_version="
|
|
29
|
-
schema_fingerprint="sha256:8c2b5486165eb2628dfb324c558c1148a48a46453f4102f0491e16503316b1c5",
|
|
27
|
+
contract_version="2.0.0",
|
|
30
28
|
required_params=("ticker", "year", "quarter"),
|
|
31
29
|
optional_params=("full_year_mode", "source"),
|
|
32
30
|
),
|
|
@@ -35,8 +33,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
35
33
|
tool_name="get_metric",
|
|
36
34
|
api_method="GET",
|
|
37
35
|
api_path="/api/metric",
|
|
38
|
-
contract_version="
|
|
39
|
-
schema_fingerprint="sha256:0350ec893a5d3a2a2510dc059711a93f6ec9665a0e068b32d8c4b2d8cb8accd8",
|
|
36
|
+
contract_version="2.0.0",
|
|
40
37
|
required_params=("ticker", "year", "quarter", "metric_name"),
|
|
41
38
|
optional_params=("full_year_mode", "source", "date_type", "role"),
|
|
42
39
|
),
|
|
@@ -45,8 +42,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
45
42
|
tool_name="get_metric_series",
|
|
46
43
|
api_method="GET",
|
|
47
44
|
api_path="/api/metric/series",
|
|
48
|
-
contract_version="
|
|
49
|
-
schema_fingerprint="sha256:dff62ae8bf4eb8c648776ac91e02e324c83a1cccbf3beeefcb7855272970a906",
|
|
45
|
+
contract_version="2.0.0",
|
|
50
46
|
required_params=("ticker", "metric_name", "end_year", "end_quarter"),
|
|
51
47
|
optional_params=(
|
|
52
48
|
"periods",
|
|
@@ -64,8 +60,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
64
60
|
tool_name="list_metrics",
|
|
65
61
|
api_method="GET",
|
|
66
62
|
api_path="/api/financials/list_metrics",
|
|
67
|
-
contract_version="1.
|
|
68
|
-
schema_fingerprint="sha256:07341bd265a257b8c90ee99b42ecef054e6eaa16c2f341f91ffae287bfe907d8",
|
|
63
|
+
contract_version="1.1.0",
|
|
69
64
|
required_params=("ticker", "year", "quarter"),
|
|
70
65
|
optional_params=(
|
|
71
66
|
"full_year_mode",
|
|
@@ -80,8 +75,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
80
75
|
tool_name="search_metrics",
|
|
81
76
|
api_method="GET",
|
|
82
77
|
api_path="/api/financials/search_metrics",
|
|
83
|
-
contract_version="1.
|
|
84
|
-
schema_fingerprint="sha256:381c0bf743038780d55c447b0c7103da0e22d13c33b866c73130b7265071853c",
|
|
78
|
+
contract_version="1.1.0",
|
|
85
79
|
required_params=("ticker", "year", "quarter", "query"),
|
|
86
80
|
optional_params=(
|
|
87
81
|
"full_year_mode",
|
|
@@ -97,8 +91,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
97
91
|
tool_name="get_statement",
|
|
98
92
|
api_method="GET",
|
|
99
93
|
api_path="/api/statement",
|
|
100
|
-
contract_version="
|
|
101
|
-
schema_fingerprint="sha256:6da91e176e78fe536130ed3ea11cf9b8dfccf923cbbfc47483d7cb2108383986",
|
|
94
|
+
contract_version="2.0.0",
|
|
102
95
|
required_params=("ticker", "statement"),
|
|
103
96
|
optional_params=(
|
|
104
97
|
"year",
|
|
@@ -116,7 +109,6 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
116
109
|
api_method="GET",
|
|
117
110
|
api_path="/api/filings",
|
|
118
111
|
contract_version="1.0.0",
|
|
119
|
-
schema_fingerprint="sha256:ffa7e669b836cbbc181bc337cb55219e55bf9a5c75ce3d27040a8aad25f8c993",
|
|
120
112
|
required_params=("ticker", "year", "quarter"),
|
|
121
113
|
optional_params=("source",),
|
|
122
114
|
),
|
|
@@ -125,8 +117,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
125
117
|
tool_name="get_filing_document",
|
|
126
118
|
api_method="GET",
|
|
127
119
|
api_path="/api/filing/document",
|
|
128
|
-
contract_version="1.
|
|
129
|
-
schema_fingerprint="sha256:4d559aded5c9760ccb498944a984a128254a76349348de297da30ee338ff123a",
|
|
120
|
+
contract_version="1.1.0",
|
|
130
121
|
optional_params=(
|
|
131
122
|
"ticker",
|
|
132
123
|
"year",
|
|
@@ -147,8 +138,7 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
147
138
|
tool_name="search_filing_text",
|
|
148
139
|
api_method="GET",
|
|
149
140
|
api_path="/api/filing/text/search",
|
|
150
|
-
contract_version="1.
|
|
151
|
-
schema_fingerprint="sha256:be08198a156e55118e9b32a0fb41ead07906469059fb27d3010f1a1f5a9c0c8c",
|
|
141
|
+
contract_version="1.1.0",
|
|
152
142
|
required_params=("ticker", "year", "quarter", "query"),
|
|
153
143
|
optional_params=("source",),
|
|
154
144
|
),
|
|
@@ -158,7 +148,6 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
158
148
|
api_method="POST",
|
|
159
149
|
api_path="/api/warm",
|
|
160
150
|
contract_version="1.0.0",
|
|
161
|
-
schema_fingerprint="sha256:1636aba36d166ecf2901e72078fc8a6182f7174e541d9183561392781e8f8cbd",
|
|
162
151
|
body_params=("items",),
|
|
163
152
|
),
|
|
164
153
|
SDKMethodSpec(
|
|
@@ -167,7 +156,6 @@ SDK_METHODS: tuple[SDKMethodSpec, ...] = (
|
|
|
167
156
|
api_method="GET",
|
|
168
157
|
api_path="/api/warm/{job_id}",
|
|
169
158
|
contract_version="1.0.0",
|
|
170
|
-
schema_fingerprint="sha256:f48e0b9a707e404c640822af06d51f3523f54538fed625a24ee06dc220cb3245",
|
|
171
159
|
path_params=("job_id",),
|
|
172
160
|
),
|
|
173
161
|
)
|
|
@@ -468,17 +468,6 @@ class EdgarClient:
|
|
|
468
468
|
")"
|
|
469
469
|
)
|
|
470
470
|
|
|
471
|
-
def _debug_state(self) -> dict[str, Any]:
|
|
472
|
-
"""Return non-secret state for tests and diagnostics."""
|
|
473
|
-
|
|
474
|
-
return {
|
|
475
|
-
"base_url": self.base_url,
|
|
476
|
-
"timeout": self.timeout,
|
|
477
|
-
"api_key_set": bool(self.api_key),
|
|
478
|
-
"closed": self._closed,
|
|
479
|
-
"user_agent": self.user_agent,
|
|
480
|
-
}
|
|
481
|
-
|
|
482
471
|
def _url(self, path: str) -> str:
|
|
483
472
|
if not path or not path.strip():
|
|
484
473
|
raise ValueError("path must be a non-empty API path")
|
|
@@ -555,7 +544,7 @@ class EdgarClient:
|
|
|
555
544
|
) -> EdgarAPIError:
|
|
556
545
|
payload = self._response_json(response)
|
|
557
546
|
message = f"HTTP {response.status_code}"
|
|
558
|
-
error_type
|
|
547
|
+
error_cls, error_type = self._error_classification(response.status_code)
|
|
559
548
|
details: Any | None = None
|
|
560
549
|
|
|
561
550
|
if isinstance(payload, Mapping):
|
|
@@ -575,7 +564,6 @@ class EdgarClient:
|
|
|
575
564
|
message = text[:300]
|
|
576
565
|
details = self._text_details(text)
|
|
577
566
|
|
|
578
|
-
error_cls = self._error_class(response.status_code)
|
|
579
567
|
return error_cls(
|
|
580
568
|
response.status_code,
|
|
581
569
|
message,
|
|
@@ -604,27 +592,18 @@ class EdgarClient:
|
|
|
604
592
|
return {**details, "cta": payload["cta"]}
|
|
605
593
|
return {"details": details, "cta": payload["cta"]}
|
|
606
594
|
|
|
607
|
-
def
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
if status_code in {400, 422}:
|
|
611
|
-
return "validation_error"
|
|
612
|
-
if status_code in {401, 403}:
|
|
613
|
-
return "auth_error"
|
|
614
|
-
if status_code == 404:
|
|
615
|
-
return "not_found"
|
|
616
|
-
return None
|
|
617
|
-
|
|
618
|
-
def _error_class(self, status_code: int) -> type[EdgarAPIError]:
|
|
595
|
+
def _error_classification(
|
|
596
|
+
self, status_code: int
|
|
597
|
+
) -> tuple[type[EdgarAPIError], str | None]:
|
|
619
598
|
if status_code in {401, 403}:
|
|
620
|
-
return EdgarAuthError
|
|
599
|
+
return EdgarAuthError, "auth_error"
|
|
621
600
|
if status_code == 429:
|
|
622
|
-
return EdgarRateLimitError
|
|
601
|
+
return EdgarRateLimitError, "rate_limit"
|
|
623
602
|
if status_code == 404:
|
|
624
|
-
return EdgarNotFoundError
|
|
603
|
+
return EdgarNotFoundError, "not_found"
|
|
625
604
|
if status_code in {400, 422}:
|
|
626
|
-
return EdgarValidationError
|
|
627
|
-
return EdgarAPIError
|
|
605
|
+
return EdgarValidationError, "validation_error"
|
|
606
|
+
return EdgarAPIError, None
|
|
628
607
|
|
|
629
608
|
def _text_details(self, text: str) -> dict[str, str] | None:
|
|
630
609
|
if not text:
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from edgarparser import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, EdgarClient
|
|
5
|
+
from edgarparser import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, EdgarClient, EdgarError
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class RecordingSession:
|
|
@@ -20,7 +20,7 @@ def test_client_defaults(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
20
20
|
|
|
21
21
|
assert client.base_url == DEFAULT_BASE_URL
|
|
22
22
|
assert client.timeout == DEFAULT_TIMEOUT
|
|
23
|
-
assert client.headers() == {"User-Agent": "edgarparser-sdk/0.1.
|
|
23
|
+
assert client.headers() == {"User-Agent": "edgarparser-sdk/0.1.2"}
|
|
24
24
|
assert "api_key=<unset>" in repr(client)
|
|
25
25
|
|
|
26
26
|
|
|
@@ -56,13 +56,11 @@ def test_client_validates_base_url_and_timeout() -> None:
|
|
|
56
56
|
EdgarClient(timeout=0)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def
|
|
59
|
+
def test_client_close_is_idempotent() -> None:
|
|
60
60
|
client = EdgarClient(api_key="x")
|
|
61
61
|
client.close()
|
|
62
62
|
client.close()
|
|
63
63
|
|
|
64
|
-
assert client._debug_state()["closed"] is True
|
|
65
|
-
|
|
66
64
|
|
|
67
65
|
def test_client_does_not_close_injected_session() -> None:
|
|
68
66
|
session = RecordingSession()
|
|
@@ -71,11 +69,11 @@ def test_client_does_not_close_injected_session() -> None:
|
|
|
71
69
|
client.close()
|
|
72
70
|
|
|
73
71
|
assert session.closed is False
|
|
74
|
-
assert client._debug_state()["closed"] is True
|
|
75
72
|
|
|
76
73
|
|
|
77
|
-
def
|
|
74
|
+
def test_context_manager_rejects_requests_after_exit() -> None:
|
|
78
75
|
with EdgarClient(api_key="x") as client:
|
|
79
|
-
|
|
76
|
+
pass
|
|
80
77
|
|
|
81
|
-
|
|
78
|
+
with pytest.raises(EdgarError, match="client is closed"):
|
|
79
|
+
client.get_financials("AAPL", year=2025, quarter=1)
|
|
@@ -5,7 +5,7 @@ def test_import_exports_client_and_version() -> None:
|
|
|
5
5
|
import edgarparser
|
|
6
6
|
from edgarparser import EdgarAPIError, EdgarClient, EdgarError
|
|
7
7
|
|
|
8
|
-
assert edgarparser.__version__ == "0.1.
|
|
8
|
+
assert edgarparser.__version__ == "0.1.2"
|
|
9
9
|
assert EdgarClient.__name__ == "EdgarClient"
|
|
10
10
|
assert EdgarError.__name__ == "EdgarError"
|
|
11
11
|
assert issubclass(EdgarAPIError, EdgarError)
|
|
@@ -93,7 +93,6 @@ def test_sdk_manifest_matches_tool_manifest_contracts() -> None:
|
|
|
93
93
|
assert tool["api_method"] == spec.api_method
|
|
94
94
|
assert tool["api_path"] == spec.api_path
|
|
95
95
|
assert tool["contract_version"] == spec.contract_version
|
|
96
|
-
assert tool["schema_fingerprint"] == spec.schema_fingerprint
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
def test_sdk_manifest_matches_fastapi_route_contracts() -> None:
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
import tarfile
|
|
6
|
+
import zipfile
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import tomllib
|
|
10
|
+
|
|
11
|
+
PACKAGE_ROOT = Path(__file__).resolve().parents[1]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_pyproject_uses_package_version_as_source_of_truth() -> None:
|
|
15
|
+
pyproject = tomllib.loads((PACKAGE_ROOT / "pyproject.toml").read_text())
|
|
16
|
+
|
|
17
|
+
assert pyproject["project"]["name"] == "edgarparser-sdk"
|
|
18
|
+
assert pyproject["project"]["dynamic"] == ["version"]
|
|
19
|
+
assert pyproject["tool"]["hatch"]["version"]["path"] == (
|
|
20
|
+
"src/edgarparser/__init__.py"
|
|
21
|
+
)
|
|
22
|
+
assert pyproject["tool"]["hatch"]["build"]["targets"]["wheel"][
|
|
23
|
+
"core-metadata-version"
|
|
24
|
+
] == "2.4"
|
|
25
|
+
assert pyproject["tool"]["hatch"]["build"]["targets"]["sdist"][
|
|
26
|
+
"core-metadata-version"
|
|
27
|
+
] == "2.4"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_distributions_use_compatible_metadata_and_wheel_contents(
|
|
31
|
+
tmp_path: Path,
|
|
32
|
+
) -> None:
|
|
33
|
+
subprocess.run(
|
|
34
|
+
[
|
|
35
|
+
sys.executable,
|
|
36
|
+
"-m",
|
|
37
|
+
"build",
|
|
38
|
+
"--outdir",
|
|
39
|
+
str(tmp_path),
|
|
40
|
+
str(PACKAGE_ROOT),
|
|
41
|
+
],
|
|
42
|
+
check=True,
|
|
43
|
+
capture_output=True,
|
|
44
|
+
text=True,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
wheel = next(tmp_path.glob("edgarparser_sdk-*.whl"))
|
|
48
|
+
with zipfile.ZipFile(wheel) as archive:
|
|
49
|
+
names = set(archive.namelist())
|
|
50
|
+
metadata_name = next(
|
|
51
|
+
name for name in names if name.endswith(".dist-info/METADATA")
|
|
52
|
+
)
|
|
53
|
+
metadata = archive.read(metadata_name)
|
|
54
|
+
|
|
55
|
+
assert metadata.splitlines()[0] == b"Metadata-Version: 2.4"
|
|
56
|
+
assert "edgarparser/py.typed" in names
|
|
57
|
+
assert any(name.endswith(".dist-info/licenses/LICENSE") for name in names)
|
|
58
|
+
|
|
59
|
+
sdist = next(tmp_path.glob("edgarparser_sdk-*.tar.gz"))
|
|
60
|
+
with tarfile.open(sdist, "r:gz") as archive:
|
|
61
|
+
pkg_info_member = next(
|
|
62
|
+
member
|
|
63
|
+
for member in archive.getmembers()
|
|
64
|
+
if member.name.endswith("/PKG-INFO")
|
|
65
|
+
and len(Path(member.name).parts) == 2
|
|
66
|
+
)
|
|
67
|
+
pkg_info_file = archive.extractfile(pkg_info_member)
|
|
68
|
+
assert pkg_info_file is not None
|
|
69
|
+
pkg_info = pkg_info_file.read()
|
|
70
|
+
|
|
71
|
+
assert pkg_info.splitlines()[0] == b"Metadata-Version: 2.4"
|
|
@@ -86,7 +86,7 @@ def test_request_builds_url_headers_params_body_and_timeout() -> None:
|
|
|
86
86
|
"method": "GET",
|
|
87
87
|
"url": "https://api.example.com/api/test",
|
|
88
88
|
"headers": {
|
|
89
|
-
"User-Agent": "edgarparser-sdk/0.1.
|
|
89
|
+
"User-Agent": "edgarparser-sdk/0.1.2",
|
|
90
90
|
"Authorization": "Bearer secret-key",
|
|
91
91
|
},
|
|
92
92
|
"params": {"ticker": "AAPL"},
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import subprocess
|
|
4
|
-
import sys
|
|
5
|
-
import zipfile
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
8
|
-
import tomllib
|
|
9
|
-
|
|
10
|
-
PACKAGE_ROOT = Path(__file__).resolve().parents[1]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_pyproject_uses_package_version_as_source_of_truth() -> None:
|
|
14
|
-
pyproject = tomllib.loads((PACKAGE_ROOT / "pyproject.toml").read_text())
|
|
15
|
-
|
|
16
|
-
assert pyproject["project"]["name"] == "edgarparser-sdk"
|
|
17
|
-
assert pyproject["project"]["dynamic"] == ["version"]
|
|
18
|
-
assert pyproject["tool"]["hatch"]["version"]["path"] == (
|
|
19
|
-
"src/edgarparser/__init__.py"
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_wheel_contains_typed_marker_and_license(tmp_path: Path) -> None:
|
|
24
|
-
subprocess.run(
|
|
25
|
-
[
|
|
26
|
-
sys.executable,
|
|
27
|
-
"-m",
|
|
28
|
-
"build",
|
|
29
|
-
"--wheel",
|
|
30
|
-
"--outdir",
|
|
31
|
-
str(tmp_path),
|
|
32
|
-
str(PACKAGE_ROOT),
|
|
33
|
-
],
|
|
34
|
-
check=True,
|
|
35
|
-
capture_output=True,
|
|
36
|
-
text=True,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
wheel = next(tmp_path.glob("edgarparser_sdk-*.whl"))
|
|
40
|
-
with zipfile.ZipFile(wheel) as archive:
|
|
41
|
-
names = set(archive.namelist())
|
|
42
|
-
|
|
43
|
-
assert "edgarparser/py.typed" in names
|
|
44
|
-
assert any(name.endswith(".dist-info/licenses/LICENSE") for name in names)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|