internetdata 2.7.3__tar.gz → 2.7.4__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 (95) hide show
  1. {internetdata-2.7.3 → internetdata-2.7.4}/PKG-INFO +1 -1
  2. {internetdata-2.7.3 → internetdata-2.7.4}/spec/openapi.yaml +4 -4
  3. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/__init__.py +1 -1
  4. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_core.py +13 -7
  5. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/organization/account_org_members.py +4 -4
  6. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_create_apikey_request.py +1 -1
  7. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/apikey_detail.py +1 -1
  8. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata.py +1 -3
  9. {internetdata-2.7.3 → internetdata-2.7.4}/tests/test_conformance.py +36 -4
  10. {internetdata-2.7.3 → internetdata-2.7.4}/.gitignore +0 -0
  11. {internetdata-2.7.3 → internetdata-2.7.4}/LICENSE +0 -0
  12. {internetdata-2.7.3 → internetdata-2.7.4}/README.md +0 -0
  13. {internetdata-2.7.3 → internetdata-2.7.4}/pyproject.toml +0 -0
  14. {internetdata-2.7.3 → internetdata-2.7.4}/scripts/download-spec.sh +0 -0
  15. {internetdata-2.7.3 → internetdata-2.7.4}/scripts/generate.sh +0 -0
  16. {internetdata-2.7.3 → internetdata-2.7.4}/scripts/publish.sh +0 -0
  17. {internetdata-2.7.3 → internetdata-2.7.4}/scripts/v2_subset.py +0 -0
  18. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/__init__.py +0 -0
  19. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/__init__.py +0 -0
  20. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/account/__init__.py +0 -0
  21. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/account/account_identity.py +0 -0
  22. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/__init__.py +0 -0
  23. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/account_create_apikey.py +0 -0
  24. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/account_list_apikeys.py +0 -0
  25. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/account_reveal_apikey.py +0 -0
  26. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/account_revoke_apikey.py +0 -0
  27. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/api_keys/account_rotate_apikey.py +0 -0
  28. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/__init__.py +0 -0
  29. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/oauth_authorize.py +0 -0
  30. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/oauth_device_authorization.py +0 -0
  31. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/oauth_metadata.py +0 -0
  32. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/oauth_revoke.py +0 -0
  33. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/authorization/oauth_token.py +0 -0
  34. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/__init__.py +0 -0
  35. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/database_checksum_v2.py +0 -0
  36. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/database_metadata_v2.py +0 -0
  37. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/download_database_v2.py +0 -0
  38. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/list_databases.py +0 -0
  39. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/database_v_2/list_downloads.py +0 -0
  40. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/organization/__init__.py +0 -0
  41. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/api/organization/account_org.py +0 -0
  42. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/client.py +0 -0
  43. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/errors.py +0 -0
  44. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/__init__.py +0 -0
  45. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_created_apikey.py +0 -0
  46. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_org.py +0 -0
  47. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_org_ref.py +0 -0
  48. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_org_wrap.py +0 -0
  49. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_rc.py +0 -0
  50. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_revealed_apikey.py +0 -0
  51. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/account_user.py +0 -0
  52. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/apikey_list.py +0 -0
  53. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database.py +0 -0
  54. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_checksum_v2_response_200.py +0 -0
  55. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_format.py +0 -0
  56. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_license_type_type_1.py +0 -0
  57. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_license_type_type_2_type_1.py +0 -0
  58. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_license_type_type_3_type_1.py +0 -0
  59. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_column.py +0 -0
  60. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_sample.py +0 -0
  61. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_sample_additional_property_item.py +0 -0
  62. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_sample_size.py +0 -0
  63. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_schema.py +0 -0
  64. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_metadata_size.py +0 -0
  65. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/database_version.py +0 -0
  66. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/db_checksums.py +0 -0
  67. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/device_authorization.py +0 -0
  68. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/device_authorization_request.py +0 -0
  69. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/download.py +0 -0
  70. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/download_outcome.py +0 -0
  71. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/error.py +0 -0
  72. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/identity.py +0 -0
  73. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/list_databases_response_200.py +0 -0
  74. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/list_downloads_response_200.py +0 -0
  75. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/oauth_authorize_code_challenge_method.py +0 -0
  76. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/oauth_authorize_response_type.py +0 -0
  77. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/oauth_error.py +0 -0
  78. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/oauth_metadata.py +0 -0
  79. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/oauth_revoke_response_200.py +0 -0
  80. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/revoke_request.py +0 -0
  81. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/standing.py +0 -0
  82. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/token_request.py +0 -0
  83. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/models/token_response.py +0 -0
  84. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/_generated/types.py +0 -0
  85. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/aio.py +0 -0
  86. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/client.py +0 -0
  87. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/errors.py +0 -0
  88. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/models.py +0 -0
  89. {internetdata-2.7.3 → internetdata-2.7.4}/src/internetdata/py.typed +0 -0
  90. {internetdata-2.7.3 → internetdata-2.7.4}/testdata/testdata.json +0 -0
  91. {internetdata-2.7.3 → internetdata-2.7.4}/tests/conftest.py +0 -0
  92. {internetdata-2.7.3 → internetdata-2.7.4}/tests/helpers.py +0 -0
  93. {internetdata-2.7.3 → internetdata-2.7.4}/tests/test_client.py +0 -0
  94. {internetdata-2.7.3 → internetdata-2.7.4}/tests/test_download.py +0 -0
  95. {internetdata-2.7.3 → internetdata-2.7.4}/tests/test_oauth.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: internetdata
