├── .gitignore ├── assets └── qos-energy.png ├── pytest.ini ├── hatch.toml ├── test ├── conftest.py ├── data │ ├── consulterMesuresDetailleesResponse.xml │ └── consulterMesuresResponse.xml ├── test_decrypt.py └── test_requests.py ├── mypy.ini ├── MANIFEST.in ├── tox.ini ├── lowatt_enedis ├── decrypt.py ├── wsdl │ ├── ConsultationMesuresDetaillees │ │ ├── ConsultationMesuresDetaillees-v2.0.wsdl │ │ ├── ConsulterMesuresDetaillees-v2.0.1.xsd │ │ ├── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ └── W3C.SoapEnv.xsd │ ├── M023_v1.2.0 │ │ ├── Services │ │ │ ├── CommandeHistoriqueDonneesMesuresFines │ │ │ │ └── B2B_M023MFI.wsdl │ │ │ ├── CommandeInformationsTechniquesEtContractuelles │ │ │ │ └── B2B_M023ITC.wsdl │ │ │ └── CommandeHistoriqueDonneesMesuresFacturantes │ │ │ │ └── B2B_M023MFA.wsdl │ │ └── xsd │ │ │ ├── m023 │ │ │ ├── ITCModel.xsd │ │ │ ├── MesuresFacturantesModel.xsd │ │ │ └── MesuresFinesModel.xsd │ │ │ └── transverse │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ ├── RecherchePoint │ │ ├── Services │ │ │ └── RecherchePoint │ │ │ │ ├── RecherchePoint-v2.0.wsdl │ │ │ │ └── RechercherPoint-v2.0.xsd │ │ └── Dictionnaires │ │ │ └── Technique │ │ │ ├── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ │ └── W3C.SoapEnv.xsd │ ├── CommandeArretServiceSouscritMesures │ │ ├── Services │ │ │ └── CommandeArretServiceSouscritMesures │ │ │ │ ├── CommanderArretServiceSouscritMesures-v1.0.xsd │ │ │ │ └── CommandeArretServiceSouscritMesures-v1.0.wsdl │ │ └── Dictionnaires │ │ │ └── Technique │ │ │ ├── W3C.SoapEnv.xsd │ │ │ └── v1.0 │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ ├── ConsultationMesuresDetailleesV3 │ │ ├── ConsultationMesuresDetaillees-v3.0.wsdl │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ ├── ConsultationMesures │ │ ├── Services │ │ │ └── ConsultationMesures │ │ │ │ ├── ConsultationMesures-v1.1.wsdl │ │ │ │ └── ConsulterMesures-v1.1.xsd │ │ └── Dictionnaires │ │ │ └── Technique │ │ │ ├── v1.0 │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ │ └── W3C.SoapEnv.xsd │ ├── RechercheServicesSouscritsMesures │ │ ├── Dictionnaires │ │ │ └── Technique │ │ │ │ ├── W3C.SoapEnv.xsd │ │ │ │ └── v1.0 │ │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ └── Services │ │ │ └── RechercheServicesSouscritsMesures │ │ │ ├── RechercherServicesSouscritsMesures-v1.0.wsdl │ │ │ └── RechercherServicesSouscritsMesures-v1.0.xsd │ ├── CommandeCollectePublicationMesures │ │ ├── Dictionnaires │ │ │ └── Technique │ │ │ │ ├── W3C.SoapEnv.xsd │ │ │ │ └── v1.0 │ │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ └── Services │ │ │ └── CommandeCollectePublicationMesures │ │ │ ├── CommandeCollectePublicationMesures-v3.0.wsdl │ │ │ └── CommanderCollectePublicationMesures-v3.0.xsd │ ├── CommandeTransmissionDonneesInfraJ │ │ ├── Dictionnaires │ │ │ └── Technique │ │ │ │ ├── W3C.SoapEnv.xsd │ │ │ │ └── v1.0 │ │ │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ └── Services │ │ │ └── CommandeTransmissionDonneesInfraJ │ │ │ ├── CommandeTransmissionDonneesInfraJ-v1.0.wsdl │ │ │ └── CommanderTransmissionDonneesInfraJ-v1.0.xsd │ ├── TransmissionHistoriqueMesures │ │ └── Services │ │ │ └── TransmissionHistoriqueMesures │ │ │ ├── CommandeTransmissionHistoriqueMesures-v1.0.wsdl │ │ │ └── CommanderTransmissionHistoriqueMesures-v1.0.xsd │ ├── ConsultationDonneesTechniquesContractuelles │ │ ├── Services │ │ │ └── ConsultationDonneesTechniquesContractuelles │ │ │ │ └── ConsultationDonneesTechniquesContractuelles-v1.0.wsdl │ │ └── Dictionnaire │ │ │ └── Technique │ │ │ ├── ENEDIS.Dictionnaire.Technique.v1.0.xsd │ │ │ └── W3C.SoapEnv.xsd │ └── CommandeAccesDonneesMesures │ │ └── Services │ │ └── CommanderAccesDonneesMesures │ │ ├── CommanderAccesDonneesMesures-V1.0.wsdl │ │ └── ENEDIS.Dictionnaire.Technique.v1.0.xsd ├── certauth.py └── __main__.py ├── ruff.toml ├── .github └── workflows │ ├── release.yml │ └── tox.yml ├── .pre-commit-config.yaml ├── pyproject.toml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /assets/qos-energy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowatt/lowatt-enedis/HEAD/assets/qos-energy.png -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = --doctest-modules --ignore test/data 3 | junit_family=xunit2 4 | -------------------------------------------------------------------------------- /hatch.toml: -------------------------------------------------------------------------------- 1 | [version] 2 | source = "vcs" 3 | 4 | [version.raw-options] 5 | local_scheme = "no-local-version" 6 | -------------------------------------------------------------------------------- /test/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture 5 | def accept(request: pytest.FixtureRequest) -> bool: 6 | value = request.config.getoption("--accept") 7 | assert isinstance(value, bool) 8 | return value 9 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | files = . 3 | strict = true 4 | warn_unused_ignores = true 5 | show_error_codes = true 6 | 7 | [mypy-suds.*] 8 | ignore_missing_imports = true 9 | 10 | [mypy-lxml.*] 11 | ignore_missing_imports = true 12 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | prune doc 2 | prune assets 3 | include COPYING 4 | include README.md 5 | include pyproject.toml 6 | include .flake8 7 | include *.ini 8 | recursive-include lowatt_enedis *.wsdl 9 | recursive-include lowatt_enedis *.xsd 10 | recursive-include test/data *.xml *.yaml 11 | recursive-include test *.py 12 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | isolated_build = true 3 | envlist = lint,py3 4 | 5 | [testenv] 6 | extras = 7 | cryptography 8 | test 9 | typing 10 | commands = 11 | mypy 12 | {envpython} -m pytest {posargs:--cov lowatt_enedis --cov-report term} 13 | passenv = 14 | PYTEST_ADDOPTS 15 | 16 | [testenv:lint] 17 | skip_install = true 18 | deps = 19 | pre-commit 20 | ruff 21 | commands = 22 | pre-commit run --all-files --show-diff-on-failure 23 | -------------------------------------------------------------------------------- /lowatt_enedis/decrypt.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | from typing import IO 3 | 4 | 5 | def decrypt_aes_128_cbc(key: str, iv: str, fd: IO[bytes]) -> bytes: 6 | """Decrypt AES 128 CBC enedis encrypted file. 7 | 8 | Should be equivalent to: 9 | openssl enc -d -aes-128-cbc -K -iv -in ERDF_<..>.zip -out output.zip 10 | """ 11 | import cryptography.hazmat.primitives.ciphers as crypto 12 | 13 | cipher = crypto.Cipher( 14 | crypto.algorithms.AES128(binascii.unhexlify(key)), 15 | crypto.modes.CBC(binascii.unhexlify(iv)), 16 | ) 17 | decryptor = cipher.decryptor() 18 | return decryptor.update(fd.read()) + decryptor.finalize() 19 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | target-version = "py39" 2 | 3 | [lint] 4 | select = [ 5 | # pycodestyle 6 | "E", 7 | # Pyflakes 8 | "F", 9 | # pyupgrade 10 | "UP", 11 | # flake8-bugbear 12 | "B", 13 | # flake8-debugger 14 | "T10", 15 | # flake8-logging 16 | "G", 17 | # flake8-comprehension 18 | "C4", 19 | # flake8-simplify 20 | "SIM", 21 | # flake8-print 22 | "T20", 23 | # individual rules 24 | "RUF100", # unused-noqa 25 | # imports 26 | "I", 27 | ] 28 | 29 | # For error codes, see https://docs.astral.sh/ruff/rules/#error-e 30 | ignore = [ 31 | # line too long 32 | "E501", 33 | ] 34 | 35 | [lint.isort] 36 | known-first-party = ["lowatt_enedis"] 37 | section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"] 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: tox 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | publish: 10 | name: Publish to PyPI registry 11 | runs-on: ubuntu-latest 12 | environment: 13 | name: pypi 14 | url: https://pypi.org/p/lowatt-enedis 15 | permissions: 16 | id-token: write 17 | steps: 18 | - name: Switch to using Python 3.11 by default 19 | uses: actions/setup-python@v2 20 | with: 21 | python-version: 3.11 22 | - name: Install build 23 | run: python3 -m pip install --user build 24 | - name: Check out src from Git 25 | uses: actions/checkout@v2 26 | - name: Build dists 27 | run: python3 -m build 28 | - name: Publish to pypi.org 29 | uses: pypa/gh-action-pypi-publish@release/v1 30 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | # 4 | # Should more or less follow lint and typing settings as found is tox.ini 5 | # 6 | # Once pre-commit package is installed in your environnement, install hooks 7 | # with `pre-commit install` 8 | repos: 9 | - repo: https://github.com/pre-commit/pre-commit-hooks 10 | rev: v4.1.0 11 | hooks: 12 | - id: trailing-whitespace 13 | exclude: 'lowatt_enedis/wsdl' 14 | - id: end-of-file-fixer 15 | exclude: 'lowatt_enedis/wsdl' 16 | - id: check-added-large-files 17 | - repo: local 18 | hooks: 19 | - id: ruff-check 20 | name: ruff-check 21 | entry: ruff check 22 | language: system 23 | types: [python] 24 | - id: ruff-format 25 | name: ruff 26 | entry: ruff format --check --diff 27 | language: system 28 | types: [python] 29 | -------------------------------------------------------------------------------- /test/data/consulterMesuresDetailleesResponse.xml: -------------------------------------------------------------------------------- 1 | 30001610071843BRUT2020-03-012020-03-08CONSPAW1002020-03-01T00:00:00.000+01:00

PT10M

B
1012020-03-01T00:10:00.000+01:00

PT10M

B
1022020-03-01T00:20:00.000+01:00

PT10M

B
1032020-03-01T00:30:00.000+01:00

PT10M

B
1042020-03-01T00:40:00.000+01:00

PT10M

B
1052020-03-01T00:50:00.000+01:00

PT10M

B
1062020-03-01T01:00:00.000+01:00

PT10M

B
1072020-03-01T01:10:00.000+01:00

PT10M

B
2 | -------------------------------------------------------------------------------- /.github/workflows/tox.yml: -------------------------------------------------------------------------------- 1 | name: tox 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | pull_request: 8 | schedule: 9 | - cron: 0 0 1 * * # every month 10 | 11 | jobs: 12 | build: 13 | name: ${{ matrix.tox_env }} 14 | runs-on: ubuntu-latest 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | include: 19 | - tox_env: lint 20 | - tox_env: py39 21 | - tox_env: py310 22 | - tox_env: py311 23 | 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Find python version 27 | id: py_ver 28 | shell: python 29 | if: ${{ contains(matrix.tox_env, 'py') }} 30 | run: | 31 | v = '${{ matrix.tox_env }}'.split('-')[0].lstrip('py') 32 | print('::set-output name=version::{0}.{1}'.format(v[0],v[1:])) 33 | - name: Install a default Python 34 | uses: actions/setup-python@v2 35 | if: ${{ ! contains(matrix.tox_env, 'py') }} 36 | with: 37 | python-version: 3.11 38 | - name: Set up Python version 39 | uses: actions/setup-python@v2 40 | if: ${{ contains(matrix.tox_env, 'py') }} 41 | with: 42 | python-version: ${{ steps.py_ver.outputs.version }} 43 | - name: Install tox 44 | run: | 45 | pip install tox 46 | - name: Run tox -e ${{ matrix.tox_env }} 47 | run: | 48 | echo "${{ matrix.PREFIX }} tox -e ${{ matrix.tox_env }}" 49 | ${{ matrix.PREFIX }} tox -e ${{ matrix.tox_env }} 50 | -------------------------------------------------------------------------------- /test/test_decrypt.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import os 3 | import sys 4 | from pathlib import Path 5 | from unittest import mock 6 | 7 | import cryptography.hazmat.primitives.ciphers as crypto 8 | import pytest 9 | 10 | from lowatt_enedis.__main__ import run 11 | 12 | 13 | def test_decrypt(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None: 14 | key = binascii.hexlify(os.urandom(16)) 15 | iv = binascii.hexlify(os.urandom(16)) 16 | cipher = crypto.Cipher( 17 | crypto.algorithms.AES128(binascii.unhexlify(key)), 18 | crypto.modes.CBC(binascii.unhexlify(iv)), 19 | ) 20 | encryptor = cipher.encryptor() 21 | encrypted = encryptor.update(b"some xml secrets") + encryptor.finalize() 22 | with (tmp_path / "encrypted").open("wb") as f: 23 | f.write(encrypted) 24 | 25 | with ( 26 | mock.patch.object( 27 | sys, 28 | "argv", 29 | [ 30 | "lowatt-enedis", 31 | "decrypt", 32 | "--key", 33 | key.decode("ascii"), 34 | "--iv", 35 | iv.decode("ascii"), 36 | "--output", 37 | str(tmp_path / "decrypted"), 38 | str(tmp_path / "encrypted"), 39 | ], 40 | ), 41 | pytest.raises(SystemExit) as cm, 42 | ): 43 | run() 44 | assert cm.value.code == 0 45 | output = capsys.readouterr() 46 | assert output.out == "" 47 | assert output.err == "" 48 | with (tmp_path / "decrypted").open("rb") as f: 49 | assert f.read() == b"some xml secrets" 50 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling", "hatch-vcs"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "lowatt-enedis" 7 | description = "Python client for Enedis SGE web-service" 8 | readme = "README.md" 9 | license = { text = "GPLv3" } 10 | authors = [{ name = "Lowatt", email = "info@lowatt.fr" }] 11 | classifiers = [ 12 | "Development Status :: 5 - Production/Stable", 13 | "Environment :: Console", 14 | "Programming Language :: Python :: 3", 15 | "Programming Language :: Python :: 3.9", 16 | "Programming Language :: Python :: 3.10", 17 | "Programming Language :: Python :: 3.11", 18 | "Programming Language :: Python :: 3 :: Only", 19 | "Operating System :: OS Independent", 20 | "Topic :: System :: Archiving :: Mirroring", 21 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 22 | ] 23 | requires-python = ">=3.9" 24 | dynamic = ["version"] 25 | dependencies = [ 26 | "certifi", 27 | "suds-py3", 28 | "rich", 29 | ] 30 | 31 | [project.urls] 32 | Source = "https://github.com/lowatt/lowatt-enedis" 33 | Tracker = "https://github.com/lowatt/lowatt-enedis/issues" 34 | 35 | [project.optional-dependencies] 36 | cryptography = [ 37 | "cryptography", # required for lowatt-enedis decrypt 38 | ] 39 | test = [ 40 | "pytest", 41 | "pytest-accept", 42 | "pytest-cov", 43 | "lxml", 44 | "freezegun", 45 | "pyyaml", 46 | "importlib_metadata;python_version<'3.10'", 47 | ] 48 | typing = [ 49 | "mypy", 50 | "types-freezegun", 51 | "types-PyYAML", 52 | ] 53 | 54 | [project.scripts] 55 | lowatt-enedis = "lowatt_enedis.__main__:run" 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lowatt-enedis 2 | 3 | A command-line tool and Python library to access 4 | [Enedis](https://www.enedis.fr/) SGE SOAP web-services, provided by 5 | [LOWATT](https://www.lowatt.fr). 6 | 7 | Disclaimer: this package is *NOT* affiliated to Enedis, but provided by Lowatt 8 | in case it could be useful to other users of the SGE web-services provided by 9 | Enedis. 10 | 11 | ## Licensing 12 | 13 | It is published under the terms of the GPL 3 license. 14 | 15 | ## Installation 16 | 17 | ``pip install lowatt-enedis`` 18 | 19 | ## Command line usage 20 | 21 | See ``lowatt-enedis --help`` for CLI usage. You'll be able to call the services 22 | controlled using options and see the SOAP response. You can take a look at 23 | ``doc/homologation.md`` for a sample session to go through Enedis'homologation 24 | process. 25 | 26 | Some flags are required by all or most of the commands so they can be 27 | configured once by their respective environment variables. 28 | 29 | | Option | Environment variable | 30 | |---------------|----------------------| 31 | | `--cert-file` | `ENEDIS_CERT_FILE` | 32 | | `--key-file` | `ENEDIS_KEY_FILE` | 33 | | `--login` | `ENEDIS_LOGIN` | 34 | | `--contrat` | `ENEDIS_CONTRAT` | 35 | 36 | ## Python library usage 37 | 38 | Here is a sample code to access to the ``ConsultationMesuresDetaillees`` from 39 | Python code : 40 | 41 | ```python 42 | import datetime 43 | import lowatt_enedis 44 | import lowatt_enedis.services 45 | 46 | config = { 47 | 'login': 'you@example.com', 48 | 'certificateFile': 'fullchain.pem', 49 | 'keyFile': 'privkey.pem', 50 | 'prm': '30000123456789', 51 | } 52 | # get client for the 'details' service using appropriate client 53 | # certificate and key 54 | client = lowatt_enedis.get_client( 55 | lowatt_enedis.COMMAND_SERVICE['details'][0], 56 | config['certificateFile'], config['keyFile'], 57 | ) 58 | # actually call the web to get values for the past week 59 | resp = lowatt_enedis.services.point_detailed_measures(client, { 60 | 'login': config['login'], 61 | 'prm': config['prm'], 62 | 'type': 'COURBE', 63 | 'courbe_type': 'PA', 64 | 'corrigee': True, 65 | 'from': datetime.date.today() - datetime.timedelta(days=7), 66 | 'to': datetime.date.today(), 67 | }) 68 | # get a list of (UTC timestamp, value(W)) 69 | data = lowatt_enedis.services.measures_resp2py(resp) 70 | ``` 71 | 72 | ## Contributions 73 | 74 | Contribution are welcome through the [Github 75 | repository](https://github.com/lowatt/lowatt_enedis). 76 | 77 | Feel free to contact for more info by writing at info@lowatt.fr. 78 | 79 | ## Sponsors 80 | 81 | [![QosEnergy](assets/qos-energy.png)](https://www.qosenergy.com/) 82 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetaillees/ConsultationMesuresDetaillees-v2.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/Services/CommandeHistoriqueDonneesMesuresFines/B2B_M023MFI.wsdl: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RecherchePoint/Services/RecherchePoint/RecherchePoint-v2.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeArretServiceSouscritMesures/Services/CommandeArretServiceSouscritMesures/CommanderArretServiceSouscritMesures-v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/Services/CommandeInformationsTechniquesEtContractuelles/B2B_M023ITC.wsdl: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetailleesV3/ConsultationMesuresDetaillees-v3.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesures/Services/ConsultationMesures/ConsultationMesures-v1.1.wsdl: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/Services/CommandeHistoriqueDonneesMesuresFacturantes/B2B_M023MFA.wsdl: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lowatt_enedis/certauth.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 by Lowatt - info@lowatt.fr 2 | # 3 | # This program is part of lowatt_enedis 4 | # 5 | # lowatt_enedis is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # lowatt_enedis is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with lowatt_enedis. If not, see . 17 | """ 18 | `lowatt_enedis.certauth` 19 | ------------------------ 20 | 21 | Provide a SUDS_ transport class to connect through an HTTPS connection using 22 | a client SSL certificate. 23 | 24 | .. autoclass:: HTTPSClientCertTransport 25 | 26 | .. _SUDS: https://suds-py3.readthedocs.io/en/latest 27 | 28 | """ 29 | 30 | import ssl 31 | from http.client import HTTPResponse, HTTPSConnection 32 | from typing import Any 33 | from urllib.request import HTTPSHandler, Request, build_opener 34 | 35 | import certifi 36 | from suds.transport.http import HttpTransport 37 | 38 | 39 | class _HTTPSClientAuthHandler(HTTPSHandler): 40 | def __init__(self, cert_file: str, key_file: str): 41 | super().__init__() 42 | self.cert_file = cert_file 43 | self.key_file = key_file 44 | 45 | def https_open(self, req: Request) -> HTTPResponse: 46 | return self.do_open(self.get_connection, req) # type: ignore[arg-type] 47 | 48 | def get_connection(self, host: str, timeout: int = 300) -> HTTPSConnection: 49 | context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) 50 | context.load_cert_chain(self.cert_file, self.key_file) 51 | context.load_verify_locations(cafile=certifi.where()) 52 | return HTTPSConnection(host, context=context) 53 | 54 | 55 | class HTTPSClientCertTransport(HttpTransport): # type: ignore[misc] 56 | """SUDS_ transport class to connect through an HTTPS connection using 57 | a client SSL certificate. 58 | 59 | :param cert_file: path to the full-chain certificate file. 60 | :param key_file: path to the private key file. 61 | 62 | Usage :: 63 | 64 | from suds.client import Client 65 | client = Client( 66 | service_url, 67 | transport=HTTPSClientCertTransport(cert_file, key_file), 68 | ) 69 | 70 | .. _SUDS: https://suds-py3.readthedocs.io/en/latest 71 | """ 72 | 73 | def __init__(self, cert_file: str, key_file: str, *args: Any, **kwargs: Any): 74 | super().__init__(*args, **kwargs) 75 | self.url_open = build_opener( 76 | _HTTPSClientAuthHandler(cert_file, key_file), 77 | ).open 78 | 79 | def u2open(self, u2request: Request) -> HTTPResponse: 80 | """Open an return a connection. 81 | 82 | :param u2request: A urllib2 request. 83 | :return: The opened file-like urllib2 object. 84 | """ 85 | return self.url_open(u2request, timeout=self.options.timeout) # type: ignore[no-any-return] 86 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesures/Services/ConsultationMesures/ConsulterMesures-v1.1.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RechercheServicesSouscritsMesures/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Prose in the spec does not specify that attributes are allowed on the Body element 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Fault reporting structure 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /lowatt_enedis/__main__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 by Lowatt - info@lowatt.fr 2 | # 3 | # This program is part of lowatt_enedis 4 | # 5 | # lowatt_enedis is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # lowatt_enedis is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with lowatt_enedis. If not, see . 17 | import argparse 18 | import sys 19 | from typing import NoReturn 20 | 21 | from suds.client import Client 22 | 23 | import lowatt_enedis.services # noqa: F401 register services 24 | from lowatt_enedis import ( 25 | COMMAND_SERVICE, 26 | WSException, 27 | arg_from_env, 28 | handle_cli_command, 29 | init_cli, 30 | wsdl, 31 | ) 32 | 33 | from . import decrypt 34 | 35 | 36 | def _cli_parser() -> argparse.ArgumentParser: 37 | parser = argparse.ArgumentParser( 38 | description="CLI access to Enedis SGE web-services.", 39 | ) 40 | 41 | subparsers = parser.add_subparsers(dest="command") 42 | init_cli(subparsers) 43 | 44 | # wsdl command 45 | subparser = subparsers.add_parser( 46 | "wsdl", 47 | help="Display WSDL information about some ws command.", 48 | ) 49 | subparser.add_argument( 50 | "service_command", 51 | help="Command name.", 52 | ) 53 | 54 | # decrypt command 55 | subparser = subparsers.add_parser( 56 | "decrypt", 57 | help="Decrypt AES-128-CBC enedis files", 58 | ) 59 | subparser.add_argument( 60 | "--key", 61 | help="Hex AES key", 62 | **arg_from_env("ENEDIS_DECRYPT_KEY"), 63 | ) 64 | subparser.add_argument( 65 | "--iv", 66 | help="Hex CBC IV", 67 | **arg_from_env("ENEDIS_DECRYPT_IV"), 68 | ) 69 | subparser.add_argument( 70 | "input_file", help="Input file", type=argparse.FileType("rb") 71 | ) 72 | subparser.add_argument( 73 | "-o", 74 | "--output", 75 | help="Output file", 76 | required=True, 77 | ) 78 | 79 | return parser 80 | 81 | 82 | def run() -> NoReturn: 83 | parser = _cli_parser() 84 | args = parser.parse_args() 85 | 86 | if args.command == "wsdl": 87 | try: 88 | service_name = COMMAND_SERVICE[args.service_command][0] 89 | except KeyError: 90 | service_name = args.service_command 91 | 92 | print(Client(wsdl(service_name))) # noqa 93 | 94 | elif args.command == "decrypt": 95 | decrypted = decrypt.decrypt_aes_128_cbc(args.key, args.iv, args.input_file) 96 | with open(args.output, "wb") as f: 97 | f.write(decrypted) 98 | elif args.command: 99 | try: 100 | handle_cli_command(args.command, args) 101 | except WSException: 102 | sys.exit(1) 103 | 104 | else: 105 | parser.print_help() 106 | sys.exit(1) 107 | 108 | sys.exit(0) 109 | 110 | 111 | if __name__ == "__main__": 112 | run() 113 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeArretServiceSouscritMesures/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Prose in the spec does not specify that attributes are allowed on the Body element 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Fault reporting structure 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeCollectePublicationMesures/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Prose in the spec does not specify that attributes are allowed on the Body element 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Fault reporting structure 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeTransmissionDonneesInfraJ/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Prose in the spec does not specify that attributes are allowed on the Body element 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Fault reporting structure 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RecherchePoint/Services/RecherchePoint/RechercherPoint-v2.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RechercheServicesSouscritsMesures/Services/RechercheServicesSouscritsMesures/RechercherServicesSouscritsMesures-v1.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RechercheServicesSouscritsMesures/Services/RechercheServicesSouscritsMesures/RechercherServicesSouscritsMesures-v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/TransmissionHistoriqueMesures/Services/TransmissionHistoriqueMesures/CommandeTransmissionHistoriqueMesures-v1.0.wsdl: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationDonneesTechniquesContractuelles/Services/ConsultationDonneesTechniquesContractuelles/ConsultationDonneesTechniquesContractuelles-v1.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeTransmissionDonneesInfraJ/Services/CommandeTransmissionDonneesInfraJ/CommandeTransmissionDonneesInfraJ-v1.0.wsdl: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeCollectePublicationMesures/Services/CommandeCollectePublicationMesures/CommandeCollectePublicationMesures-v3.0.wsdl: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeArretServiceSouscritMesures/Services/CommandeArretServiceSouscritMesures/CommandeArretServiceSouscritMesures-v1.0.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetaillees/ConsulterMesuresDetaillees-v2.0.1.xsd: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeAccesDonneesMesures/Services/CommanderAccesDonneesMesures/CommanderAccesDonneesMesures-V1.0.wsdl: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 14 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeTransmissionDonneesInfraJ/Services/CommandeTransmissionDonneesInfraJ/CommanderTransmissionDonneesInfraJ-v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RechercheServicesSouscritsMesures/Dictionnaires/Technique/v1.0/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/xsd/m023/ITCModel.xsd: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetaillees/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationDonneesTechniquesContractuelles/Dictionnaire/Technique/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeCollectePublicationMesures/Dictionnaires/Technique/v1.0/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeTransmissionDonneesInfraJ/Dictionnaires/Technique/v1.0/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeArretServiceSouscritMesures/Dictionnaires/Technique/v1.0/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RecherchePoint/Dictionnaires/Technique/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesures/Dictionnaires/Technique/v1.0/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeCollectePublicationMesures/Services/CommandeCollectePublicationMesures/CommanderCollectePublicationMesures-v3.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /test/data/consulterMesuresResponse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Succès 6 | 7 | 8 | 07151808919109 9 | 10 | 11 | 12 | you@example.com 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Energie Active 23 | 24 | 25 | 26 | Base 27 | 28 | 29 | 30 | Base 31 | 32 | 33 | kWh 34 | 35 | 36 | 483 37 | 38 | 2021-02-03 39 | 40 | 2021-03-05 41 | 42 | 43 | Réelle 44 | 45 | 46 | 47 | Publication cyclique 48 | 49 | 50 | 51 | Initiale 52 | 53 | 54 | 55 | 56 | 494 57 | 58 | 2021-01-05 59 | 60 | 2021-02-03 61 | 62 | 63 | Réelle 64 | 65 | 66 | 67 | Publication cyclique 68 | 69 | 70 | 71 | Initiale 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Energie Active 82 | 83 | 84 | 85 | BASE 86 | 87 | 88 | 89 | FC000013 90 | 91 | 92 | kWh 93 | 94 | 95 | 483 96 | 97 | 2021-02-03 98 | 99 | 2021-03-05 100 | 101 | 102 | Réelle 103 | 104 | 105 | 106 | Publication cyclique 107 | 108 | 109 | 110 | Initiale 111 | 112 | 113 | 114 | 115 | 494 116 | 117 | 2021-01-05 118 | 119 | 2021-02-03 120 | 121 | 122 | Réelle 123 | 124 | 125 | 126 | Publication cyclique 127 | 128 | 129 | 130 | Initiale 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/xsd/m023/MesuresFacturantesModel.xsd: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/TransmissionHistoriqueMesures/Services/TransmissionHistoriqueMesures/CommanderTransmissionHistoriqueMesures-v1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/xsd/transverse/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetailleesV3/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/CommandeAccesDonneesMesures/Services/CommanderAccesDonneesMesures/ENEDIS.Dictionnaire.Technique.v1.0.xsd: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/M023_v1.2.0/xsd/m023/MesuresFinesModel.xsd: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /test/test_requests.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import doctest 3 | import importlib 4 | import re 5 | import shlex 6 | import subprocess 7 | import sys 8 | from collections.abc import Iterator 9 | from pathlib import Path 10 | from typing import TypedDict 11 | from unittest.mock import patch 12 | 13 | if sys.version_info < (3, 10): 14 | import importlib_metadata 15 | else: 16 | from importlib import metadata as importlib_metadata 17 | 18 | import freezegun 19 | import lxml.doctestcompare 20 | import lxml.etree 21 | import lxml.objectify 22 | import pytest 23 | import yaml 24 | 25 | import lowatt_enedis.services 26 | 27 | 28 | def get_cases(_cache: dict[None, dict[str, str]] = {}) -> dict[str, str]: # noqa: B006 29 | with contextlib.suppress(KeyError): 30 | return _cache[None] 31 | cases: dict[str, str] = {} 32 | with (Path(__file__).parent.parent / "doc" / "homologation.md").open() as f: 33 | for line in f: 34 | match = re.search(r"\|(.*)\|.*`(lowatt-enedis .*)`.*$", line) 35 | if match: 36 | case, command = match.groups() 37 | case = case.strip() 38 | assert case not in cases 39 | cases[case] = command 40 | assert len(cases) == 72 41 | _cache[None] = cases 42 | return cases 43 | 44 | 45 | class ExpectedDict(TypedDict): 46 | url: str 47 | data: str 48 | 49 | 50 | EXPECTED_FILENAME = Path(__file__).parent / "data" / "requests.yaml" 51 | 52 | 53 | def get_expected( 54 | _cache: dict[None, dict[str, ExpectedDict]] = {}, # noqa: B006 55 | ) -> dict[str, ExpectedDict]: 56 | with contextlib.suppress(KeyError): 57 | return _cache[None] 58 | with EXPECTED_FILENAME.open() as f: 59 | result = _cache[None] = yaml.safe_load(f) 60 | return result # type: ignore[no-any-return] 61 | 62 | 63 | class Dumper(yaml.SafeDumper): 64 | pass 65 | 66 | 67 | def multiline_dump(dumper: yaml.SafeDumper, data: str) -> yaml.ScalarNode: 68 | if len(data.splitlines()) > 1: 69 | return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") 70 | return dumper.represent_scalar("tag:yaml.org,2002:str", data) 71 | 72 | 73 | Dumper.add_representer(str, multiline_dump) 74 | 75 | 76 | def set_expected(case: str, expected: ExpectedDict) -> None: 77 | try: 78 | with EXPECTED_FILENAME.open() as f: 79 | result = yaml.safe_load(f) 80 | except FileNotFoundError: 81 | result = {} 82 | 83 | result[case] = expected 84 | 85 | with EXPECTED_FILENAME.open("w") as f: 86 | yaml.dump(result, f, allow_unicode=True, sort_keys=True, Dumper=Dumper) 87 | 88 | 89 | @contextlib.contextmanager 90 | def override_sys_argv(argv: list[str]) -> Iterator[None]: 91 | old, sys.argv = sys.argv, argv 92 | try: 93 | yield 94 | finally: 95 | sys.argv = old 96 | 97 | 98 | @pytest.fixture(scope="session") 99 | def certs(tmp_path_factory: pytest.TempPathFactory) -> tuple[Path, Path]: 100 | certs = tmp_path_factory.mktemp("certs") 101 | certfile, keyfile = certs / "cert.pem", certs / "key.pem" 102 | subprocess.check_call( 103 | [ 104 | "openssl", 105 | "req", 106 | "-x509", 107 | "-newkey", 108 | "rsa:2048", 109 | "-nodes", 110 | "-keyout", 111 | str(keyfile), 112 | "-out", 113 | str(certfile), 114 | "-batch", 115 | ], 116 | ) 117 | return certfile, keyfile 118 | 119 | 120 | def assert_xml_equal(actual: str, expected: str) -> None: 121 | checker = lxml.doctestcompare.LXMLOutputChecker() 122 | if not checker.check_output(actual, expected, 0): 123 | message = checker.output_difference(doctest.Example("", expected), actual, 0) 124 | raise AssertionError(message) 125 | 126 | 127 | @pytest.mark.parametrize("case", list(get_cases())) 128 | def test_requests( 129 | case: str, tmp_path: Path, certs: tuple[Path, Path], accept: bool 130 | ) -> None: 131 | # fix some defaults set at import time 132 | with ( 133 | freezegun.freeze_time("2022-02-22"), 134 | patch.dict("os.environ", {"ENEDIS_CONTRAT": "1234"}), 135 | ): 136 | importlib.reload(lowatt_enedis.services) 137 | (entrypoint,) = importlib_metadata.entry_points( 138 | group="console_scripts", 139 | name="lowatt-enedis", 140 | ) 141 | assert entrypoint 142 | func = entrypoint.load() 143 | command = shlex.split(get_cases()[case]) 144 | 145 | with ( 146 | override_sys_argv(command), 147 | patch.dict( 148 | "os.environ", 149 | { 150 | "ENEDIS_LOGIN": "test@example.com", 151 | "ENEDIS_CERT_FILE": str(certs[0]), 152 | "ENEDIS_KEY_FILE": str(certs[1]), 153 | "ENEDIS_HOMOLOGATION": "true", 154 | }, 155 | ), 156 | patch("lowatt_enedis.certauth._HTTPSClientAuthHandler.https_open") as client, 157 | ): 158 | 159 | class FakeResponse: 160 | code = 500 161 | msg = b"" 162 | 163 | def info(self) -> dict[str, str]: 164 | return {} 165 | 166 | def read(self) -> bytes: 167 | return ( 168 | b'' 169 | b'' 170 | b'' 171 | b'' 172 | b"" 173 | b"" 174 | b"" 175 | ) 176 | 177 | def close(self) -> None: 178 | pass 179 | 180 | resp = FakeResponse() 181 | client.return_value = resp 182 | with pytest.raises(SystemExit) as cm: 183 | func() 184 | assert cm.value.code == 1 185 | req = client.mock_calls[0].args[0] 186 | data = lxml.etree.tostring( 187 | lxml.objectify.fromstring(req.data), encoding="utf8", pretty_print=True 188 | ).decode() 189 | actual: ExpectedDict = {"url": req.full_url, "data": data} 190 | if accept: 191 | set_expected(case, actual) 192 | else: 193 | expected = get_expected()[case] 194 | assert actual["url"] == expected["url"] 195 | assert_xml_equal(actual["data"], expected["data"]) 196 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesures/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Prose in the spec does not specify that attributes are allowed on the Body element 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Fault reporting structure 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationDonneesTechniquesContractuelles/Dictionnaire/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Prose in the spec does not specify that attributes are allowed on the Body element 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Fault reporting structure 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/ConsultationMesuresDetaillees/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Prose in the spec does not specify that attributes are allowed on the Body element 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Fault reporting structure 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /lowatt_enedis/wsdl/RecherchePoint/Dictionnaires/Technique/W3C.SoapEnv.xsd: -------------------------------------------------------------------------------- 1 | 2 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Prose in the spec does not specify that attributes are allowed on the Body element 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Fault reporting structure 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | --------------------------------------------------------------------------------