boarddata 4.4.4__tar.gz → 4.4.8__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.
- {boarddata-4.4.4 → boarddata-4.4.8}/PKG-INFO +1 -1
- {boarddata-4.4.4 → boarddata-4.4.8}/__init__.py +1 -1
- {boarddata-4.4.4 → boarddata-4.4.8}/_auditors.py +21 -1
- {boarddata-4.4.4 → boarddata-4.4.8}/_directors.py +42 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/boarddata.egg-info/PKG-INFO +1 -1
- {boarddata-4.4.4 → boarddata-4.4.8}/pyproject.toml +1 -1
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_auditors.py +20 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_directors.py +52 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/directors.py +16 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/CLAUDE.md +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/README.md +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_assemblies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_base.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_comex.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_companies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_criteria.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_documents.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_esg.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_indexes.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_persons.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_sentinel.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/_utilities.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/boarddata.egg-info/SOURCES.txt +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/boarddata.egg-info/dependency_links.txt +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/boarddata.egg-info/requires.txt +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/boarddata.egg-info/top_level.txt +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/cache.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/client.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/errors.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/py.typed +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/setup.cfg +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/__init__.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/conftest.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_assemblies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_base.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_build_payload.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_cache.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_comex.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_companies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_config.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_criteria.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_documents.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_esg.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_indexes.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_persons.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_sentinel.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/tests/test_utilities.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/__init__.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/assemblies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/auditors.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/comex.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/companies.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/core.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/criteria.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/documents.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/esg.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/indexes.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/persons.py +0 -0
- {boarddata-4.4.4 → boarddata-4.4.8}/types/sentinel.py +0 -0
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from .types.auditors import AuditorCompensationItem, AuditorCreateResponse, AuditorDetail
|
|
8
|
+
from .types.auditors import AuditorCompanyItem, AuditorCompensationItem, AuditorCreateResponse, AuditorDetail
|
|
9
9
|
from .types.core import FieldSourcePayload, PaginatedResponse
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger("boarddata")
|
|
@@ -153,6 +153,26 @@ class AuditorMixin:
|
|
|
153
153
|
"""
|
|
154
154
|
return self._get("auditor-companies/", **params) # type: ignore[attr-defined]
|
|
155
155
|
|
|
156
|
+
def create_auditor_company(
|
|
157
|
+
self,
|
|
158
|
+
name: str,
|
|
159
|
+
country: str = "",
|
|
160
|
+
) -> AuditorCompanyItem:
|
|
161
|
+
"""Create an auditor company (get-or-create on the server).
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
name: Audit firm name (e.g. ``"Deloitte & Associés"``).
|
|
165
|
+
country: ISO 3166-1 alpha-2 country code (e.g. ``"FR"``).
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
AuditorCompanyItem with id, name, and country.
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
BoardDataError: On non-2xx API response.
|
|
172
|
+
"""
|
|
173
|
+
payload = self._build_payload(name=name, country=country) # type: ignore[attr-defined]
|
|
174
|
+
return self._post("auditor-companies/", payload) # type: ignore[attr-defined]
|
|
175
|
+
|
|
156
176
|
# ------------------------------------------------------------------
|
|
157
177
|
# Auditor compensations
|
|
158
178
|
# ------------------------------------------------------------------
|
|
@@ -103,6 +103,10 @@ class DirectorMixin:
|
|
|
103
103
|
valid_to: str | None = None,
|
|
104
104
|
is_independent: bool | None = None,
|
|
105
105
|
is_executive: bool | None = None,
|
|
106
|
+
is_chairman: bool | None = None,
|
|
107
|
+
is_lead_independent: bool | None = None,
|
|
108
|
+
is_employee_representative: bool | None = None,
|
|
109
|
+
is_employee_shareholder_representative: bool | None = None,
|
|
106
110
|
appointment_method: str | None = None,
|
|
107
111
|
entity_type: str | None = None,
|
|
108
112
|
representative_name: str | None = None,
|
|
@@ -119,6 +123,12 @@ class DirectorMixin:
|
|
|
119
123
|
valid_to: End date (``"YYYY-MM-DD"``) or None if current.
|
|
120
124
|
is_independent: Whether the director is independent.
|
|
121
125
|
is_executive: Whether the director is executive.
|
|
126
|
+
is_chairman: Whether the director is Chairman of the Board.
|
|
127
|
+
is_lead_independent: Whether the director is Lead Independent Director.
|
|
128
|
+
is_employee_representative: Whether the director represents employees
|
|
129
|
+
(appointed by works council / employee vote).
|
|
130
|
+
is_employee_shareholder_representative: Whether the director represents
|
|
131
|
+
employee shareholders (AG-elected, distinct from employee reps).
|
|
122
132
|
appointment_method: How they were appointed.
|
|
123
133
|
entity_type: Entity type (physical, legal).
|
|
124
134
|
representative_name: Name of legal entity representative.
|
|
@@ -139,6 +149,10 @@ class DirectorMixin:
|
|
|
139
149
|
valid_to=valid_to,
|
|
140
150
|
is_independent=is_independent,
|
|
141
151
|
is_executive=is_executive,
|
|
152
|
+
is_chairman=is_chairman,
|
|
153
|
+
is_lead_independent=is_lead_independent,
|
|
154
|
+
is_employee_representative=is_employee_representative,
|
|
155
|
+
is_employee_shareholder_representative=is_employee_shareholder_representative,
|
|
142
156
|
appointment_method=appointment_method,
|
|
143
157
|
entity_type=entity_type,
|
|
144
158
|
representative_name=representative_name,
|
|
@@ -156,6 +170,10 @@ class DirectorMixin:
|
|
|
156
170
|
valid_to: str | None = None,
|
|
157
171
|
is_independent: bool | None = None,
|
|
158
172
|
is_executive: bool | None = None,
|
|
173
|
+
is_chairman: bool | None = None,
|
|
174
|
+
is_lead_independent: bool | None = None,
|
|
175
|
+
is_employee_representative: bool | None = None,
|
|
176
|
+
is_employee_shareholder_representative: bool | None = None,
|
|
159
177
|
appointment_method: str | None = None,
|
|
160
178
|
entity_type: str | None = None,
|
|
161
179
|
representative_name: str | None = None,
|
|
@@ -171,6 +189,12 @@ class DirectorMixin:
|
|
|
171
189
|
valid_to: End date (``"YYYY-MM-DD"``).
|
|
172
190
|
is_independent: Whether the director is independent.
|
|
173
191
|
is_executive: Whether the director is executive.
|
|
192
|
+
is_chairman: Whether the director is Chairman of the Board.
|
|
193
|
+
is_lead_independent: Whether the director is Lead Independent Director.
|
|
194
|
+
is_employee_representative: Whether the director represents employees
|
|
195
|
+
(appointed by works council / employee vote).
|
|
196
|
+
is_employee_shareholder_representative: Whether the director represents
|
|
197
|
+
employee shareholders (AG-elected, distinct from employee reps).
|
|
174
198
|
appointment_method: How they were appointed.
|
|
175
199
|
entity_type: Entity type.
|
|
176
200
|
representative_name: Name of legal entity representative.
|
|
@@ -189,6 +213,10 @@ class DirectorMixin:
|
|
|
189
213
|
valid_to=valid_to,
|
|
190
214
|
is_independent=is_independent,
|
|
191
215
|
is_executive=is_executive,
|
|
216
|
+
is_chairman=is_chairman,
|
|
217
|
+
is_lead_independent=is_lead_independent,
|
|
218
|
+
is_employee_representative=is_employee_representative,
|
|
219
|
+
is_employee_shareholder_representative=is_employee_shareholder_representative,
|
|
192
220
|
appointment_method=appointment_method,
|
|
193
221
|
entity_type=entity_type,
|
|
194
222
|
representative_name=representative_name,
|
|
@@ -443,6 +471,10 @@ class DirectorMixin:
|
|
|
443
471
|
valid_to: str | None = None,
|
|
444
472
|
is_independent: bool | None = None,
|
|
445
473
|
is_executive: bool | None = None,
|
|
474
|
+
is_chairman: bool | None = None,
|
|
475
|
+
is_lead_independent: bool | None = None,
|
|
476
|
+
is_employee_representative: bool | None = None,
|
|
477
|
+
is_employee_shareholder_representative: bool | None = None,
|
|
446
478
|
appointment_method: str | None = None,
|
|
447
479
|
entity_type: str | None = None,
|
|
448
480
|
representative_name: str | None = None,
|
|
@@ -459,6 +491,12 @@ class DirectorMixin:
|
|
|
459
491
|
valid_to: End date (``"YYYY-MM-DD"``).
|
|
460
492
|
is_independent: Whether the director is independent.
|
|
461
493
|
is_executive: Whether the director is executive.
|
|
494
|
+
is_chairman: Whether the director is Chairman of the Board.
|
|
495
|
+
is_lead_independent: Whether the director is Lead Independent Director.
|
|
496
|
+
is_employee_representative: Whether the director represents employees
|
|
497
|
+
(appointed by works council / employee vote).
|
|
498
|
+
is_employee_shareholder_representative: Whether the director represents
|
|
499
|
+
employee shareholders (AG-elected, distinct from employee reps).
|
|
462
500
|
appointment_method: How they were appointed.
|
|
463
501
|
entity_type: Entity type.
|
|
464
502
|
representative_name: Name of legal entity representative.
|
|
@@ -490,6 +528,10 @@ class DirectorMixin:
|
|
|
490
528
|
valid_to=valid_to,
|
|
491
529
|
is_independent=is_independent,
|
|
492
530
|
is_executive=is_executive,
|
|
531
|
+
is_chairman=is_chairman,
|
|
532
|
+
is_lead_independent=is_lead_independent,
|
|
533
|
+
is_employee_representative=is_employee_representative,
|
|
534
|
+
is_employee_shareholder_representative=is_employee_shareholder_representative,
|
|
493
535
|
appointment_method=appointment_method,
|
|
494
536
|
entity_type=entity_type,
|
|
495
537
|
representative_name=representative_name,
|
|
@@ -38,6 +38,26 @@ class TestCreateAuditor:
|
|
|
38
38
|
assert payload["auditor_type"] == "PRINCIPAL"
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
class TestCreateAuditorCompany:
|
|
42
|
+
def test_sends_name_and_country(self):
|
|
43
|
+
c = make_client()
|
|
44
|
+
c._request.return_value = {"id": "ac1", "name": "Deloitte", "country": "FR"}
|
|
45
|
+
result = c.create_auditor_company("Deloitte", "FR")
|
|
46
|
+
_, kwargs = c._request.call_args
|
|
47
|
+
payload = kwargs["json"]
|
|
48
|
+
assert payload["name"] == "Deloitte"
|
|
49
|
+
assert payload["country"] == "FR"
|
|
50
|
+
assert result["id"] == "ac1"
|
|
51
|
+
|
|
52
|
+
def test_country_defaults_to_empty(self):
|
|
53
|
+
c = make_client()
|
|
54
|
+
c._request.return_value = {"id": "ac2", "name": "KPMG", "country": ""}
|
|
55
|
+
c.create_auditor_company("KPMG")
|
|
56
|
+
_, kwargs = c._request.call_args
|
|
57
|
+
payload = kwargs["json"]
|
|
58
|
+
assert payload["country"] == ""
|
|
59
|
+
|
|
60
|
+
|
|
41
61
|
class TestCreateAuditorCompensation:
|
|
42
62
|
def test_sends_audit_fields(self):
|
|
43
63
|
c = make_client()
|
|
@@ -61,3 +61,55 @@ class TestUpsertDirector:
|
|
|
61
61
|
result = c.upsert_director("comp-uuid", "pers-uuid", title="Director")
|
|
62
62
|
assert result["action"] == "created"
|
|
63
63
|
assert result["id"] == "new-uuid"
|
|
64
|
+
|
|
65
|
+
def test_sends_board_classification_flags(self):
|
|
66
|
+
c = make_client()
|
|
67
|
+
c._request.side_effect = [
|
|
68
|
+
{"count": 0, "results": []},
|
|
69
|
+
{"id": "new-uuid"},
|
|
70
|
+
]
|
|
71
|
+
c.upsert_director(
|
|
72
|
+
"comp-uuid",
|
|
73
|
+
"pers-uuid",
|
|
74
|
+
title="Chairman & CEO",
|
|
75
|
+
is_chairman=True,
|
|
76
|
+
is_lead_independent=False,
|
|
77
|
+
is_employee_representative=False,
|
|
78
|
+
is_employee_shareholder_representative=False,
|
|
79
|
+
)
|
|
80
|
+
_, kwargs = c._request.call_args
|
|
81
|
+
payload = kwargs["json"]
|
|
82
|
+
assert payload["is_chairman"] is True
|
|
83
|
+
assert payload["is_lead_independent"] is False
|
|
84
|
+
assert payload["is_employee_representative"] is False
|
|
85
|
+
assert payload["is_employee_shareholder_representative"] is False
|
|
86
|
+
|
|
87
|
+
def test_omits_unset_classification_flags(self):
|
|
88
|
+
c = make_client()
|
|
89
|
+
c._request.side_effect = [
|
|
90
|
+
{"count": 0, "results": []},
|
|
91
|
+
{"id": "new-uuid"},
|
|
92
|
+
]
|
|
93
|
+
c.upsert_director("comp-uuid", "pers-uuid", title="Director")
|
|
94
|
+
_, kwargs = c._request.call_args
|
|
95
|
+
payload = kwargs["json"]
|
|
96
|
+
assert "is_chairman" not in payload
|
|
97
|
+
assert "is_lead_independent" not in payload
|
|
98
|
+
assert "is_employee_representative" not in payload
|
|
99
|
+
assert "is_employee_shareholder_representative" not in payload
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TestUpdateDirector:
|
|
103
|
+
def test_sends_board_classification_flags(self):
|
|
104
|
+
c = make_client()
|
|
105
|
+
c._request.return_value = {"id": "dir-uuid"}
|
|
106
|
+
c.update_director(
|
|
107
|
+
"dir-uuid",
|
|
108
|
+
is_lead_independent=True,
|
|
109
|
+
is_employee_representative=True,
|
|
110
|
+
)
|
|
111
|
+
_, kwargs = c._request.call_args
|
|
112
|
+
payload = kwargs["json"]
|
|
113
|
+
assert payload["is_lead_independent"] is True
|
|
114
|
+
assert payload["is_employee_representative"] is True
|
|
115
|
+
assert "is_chairman" not in payload
|
|
@@ -114,6 +114,10 @@ class DirectorListItem(TypedDict):
|
|
|
114
114
|
valid_to: str | None
|
|
115
115
|
is_independent: bool
|
|
116
116
|
is_executive: bool
|
|
117
|
+
is_chairman: bool
|
|
118
|
+
is_lead_independent: bool
|
|
119
|
+
is_employee_representative: bool
|
|
120
|
+
is_employee_shareholder_representative: bool
|
|
117
121
|
appointment_method: str
|
|
118
122
|
entity_type: str
|
|
119
123
|
representative_name: str
|
|
@@ -137,6 +141,10 @@ class DirectorDetail(TypedDict):
|
|
|
137
141
|
cause_end: str
|
|
138
142
|
is_independent: bool
|
|
139
143
|
is_executive: bool
|
|
144
|
+
is_chairman: bool
|
|
145
|
+
is_lead_independent: bool
|
|
146
|
+
is_employee_representative: bool
|
|
147
|
+
is_employee_shareholder_representative: bool
|
|
140
148
|
appointment_method: str
|
|
141
149
|
entity_type: str
|
|
142
150
|
representative_name: str
|
|
@@ -154,6 +162,10 @@ class CreateDirectorPayload(TypedDict):
|
|
|
154
162
|
valid_to: NotRequired[str | None]
|
|
155
163
|
is_independent: NotRequired[bool]
|
|
156
164
|
is_executive: NotRequired[bool]
|
|
165
|
+
is_chairman: NotRequired[bool]
|
|
166
|
+
is_lead_independent: NotRequired[bool]
|
|
167
|
+
is_employee_representative: NotRequired[bool]
|
|
168
|
+
is_employee_shareholder_representative: NotRequired[bool]
|
|
157
169
|
appointment_method: NotRequired[str]
|
|
158
170
|
entity_type: NotRequired[str]
|
|
159
171
|
representative_name: NotRequired[str]
|
|
@@ -167,6 +179,10 @@ class UpdateDirectorPayload(TypedDict, total=False):
|
|
|
167
179
|
valid_to: str | None
|
|
168
180
|
is_independent: bool
|
|
169
181
|
is_executive: bool
|
|
182
|
+
is_chairman: bool
|
|
183
|
+
is_lead_independent: bool
|
|
184
|
+
is_employee_representative: bool
|
|
185
|
+
is_employee_shareholder_representative: bool
|
|
170
186
|
appointment_method: str
|
|
171
187
|
entity_type: str
|
|
172
188
|
representative_name: str
|
|
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
|
|
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
|