boarddata 4.0.2__tar.gz → 4.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.
Files changed (59) hide show
  1. {boarddata-4.0.2 → boarddata-4.1.2}/PKG-INFO +1 -1
  2. {boarddata-4.0.2 → boarddata-4.1.2}/__init__.py +1 -1
  3. {boarddata-4.0.2 → boarddata-4.1.2}/_base.py +14 -6
  4. {boarddata-4.0.2 → boarddata-4.1.2}/_companies.py +3 -0
  5. boarddata-4.1.2/_indexes.py +127 -0
  6. {boarddata-4.0.2 → boarddata-4.1.2}/boarddata.egg-info/PKG-INFO +1 -1
  7. {boarddata-4.0.2 → boarddata-4.1.2}/boarddata.egg-info/SOURCES.txt +4 -0
  8. {boarddata-4.0.2 → boarddata-4.1.2}/cache.py +3 -0
  9. {boarddata-4.0.2 → boarddata-4.1.2}/client.py +2 -0
  10. {boarddata-4.0.2 → boarddata-4.1.2}/pyproject.toml +1 -1
  11. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_config.py +2 -2
  12. boarddata-4.1.2/tests/test_indexes.py +112 -0
  13. {boarddata-4.0.2 → boarddata-4.1.2}/types/__init__.py +15 -0
  14. boarddata-4.1.2/types/indexes.py +67 -0
  15. {boarddata-4.0.2 → boarddata-4.1.2}/CLAUDE.md +0 -0
  16. {boarddata-4.0.2 → boarddata-4.1.2}/README.md +0 -0
  17. {boarddata-4.0.2 → boarddata-4.1.2}/_assemblies.py +0 -0
  18. {boarddata-4.0.2 → boarddata-4.1.2}/_auditors.py +0 -0
  19. {boarddata-4.0.2 → boarddata-4.1.2}/_comex.py +0 -0
  20. {boarddata-4.0.2 → boarddata-4.1.2}/_criteria.py +0 -0
  21. {boarddata-4.0.2 → boarddata-4.1.2}/_directors.py +0 -0
  22. {boarddata-4.0.2 → boarddata-4.1.2}/_documents.py +0 -0
  23. {boarddata-4.0.2 → boarddata-4.1.2}/_esg.py +0 -0
  24. {boarddata-4.0.2 → boarddata-4.1.2}/_persons.py +0 -0
  25. {boarddata-4.0.2 → boarddata-4.1.2}/_sentinel.py +0 -0
  26. {boarddata-4.0.2 → boarddata-4.1.2}/_utilities.py +0 -0
  27. {boarddata-4.0.2 → boarddata-4.1.2}/boarddata.egg-info/dependency_links.txt +0 -0
  28. {boarddata-4.0.2 → boarddata-4.1.2}/boarddata.egg-info/requires.txt +0 -0
  29. {boarddata-4.0.2 → boarddata-4.1.2}/boarddata.egg-info/top_level.txt +0 -0
  30. {boarddata-4.0.2 → boarddata-4.1.2}/errors.py +0 -0
  31. {boarddata-4.0.2 → boarddata-4.1.2}/py.typed +0 -0
  32. {boarddata-4.0.2 → boarddata-4.1.2}/setup.cfg +0 -0
  33. {boarddata-4.0.2 → boarddata-4.1.2}/tests/__init__.py +0 -0
  34. {boarddata-4.0.2 → boarddata-4.1.2}/tests/conftest.py +0 -0
  35. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_assemblies.py +0 -0
  36. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_auditors.py +0 -0
  37. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_base.py +0 -0
  38. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_build_payload.py +0 -0
  39. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_cache.py +0 -0
  40. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_comex.py +0 -0
  41. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_companies.py +0 -0
  42. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_criteria.py +0 -0
  43. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_directors.py +0 -0
  44. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_documents.py +0 -0
  45. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_esg.py +0 -0
  46. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_persons.py +0 -0
  47. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_sentinel.py +0 -0
  48. {boarddata-4.0.2 → boarddata-4.1.2}/tests/test_utilities.py +0 -0
  49. {boarddata-4.0.2 → boarddata-4.1.2}/types/assemblies.py +0 -0
  50. {boarddata-4.0.2 → boarddata-4.1.2}/types/auditors.py +0 -0
  51. {boarddata-4.0.2 → boarddata-4.1.2}/types/comex.py +0 -0
  52. {boarddata-4.0.2 → boarddata-4.1.2}/types/companies.py +0 -0
  53. {boarddata-4.0.2 → boarddata-4.1.2}/types/core.py +0 -0
  54. {boarddata-4.0.2 → boarddata-4.1.2}/types/criteria.py +0 -0
  55. {boarddata-4.0.2 → boarddata-4.1.2}/types/directors.py +0 -0
  56. {boarddata-4.0.2 → boarddata-4.1.2}/types/documents.py +0 -0
  57. {boarddata-4.0.2 → boarddata-4.1.2}/types/esg.py +0 -0
  58. {boarddata-4.0.2 → boarddata-4.1.2}/types/persons.py +0 -0
  59. {boarddata-4.0.2 → boarddata-4.1.2}/types/sentinel.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boarddata