3
- Version: 2.7.3
3
+ Version: 2.7.4
4
4
  Summary: Official Python client library for the InternetData API. Download and verify licensed IP datasets.
5
5
  Project-URL: Homepage, https://internetdata.io
6
6
  Project-URL: Documentation, https://docs.internetdata.io
@@ -12,7 +12,7 @@ info:
12
12
  email: support@internetdata.io
13
13
  url: https://internetdata.io
14
14
  termsOfService: https://internetdata.io/terms
15
- version: 2026.10.13
15
+ version: 2026.10.15
16
16
  servers:
17
17
  - url: https://internetdata.io
18
18
  tags:
@@ -416,7 +416,7 @@ paths:
416
416
  summary: Members
417
417
  description: |
418
418
  Read-only. Adding or removing a member is an invitation flow with email
419
- in the middle rather than a POST, and modelling it as one here would
419
+ in the middle rather than a POST, and modeling it as one here would
420
420
  promise something this API does not do.
421
421
  security:
422
422
  - BearerAuth:
@@ -1365,7 +1365,7 @@ components:
1365
1365
  type: string
1366
1366
  key_prefix:
1367
1367
  type: string
1368
- description: The leading, non-secret part, so a key is recognisable without storing it.
1368
+ description: The leading, non-secret part, so a key is recognizable without storing it.
1369
1369
  created:
1370
1370
  type: string
1371
1371
  format: date-time
@@ -1405,7 +1405,7 @@ components:
1405
1405
  properties:
1406
1406
  name:
1407
1407
  type: string
1408
- description: A label you will recognise later. Shown wherever the key is listed.
1408
+ description: A label you will recognize later. Shown wherever the key is listed.
1409
1409
  allowed_scopes:
1410
1410
  type: array
1411
1411
  items:
@@ -39,7 +39,7 @@ from .models import (
39
39
  TokenResponse,
40
40
  )
41
41
 
42
- __version__ = "2.7.3"
42
+ __version__ = "2.7.4"
43
43
 
