myelectricaldatapy 2.2.5__tar.gz → 2.2.7__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.
- myelectricaldatapy-2.2.7/.devcontainer/devcontainer-lock.json +14 -0
- myelectricaldatapy-2.2.7/.devcontainer/devcontainer.json +60 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.github/workflows/python-lint.yml +6 -9
- myelectricaldatapy-2.2.7/.github/workflows/python-publish.yml +31 -0
- myelectricaldatapy-2.2.7/.github/workflows/release.yml +35 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.gitignore +4 -2
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.pre-commit-config.yaml +6 -6
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/PKG-INFO +9 -4
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/__init__.py +1 -3
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/analytics.py +25 -10
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/myelectricaldata.py +3 -10
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/mypdl.py +13 -6
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/PKG-INFO +9 -4
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/SOURCES.txt +4 -4
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/requires.txt +5 -0
- myelectricaldatapy-2.2.7/myelectricaldatapy.egg-info/scm_file_list.json +40 -0
- myelectricaldatapy-2.2.7/myelectricaldatapy.egg-info/scm_version.json +8 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/pyproject.toml +13 -3
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/conftest.py +1 -1
- myelectricaldatapy-2.2.7/tests/fixtures/tempo.json +1 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/test_load_data.py +30 -2
- myelectricaldatapy-2.2.5/.flake8 +0 -3
- myelectricaldatapy-2.2.5/.github/workflows/python-publish.yml +0 -36
- myelectricaldatapy-2.2.5/.github/workflows/release.yml +0 -59
- myelectricaldatapy-2.2.5/MANIFEST.in +0 -6
- myelectricaldatapy-2.2.5/requirements-dev.txt +0 -14
- myelectricaldatapy-2.2.5/requirements.txt +0 -3
- myelectricaldatapy-2.2.5/tests/fixtures/tempo.json +0 -1
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.github/dependabot.yml +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.github/workflows/auto-approve.yml +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/.vscode/settings.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/LICENSE +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/README.md +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/_secrets.yaml +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/example.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/auth.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/const.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/exceptions.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/py.typed +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/dependency_links.txt +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/top_level.txt +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/setup.cfg +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/__init__.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/consts.py +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/access.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/address.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/contract.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/daily.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/detail.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/ecowatt.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/fixtures/invalid_access.json +0 -0
- {myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/tests/test_analytics.py +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"features": {
|
|
3
|
+
"ghcr.io/devcontainers-extra/features/prek:1": {
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"resolved": "ghcr.io/devcontainers-extra/features/prek@sha256:eb55e266252d8560cf726f27c5675e397bb833067a21428c50b273a59842f649",
|
|
6
|
+
"integrity": "sha256:eb55e266252d8560cf726f27c5675e397bb833067a21428c50b273a59842f649"
|
|
7
|
+
},
|
|
8
|
+
"ghcr.io/devcontainers-extra/features/uv:1": {
|
|
9
|
+
"version": "1.0.2",
|
|
10
|
+
"resolved": "ghcr.io/devcontainers-extra/features/uv@sha256:1ac5b9f17a9e9e745933d0ac2ecf758e06ed3da4423cd22c94cce4d482fd2dd8",
|
|
11
|
+
"integrity": "sha256:1ac5b9f17a9e9e745933d0ac2ecf758e06ed3da4423cd22c94cce4d482fd2dd8"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
|
2
|
+
// README at: https://github.com/devcontainers/templates/tree/main/src/python
|
|
3
|
+
{
|
|
4
|
+
"name": "Python 3",
|
|
5
|
+
"image": "mcr.microsoft.com/devcontainers/python:3-3.14-trixie",
|
|
6
|
+
"features": {
|
|
7
|
+
"ghcr.io/devcontainers-extra/features/prek:1": {},
|
|
8
|
+
"ghcr.io/devcontainers-extra/features/uv:1": {}
|
|
9
|
+
},
|
|
10
|
+
"postCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && prek install --overwrite && uv venv --seed --clear && uv pip install --no-cache-dir --link-mode=copy -e '.[dev]'",
|
|
11
|
+
"customizations": {
|
|
12
|
+
"vscode": {
|
|
13
|
+
"extensions": [
|
|
14
|
+
"ms-python.python",
|
|
15
|
+
"ms-python.vscode-pylance",
|
|
16
|
+
"charliermarsh.ruff",
|
|
17
|
+
"esbenp.prettier-vscode",
|
|
18
|
+
"dbaeumer.vscode-eslint",
|
|
19
|
+
"ms-azuretools.vscode-docker",
|
|
20
|
+
"ms-vscode-remote.remote-containers",
|
|
21
|
+
"streetsidesoftware.code-spell-checker",
|
|
22
|
+
"streetsidesoftware.code-spell-checker-french",
|
|
23
|
+
"anthropic.claude-code"
|
|
24
|
+
],
|
|
25
|
+
"settings": {
|
|
26
|
+
// ── Python ──────────────────────────────────────────────────────
|
|
27
|
+
"python.terminal.activateEnvInCurrentTerminal": true,
|
|
28
|
+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
|
|
29
|
+
"[python]": {
|
|
30
|
+
"pythonPath": "${workspaceFolder}/.venv/bin/python",
|
|
31
|
+
"editor.defaultFormatter": "charliermarsh.ruff",
|
|
32
|
+
"editor.formatOnSave": true,
|
|
33
|
+
"editor.formatOnPaste": false,
|
|
34
|
+
"editor.formatOnType": true,
|
|
35
|
+
"editor.codeActionsOnSave": {
|
|
36
|
+
"source.fixAll": "explicit",
|
|
37
|
+
"source.organizeImports": "explicit"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"ruff.enable": true,
|
|
41
|
+
"ruff.organizeImports": true,
|
|
42
|
+
"[json]": {
|
|
43
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
44
|
+
},
|
|
45
|
+
"[yaml]": {
|
|
46
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
47
|
+
},
|
|
48
|
+
// ── Général ──────────────────────────────────────────────────────
|
|
49
|
+
"editor.tabSize": 2,
|
|
50
|
+
"editor.insertSpaces": true,
|
|
51
|
+
"files.eol": "\n",
|
|
52
|
+
"files.insertFinalNewline": true,
|
|
53
|
+
"files.trimTrailingWhitespace": true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"mounts": [
|
|
58
|
+
"source=${env:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -13,18 +13,15 @@ jobs:
|
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
15
|
- name: 📥 Checkout the repository
|
|
16
|
-
uses: actions/checkout@
|
|
16
|
+
uses: actions/checkout@v7
|
|
17
17
|
|
|
18
|
-
- name:
|
|
19
|
-
uses:
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v7
|
|
20
20
|
with:
|
|
21
21
|
python-version: ${{ matrix.python-version }}
|
|
22
22
|
|
|
23
23
|
- name: 📦 Install dependencies
|
|
24
|
-
run:
|
|
25
|
-
python -m pip install --upgrade pip
|
|
26
|
-
pip install -r requirements.txt
|
|
27
|
-
pip install pylint
|
|
24
|
+
run: uv sync --extra dev
|
|
28
25
|
|
|
29
|
-
- name: Run
|
|
30
|
-
|
|
26
|
+
- name: Run prek
|
|
27
|
+
run: uv run prek run --all-files
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Upload Python Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: ["published"]
|
|
6
|
+
workflow_call:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
deploy:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
name: Deploy to PyPi
|
|
13
|
+
environment: release
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
steps:
|
|
17
|
+
- name: 📥 Checkout the repository
|
|
18
|
+
uses: actions/checkout@v7
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.13"
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: uv build
|
|
29
|
+
|
|
30
|
+
- name: 🚀 Publish to PyPi
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@v1.14.2
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Create release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags:
|
|
5
|
+
- "*.*.*" # Push events to matching i.e. 1.0.0, 4.0.1
|
|
6
|
+
jobs:
|
|
7
|
+
release:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
# To use this repository's private action, you must check out the repository
|
|
11
|
+
- name: 📥 Checkout the repository
|
|
12
|
+
uses: actions/checkout@v7
|
|
13
|
+
|
|
14
|
+
- name: Generate changelog
|
|
15
|
+
id: changelog
|
|
16
|
+
uses: metcalfc/changelog-generator@v4.7.0
|
|
17
|
+
with:
|
|
18
|
+
myToken: ${{ secrets.GITHUB_TOKEN }}
|
|
19
|
+
|
|
20
|
+
- name: Create Release
|
|
21
|
+
uses: softprops/action-gh-release@v3
|
|
22
|
+
with:
|
|
23
|
+
name: ${{ github.ref_name }}
|
|
24
|
+
body: ${{ steps.changelog.outputs.changelog }}
|
|
25
|
+
draft: false
|
|
26
|
+
prerelease: ${{ contains(github.ref_name, '-') }}
|
|
27
|
+
token: ${{ secrets.RELEASE_TOKEN }}
|
|
28
|
+
publish:
|
|
29
|
+
needs: release
|
|
30
|
+
permissions:
|
|
31
|
+
contents: write
|
|
32
|
+
packages: write
|
|
33
|
+
id-token: write
|
|
34
|
+
if: ${{ ! contains(github.ref_name, '-') }}
|
|
35
|
+
uses: ./.github/workflows/python-publish.yml
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
repos:
|
|
3
3
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
-
rev: v0.
|
|
4
|
+
rev: v0.16.2
|
|
5
5
|
hooks:
|
|
6
6
|
- id: ruff
|
|
7
7
|
args:
|
|
8
8
|
- --fix
|
|
9
9
|
- id: ruff-format
|
|
10
10
|
- repo: https://github.com/codespell-project/codespell
|
|
11
|
-
rev: v2.4.
|
|
11
|
+
rev: v2.4.3
|
|
12
12
|
hooks:
|
|
13
13
|
- id: codespell
|
|
14
14
|
args:
|
|
@@ -17,14 +17,14 @@ repos:
|
|
|
17
17
|
- --quiet-level=2
|
|
18
18
|
exclude_types: [csv, json]
|
|
19
19
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
20
|
-
rev:
|
|
20
|
+
rev: v6.0.0
|
|
21
21
|
hooks:
|
|
22
22
|
- id: check-executables-have-shebangs
|
|
23
23
|
stages: [manual]
|
|
24
24
|
- id: check-json
|
|
25
25
|
exclude: (.vscode|.devcontainer)
|
|
26
26
|
- repo: https://github.com/adrienverge/yamllint.git
|
|
27
|
-
rev: v1.
|
|
27
|
+
rev: v1.38.0
|
|
28
28
|
hooks:
|
|
29
29
|
- id: yamllint
|
|
30
30
|
exclude: (.github|.vscode|.devcontainer)
|
|
@@ -33,7 +33,7 @@ repos:
|
|
|
33
33
|
hooks:
|
|
34
34
|
- id: prettier
|
|
35
35
|
- repo: https://github.com/cdce8p/python-typing-update
|
|
36
|
-
rev: v0.
|
|
36
|
+
rev: v0.8.1
|
|
37
37
|
hooks:
|
|
38
38
|
# Run `python-typing-update` hook manually from time to time
|
|
39
39
|
# to update python typing syntax.
|
|
@@ -46,7 +46,7 @@ repos:
|
|
|
46
46
|
- --force
|
|
47
47
|
- --keep-updates
|
|
48
48
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
49
|
-
rev:
|
|
49
|
+
rev: v2.3.0
|
|
50
50
|
hooks:
|
|
51
51
|
- id: mypy
|
|
52
52
|
args: [--strict, --ignore-missing-imports]
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: myelectricaldatapy
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.7
|
|
4
4
|
Summary: Fetch Linky data from myelectricaldata.fr
|
|
5
5
|
Author-email: Cyr-ius <cyr-ius@ipocus.net>
|
|
6
|
-
License: GPL-3
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://github.com/cyr-ius/myelectricaldatapy
|
|
8
8
|
Keywords: enedis,linky,async,myelectricaldata
|
|
9
|
+
Platform: any
|
|
9
10
|
Classifier: Programming Language :: Python
|
|
10
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
17
|
Classifier: Framework :: AsyncIO
|
|
16
18
|
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: Intended Audience :: System Administrators
|
|
18
19
|
Classifier: Topic :: Home Automation
|
|
19
20
|
Requires-Python: >=3.10.0
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
@@ -22,6 +23,10 @@ License-File: LICENSE
|
|
|
22
23
|
Requires-Dist: aiohttp>=3.8.1
|
|
23
24
|
Requires-Dist: pandas>=2.0.2
|
|
24
25
|
Requires-Dist: voluptuous>=0.13.1
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: prek; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff; extra == "dev"
|
|
29
|
+
Requires-Dist: yamllint; extra == "dev"
|
|
25
30
|
Dynamic: license-file
|
|
26
31
|
|
|
27
32
|
# myelectricaldatapy
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# -*- coding:utf-8 -*-
|
|
2
|
-
|
|
3
1
|
"""myelectricaldatapy package."""
|
|
4
2
|
|
|
5
3
|
from .exceptions import (
|
|
@@ -13,8 +11,8 @@ from .mypdl import EnedisByPDL
|
|
|
13
11
|
|
|
14
12
|
__all__ = [
|
|
15
13
|
"Enedis",
|
|
16
|
-
"EnedisException",
|
|
17
14
|
"EnedisByPDL",
|
|
15
|
+
"EnedisException",
|
|
18
16
|
"HttpRequestError",
|
|
19
17
|
"LimitReached",
|
|
20
18
|
"TimeoutExceededError",
|
|
@@ -2,19 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Collection
|
|
5
6
|
from datetime import datetime as dt, timedelta
|
|
7
|
+
import os
|
|
6
8
|
import re
|
|
7
|
-
from typing import Any
|
|
9
|
+
from typing import Any
|
|
10
|
+
from zoneinfo import ZoneInfo
|
|
8
11
|
|
|
9
12
|
import pandas as pd
|
|
10
13
|
|
|
11
14
|
from .const import ATTR_OFFPEAK, ATTR_STANDARD
|
|
12
15
|
|
|
13
16
|
|
|
17
|
+
def _local_timezone() -> Any:
|
|
18
|
+
"""Resolve the local IANA timezone so DST offsets stay correct per-date.
|
|
19
|
+
|
|
20
|
+
Falls back to the fixed UTC offset captured at call time when the
|
|
21
|
+
system timezone database cannot be resolved (e.g. non-Linux hosts).
|
|
22
|
+
"""
|
|
23
|
+
try:
|
|
24
|
+
tz_path = os.path.realpath("/etc/localtime")
|
|
25
|
+
return ZoneInfo(tz_path.split("zoneinfo/")[-1])
|
|
26
|
+
except Exception: # noqa: BLE001
|
|
27
|
+
return dt.now().astimezone().tzinfo
|
|
28
|
+
|
|
29
|
+
|
|
14
30
|
class EnedisAnalytics:
|
|
15
31
|
"""Data analaytics."""
|
|
16
32
|
|
|
17
|
-
local_timezone =
|
|
33
|
+
local_timezone = _local_timezone()
|
|
18
34
|
|
|
19
35
|
def __init__(self, data: Collection[Collection[str]]) -> None:
|
|
20
36
|
"""Initialize Dataframe."""
|
|
@@ -25,15 +41,17 @@ class EnedisAnalytics:
|
|
|
25
41
|
convertKwh: bool = False,
|
|
26
42
|
convertUTC: bool = False,
|
|
27
43
|
start_date: dt | None = None,
|
|
28
|
-
intervals: list[
|
|
44
|
+
intervals: list[tuple[str, str]] | None = None,
|
|
29
45
|
groupby: bool = False,
|
|
30
46
|
summary: bool = False,
|
|
31
|
-
cum_value: dict[str, Any] =
|
|
32
|
-
cum_price: dict[str, Any] =
|
|
47
|
+
cum_value: dict[str, Any] | None = None,
|
|
48
|
+
cum_price: dict[str, Any] | None = None,
|
|
33
49
|
prices: dict[str, Any] | None = None,
|
|
34
50
|
tempo: dict[str, str] | None = None,
|
|
35
51
|
) -> Any:
|
|
36
52
|
"""Convert data to analyze."""
|
|
53
|
+
cum_value = cum_value or {}
|
|
54
|
+
cum_price = cum_price or {}
|
|
37
55
|
step_hour = False
|
|
38
56
|
if not self.df.empty:
|
|
39
57
|
# Convert str to datetime
|
|
@@ -54,10 +72,7 @@ class EnedisAnalytics:
|
|
|
54
72
|
if "interval_length" in self.df:
|
|
55
73
|
step_hour = True
|
|
56
74
|
self.df.loc[
|
|
57
|
-
(
|
|
58
|
-
self.df.date.dt.minute
|
|
59
|
-
== dt.strptime("00:00:00", "%H:%M:%S").minute
|
|
60
|
-
),
|
|
75
|
+
(self.df.date.dt.minute == 0),
|
|
61
76
|
"date",
|
|
62
77
|
] = self.df.date - timedelta(minutes=1)
|
|
63
78
|
|
|
@@ -138,7 +153,7 @@ class EnedisAnalytics:
|
|
|
138
153
|
return int(rslt[0]) / 60
|
|
139
154
|
return 1
|
|
140
155
|
|
|
141
|
-
def _get_data_interval(self, intervals: list[
|
|
156
|
+
def _get_data_interval(self, intervals: list[tuple[str, str]]) -> pd.DataFrame:
|
|
142
157
|
"""Group date from range time."""
|
|
143
158
|
for interval in intervals:
|
|
144
159
|
# Convert str to datetime
|
{myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy/myelectricaldata.py
RENAMED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Generator
|
|
5
6
|
from datetime import date, datetime as dt, timedelta
|
|
6
7
|
import logging
|
|
7
8
|
import re
|
|
8
|
-
from typing import Any,
|
|
9
|
+
from typing import Any, cast
|
|
9
10
|
|
|
10
11
|
from aiohttp import ClientSession
|
|
11
12
|
|
|
@@ -27,7 +28,6 @@ class Enedis:
|
|
|
27
28
|
self.auth = EnedisAuth(session, token, timeout)
|
|
28
29
|
self.async_request = self.auth.async_request
|
|
29
30
|
self.offpeaks: list[str] = []
|
|
30
|
-
self.dt_offpeak: list[dt] = []
|
|
31
31
|
self.last_access: date | None = None
|
|
32
32
|
|
|
33
33
|
async def async_fetch_datas(
|
|
@@ -68,13 +68,6 @@ class Enedis:
|
|
|
68
68
|
contract = usage_point.get("contracts", {})
|
|
69
69
|
if offpeak_hours := contract.get("offpeak_hours"):
|
|
70
70
|
self.offpeaks = re.findall("(?:(\\w+)-(\\w+))+", offpeak_hours)
|
|
71
|
-
self.dt_offpeak = [
|
|
72
|
-
( # type: ignore
|
|
73
|
-
dt.strptime(offpeak[0], "%HH%M"),
|
|
74
|
-
dt.strptime(offpeak[1], "%HH%M"),
|
|
75
|
-
)
|
|
76
|
-
for offpeak in self.offpeaks
|
|
77
|
-
]
|
|
78
71
|
return contract
|
|
79
72
|
|
|
80
73
|
async def async_get_contracts(self, pdl: str) -> Any:
|
|
@@ -136,7 +129,7 @@ class Enedis:
|
|
|
136
129
|
for range_time in self.offpeaks:
|
|
137
130
|
starting = dt.strptime(range_time[0], "%HH%M").time()
|
|
138
131
|
ending = dt.strptime(range_time[1], "%HH%M").time()
|
|
139
|
-
if
|
|
132
|
+
if starting < start_time <= ending:
|
|
140
133
|
return True
|
|
141
134
|
return False
|
|
142
135
|
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Callable
|
|
5
6
|
from datetime import date, datetime as dt, timedelta
|
|
6
7
|
import logging
|
|
7
|
-
from typing import Any
|
|
8
|
+
from typing import Any
|
|
8
9
|
|
|
9
10
|
from aiohttp import ClientSession
|
|
10
11
|
import voluptuous as vol
|
|
@@ -116,7 +117,7 @@ class EnedisByPDL:
|
|
|
116
117
|
self.ecowatt: dict[str, Any] = {}
|
|
117
118
|
self.has_collected: bool = False
|
|
118
119
|
self.has_parameters: bool = False
|
|
119
|
-
self.intervals: list[
|
|
120
|
+
self.intervals: list[tuple[str, str]] = []
|
|
120
121
|
self.last_access: dt = dt.now()
|
|
121
122
|
self.last_refresh: date | None = None
|
|
122
123
|
self.max_power: dict[str, Any] = {}
|
|
@@ -141,7 +142,7 @@ class EnedisByPDL:
|
|
|
141
142
|
@property
|
|
142
143
|
def tempo_day(self) -> str | None:
|
|
143
144
|
"""Tempo day."""
|
|
144
|
-
str_date = dt.now().strftime("%Y
|
|
145
|
+
str_date = dt.now().strftime("%Y-%m-%d")
|
|
145
146
|
return self.tempo.get(str_date)
|
|
146
147
|
|
|
147
148
|
@property
|
|
@@ -181,13 +182,19 @@ class EnedisByPDL:
|
|
|
181
182
|
start = dt.now() - timedelta(days=1095)
|
|
182
183
|
end = dt.now() + timedelta(days=1)
|
|
183
184
|
if force_refresh or self.last_access.date() != dt.now().date():
|
|
185
|
+
self.access = {}
|
|
184
186
|
self.contract = {}
|
|
185
187
|
self.address = {}
|
|
186
188
|
self.ecowatt = {}
|
|
187
189
|
self.max_power = {}
|
|
188
190
|
self.has_collected = False
|
|
189
191
|
try:
|
|
190
|
-
|
|
192
|
+
if not self.access:
|
|
193
|
+
# Quota is scarce (ex: 50 calls/day on Enedis API), so the
|
|
194
|
+
# access/quota check is only refreshed once a day (or on
|
|
195
|
+
# force_refresh) instead of on every update cycle.
|
|
196
|
+
self.access = await self._api.async_valid_access(self.pdl)
|
|
197
|
+
|
|
191
198
|
if self.access.get("quota_reached", False):
|
|
192
199
|
detail = self.access.get("information", "Quota reached")
|
|
193
200
|
raise LimitReached(409, {"detail": detail})
|
|
@@ -241,7 +248,7 @@ class EnedisByPDL:
|
|
|
241
248
|
"""Enable or Disable Max power Subscription."""
|
|
242
249
|
self._maxpower_subs = activate is True
|
|
243
250
|
|
|
244
|
-
def _set_intervals(self, mode: str, intervals: list[
|
|
251
|
+
def _set_intervals(self, mode: str, intervals: list[tuple[str, str]]) -> None:
|
|
245
252
|
"""Set intervals."""
|
|
246
253
|
if isinstance(intervals, list):
|
|
247
254
|
self.intervals = intervals
|
|
@@ -293,7 +300,7 @@ class EnedisByPDL:
|
|
|
293
300
|
service: str,
|
|
294
301
|
start: dt | None = None,
|
|
295
302
|
end: dt | None = None,
|
|
296
|
-
intervals: list[
|
|
303
|
+
intervals: list[tuple[str, str]] | None = None,
|
|
297
304
|
prices: dict[str, Any] | None = None,
|
|
298
305
|
cum_value: dict[str, Any] | None = None,
|
|
299
306
|
cum_price: dict[str, Any] | None = None,
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: myelectricaldatapy
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.7
|
|
4
4
|
Summary: Fetch Linky data from myelectricaldata.fr
|
|
5
5
|
Author-email: Cyr-ius <cyr-ius@ipocus.net>
|
|
6
|
-
License: GPL-3
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
7
|
Project-URL: Homepage, https://github.com/cyr-ius/myelectricaldatapy
|
|
8
8
|
Keywords: enedis,linky,async,myelectricaldata
|
|
9
|
+
Platform: any
|
|
9
10
|
Classifier: Programming Language :: Python
|
|
10
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
17
|
Classifier: Framework :: AsyncIO
|
|
16
18
|
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: Intended Audience :: System Administrators
|
|
18
19
|
Classifier: Topic :: Home Automation
|
|
19
20
|
Requires-Python: >=3.10.0
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
@@ -22,6 +23,10 @@ License-File: LICENSE
|
|
|
22
23
|
Requires-Dist: aiohttp>=3.8.1
|
|
23
24
|
Requires-Dist: pandas>=2.0.2
|
|
24
25
|
Requires-Dist: voluptuous>=0.13.1
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: prek; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff; extra == "dev"
|
|
29
|
+
Requires-Dist: yamllint; extra == "dev"
|
|
25
30
|
Dynamic: license-file
|
|
26
31
|
|
|
27
32
|
# myelectricaldatapy
|
{myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/SOURCES.txt
RENAMED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
.flake8
|
|
2
1
|
.gitignore
|
|
3
2
|
.pre-commit-config.yaml
|
|
4
3
|
LICENSE
|
|
5
|
-
MANIFEST.in
|
|
6
4
|
README.md
|
|
7
5
|
_secrets.yaml
|
|
8
6
|
example.py
|
|
9
7
|
pyproject.toml
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
.devcontainer/devcontainer-lock.json
|
|
9
|
+
.devcontainer/devcontainer.json
|
|
12
10
|
.github/dependabot.yml
|
|
13
11
|
.github/workflows/auto-approve.yml
|
|
14
12
|
.github/workflows/python-lint.yml
|
|
@@ -27,6 +25,8 @@ myelectricaldatapy.egg-info/PKG-INFO
|
|
|
27
25
|
myelectricaldatapy.egg-info/SOURCES.txt
|
|
28
26
|
myelectricaldatapy.egg-info/dependency_links.txt
|
|
29
27
|
myelectricaldatapy.egg-info/requires.txt
|
|
28
|
+
myelectricaldatapy.egg-info/scm_file_list.json
|
|
29
|
+
myelectricaldatapy.egg-info/scm_version.json
|
|
30
30
|
myelectricaldatapy.egg-info/top_level.txt
|
|
31
31
|
tests/__init__.py
|
|
32
32
|
tests/conftest.py
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": [
|
|
3
|
+
".devcontainer/devcontainer-lock.json",
|
|
4
|
+
".devcontainer/devcontainer.json",
|
|
5
|
+
".github/dependabot.yml",
|
|
6
|
+
".github/workflows/auto-approve.yml",
|
|
7
|
+
".github/workflows/python-lint.yml",
|
|
8
|
+
".github/workflows/python-publish.yml",
|
|
9
|
+
".github/workflows/release.yml",
|
|
10
|
+
".gitignore",
|
|
11
|
+
".pre-commit-config.yaml",
|
|
12
|
+
".vscode/settings.json",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"README.md",
|
|
15
|
+
"_secrets.yaml",
|
|
16
|
+
"example.py",
|
|
17
|
+
"myelectricaldatapy/__init__.py",
|
|
18
|
+
"myelectricaldatapy/analytics.py",
|
|
19
|
+
"myelectricaldatapy/auth.py",
|
|
20
|
+
"myelectricaldatapy/const.py",
|
|
21
|
+
"myelectricaldatapy/exceptions.py",
|
|
22
|
+
"myelectricaldatapy/myelectricaldata.py",
|
|
23
|
+
"myelectricaldatapy/mypdl.py",
|
|
24
|
+
"myelectricaldatapy/py.typed",
|
|
25
|
+
"pyproject.toml",
|
|
26
|
+
"tests/__init__.py",
|
|
27
|
+
"tests/conftest.py",
|
|
28
|
+
"tests/consts.py",
|
|
29
|
+
"tests/fixtures/access.json",
|
|
30
|
+
"tests/fixtures/address.json",
|
|
31
|
+
"tests/fixtures/contract.json",
|
|
32
|
+
"tests/fixtures/daily.json",
|
|
33
|
+
"tests/fixtures/detail.json",
|
|
34
|
+
"tests/fixtures/ecowatt.json",
|
|
35
|
+
"tests/fixtures/invalid_access.json",
|
|
36
|
+
"tests/fixtures/tempo.json",
|
|
37
|
+
"tests/test_analytics.py",
|
|
38
|
+
"tests/test_load_data.py"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "myelectricaldatapy"
|
|
7
7
|
dynamic = ["version"]
|
|
8
|
-
license =
|
|
8
|
+
license = "GPL-3.0-or-later"
|
|
9
9
|
description = "Fetch Linky data from myelectricaldata.fr"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
authors = [
|
|
@@ -15,13 +15,13 @@ keywords = ["enedis", "linky", "async", "myelectricaldata"]
|
|
|
15
15
|
classifiers = [
|
|
16
16
|
"Programming Language :: Python",
|
|
17
17
|
"Development Status :: 5 - Production/Stable",
|
|
18
|
-
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
19
18
|
"Programming Language :: Python :: 3",
|
|
20
19
|
"Programming Language :: Python :: 3.10",
|
|
21
20
|
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
22
23
|
"Framework :: AsyncIO",
|
|
23
24
|
"Intended Audience :: Developers",
|
|
24
|
-
"Intended Audience :: System Administrators",
|
|
25
25
|
"Topic :: Home Automation",
|
|
26
26
|
]
|
|
27
27
|
requires-python = ">=3.10.0"
|
|
@@ -31,11 +31,21 @@ dependencies = [
|
|
|
31
31
|
"voluptuous>=0.13.1",
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"prek",
|
|
37
|
+
"ruff",
|
|
38
|
+
"yamllint",
|
|
39
|
+
]
|
|
40
|
+
|
|
34
41
|
[project.urls]
|
|
35
42
|
Homepage = "https://github.com/cyr-ius/myelectricaldatapy"
|
|
36
43
|
|
|
37
44
|
[tool.setuptools_scm]
|
|
38
45
|
|
|
46
|
+
[tool.setuptools]
|
|
47
|
+
platforms = ["any"]
|
|
48
|
+
|
|
39
49
|
[tool.pytest.ini_options]
|
|
40
50
|
asyncio_mode = "auto"
|
|
41
51
|
|
|
@@ -48,7 +48,7 @@ def mock_tempo(return_invalid: bool = False) -> dict[str, Any]:
|
|
|
48
48
|
def mock_ecowatt(request) -> dict[str, Any]:
|
|
49
49
|
if hasattr(request, "param") and request.param:
|
|
50
50
|
return {
|
|
51
|
-
"detail": "Pas de données disponible entre la date du 2023-01-22 00:00:00 et 2023-01-22 00:00:00"
|
|
51
|
+
"detail": "Pas de données disponible entre la date du 2023-01-22 00:00:00 et 2023-01-22 00:00:00"
|
|
52
52
|
}
|
|
53
53
|
return json.loads(load_fixture("ecowatt.json"))
|
|
54
54
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "2023-03-01": "blue", "2023-03-02": "red", "2023-03-03": "blue" }
|
|
@@ -44,7 +44,7 @@ async def test_tempoday(mock_enedis: Mock) -> None: # pylint: disable=unused-ar
|
|
|
44
44
|
"""Test get tempo day."""
|
|
45
45
|
api = Enedis(token=TOKEN, session=ClientSession())
|
|
46
46
|
resultat = await api.async_get_tempo()
|
|
47
|
-
assert resultat["2023-
|
|
47
|
+
assert resultat["2023-03-01"] == "blue"
|
|
48
48
|
|
|
49
49
|
mypdl = EnedisByPDL(pdl=PDL, token=TOKEN, session=ClientSession())
|
|
50
50
|
mypdl.set_collects("consumption_load_curve")
|
|
@@ -54,6 +54,34 @@ async def test_tempoday(mock_enedis: Mock) -> None: # pylint: disable=unused-ar
|
|
|
54
54
|
assert mypdl.tempo_day == "blue"
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
@freeze_time("2023-03-01")
|
|
58
|
+
async def test_check_offpeak(mock_contract) -> None:
|
|
59
|
+
"""Test off-peak hour detection against the real contract's schedule.
|
|
60
|
+
|
|
61
|
+
contract.json's offpeak_hours is "HC (1H30-8H00;12H30-14H00)". Patches
|
|
62
|
+
the HTTP layer (not async_get_contract itself) so the real parsing in
|
|
63
|
+
Enedis.async_get_contract runs and populates self.offpeaks.
|
|
64
|
+
"""
|
|
65
|
+
with patch.object(
|
|
66
|
+
myelectricaldatapy.auth.EnedisAuth,
|
|
67
|
+
"async_request",
|
|
68
|
+
return_value=mock_contract,
|
|
69
|
+
):
|
|
70
|
+
api = Enedis(token=TOKEN, session=ClientSession())
|
|
71
|
+
assert await api.async_has_offpeak(PDL) is True
|
|
72
|
+
|
|
73
|
+
# 03:00 falls inside the 01:30-08:00 off-peak window
|
|
74
|
+
assert await api.async_check_offpeak(PDL, dt(2023, 3, 1, 3, 0)) is True
|
|
75
|
+
# exactly on the lower bound is excluded (start, end] convention
|
|
76
|
+
assert await api.async_check_offpeak(PDL, dt(2023, 3, 1, 1, 30)) is False
|
|
77
|
+
# exactly on the upper bound is included
|
|
78
|
+
assert await api.async_check_offpeak(PDL, dt(2023, 3, 1, 8, 0)) is True
|
|
79
|
+
# standard hours, not off-peak
|
|
80
|
+
assert await api.async_check_offpeak(PDL, dt(2023, 3, 1, 10, 0)) is False
|
|
81
|
+
# second window 12:30-14:00
|
|
82
|
+
assert await api.async_check_offpeak(PDL, dt(2023, 3, 1, 13, 0)) is True
|
|
83
|
+
|
|
84
|
+
|
|
57
85
|
async def test_valid_access(mock_enedis: Mock) -> None: # pylint: disable=unused-argument
|
|
58
86
|
"""Test access."""
|
|
59
87
|
api = Enedis(token=TOKEN, session=ClientSession())
|
|
@@ -92,7 +120,7 @@ async def test_fetch_data(mock_detail) -> None:
|
|
|
92
120
|
)
|
|
93
121
|
assert (
|
|
94
122
|
resultat["meter_reading"]["interval_reading"]
|
|
95
|
-
== mock_detail["meter_reading"]["interval_reading"]
|
|
123
|
+
== mock_detail["meter_reading"]["interval_reading"]
|
|
96
124
|
)
|
|
97
125
|
|
|
98
126
|
|
myelectricaldatapy-2.2.5/.flake8
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: Upload Python Package
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: ["published"]
|
|
6
|
-
workflow_call:
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
deploy:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
name: Deploy to PyPi
|
|
13
|
-
environment: release
|
|
14
|
-
permissions:
|
|
15
|
-
id-token: write
|
|
16
|
-
steps:
|
|
17
|
-
- name: 📥 Checkout the repository
|
|
18
|
-
uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name: Set up Python
|
|
21
|
-
uses: actions/setup-python@v5
|
|
22
|
-
with:
|
|
23
|
-
python-version: "3.x"
|
|
24
|
-
|
|
25
|
-
- name: 📦 Install dependencies
|
|
26
|
-
run: |
|
|
27
|
-
python -m pip install --upgrade pip
|
|
28
|
-
pip install setuptools wheel twine build
|
|
29
|
-
|
|
30
|
-
- name: Build package
|
|
31
|
-
shell: bash
|
|
32
|
-
run: |
|
|
33
|
-
python -m build
|
|
34
|
-
|
|
35
|
-
- name: 🚀 Publish to PyPi
|
|
36
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
name: Create release
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
tags:
|
|
5
|
-
- "*.*.*" # Push events to matching i.e. 1.0.0, 4.0.1
|
|
6
|
-
jobs:
|
|
7
|
-
release:
|
|
8
|
-
runs-on: ubuntu-latest
|
|
9
|
-
steps:
|
|
10
|
-
# To use this repository's private action, you must check out the repository
|
|
11
|
-
- name: 📥 Checkout the repository
|
|
12
|
-
uses: actions/checkout@v4
|
|
13
|
-
|
|
14
|
-
- name: Generate changelog
|
|
15
|
-
id: changelog
|
|
16
|
-
uses: metcalfc/changelog-generator@v4.6.2
|
|
17
|
-
with:
|
|
18
|
-
myToken: ${{ secrets.GITHUB_TOKEN }}
|
|
19
|
-
|
|
20
|
-
- name: Create Release
|
|
21
|
-
id: create_release
|
|
22
|
-
uses: actions/create-release@latest
|
|
23
|
-
env:
|
|
24
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
25
|
-
with:
|
|
26
|
-
tag_name: ${{ github.ref }}
|
|
27
|
-
release_name: ${{ github.ref }}
|
|
28
|
-
body: ${{ steps.changelog.outputs.changelog }}
|
|
29
|
-
draft: false
|
|
30
|
-
prerelease: ${{ contains(github.ref_name,'-') }}
|
|
31
|
-
publish:
|
|
32
|
-
runs-on: ubuntu-latest
|
|
33
|
-
needs: release
|
|
34
|
-
permissions:
|
|
35
|
-
contents: write
|
|
36
|
-
packages: write
|
|
37
|
-
id-token: write
|
|
38
|
-
if: ${{ ! contains(github.ref_name, '-') }}
|
|
39
|
-
steps:
|
|
40
|
-
- name: 📥 Checkout the repository
|
|
41
|
-
uses: actions/checkout@v4
|
|
42
|
-
|
|
43
|
-
- name: Set up Python
|
|
44
|
-
uses: actions/setup-python@v5
|
|
45
|
-
with:
|
|
46
|
-
python-version: "3.x"
|
|
47
|
-
|
|
48
|
-
- name: 📦 Install dependencies
|
|
49
|
-
run: |
|
|
50
|
-
python -m pip install --upgrade pip
|
|
51
|
-
pip install setuptools wheel twine build
|
|
52
|
-
|
|
53
|
-
- name: Build package
|
|
54
|
-
shell: bash
|
|
55
|
-
run: |
|
|
56
|
-
python -m build
|
|
57
|
-
|
|
58
|
-
- name: 🚀 Publish to PyPi
|
|
59
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "2023-3-1": "blue", "2023-3-2": "red", "2023-3-3": "blue" }
|
|
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
|
{myelectricaldatapy-2.2.5 → myelectricaldatapy-2.2.7}/myelectricaldatapy.egg-info/top_level.txt
RENAMED
|
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
|