internetdata 2.7.4__tar.gz → 2.7.5__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.4 → internetdata-2.7.5}/PKG-INFO +1 -1
  2. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/__init__.py +1 -1
  3. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/models.py +52 -28
  4. {internetdata-2.7.4 → internetdata-2.7.5}/tests/test_client.py +44 -0
  5. {internetdata-2.7.4 → internetdata-2.7.5}/.gitignore +0 -0
  6. {internetdata-2.7.4 → internetdata-2.7.5}/LICENSE +0 -0
  7. {internetdata-2.7.4 → internetdata-2.7.5}/README.md +0 -0
  8. {internetdata-2.7.4 → internetdata-2.7.5}/pyproject.toml +0 -0
  9. {internetdata-2.7.4 → internetdata-2.7.5}/scripts/download-spec.sh +0 -0
  10. {internetdata-2.7.4 → internetdata-2.7.5}/scripts/generate.sh +0 -0
  11. {internetdata-2.7.4 → internetdata-2.7.5}/scripts/publish.sh +0 -0
  12. {internetdata-2.7.4 → internetdata-2.7.5}/scripts/v2_subset.py +0 -0
  13. {internetdata-2.7.4 → internetdata-2.7.5}/spec/openapi.yaml +0 -0
  14. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_core.py +0 -0
  15. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/__init__.py +0 -0
  16. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/__init__.py +0 -0
  17. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/account/__init__.py +0 -0
  18. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/account/account_identity.py +0 -0
  19. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/__init__.py +0 -0
  20. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/account_create_apikey.py +0 -0
  21. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/account_list_apikeys.py +0 -0
  22. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/account_reveal_apikey.py +0 -0
  23. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/account_revoke_apikey.py +0 -0
  24. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/api_keys/account_rotate_apikey.py +0 -0
  25. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/__init__.py +0 -0
  26. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/oauth_authorize.py +0 -0
  27. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/oauth_device_authorization.py +0 -0
  28. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/oauth_metadata.py +0 -0
  29. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/oauth_revoke.py +0 -0
  30. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/authorization/oauth_token.py +0 -0
  31. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/__init__.py +0 -0
  32. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/database_checksum_v2.py +0 -0
  33. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/database_metadata_v2.py +0 -0
  34. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/download_database_v2.py +0 -0
  35. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/list_databases.py +0 -0
  36. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/database_v_2/list_downloads.py +0 -0
  37. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/organization/__init__.py +0 -0
  38. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/organization/account_org.py +0 -0
  39. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/api/organization/account_org_members.py +0 -0
  40. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/client.py +0 -0
  41. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/errors.py +0 -0
  42. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/__init__.py +0 -0
  43. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_create_apikey_request.py +0 -0
  44. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_created_apikey.py +0 -0
  45. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_org.py +0 -0
  46. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_org_ref.py +0 -0
  47. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_org_wrap.py +0 -0
  48. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_rc.py +0 -0
  49. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_revealed_apikey.py +0 -0
  50. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/account_user.py +0 -0
  51. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/apikey_detail.py +0 -0
  52. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/apikey_list.py +0 -0
  53. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database.py +0 -0
  54. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_checksum_v2_response_200.py +0 -0
  55. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_format.py +0 -0
  56. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_license_type_type_1.py +0 -0
  57. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_license_type_type_2_type_1.py +0 -0
  58. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_license_type_type_3_type_1.py +0 -0
  59. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata.py +0 -0
  60. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_column.py +0 -0
  61. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_sample.py +0 -0
  62. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_sample_additional_property_item.py +0 -0
  63. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_sample_size.py +0 -0
  64. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_schema.py +0 -0
  65. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_metadata_size.py +0 -0
  66. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/database_version.py +0 -0
  67. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/db_checksums.py +0 -0
  68. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/device_authorization.py +0 -0
  69. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/device_authorization_request.py +0 -0
  70. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/download.py +0 -0
  71. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/download_outcome.py +0 -0
  72. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/error.py +0 -0
  73. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/identity.py +0 -0
  74. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/list_databases_response_200.py +0 -0
  75. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/list_downloads_response_200.py +0 -0
  76. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/oauth_authorize_code_challenge_method.py +0 -0
  77. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/oauth_authorize_response_type.py +0 -0
  78. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/oauth_error.py +0 -0
  79. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/oauth_metadata.py +0 -0
  80. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/oauth_revoke_response_200.py +0 -0
  81. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/revoke_request.py +0 -0
  82. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/standing.py +0 -0
  83. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/token_request.py +0 -0
  84. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/models/token_response.py +0 -0
  85. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/_generated/types.py +0 -0
  86. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/aio.py +0 -0
  87. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/client.py +0 -0
  88. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/errors.py +0 -0
  89. {internetdata-2.7.4 → internetdata-2.7.5}/src/internetdata/py.typed +0 -0
  90. {internetdata-2.7.4 → internetdata-2.7.5}/testdata/testdata.json +0 -0
  91. {internetdata-2.7.4 → internetdata-2.7.5}/tests/conftest.py +0 -0
  92. {internetdata-2.7.4 → internetdata-2.7.5}/tests/helpers.py +0 -0
  93. {internetdata-2.7.4 → internetdata-2.7.5}/tests/test_conformance.py +0 -0
  94. {internetdata-2.7.4 → internetdata-2.7.5}/tests/test_download.py +0 -0
  95. {internetdata-2.7.4 → internetdata-2.7.5}/tests/test_oauth.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: internetdata