44
44
  __all__ = [
45
45
  "DATABASE_FORMATS",
@@ -81,6 +81,11 @@ def build_client(
81
81
  the `Authorization` header when it CONSTRUCTS the httpx client itself.
82
82
  """
83
83
  api_key = check_api_key(api_key)
84
+ # httpx drops one trailing slash when it joins a path onto the base URL and keeps the
85
+ # rest, so a second or third reached the API as `//api/v2/database/list`, which prod
86
+ # answers with a redirect this client does not follow: every call failed (2.7.3,
87
+ # measured 2026-10-16).
88
+ base_url = base_url.rstrip("/")
84
89
  httpx_args: dict[str, Any] = {}
85
90
  if transport is not None:
86
91
  httpx_args["transport"] = transport
@@ -135,19 +140,20 @@ def build_async_transfer_client(
135
140
  def check_api_key(api_key: str | None) -> str | None:
136
141
  """`api_key` without the blanks around it, or None when nothing else is left.
137
142
 
138
- Refused where it is SET when a control character remains: httpx refuses a header
139
- holding a CR, LF or NUL, so every call failed as a retried `network` error with nothing
140
- sent, while a tab or DEL inside the key went out on the wire. Untrimmed, a key of blanks
141
- was sent as one rather than as no key, and failed every call the same way (2.7.1,
142
- measured 2026-10-12).
143
+ Refused where it is SET when a control character remains, or a character outside
144
+ ASCII, which httpx cannot put in a header: a CR, LF or NUL failed every call as a
145
+ retried `network` error with nothing sent, a C1 control or any other non-ASCII
146
+ character as a raw `UnicodeEncodeError` (2.7.3, measured 2026-10-16), while a tab or
147
+ DEL went out on the wire. Untrimmed, a key of blanks was sent as one rather than as no
148
+ key, and failed every call the same way (2.7.1, measured 2026-10-12).
143
149
  """
144
150
  if api_key is None:
145
151
  return None
146
152
  if not isinstance(api_key, str):
147
153
  raise TypeError(f"api_key must be a string or None, not {type(api_key).__name__}")
148
154
  key = api_key.strip()
149
- if any(ord(char) < 0x20 or ord(char) == 0x7F for char in key):
150
- raise ValueError("api_key holds a control character")
155
+ if any(ord(char) < 0x20 or ord(char) >= 0x7F for char in key):
156
+ raise ValueError("api_key holds a control character or one outside ASCII")
151
157
  return key or None
152
158
 
153
159
 
@@ -61,7 +61,7 @@ def sync_detailed(
61
61
  """Members
62
62
 
63
63
  Read-only. Adding or removing a member is an invitation flow with email
64
- in the middle rather than a POST, and modelling it as one here would
64
+ in the middle rather than a POST, and modeling it as one here would
65
65
  promise something this API does not do.
66
66
 
67
67
  Raises:
@@ -88,7 +88,7 @@ def sync(
88
88
  """Members
89
89
 
90
90
  Read-only. Adding or removing a member is an invitation flow with email
91
- in the middle rather than a POST, and modelling it as one here would
91
+ in the middle rather than a POST, and modeling it as one here would
92
92
  promise something this API does not do.
93
93
 
94
94
  Raises:
@@ -111,7 +111,7 @@ async def asyncio_detailed(
111
111
  """Members
112
112
 
113
113
  Read-only. Adding or removing a member is an invitation flow with email
114
- in the middle rather than a POST, and modelling it as one here would
114
+ in the middle rather than a POST, and modeling it as one here would
115
115
  promise something this API does not do.
116
116
 
117
117
  Raises:
@@ -136,7 +136,7 @@ async def asyncio(
136
136
  """Members
137
137
 
138
138
  Read-only. Adding or removing a member is an invitation flow with email
139
- in the middle rather than a POST, and modelling it as one here would
139
+ in the middle rather than a POST, and modeling it as one here would
140
140
  promise something this API does not do.
141
141
 
142
142
  Raises:
@@ -15,7 +15,7 @@ T = TypeVar("T", bound="AccountCreateApikeyRequest")
15
15
  class AccountCreateApikeyRequest:
16
16
  """
17
17
  Attributes:
18
- name (str): A label you will recognise later. Shown wherever the key is listed.
18
+ name (str): A label you will recognize later. Shown wherever the key is listed.
19
19
  allowed_scopes (list[str] | Unset): What the new key may do. Omit for a key that carries no named scope, which
20
20
  is the safe default.
21
21
  """
@@ -20,7 +20,7 @@ class ApikeyDetail:
20
20
  Attributes:
21
21
  id (UUID):
22
22
  name (str):
23
- key_prefix (str): The leading, non-secret part, so a key is recognisable without storing it.
23
+ key_prefix (str): The leading, non-secret part, so a key is recognizable without storing it.
24
24
  created (datetime.datetime):
25
25
  expires (datetime.datetime | None | Unset):
26
26
  last_used_at (datetime.datetime | None | Unset):
@@ -95,9 +95,7 @@ class DatabaseMetadata:
95
95
  @classmethod
96
96
  def from_dict(cls, src_dict: Mapping[str, Any]) -> Self:
97
97
  from ..models.database_metadata_sample import DatabaseMetadataSample
98
- from ..models.database_metadata_sample_size import (
99
- DatabaseMetadataSampleSize,
100
- )
98
+ from ..models.database_metadata_sample_size import DatabaseMetadataSampleSize
101
99
  from ..models.database_metadata_schema import DatabaseMetadataSchema
102
100
  from ..models.database_metadata_size import DatabaseMetadataSize
103
101
 
@@ -274,12 +274,44 @@ def test_the_api_key_is_trimmed(make_client: ClientFactory) -> None:
274
274
 
275
275
 
276
276
  @pytest.mark.parametrize(
277
- "api_key", ["key\r\nX-Injected: 1", "ke\ty", "key\x00", "key\x7f", "k\ney"]
277
+ "api_key", ["key\r\nX-Injected: 1", "ke\ty", "key\x00", "key\x7f", "k\ney", "k\x85ey", "kéy"]
278
278
  )
279
- def test_a_control_character_in_the_api_key_is_refused_where_it_is_set(
279
+ def test_a_control_character_or_one_outside_ascii_is_refused_where_the_key_is_set(
280
280
  make_client: ClientFactory, api_key: str
281
281
  ) -> None:
282
282
  """Accepted, a CR, LF or NUL failed every call as a retried network error with nothing
283
- sent, and a tab or DEL went out on the wire inside the header (2.7.1)."""
284
- with pytest.raises(ValueError, match="control character"):
283
+ sent, and a tab or DEL went out on the wire inside the header (2.7.1). A C1 control or
284
+ any other character outside ASCII failed every call with a raw UnicodeEncodeError and
285
+ nothing sent, since httpx encodes a header value as ASCII (2.7.3)."""
286
+ with pytest.raises(ValueError, match="control character or one outside ASCII"):
285
287
  make_client(api_key=api_key)
288
+
289
+
290
+ @pytest.mark.parametrize("slashes", [1, 2, 3])
291
+ def test_every_trailing_slash_on_the_base_url_is_dropped(
292
+ make_client: ClientFactory, slashes: int
293
+ ) -> None:
294
+ """httpx drops one when it joins a path on and keeps the rest, so through 2.7.3 a
295
+ second reached the API as `//api/v2/database/list`, which prod answers with a
296
+ redirect this client does not follow."""
297
+ digests = {"md5": "m", "sha1": "s1", "sha256": "s256", "sha512": "s512"}
298
+ stub = Stub(
299
+ {
300
+ LIST_PATH: {"body": {"databases": []}},
301
+ CHECKSUM_PATH: {"body": {"id": "bogon_ip_v1", "format": "csvgz", "checksums": digests}},
302
+ "/.well-known/oauth-authorization-server": {
303
+ "body": {
304
+ "issuer": "https://api.example",
305
+ "authorization_endpoint": "https://api.example/oauth/authorize",
306
+ "token_endpoint": "https://api.example/oauth/token",
307
+ }
308
+ },
309
+ }
310
+ )
311
+ client = make_client(transport=stub.transport, base_url="https://api.example" + "/" * slashes)
312
+
313
+ client.database.list()
314
+ client.database.checksums("bogon_ip_v1", "csvgz")
315
+ client.oauth.metadata()
316
+
317
+ assert stub.paths() == [LIST_PATH, CHECKSUM_PATH, "/.well-known/oauth-authorization-server"]
File without changes
File without changes
File without changes