3
- Version: 4.0.2
3
+ Version: 4.1.2
4
4
  Summary: Python SDK for the BoardData V2 REST API
5
5
  License: MIT
6
6
  Classifier: Development Status :: 4 - Beta
@@ -7,7 +7,7 @@ from .errors import BoardDataError
7
7
 
8
8
  from . import types as types # noqa: F401 — makes types accessible as boarddata.types
9
9
 
10
- __version__ = "4.0.2"
10
+ __version__ = "4.1.2"
11
11
  __all__ = [
12
12
  "Base",
13
13
  "BoardDataClient",
@@ -105,15 +105,20 @@ class Base:
105
105
  timeout: int = 30,
106
106
  token_cache: TokenCache | None = None,
107
107
  ) -> None:
108
+ if not base_url.startswith("https://"):
109
+ logger.warning("base_url does not use HTTPS — credentials will be sent in plaintext")
108
110
  self.base_url = base_url.rstrip("/")
109
- self.client_id = client_id
110
- self.client_secret = client_secret
111
+ self._client_id = client_id
112
+ self._client_secret = client_secret
111
113
  self.timeout = timeout
112
114
  self._token_cache = token_cache
113
115
 
114
116
  self._token: str | None = None
115
117
  self._token_expires_at: float = 0
116
118
 
119
+ def __repr__(self) -> str:
120
+ return f"<{type(self).__name__} base_url={self.base_url!r}>"
121
+
117
122
  # ------------------------------------------------------------------
118
123
  # Auth
119
124
  # ------------------------------------------------------------------
@@ -132,13 +137,13 @@ class Base:
132
137
  logger.debug("Loaded cached OAuth2 token from storage")
133
138
  return self._token
134
139
  except Exception:
135
- logger.debug("Could not read token from cache")
140
+ logger.warning("Could not read token from cache", exc_info=True)
136
141
 
137
142
  resp = requests.post(
138
143
  f"{self.base_url}/api/oauth/token/",
139
144
  data={
140
- "client_id": self.client_id,
141
- "client_secret": self.client_secret,
145
+ "client_id": self._client_id,
146
+ "client_secret": self._client_secret,
142
147
  "grant_type": "client_credentials",
143
148
  "scope": "read write",
144
149
  },
@@ -157,7 +162,7 @@ class Base:
157
162
  })
158
163
  logger.debug("Persisted OAuth2 token to storage")
159
164
  except Exception:
160
- logger.debug("Could not persist token to cache")
165
+ logger.warning("Could not persist token to cache", exc_info=True)
161
166
 
162
167
  return self._token # type: ignore[return-value]
163
168
 
@@ -173,6 +178,9 @@ class Base:
173
178
 
174
179
  def _url(self, path: str) -> str:
175
180
  path = path.lstrip("/")
181
+ if ".." in path.split("/"):
182
+ msg = f"Path traversal detected in URL path: {path!r}"
183
+ raise ValueError(msg)
176
184
  return f"{self.base_url}/api/{path}"
177
185
 
