electricore-client 0.1.0__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.
@@ -0,0 +1,202 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ !deploy/lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # UV
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ #uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ #poetry.lock
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ #pdm.lock
114
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
115
+ # in version control.
116
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
117
+ .pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
122
+ __pypackages__/
123
+
124
+ # Celery stuff
125
+ celerybeat-schedule
126
+ celerybeat.pid
127
+
128
+ # SageMath parsed files
129
+ *.sage.py
130
+
131
+ # Environments
132
+ .env
133
+ .venv
134
+ env/
135
+ venv/
136
+ ENV/
137
+ env.bak/
138
+ venv.bak/
139
+
140
+ # Spyder project settings
141
+ .spyderproject
142
+ .spyproject
143
+
144
+ # Rope project settings
145
+ .ropeproject
146
+
147
+ # mkdocs documentation
148
+ /site
149
+
150
+ # mypy
151
+ .mypy_cache/
152
+ .dmypy.json
153
+ dmypy.json
154
+
155
+ # Pyre type checker
156
+ .pyre/
157
+
158
+ # pytype static type analyzer
159
+ .pytype/
160
+
161
+ # Cython debug symbols
162
+ cython_debug/
163
+
164
+ # PyCharm
165
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
166
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
167
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
168
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
169
+ #.idea/
170
+
171
+ # PyPI configuration file
172
+ .pypirc
173
+
174
+ # Codanna code intelligence cache
175
+ .codanna/
176
+ .codannaignore
177
+ .fastembed_cache/
178
+
179
+ # DLT secrets (credentials, API keys)
180
+ electricore/ingestion/.dlt/secrets.toml
181
+
182
+ # Données locales générées
183
+ *.duckdb
184
+ perimetre_manquants/
185
+ surveillance_perimetre_manquants.csv
186
+ .serena/
187
+
188
+ # Artefacts de déploiement Docker générés à partir des fichiers .example
189
+ # (les utilisateurs copient *.example vers la version sans suffixe pour les éditer)
190
+ deploy/docker/Caddyfile
191
+ deploy/docker/crontab
192
+ deploy/docker/docker-compose.*.yml
193
+ !deploy/docker/docker-compose.yml
194
+
195
+ # Sortie locale du skill /sota-scan
196
+ .sota/
197
+
198
+ # Artefacts de build dbt (target par base, cf. pipeline_dbt)
199
+ electricore/ingestion/.dbt_target_*/
200
+
201
+ # repo-scoped GitHub PAT for in-sandbox automation — never commit
202
+ .gh-token
@@ -0,0 +1,31 @@
1
+ # Changelog — electricore-client
2
+
3
+ Toutes les évolutions notables de ce paquet sont consignées ici.
4
+ Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) ;
5
+ le versionnage suit [SemVer](https://semver.org/lang/fr/).
6
+
7
+ ## [0.1.0] — non publié
8
+
9
+ ### Ajouté
10
+ - Squelette du paquet `electricore-client` (top-level `electricore_client`),
11
+ distribué séparément du moteur. Dépendances de base **httpx + pydantic**.
12
+ - Substrat de transport partagé `_BaseClient` : URL de base, en-tête
13
+ `X-API-Key`, timeout, conversion d'erreur HTTP **503 → `IngestionEnCours`**,
14
+ garde de version de contrat asymétrique (warn si serveur en avance, raise si
15
+ en retard).
16
+ - Modèle d'en-têtes de métadonnées `EnTetesMeta` (`contract_version`, `mois`,
17
+ `grain`).
18
+ - Méthode `meta_periodes(...)` : flux JSONL typé de `PeriodeMeta` (contrat v3,
19
+ relevés imbriqués ADR-0038), context-manager, métadonnées en en-têtes,
20
+ sans pagination, `.collect()`.
21
+ - Méthode `chronologie(...)` : flux JSONL d'une union discriminée
22
+ `LigneChronologie` (`LigneEvenement | LigneReleve | LignePeriodeEnergie`,
23
+ contrat v1), validation `pdl` XOR `rsc` côté client.
24
+ - Méthode `turpe_variable(...)` : POST RPC, résultats typés indexés par l'`id`
25
+ opaque ré-émis. Modèles `LigneTurpeVariable` / résultat single-sourcés.
26
+ - Extra `[arrow]` : client Arrow historique (`flux/releves/facturation/accise/
27
+ cta` → `pl.DataFrame`) dans `electricore_client.arrow`, polars importé
28
+ paresseusement (la base reste polars-free).
29
+ - CI/CD : `release-client.yml` (tags `client-v*`, publication PyPI Trusted
30
+ Publishing / OIDC) + job `test-client` (install isolé, garantie polars-free).
31
+ Conception : ADR-0043.
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: electricore-client
3
+ Version: 0.1.0
4
+ Summary: Client Python léger (httpx + pydantic) vers l'API facturiste electricore — sans polars/duckdb/fastapi
5
+ Project-URL: Homepage, https://github.com/Energie-De-Nantes/electricore
6
+ Project-URL: Repository, https://github.com/Energie-De-Nantes/electricore
7
+ Project-URL: Issues, https://github.com/Energie-De-Nantes/electricore/issues
8
+ Author: Virgile
9
+ License: AGPL-3.0
10
+ Keywords: api-client,electricore,enedis,energy,facturation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Provides-Extra: arrow
25
+ Requires-Dist: polars<2.0.0,>=1.0.0; extra == 'arrow'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # electricore-client
29
+
30
+ Client Python **léger** vers l'API facturiste [electricore](https://github.com/Energie-De-Nantes/electricore).
31
+
32
+ Dépendances de base : **httpx + pydantic uniquement** — pas de polars, duckdb ni
33
+ fastapi. Pensé pour être consommé par `souscriptions_odoo` (Odoo 19) et tout
34
+ intégrateur qui n'a pas besoin de tirer le moteur entier.
35
+
36
+ Lecture seule sur electricore (« Odoo tire d'electricore », ADR-0027/0012).
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install electricore-client # base : httpx + pydantic
42
+ pip install "electricore-client[arrow]" # + client Arrow (DataFrames polars)
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ```python
48
+ from electricore_client import ElectricoreClient
49
+
50
+ client = ElectricoreClient(url="https://electricore.example", api_key="…")
51
+
52
+ # Méta-périodes mensuelles (flux JSONL typé, sans pagination)
53
+ with client.meta_periodes(mois="2026-05-01") as stream:
54
+ print(stream.contract_version) # version de contrat (en-tête)
55
+ for periode in stream: # itère des PeriodeMeta typés
56
+ ...
57
+
58
+ # Chronologie d'un point ou d'un contrat (union discriminée)
59
+ with client.chronologie(pdl="12345678901234") as stream:
60
+ lignes = stream.collect()
61
+
62
+ # Calculateur TURPE variable (POST RPC, pas un stream)
63
+ resultats = client.turpe_variable([...]) # résultats indexés par id opaque
64
+ ```
65
+
66
+ Le client Arrow historique (`flux/releves/facturation/accise/cta` → `pl.DataFrame`)
67
+ vit dans `electricore_client.arrow`, derrière l'extra `[arrow]`.
68
+
69
+ ## Conception
70
+
71
+ Voir [ADR-0043](https://github.com/Energie-De-Nantes/electricore/blob/main/docs/adr/0043-electricore-client-paquet-separe.md).
@@ -0,0 +1,44 @@
1
+ # electricore-client
2
+
3
+ Client Python **léger** vers l'API facturiste [electricore](https://github.com/Energie-De-Nantes/electricore).
4
+
5
+ Dépendances de base : **httpx + pydantic uniquement** — pas de polars, duckdb ni
6
+ fastapi. Pensé pour être consommé par `souscriptions_odoo` (Odoo 19) et tout
7
+ intégrateur qui n'a pas besoin de tirer le moteur entier.
8
+
9
+ Lecture seule sur electricore (« Odoo tire d'electricore », ADR-0027/0012).
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install electricore-client # base : httpx + pydantic
15
+ pip install "electricore-client[arrow]" # + client Arrow (DataFrames polars)
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```python
21
+ from electricore_client import ElectricoreClient
22
+
23
+ client = ElectricoreClient(url="https://electricore.example", api_key="…")
24
+
25
+ # Méta-périodes mensuelles (flux JSONL typé, sans pagination)
26
+ with client.meta_periodes(mois="2026-05-01") as stream:
27
+ print(stream.contract_version) # version de contrat (en-tête)
28
+ for periode in stream: # itère des PeriodeMeta typés
29
+ ...
30
+
31
+ # Chronologie d'un point ou d'un contrat (union discriminée)
32
+ with client.chronologie(pdl="12345678901234") as stream:
33
+ lignes = stream.collect()
34
+
35
+ # Calculateur TURPE variable (POST RPC, pas un stream)
36
+ resultats = client.turpe_variable([...]) # résultats indexés par id opaque
37
+ ```
38
+
39
+ Le client Arrow historique (`flux/releves/facturation/accise/cta` → `pl.DataFrame`)
40
+ vit dans `electricore_client.arrow`, derrière l'extra `[arrow]`.
41
+
42
+ ## Conception
43
+
44
+ Voir [ADR-0043](https://github.com/Energie-De-Nantes/electricore/blob/main/docs/adr/0043-electricore-client-paquet-separe.md).
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "electricore-client"
3
+ version = "0.1.0"
4
+ description = "Client Python léger (httpx + pydantic) vers l'API facturiste electricore — sans polars/duckdb/fastapi"
5
+ authors = [
6
+ {name = "Virgile"}
7
+ ]
8
+ license = {text = "AGPL-3.0"}
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ keywords = [
12
+ "electricore",
13
+ "energy",
14
+ "enedis",
15
+ "api-client",
16
+ "facturation",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Developers",
21
+ "License :: OSI Approved :: GNU Affero General Public License v3",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Typing :: Typed",
29
+ ]
30
+ # Deps de base STRICTEMENT légères : httpx + pydantic (aucune trace de
31
+ # polars/duckdb/fastapi). C'est l'invariant prouvé par le test de pureté.
32
+ dependencies = [
33
+ "httpx>=0.27.0",
34
+ "pydantic>=2.0.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ # Extra `arrow` : recolle le client Arrow historique (DataFrames polars).
39
+ # polars n'est importé que paresseusement, dans le sous-module Arrow — jamais
40
+ # au top-level (l'invariant de pureté tient sans cet extra).
41
+ arrow = [
42
+ "polars>=1.0.0,<2.0.0",
43
+ ]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/Energie-De-Nantes/electricore"
47
+ Repository = "https://github.com/Energie-De-Nantes/electricore"
48
+ Issues = "https://github.com/Energie-De-Nantes/electricore/issues"
49
+
50
+ [build-system]
51
+ requires = ["hatchling"]
52
+ build-backend = "hatchling.build"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/electricore_client"]
56
+
57
+ [dependency-groups]
58
+ test = [
59
+ "pytest>=8.2.0",
60
+ ]
@@ -0,0 +1,53 @@
1
+ """electricore-client — client léger vers l'API facturiste electricore.
2
+
3
+ Distribué séparément du moteur, dépendances de base **httpx + pydantic
4
+ uniquement** : ce paquet n'importe jamais polars/duckdb/fastapi au top-level
5
+ (invariant prouvé par le test de pureté). Le client Arrow historique
6
+ (DataFrames polars) vit dans le sous-module `electricore_client.arrow`, derrière
7
+ l'extra `[arrow]`, et n'est *pas* importé ici.
8
+
9
+ Lecture seule sur electricore (ADR-0012). Voir ADR-0043 pour la conception.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from .client import ElectricoreClient
15
+ from .exceptions import (
16
+ ContractVersionError,
17
+ ElectricoreClientError,
18
+ IngestionEnCours,
19
+ )
20
+ from .headers import EnTetesMeta
21
+ from .models import (
22
+ LigneChronologie,
23
+ LigneEvenement,
24
+ LignePeriodeEnergie,
25
+ LigneReleve,
26
+ LigneTurpeVariable,
27
+ ObjetReleve,
28
+ PeriodeMeta,
29
+ ResultatTurpeVariable,
30
+ TurpeVariableRequest,
31
+ )
32
+ from .streaming import JsonlStream
33
+
34
+ __version__ = "0.1.0"
35
+
36
+ __all__ = [
37
+ "ElectricoreClient",
38
+ "ElectricoreClientError",
39
+ "IngestionEnCours",
40
+ "ContractVersionError",
41
+ "EnTetesMeta",
42
+ "JsonlStream",
43
+ "PeriodeMeta",
44
+ "ObjetReleve",
45
+ "LigneChronologie",
46
+ "LigneEvenement",
47
+ "LigneReleve",
48
+ "LignePeriodeEnergie",
49
+ "LigneTurpeVariable",
50
+ "TurpeVariableRequest",
51
+ "ResultatTurpeVariable",
52
+ "__version__",
53
+ ]
@@ -0,0 +1,128 @@
1
+ """Client Arrow historique : endpoints structurés en `pl.DataFrame` (extra `[arrow]`).
2
+
3
+ Ce sous-module **n'est jamais importé au top-level** de `electricore_client` :
4
+ il porte le seul code qui dépend de polars, et l'importe **paresseusement** (à
5
+ l'appel d'une méthode). La base du paquet reste donc polars-free — l'invariant
6
+ prouvé par le test de pureté tient même quand `[arrow]` n'est pas installé.
7
+
8
+ Endpoints Arrow IPC (`/flux/{table}.arrow`, `/releves.arrow`, `/facturation/
9
+ detail.arrow`, `/taxes/{accise,cta}/detail.arrow`) — pour les notebooks distants
10
+ qui n'ont pas la base DuckDB en local (ADR-0009). Lecture seule (ADR-0012).
11
+
12
+ Installer avec l'extra : `pip install "electricore-client[arrow]"`.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import io
18
+ from typing import TYPE_CHECKING, Any
19
+
20
+ from .transport import _BaseClient
21
+
22
+ if TYPE_CHECKING: # pragma: no cover - annotations only, jamais exécuté
23
+ import polars as pl
24
+
25
+ _HINT_INSTALL = (
26
+ 'Le client Arrow nécessite polars : installez l\'extra `arrow` (`pip install "electricore-client[arrow]"`).'
27
+ )
28
+
29
+
30
+ def _polars():
31
+ """Importe polars paresseusement, avec un message d'install clair s'il manque."""
32
+ try:
33
+ import polars as pl
34
+ except ModuleNotFoundError as exc: # pragma: no cover - testé via monkeypatch
35
+ raise ModuleNotFoundError(_HINT_INSTALL) from exc
36
+ return pl
37
+
38
+
39
+ class ElectricoreArrowClient(_BaseClient):
40
+ """Client Arrow synchrone : endpoints structurés rendus en `pl.DataFrame`.
41
+
42
+ Hérite du substrat de transport partagé (URL, `X-API-Key`, timeout, 503 →
43
+ `IngestionEnCours`). polars n'est tiré qu'au premier appel de méthode.
44
+ """
45
+
46
+ def _get_arrow(self, path: str, params: dict) -> pl.DataFrame:
47
+ pl = _polars()
48
+ response = self._http.get(f"{self.url}{path}", params=params, headers=self._headers)
49
+ self._raise_for_status(response)
50
+ return pl.read_ipc_stream(io.BytesIO(response.content))
51
+
52
+ def flux(
53
+ self,
54
+ table_name: str,
55
+ *,
56
+ prm: str | None = None,
57
+ limit: int = 1_000_000,
58
+ ) -> pl.DataFrame:
59
+ """Contenu brut d'un flux Enedis (c15, r151, f15, etc.) en Polars.
60
+
61
+ Équivalent HTTP des `c15()`/`r151()`/`f15()` du `DuckDBQuery` — pour les
62
+ notebooks distants sans accès local à la base (ADR-0009).
63
+
64
+ Args:
65
+ table_name: nom de la table flux (`c15`, `r151`, `r15`, `f15_detail`, …).
66
+ prm: filtre optionnel sur la colonne `pdl`.
67
+ limit: nombre maximum de lignes (défaut 1 000 000, max serveur 10 000 000).
68
+ """
69
+ params: dict[str, Any] = {"limit": limit}
70
+ if prm:
71
+ params["prm"] = prm
72
+ return self._get_arrow(f"/flux/{table_name}.arrow", params)
73
+
74
+ def releves(
75
+ self,
76
+ *,
77
+ prm: str | None = None,
78
+ source: str | None = None,
79
+ debut: str | None = None,
80
+ fin: str | None = None,
81
+ limit: int = 1_000_000,
82
+ ) -> pl.DataFrame:
83
+ """Mart de relevés canonique `releves` (ADR-0029) en Polars.
84
+
85
+ Args:
86
+ prm: filtre optionnel sur la colonne `pdl`.
87
+ source: filtre optionnel (`flux_R151` / `flux_R64` / `flux_C15`).
88
+ debut: borne basse incluse sur `date_releve` (ex. `"2025-01-01"`).
89
+ fin: borne haute incluse sur `date_releve` (ex. `"2025-12-31"`).
90
+ limit: nombre maximum de lignes (défaut 1 000 000, max serveur 10 000 000).
91
+ """
92
+ params: dict[str, Any] = {"limit": limit}
93
+ if prm:
94
+ params["prm"] = prm
95
+ if source:
96
+ params["source"] = source
97
+ if debut:
98
+ params["debut"] = debut
99
+ if fin:
100
+ params["fin"] = fin
101
+ return self._get_arrow("/releves.arrow", params)
102
+
103
+ def facturation(self, mois: str | None = None) -> pl.DataFrame:
104
+ """`lignes_facture_rapprochees` pour le mois donné.
105
+
106
+ Args:
107
+ mois: "YYYY-MM-DD" — défaut : dernier mois disponible côté serveur.
108
+ """
109
+ return self._get_arrow("/facturation/detail.arrow", {"mois": mois} if mois else {})
110
+
111
+ def accise(self, trimestre: str | None = None) -> pl.DataFrame:
112
+ """Détail Accise TICFE pour le trimestre donné.
113
+
114
+ Args:
115
+ trimestre: "YYYY-TX" (ex. "2025-T1") — défaut : tous les trimestres.
116
+ """
117
+ return self._get_arrow("/taxes/accise/detail.arrow", {"trimestre": trimestre} if trimestre else {})
118
+
119
+ def cta(self, trimestre: str | None = None) -> pl.DataFrame:
120
+ """Détail CTA mensuel pour le trimestre donné.
121
+
122
+ Args:
123
+ trimestre: "YYYY-TX" (ex. "2025-T1") — défaut : tous les trimestres.
124
+ """
125
+ return self._get_arrow("/taxes/cta/detail.arrow", {"trimestre": trimestre} if trimestre else {})
126
+
127
+
128
+ __all__ = ["ElectricoreArrowClient"]