3
- Version: 2.7.4
3
+ Version: 2.7.5
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
@@ -39,7 +39,7 @@ from .models import (
39
39
  TokenResponse,
40
40
  )
41
41
 
42
- __version__ = "2.7.4"
42
+ __version__ = "2.7.5"
43
43
 
44
44
  __all__ = [
45
45
  "DATABASE_FORMATS",
@@ -174,85 +174,109 @@ class Download:
174
174
 
175
175
  def to_database(body: dict[str, Any]) -> Database:
176
176
  return Database(
177
- base=_present(body, "base"),
178
- name=_present(body, "name"),
179
- summary=_present(body, "summary"),
180
- standing=_present(body, "standing"),
181
- license_type=body["license_type"],
177
+ base=_present(body, "base", str),
178
+ name=_present(body, "name", str),
179
+ summary=_present(body, "summary", str),
180
+ standing=_present(body, "standing", str),
181
+ license_type=_nullable(body, "license_type", str),
182
182
  starts=_datetime(body["starts"]),
183
183
  expires=_datetime(body["expires"]),
184
184
  renews_at=_datetime(body["renews_at"]),
185
185
  notice_due_at=_datetime(body["notice_due_at"]),
186
- versions=tuple(to_version(v) for v in _present(body, "versions")),
186
+ versions=tuple(to_version(v) for v in _present(body, "versions", list)),
187
187
  raw=body,
188
- open=_present(body, "open"),
188
+ open=_present(body, "open", bool),
189
189
  )
190
190
 
191
191
 
192
192
  def to_version(body: dict[str, Any]) -> DatabaseVersion:
193
193
  return DatabaseVersion(
194
- id=_present(body, "id"),
195
- version=_present(body, "version"),
196
- summary=_present(body, "summary"),
197
- formats=tuple(_present(body, "formats")),
194
+ id=_present(body, "id", str),
195
+ version=_present(body, "version", int),
196
+ summary=_present(body, "summary", str),
197
+ formats=_strings(_present(body, "formats", list), "formats"),
198
198
  sample_formats=_optional_tuple(body.get("sample_formats")),
199
199
  )
200
200
 
201
201
 
202
202
  def to_metadata(body: dict[str, Any]) -> DatabaseMetadata:
203
203
  return DatabaseMetadata(
204
- id=_present(body, "id"),
204
+ id=_present(body, "id", str),
205
205
  updated=datetime.date.fromisoformat(body["updated"]),
206
- entries=_present(body, "entries"),
206
+ entries=_present(body, "entries", int),
207
207
  schema={
208
208
  fmt: tuple(to_column(c) for c in columns) for fmt, columns in body["schema"].items()
209
209
  },
210
- size=dict(body["size"]),
210
+ size=_sizes(_present(body, "size", dict), "size"),
211
211
  update_freq=body.get("update_freq"),
212
212
  sample={fmt: tuple(rows) for fmt, rows in body.get("sample", {}).items()},
213
213
  raw=body,
214
- sample_size=dict(body["sample_size"]) if body.get("sample_size") is not None else None,
215
- sample_entries=body.get("sample_entries"),
214
+ sample_size=_sizes(body["sample_size"], "sample_size")
215
+ if body.get("sample_size") is not None
216
+ else None,
217
+ sample_entries=_nullable(body, "sample_entries", int, absent=True),
216
218
  )
217
219
 
218
220
 
219
221
  def to_column(body: dict[str, Any]) -> MetadataColumn:
220
222
  return MetadataColumn(
221
- name=_present(body, "name"),
222
- type=_present(body, "type"),
223
+ name=_present(body, "name", str),
224
+ type=_present(body, "type", str),
223
225
  description=body.get("description"),
224
226
  )
225
227
 
226
228
 
227
229
  def to_download(body: dict[str, Any]) -> Download:
228
230
  return Download(
229
- dataset_id=_present(body, "dataset_id"),
230
- format=_present(body, "format"),
231
- outcome=_present(body, "outcome"),
231
+ dataset_id=_present(body, "dataset_id", str),
232
+ format=_present(body, "format", str),
233
+ outcome=_present(body, "outcome", str),
232
234
  created=datetime.datetime.fromisoformat(body["created"]),
233
- bytes=body["bytes"],
234
- http_status=body["http_status"],
235
+ bytes=_nullable(body, "bytes", int),
236
+ http_status=_nullable(body, "http_status", int),
235
237
  apikey_id=body["apikey_id"],
236
238
  client_ip=body["client_ip"],
237
239
  user_agent=body["user_agent"],
238
- sample=_present(body, "sample"),
239
- open=_present(body, "open"),
240
+ sample=_present(body, "sample", bool),
241
+ open=_present(body, "open", bool),
240
242
  )
241
243
 
242
244
 
243
- def _present(body: dict[str, Any], name: str) -> Any:
244
- """A member the spec requires and never sends as null.
245
+ def _present(body: dict[str, Any], name: str, kind: type) -> Any:
246
+ """A member the spec requires and never sends as null, of the type it gives.
245
247
 
246
248
  A null one is the server's failure, raised for the caller to report as one, rather
247
249
  than handed back in the answer: 2.7.1 listed a family whose `base` was null as a
248
- family with no base (measured 2026-10-12).
250
+ family with no base (measured 2026-10-12). So is one of another type: 2.7.4 handed
251
+ back a version served as `"3"` as that string (measured 2026-10-16).
249
252
  """
250
253
  value = body[name]
251
254
  if value is None:
252
255
  raise ValueError(f"{name} is null")
256
+ return _of_type(value, name, kind)
257
+
258
+
259
+ def _nullable(body: dict[str, Any], name: str, kind: type, absent: bool = False) -> Any:
260
+ """A member that may be null, or with `absent` left out, and is otherwise of `kind`."""
261
+ value = body.get(name) if absent else body[name]
262
+ return None if value is None else _of_type(value, name, kind)
263
+
264
+
265
+ def _of_type(value: Any, name: str, kind: type) -> Any:
266
+ # A bool is an int to isinstance, and neither may stand for the other.
267
+ if isinstance(value, bool) != (kind is bool) or not isinstance(value, kind):
268
+ raise ValueError(f"{name} is not a {kind.__name__}: {value!r}")
253
269
  return value
254
270
 
255
271
 
272
+ def _strings(values: list[Any], name: str) -> tuple[Any, ...]:
273
+ return tuple(_of_type(v, name, str) for v in values)
274
+
275
+
276
+ def _sizes(sizes: Any, name: str) -> dict[str, int]:
277
+ return {fmt: _of_type(n, name, int) for fmt, n in _of_type(sizes, name, dict).items()}
278
+
279
+
256
280
  def _optional_tuple(value: Any) -> tuple[Any, ...] | None:
257
281
  return tuple(value) if value is not None else None
258
282
 
@@ -410,6 +410,50 @@ UNREADABLE_MEMBERS: dict[str, tuple[str, dict[str, Any]]] = {
410
410
  ),
411
411
  }
412
412
 
413
+
414
+ def _with(member: str, value: Any, entry: dict[str, Any]) -> dict[str, Any]:
415
+ return {**entry, member: value}
416
+
417
+
418
+ def _version_with(member: str, value: Any) -> dict[str, Any]:
419
+ family = database("bogon_ip")
420
+ return {**family, "versions": [_with(member, value, family["versions"][0])]}
421
+
422
+
423
+ _DOWNLOAD = cast(list[dict[str, Any]], DOWNLOADS["downloads"])[0]
424
+
425
+ # A member of another type than the spec gives it, which 2.7.4 handed back in the answer:
426
+ # a version served as "3" came back as that string (measured 2026-10-16).
427
+ UNREADABLE_MEMBERS.update(
428
+ {
429
+ "list version as a numeric string": (
430
+ LIST_PATH,
431
+ {"databases": [_version_with("version", "3")]},
432
+ ),
433
+ "list version as true": (LIST_PATH, {"databases": [_version_with("version", True)]}),
434
+ "list format as a number": (LIST_PATH, {"databases": [_version_with("formats", [1])]}),
435
+ "list base as a number": (
436
+ LIST_PATH,
437
+ {"databases": [_with("base", 7, database("bogon_ip"))]},
438
+ ),
439
+ "list open as a string": (
440
+ LIST_PATH,
441
+ {"databases": [_with("open", "false", database("bogon_ip"))]},
442
+ ),
443
+ "list license_type as a number": (
444
+ LIST_PATH,
445
+ {"databases": [_with("license_type", 1, database("bogon_ip"))]},
446
+ ),
447
+ "metadata entries as a string": (METADATA_PATH, _with("entries", "42", METADATA)),
448
+ "metadata size as a string": (METADATA_PATH, _with("size", {"csvgz": "760"}, METADATA)),
449
+ "downloads bytes as a string": (
450
+ DOWNLOADS_PATH,
451
+ {"downloads": [_with("bytes", "760", _DOWNLOAD)]},
452
+ ),
453
+ "downloads sample as 1": (DOWNLOADS_PATH, {"downloads": [_with("sample", 1, _DOWNLOAD)]}),
454
+ }
455
+ )
456
+
413
457
  MEMBER_CALLS = {LIST_PATH: "list", METADATA_PATH: "metadata", DOWNLOADS_PATH: "downloads"}
414
458
 
415
459
 
File without changes
File without changes
File without changes