178
186
  def _request(
@@ -58,6 +58,7 @@ class CompanyMixin:
58
58
  isin: str | None = None,
59
59
  country: str | None = None,
60
60
  sector: str | None = None,
61
+ ticker: str | None = None,
61
62
  page: int | None = None,
62
63
  page_size: int | None = None,
63
64
  ) -> PaginatedResponse:
@@ -68,6 +69,7 @@ class CompanyMixin:
68
69
  isin: Filter by exact ISIN code.
69
70
  country: Filter by ISO country code (e.g. ``"FR"``).
70
71
  sector: Filter by sector name(s), comma-separated.
72
+ ticker: Filter by exact stock ticker symbol.
71
73
  page: Page number (1-indexed).
72
74
  page_size: Results per page (default 25).
73
75
 
@@ -88,6 +90,7 @@ class CompanyMixin:
88
90
  isin=isin,
89
91
  country=country,
90
92
  sector=sector,
93
+ ticker=ticker,
91
94
  page=page,
92
95
  page_size=page_size,
93
96
  )
@@ -0,0 +1,127 @@
1
+ """Index and IndexMembership API methods."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ class IndexMixin:
9
+ """Index and IndexMembership CRUD.
10
+
11
+ Requires ``Base`` in the MRO (provides ``_get``, ``_post``, ``_patch``,
12
+ ``_delete``, ``_build_payload``).
13
+ """
14
+
15
+ # -- Index CRUD --
16
+
17
+ def list_indexes(
18
+ self,
19
+ *,
20
+ page: int | None = None,
21
+ page_size: int | None = None,
22
+ ) -> Any:
23
+ return self._get( # type: ignore[attr-defined]
24
+ "indexes/",
25
+ page=page,
26
+ page_size=page_size,
27
+ )
28
+
29
+ def get_index(self, index_id: str) -> Any:
30
+ return self._get(f"indexes/{index_id}/") # type: ignore[attr-defined]
31
+
32
+ def create_index(
33
+ self,
34
+ name: str,
35
+ *,
36
+ description: str | None = None,
37
+ data_source_url: str | None = None,
38
+ data_source_type: str | None = None,
39
+ data_source_config: dict[str, Any] | None = None,
40
+ display_source_url: str | None = None,
41
+ ) -> Any:
42
+ payload = self._build_payload( # type: ignore[attr-defined]
43
+ name=name,
44
+ description=description,
45
+ data_source_url=data_source_url,
46
+ data_source_type=data_source_type,
47
+ data_source_config=data_source_config,
48
+ display_source_url=display_source_url,
49
+ )
50
+ return self._post("indexes/", payload) # type: ignore[attr-defined]
51
+
52
+ def update_index(
53
+ self,
54
+ index_id: str,
55
+ *,
56
+ name: str | None = None,
57
+ description: str | None = None,
58
+ data_source_url: str | None = None,
59
+ data_source_type: str | None = None,
60
+ data_source_config: dict[str, Any] | None = None,
61
+ display_source_url: str | None = None,
62
+ ) -> Any:
63
+ payload = self._build_payload( # type: ignore[attr-defined]
64
+ name=name,
65
+ description=description,
66
+ data_source_url=data_source_url,
67
+ data_source_type=data_source_type,
68
+ data_source_config=data_source_config,
69
+ display_source_url=display_source_url,
70
+ )
71
+ return self._patch(f"indexes/{index_id}/", payload) # type: ignore[attr-defined]
72
+
73
+ # -- IndexMembership CRUD --
74
+
75
+ def list_index_memberships(
76
+ self,
77
+ *,
78
+ index_id: str | None = None,
79
+ company_id: str | None = None,
80
+ active_only: bool | None = None,
81
+ page: int | None = None,
82
+ page_size: int | None = None,
83
+ ) -> Any:
84
+ params: dict[str, Any] = {}
85
+ if index_id is not None:
86
+ params["index"] = index_id
87
+ if company_id is not None:
88
+ params["company"] = company_id
89
+ if active_only is not None:
90
+ params["active_only"] = "true" if active_only else "false"
91
+ if page is not None:
92
+ params["page"] = page
93
+ if page_size is not None:
94
+ params["page_size"] = page_size
95
+ return self._get("index-memberships/", **params) # type: ignore[attr-defined]
96
+
97
+ def create_index_membership(
98
+ self,
99
+ company_id: str,
100
+ index_id: str,
101
+ *,
102
+ valid_from: str | None = None,
103
+ valid_to: str | None = None,
104
+ ) -> Any:
105
+ payload: dict[str, Any] = {
106
+ "company": company_id,
107
+ "index": index_id,
108
+ "valid_from": valid_from,
109
+ "valid_to": valid_to,
110
+ }
111
+ return self._post("index-memberships/", payload) # type: ignore[attr-defined]
112
+
113
+ def update_index_membership(
114
+ self,
115
+ membership_id: str,
116
+ *,
117
+ valid_from: str | None = None,
118
+ valid_to: str | None = None,
119
+ ) -> Any:
120
+ payload = self._build_payload( # type: ignore[attr-defined]
121
+ valid_from=valid_from,
122
+ valid_to=valid_to,
123
+ )
124
+ return self._patch( # type: ignore[attr-defined]
125
+ f"index-memberships/{membership_id}/",
126
+ payload,
127
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boarddata
3
- Version: 4.0.2
3
+ Version: 4.1.2
4
4
  Summary: Python SDK for the BoardData V2 REST API
5
5
  License: MIT
6
6
  Classifier: Development Status :: 4 - Beta
@@ -10,6 +10,7 @@ _criteria.py
10
10
  _directors.py
11
11
  _documents.py
12
12
  _esg.py
13
+ _indexes.py
13
14
  _persons.py
14
15
  _sentinel.py
15
16
  _utilities.py
@@ -29,6 +30,7 @@ pyproject.toml
29
30
  ./_directors.py
30
31
  ./_documents.py
31
32
  ./_esg.py
33
+ ./_indexes.py
32
34
  ./_persons.py
33
35
  ./_sentinel.py
34
36
  ./_utilities.py
@@ -55,6 +57,7 @@ tests/test_criteria.py
55
57
  tests/test_directors.py
56
58
  tests/test_documents.py
57
59
  tests/test_esg.py
60
+ tests/test_indexes.py
58
61
  tests/test_persons.py
59
62
  tests/test_sentinel.py
60
63
  tests/test_utilities.py
@@ -68,5 +71,6 @@ types/criteria.py
68
71
  types/directors.py
69
72
  types/documents.py
70
73
  types/esg.py
74
+ types/indexes.py
71
75
  types/persons.py
72
76
  types/sentinel.py
@@ -34,9 +34,12 @@ class FileTokenCache:
34
34
 
35
35
  def write(self, data: dict[str, Any]) -> None:
36
36
  """Persist token data."""
37
+ import os
38
+
37
39
  p = Path(self._path)
38
40
  p.parent.mkdir(parents=True, exist_ok=True)
39
41
  p.write_text(json.dumps(data))
42
+ os.chmod(p, 0o600)
40
43
 
41
44
 
42
45
  class ScalewaySecretTokenCache:
@@ -11,6 +11,7 @@ from ._criteria import CriteriaMixin
11
11
  from ._directors import DirectorMixin
12
12
  from ._documents import DocumentMixin
13
13
  from ._esg import ESGMixin
14
+ from ._indexes import IndexMixin
14
15
  from ._persons import PersonMixin
15
16
  from ._sentinel import SentinelMixin
16
17
  from ._utilities import UtilitiesMixin
@@ -27,6 +28,7 @@ class BoardDataClient(
27
28
  ESGMixin,
28
29
  SentinelMixin,
29
30
  CriteriaMixin,
31
+ IndexMixin,
30
32
  UtilitiesMixin,
31
33
  Base,
32
34
  ):
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "boarddata"
7
- version = "4.0.2"
7
+ version = "4.1.2"
8
8
  description = "Python SDK for the BoardData V2 REST API"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -20,8 +20,8 @@ class TestFromEnv:
20
20
  def test_creates_client_from_env(self) -> None:
21
21
  client = BoardDataClient.from_env()
22
22
  assert client.base_url == "https://api.example.com"
23
- assert client.client_id == "cid"
24
- assert client.client_secret == "csecret"
23
+ assert client._client_id == "cid"
24
+ assert client._client_secret == "csecret"
25
25
 
26
26
  @patch.dict(os.environ, {}, clear=True)
27
27
  def test_raises_when_env_missing(self) -> None:
@@ -0,0 +1,112 @@
1
+ """Tests for IndexMixin methods.
2
+
3
+ Uses the shared ``client`` fixture from ``conftest.py`` which creates a
4
+ ``BoardDataClient`` with mocked ``_request`` and ``_get_token``.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import pytest
10
+
11
+
12
+ class TestListIndexes:
13
+ def test_calls_correct_path(self, client):
14
+ client._request.return_value = {"count": 0, "results": []}
15
+ client.list_indexes()
16
+ args, kwargs = client._request.call_args
17
+ assert args == ("GET", "indexes/")
18
+
19
+ def test_returns_paginated_response(self, client):
20
+ client._request.return_value = {
21
+ "count": 1,
22
+ "next": None,
23
+ "previous": None,
24
+ "results": [{"id": "uuid1", "name": "CAC 40"}],
25
+ }
26
+ result = client.list_indexes()
27
+ assert result["count"] == 1
28
+
29
+
30
+ class TestGetIndex:
31
+ def test_calls_correct_path(self, client):
32
+ client._request.return_value = {"id": "uuid1", "name": "CAC 40"}
33
+ client.get_index("uuid1")
34
+ args, kwargs = client._request.call_args
35
+ assert args == ("GET", "indexes/uuid1/")
36
+
37
+
38
+ class TestCreateIndex:
39
+ def test_sends_payload(self, client):
40
+ client._request.return_value = {"id": "uuid1", "name": "CAC 40"}
41
+ client.create_index(name="CAC 40", data_source_type="wikipedia")
42
+ args, kwargs = client._request.call_args
43
+ assert args == ("POST", "indexes/")
44
+ assert kwargs["json"]["name"] == "CAC 40"
45
+ assert kwargs["json"]["data_source_type"] == "wikipedia"
46
+
47
+ def test_excludes_none_values(self, client):
48
+ client._request.return_value = {"id": "uuid1", "name": "CAC 40"}
49
+ client.create_index(name="CAC 40")
50
+ _, kwargs = client._request.call_args
51
+ assert "data_source_type" not in kwargs["json"]
52
+
53
+
54
+ class TestUpdateIndex:
55
+ def test_sends_patch(self, client):
56
+ client._request.return_value = {"id": "uuid1", "name": "CAC 40"}
57
+ client.update_index("uuid1", description="French blue-chip")
58
+ args, kwargs = client._request.call_args
59
+ assert args == ("PATCH", "indexes/uuid1/")
60
+ assert kwargs["json"]["description"] == "French blue-chip"
61
+
62
+
63
+ class TestListIndexMemberships:
64
+ def test_calls_correct_path(self, client):
65
+ client._request.return_value = {"count": 0, "results": []}
66
+ client.list_index_memberships()
67
+ args, kwargs = client._request.call_args
68
+ assert args == ("GET", "index-memberships/")
69
+
70
+ def test_passes_filters(self, client):
71
+ client._request.return_value = {"count": 0, "results": []}
72
+ client.list_index_memberships(index_id="uuid1", active_only=True)
73
+ _, kwargs = client._request.call_args
74
+ assert kwargs["params"]["index"] == "uuid1"
75
+ assert kwargs["params"]["active_only"] == "true"
76
+
77
+
78
+ class TestCreateIndexMembership:
79
+ def test_sends_payload(self, client):
80
+ client._request.return_value = {"id": "m-uuid"}
81
+ client.create_index_membership(
82
+ company_id="c-uuid", index_id="i-uuid"
83
+ )
84
+ args, kwargs = client._request.call_args
85
+ assert args == ("POST", "index-memberships/")
86
+ assert kwargs["json"]["company"] == "c-uuid"
87
+ assert kwargs["json"]["index"] == "i-uuid"
88
+
89
+ def test_sends_valid_from_none(self, client):
90
+ client._request.return_value = {"id": "m-uuid"}
91
+ client.create_index_membership(
92
+ company_id="c-uuid", index_id="i-uuid", valid_from=None
93
+ )
94
+ _, kwargs = client._request.call_args
95
+ assert kwargs["json"]["valid_from"] is None
96
+
97
+
98
+ class TestUpdateIndexMembership:
99
+ def test_sends_patch(self, client):
100
+ client._request.return_value = {"id": "m-uuid"}
101
+ client.update_index_membership("m-uuid", valid_to="2026-04-07")
102
+ args, kwargs = client._request.call_args
103
+ assert args == ("PATCH", "index-memberships/m-uuid/")
104
+ assert kwargs["json"]["valid_to"] == "2026-04-07"
105
+
106
+
107
+ class TestListCompaniesTickerFilter:
108
+ def test_passes_ticker_param(self, client):
109
+ client._request.return_value = {"count": 0, "results": []}
110
+ client.list_companies(ticker="AI")
111
+ _, kwargs = client._request.call_args
112
+ assert kwargs["params"]["ticker"] == "AI"
@@ -1,5 +1,13 @@
1
1
  """BoardData API type definitions."""
2
2
 
3
+ from .indexes import (
4
+ CreateIndexMembershipPayload,
5
+ CreateIndexPayload,
6
+ IndexItem,
7
+ IndexMembershipItem,
8
+ UpdateIndexMembershipPayload,
9
+ UpdateIndexPayload,
10
+ )
3
11
  from .esg import (
4
12
  CompanyESGBenchmarkItem,
5
13
  IROBatchItemPayload,
@@ -117,6 +125,13 @@ from .sentinel import (
117
125
  )
118
126
 
119
127
  __all__ = [
128
+ # indexes
129
+ "CreateIndexMembershipPayload",
130
+ "CreateIndexPayload",
131
+ "IndexItem",
132
+ "IndexMembershipItem",
133
+ "UpdateIndexMembershipPayload",
134
+ "UpdateIndexPayload",
120
135
  # esg
121
136
  "CompanyESGBenchmarkItem",
122
137
  "IROBatchItemPayload",
@@ -0,0 +1,67 @@
1
+ """TypedDict definitions for Index and IndexMembership API types."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ try:
8
+ from typing import NotRequired, TypedDict
9
+ except ImportError:
10
+ from typing_extensions import NotRequired, TypedDict
11
+
12
+
13
+ # -- Response types --
14
+
15
+
16
+ class IndexItem(TypedDict):
17
+ id: str
18
+ name: str
19
+ description: str
20
+ data_source_url: str
21
+ data_source_type: str
22
+ data_source_config: dict[str, Any]
23
+ display_source_url: str
24
+
25
+
26
+ class IndexMembershipItem(TypedDict):
27
+ id: str
28
+ company: str
29
+ company_name: str
30
+ company_ticker: str
31
+ index: str
32
+ index_name: str
33
+ valid_from: str | None
34
+ valid_to: str | None
35
+
36
+
37
+ # -- Create/Update payloads --
38
+
39
+
40
+ class CreateIndexPayload(TypedDict):
41
+ name: str
42
+ description: NotRequired[str]
43
+ data_source_url: NotRequired[str]
44
+ data_source_type: NotRequired[str]
45
+ data_source_config: NotRequired[dict[str, Any]]
46
+ display_source_url: NotRequired[str]
47
+
48
+
49
+ class UpdateIndexPayload(TypedDict, total=False):
50
+ name: str
51
+ description: str
52
+ data_source_url: str
53
+ data_source_type: str
54
+ data_source_config: dict[str, Any]
55
+ display_source_url: str
56
+
57
+
58
+ class CreateIndexMembershipPayload(TypedDict):
59
+ company: str
60
+ index: str
61
+ valid_from: NotRequired[str | None]
62
+ valid_to: NotRequired[str | None]
63
+
64
+
65
+ class UpdateIndexMembershipPayload(TypedDict, total=False):
66
+ valid_from: str | None
67
+ valid_to: str | None
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
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
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
File without changes
File without changes
File without changes
File without changes
File without changes