aemo-mdff-reader 2.0.2__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/CHANGELOG.md +61 -0
- aemo_mdff_reader-2.1.0/CONTRIBUTING.md +222 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/PKG-INFO +15 -8
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/README.md +13 -5
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/__init__.py +1 -1
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/cli.py +1 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/sql/__init__.py +6 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/sql/store.py +11 -3
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/PKG-INFO +15 -8
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/pyproject.toml +6 -10
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_parser.py +6 -3
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_spec.py +7 -2
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_sql.py +1 -1
- aemo_mdff_reader-2.0.2/CONTRIBUTING.md +0 -118
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/LICENSE +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/MANIFEST.in +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/aggregate.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/parser.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/py.typed +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/reader.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/spec.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/sql/query.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader/types.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/SOURCES.txt +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/dependency_links.txt +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/entry_points.txt +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/requires.txt +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/top_level.txt +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/benchmarks/bench_parser.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/setup.cfg +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/setup.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/__init__.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/fixtures/generate.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/fixtures/sample_nem12.csv +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/fixtures/sample_nem13.csv +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_cli.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_datetime_formats.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_edge_cases.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_ergonomics.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_events_b2b.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_large_files.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_nem13.py +0 -0
- {aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/tests/test_validation.py +0 -0
|
@@ -4,6 +4,67 @@ All notable changes are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the
|
|
5
5
|
project follows [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.1.0](https://github.com/Utilified/aemo-mdff-reader/compare/v2.0.4...v2.1.0) (2026-05-10)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* drop Python 3.9, hash-pin CI installs, scope release-please permissions ([447ec98](https://github.com/Utilified/aemo-mdff-reader/commit/447ec98408edabfab45d28841a2e714d54f8dd11))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Documentation
|
|
16
|
+
|
|
17
|
+
* remove broken OpenSSF Best Practices badge ([#21](https://github.com/Utilified/aemo-mdff-reader/issues/21)) ([91a68d5](https://github.com/Utilified/aemo-mdff-reader/commit/91a68d5a4b4fd4c027488b4fe770c4cd142a7454))
|
|
18
|
+
|
|
19
|
+
## [2.0.4](https://github.com/Utilified/aemo-mdff-reader/compare/v2.0.3...v2.0.4) (2026-05-10)
|
|
20
|
+
|
|
21
|
+
First release published to PyPI after the supply-chain hardening landed
|
|
22
|
+
in v2.0.3 — which itself failed to publish due to two release-pipeline
|
|
23
|
+
bugs (see notice on the v2.0.3 GitHub Release). PyPI users upgrading
|
|
24
|
+
from 2.0.2 receive **both** the v2.0.3 hardening (SLSA build provenance,
|
|
25
|
+
CycloneDX SBOM, release-please automation, dependabot grouping) and the
|
|
26
|
+
fixes below in one upgrade. No source or behavioural changes versus 2.0.2.
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* release-please dispatch + SBOM directory creation ([#17](https://github.com/Utilified/aemo-mdff-reader/issues/17)) ([8e3cd13](https://github.com/Utilified/aemo-mdff-reader/commit/8e3cd13ca11bad3399efd2e5fd2fe5ae6bcb2a90))
|
|
31
|
+
|
|
32
|
+
## [2.0.3](https://github.com/Utilified/aemo-mdff-reader/compare/v2.0.2...v2.0.3) (2026-05-10)
|
|
33
|
+
|
|
34
|
+
Supply-chain hardening and release-process automation. No source or
|
|
35
|
+
behavioural changes versus 2.0.2 — same wheel/sdist content, plus
|
|
36
|
+
provenance, SBOM, and an automated release pipeline.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- SLSA build provenance attestations on the wheel and sdist (via
|
|
41
|
+
`actions/attest-build-provenance`). Verifiable with
|
|
42
|
+
`gh attestation verify`.
|
|
43
|
+
- CycloneDX SBOM generated by `anchore/sbom-action` and attested
|
|
44
|
+
against both artifacts (via `actions/attest-sbom`). SBOM is also
|
|
45
|
+
attached to each GitHub Release alongside the sigstore signatures.
|
|
46
|
+
- `release-please` automation: releases are now proposed and cut
|
|
47
|
+
from Conventional Commits. Merging the auto-generated release PR
|
|
48
|
+
creates the tag, which dispatches the existing `release.yml`
|
|
49
|
+
pipeline. See [CONTRIBUTING.md](CONTRIBUTING.md) for the flow.
|
|
50
|
+
- Dependabot grouping: minor/patch GitHub Actions bumps land as a
|
|
51
|
+
single weekly PR; minor/patch runtime-extras bumps (pandas /
|
|
52
|
+
pyarrow / PyMySQL) land as a separate weekly PR. Majors stay
|
|
53
|
+
individual.
|
|
54
|
+
- README badges for CodeQL, OpenSSF Scorecard, and OpenSSF Best
|
|
55
|
+
Practices.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Branch protection on `main` now requires PR conversation resolution
|
|
60
|
+
before merge.
|
|
61
|
+
- GitHub Discussions enabled on the repository as a Q&A surface
|
|
62
|
+
separate from the issue tracker.
|
|
63
|
+
|
|
64
|
+
### Bug Fixes
|
|
65
|
+
|
|
66
|
+
* rename release-please config to default path ([#15](https://github.com/Utilified/aemo-mdff-reader/issues/15)) ([843d25f](https://github.com/Utilified/aemo-mdff-reader/commit/843d25ff8c35944e08eb70ebfdb076acdf1c9855))
|
|
67
|
+
|
|
7
68
|
## [Unreleased]
|
|
8
69
|
|
|
9
70
|
## [2.0.2] — 2026-05-10
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in improving aemo-mdff-reader. The repository
|
|
4
|
+
is small and the bar for contributions is straightforward: a pull
|
|
5
|
+
request that passes CI and doesn't regress the public benchmark is
|
|
6
|
+
welcome.
|
|
7
|
+
|
|
8
|
+
Naming: everything (GitHub repo `Utilified/aemo-mdff-reader`, PyPI
|
|
9
|
+
distribution `aemo-mdff-reader`, Python import `aemo_mdff_reader`,
|
|
10
|
+
CLI `aemo-mdff-reader`) is consistently named after the AEMO spec —
|
|
11
|
+
MDFF, the Meter Data File Format that covers both NEM12 (interval) and
|
|
12
|
+
NEM13 (accumulation) formats. GitHub serves redirects from the
|
|
13
|
+
previous `Utilified/nem12-reader` repo URL so existing git pins
|
|
14
|
+
continue to work; v1 callers importing `from nem12_reader …` need to
|
|
15
|
+
update to `from aemo_mdff_reader …`.
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/Utilified/aemo-mdff-reader.git
|
|
21
|
+
cd aemo-mdff-reader
|
|
22
|
+
python -m venv .venv && source .venv/bin/activate
|
|
23
|
+
pip install -e .[dev]
|
|
24
|
+
pytest
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## CI requirements files
|
|
28
|
+
|
|
29
|
+
`requirements/{dev,lint,build,audit}.txt` are hash-pinned lock files
|
|
30
|
+
consumed by CI (`pip install --require-hashes`). They satisfy
|
|
31
|
+
Scorecard's `PinnedDependenciesID` and protect CI against a compromised
|
|
32
|
+
PyPI mirror. Dependabot refreshes them weekly.
|
|
33
|
+
|
|
34
|
+
Source `.in` files are committed alongside the locks in `requirements/`.
|
|
35
|
+
To regenerate manually after editing them or `pyproject.toml`:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install uv
|
|
39
|
+
uv pip compile --generate-hashes --strip-extras --python-version 3.10 --output-file requirements/dev.txt requirements/dev.in
|
|
40
|
+
uv pip compile --generate-hashes --strip-extras --python-version 3.10 --output-file requirements/lint.txt requirements/lint.in
|
|
41
|
+
uv pip compile --generate-hashes --strip-extras --python-version 3.10 --output-file requirements/build.txt requirements/build.in
|
|
42
|
+
uv pip compile --generate-hashes --strip-extras --python-version 3.10 --output-file requirements/audit.txt requirements/audit.in
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`uv` is used over `pip-tools` because its resolver handles the
|
|
46
|
+
3.10–3.12 matrix without back-tracking failures, and it emits hashes
|
|
47
|
+
for every wheel of each pinned version (so a single lock file works
|
|
48
|
+
across the whole CI matrix). The `--python-version 3.10` flag pins
|
|
49
|
+
resolution to the lowest supported interpreter so packages whose
|
|
50
|
+
latest releases dropped 3.10 are correctly stepped back to a
|
|
51
|
+
compatible version.
|
|
52
|
+
|
|
53
|
+
## Running the test suite
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pytest -v
|
|
57
|
+
pytest --cov=aemo_mdff_reader --cov-report=term-missing
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A small, sanitized NEM12 sample lives at
|
|
61
|
+
`tests/fixtures/sample_nem12.csv`. To generate larger synthetic files
|
|
62
|
+
for ad-hoc testing or benchmarking:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
python tests/fixtures/generate.py /tmp/big.csv --nmis 4 --days 365 --interval-minutes 5
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Performance
|
|
69
|
+
|
|
70
|
+
`benchmarks/bench_parser.py` is the canonical performance test. Please
|
|
71
|
+
run it before and after changes that touch the hot path
|
|
72
|
+
(`parser.py::_emit_intervals`, `parse_to_columns`, `to_columns`):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
python benchmarks/bench_parser.py --nmis 4 --days 365 --interval-minutes 5
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The streaming and columnar fast paths must remain at or above the
|
|
79
|
+
current published throughput.
|
|
80
|
+
|
|
81
|
+
## Code style
|
|
82
|
+
|
|
83
|
+
- Pure stdlib in the core. **No** new required runtime dependencies.
|
|
84
|
+
Optional features go behind `[project.optional-dependencies]`.
|
|
85
|
+
- Type hints on all public symbols.
|
|
86
|
+
- Keep `aemo_mdff_reader.types` slots-based — per-row allocation is on
|
|
87
|
+
the hot path.
|
|
88
|
+
|
|
89
|
+
## Commit messages
|
|
90
|
+
|
|
91
|
+
Releases are generated automatically from commits using
|
|
92
|
+
[release-please](https://github.com/googleapis/release-please), so the
|
|
93
|
+
commit subject prefix is load-bearing — it determines whether a release
|
|
94
|
+
is cut and what kind of version bump it gets.
|
|
95
|
+
|
|
96
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
97
|
+
|
|
98
|
+
| Prefix | Effect on next release |
|
|
99
|
+
| ---------------------------------- | -------------------------------------- |
|
|
100
|
+
| `feat: …` | minor bump (e.g. 2.0.x → 2.1.0) |
|
|
101
|
+
| `fix: …` | patch bump (e.g. 2.0.0 → 2.0.1) |
|
|
102
|
+
| `feat!: …` or `BREAKING CHANGE:` footer | major bump (e.g. 2.x → 3.0.0) |
|
|
103
|
+
| `chore: …` / `docs: …` / `refactor: …` / `style: …` / `test: …` / `ci: …` / `build: …` | no release on its own |
|
|
104
|
+
| any commit with `Release-As: x.y.z` footer | forces that exact version |
|
|
105
|
+
|
|
106
|
+
Subject line: imperative mood, under 72 chars, lowercase after the
|
|
107
|
+
prefix. Examples that work well:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
feat: stream NEM13 250 records via parse_accumulations
|
|
111
|
+
fix: handle CRLF line endings in 300-record payloads
|
|
112
|
+
chore: bump CI matrix to include Python 3.13
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Squash-merge is preferred — the squash commit message becomes the
|
|
116
|
+
release-please input, so make it count.
|
|
117
|
+
|
|
118
|
+
## Reporting issues
|
|
119
|
+
|
|
120
|
+
Please open an issue with:
|
|
121
|
+
|
|
122
|
+
1. The Python version and OS.
|
|
123
|
+
2. A minimal reproducer (a few NEM12 rows is usually enough).
|
|
124
|
+
3. The expected vs actual behaviour.
|
|
125
|
+
|
|
126
|
+
If you can share a sanitized sample file (no real NMIs / meter
|
|
127
|
+
serials), please attach it to the issue.
|
|
128
|
+
|
|
129
|
+
## Releasing
|
|
130
|
+
|
|
131
|
+
Releases are automated via [release-please](https://github.com/googleapis/release-please).
|
|
132
|
+
Maintainers do not run `git tag` by hand for normal releases.
|
|
133
|
+
|
|
134
|
+
### Normal flow (Conventional Commits drive it)
|
|
135
|
+
|
|
136
|
+
1. Land a `feat:` or `fix:` commit on `main` (via squash-merged PR).
|
|
137
|
+
2. The `release-please` workflow runs and either opens a new release PR
|
|
138
|
+
titled `chore(main): release X.Y.Z` or updates the existing one.
|
|
139
|
+
The PR auto-bumps `pyproject.toml` and `aemo_mdff_reader/__init__.py`
|
|
140
|
+
(the `# x-release-please-version` annotation in `__init__.py` marks
|
|
141
|
+
the line release-please rewrites) and drafts the `CHANGELOG.md`
|
|
142
|
+
entry from the commit log.
|
|
143
|
+
3. Review the release PR. Edit the changelog entry directly on the PR
|
|
144
|
+
if you want to massage wording — release-please will keep your
|
|
145
|
+
edits across reruns. When happy, **squash-merge** it.
|
|
146
|
+
4. release-please creates the `vX.Y.Z` git tag on merge.
|
|
147
|
+
5. Because tags created by `GITHUB_TOKEN` do not trigger downstream
|
|
148
|
+
tag-push workflows (GitHub anti-recursion guard), `release-please.yml`
|
|
149
|
+
explicitly dispatches `release.yml` for the new tag.
|
|
150
|
+
6. `release.yml` runs the publish pipeline:
|
|
151
|
+
build → SLSA build provenance attestation → CycloneDX SBOM +
|
|
152
|
+
attestation → upload artefacts → wait on the `pypi` Environment
|
|
153
|
+
reviewer → sigstore sign → PyPI Trusted Publishing → GitHub Release
|
|
154
|
+
with wheel + sdist + signatures + SBOM attached.
|
|
155
|
+
7. Approve the deployment in the `pypi` Environment when GitHub
|
|
156
|
+
notifies you. The publish completes; verify at
|
|
157
|
+
https://pypi.org/project/aemo-mdff-reader/ and
|
|
158
|
+
https://github.com/Utilified/aemo-mdff-reader/releases.
|
|
159
|
+
|
|
160
|
+
### Forcing a release without a feat/fix commit
|
|
161
|
+
|
|
162
|
+
Two options:
|
|
163
|
+
|
|
164
|
+
- Add `Release-As: x.y.z` as a commit-message footer on a commit
|
|
165
|
+
landing on `main` (works for `chore:` / `docs:` etc. that wouldn't
|
|
166
|
+
trigger a release on their own).
|
|
167
|
+
- Manually trigger the `release-please` workflow via GitHub Actions →
|
|
168
|
+
*release-please* → "Run workflow" (workflow_dispatch).
|
|
169
|
+
|
|
170
|
+
### Emergency manual release (rare)
|
|
171
|
+
|
|
172
|
+
`release.yml` still listens on tag-push, so a maintainer can bypass
|
|
173
|
+
release-please entirely:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Bump version in pyproject.toml AND aemo_mdff_reader/__init__.py
|
|
177
|
+
# (preserve the `# x-release-please-version` comment on __init__.py),
|
|
178
|
+
# update CHANGELOG.md, then:
|
|
179
|
+
git commit -am "release: vX.Y.Z"
|
|
180
|
+
git tag vX.Y.Z
|
|
181
|
+
git push origin main vX.Y.Z
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Use only if release-please is broken — otherwise you'll fight it on
|
|
185
|
+
the next push.
|
|
186
|
+
|
|
187
|
+
### One-time infrastructure setup (per project)
|
|
188
|
+
|
|
189
|
+
Already done for `aemo-mdff-reader`; documented here for posterity.
|
|
190
|
+
|
|
191
|
+
1. **PyPI Trusted Publishing**: register the project at
|
|
192
|
+
https://pypi.org/manage/account/publishing/ with:
|
|
193
|
+
- PyPI project name: `aemo-mdff-reader`
|
|
194
|
+
- Owner: `Utilified`
|
|
195
|
+
- Repository: `aemo-mdff-reader`
|
|
196
|
+
- Workflow filename: `release.yml`
|
|
197
|
+
- Environment name: `pypi`
|
|
198
|
+
2. **GitHub Environment**: in *Settings → Environments*, create an
|
|
199
|
+
environment named `pypi`. Add required reviewers (recommended) and
|
|
200
|
+
restrict the deployment branch policy to `v*` tags.
|
|
201
|
+
3. **Repository variable**: set `PYPI_PUBLISH_ENABLED=true` under
|
|
202
|
+
*Settings → Secrets and variables → Actions → Variables*. The
|
|
203
|
+
publish job is gated on this so the workflow runs cleanly while
|
|
204
|
+
Trusted Publishing is being configured (build + sign succeed;
|
|
205
|
+
publish skips).
|
|
206
|
+
4. **Workflow permissions**: under *Settings → Actions → General →
|
|
207
|
+
Workflow permissions*, set "Read and write permissions" and tick
|
|
208
|
+
"Allow GitHub Actions to create and approve pull requests" — the
|
|
209
|
+
`release-please` action needs both to open release PRs.
|
|
210
|
+
|
|
211
|
+
### Local dry run of the build
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
python -m build
|
|
215
|
+
twine check --strict dist/*
|
|
216
|
+
python -m venv /tmp/smoke && /tmp/smoke/bin/pip install dist/*.whl
|
|
217
|
+
/tmp/smoke/bin/aemo-mdff-reader --version
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
There is no way to dry-run the publish step — Trusted Publishing only
|
|
221
|
+
authenticates a real `release.yml` run on a real tag. The first
|
|
222
|
+
release after touching `release.yml` is the de-facto integration test.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aemo-mdff-reader
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Fast streaming reader for AEMO MDFF NEM12 / NEM13 metering files. Zero required dependencies.
|
|
5
5
|
Author: Utilified Holdings Pty Ltd
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,7 +15,6 @@ Classifier: Intended Audience :: Information Technology
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -23,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
23
22
|
Classifier: Topic :: Office/Business :: Financial
|
|
24
23
|
Classifier: Topic :: Scientific/Engineering
|
|
25
24
|
Classifier: Topic :: Utilities
|
|
26
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.10
|
|
27
26
|
Description-Content-Type: text/markdown
|
|
28
27
|
License-File: LICENSE
|
|
29
28
|
Provides-Extra: pandas
|
|
@@ -49,8 +48,10 @@ Dynamic: license-file
|
|
|
49
48
|
|
|
50
49
|
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/ci.yml)
|
|
51
50
|
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
52
|
-
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
53
52
|
[](LICENSE)
|
|
53
|
+
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/codeql.yml)
|
|
54
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Utilified/aemo-mdff-reader)
|
|
54
55
|
|
|
55
56
|
Fast, zero-dependency streaming reader for AEMO **NEM12** and **NEM13**
|
|
56
57
|
metering files. Implements AEMO MDFF (Meter Data File Format) v2.6.
|
|
@@ -237,10 +238,16 @@ pip install -e .[dev]
|
|
|
237
238
|
pytest
|
|
238
239
|
```
|
|
239
240
|
|
|
240
|
-
CI runs ruff, mypy --strict, the test matrix on Python 3.
|
|
241
|
-
Linux / macOS / Windows, `pip-audit`, `bandit`,
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
CI runs ruff, mypy --strict, the test matrix on Python 3.10 → 3.12 /
|
|
242
|
+
Linux / macOS / Windows, `pip-audit`, `bandit`, CodeQL, OpenSSF
|
|
243
|
+
Scorecard, and a wheel-install smoke test.
|
|
244
|
+
|
|
245
|
+
Releases are automated by [release-please](https://github.com/googleapis/release-please)
|
|
246
|
+
from [Conventional Commits](https://www.conventionalcommits.org/) on
|
|
247
|
+
`main`, then signed with sigstore, attested with SLSA build provenance
|
|
248
|
+
and a CycloneDX SBOM, and published to PyPI via Trusted Publishing.
|
|
249
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the contributor commit
|
|
250
|
+
conventions and the full release flow.
|
|
244
251
|
|
|
245
252
|
## License
|
|
246
253
|
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/ci.yml)
|
|
4
4
|
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
5
|
-
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
6
6
|
[](LICENSE)
|
|
7
|
+
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/codeql.yml)
|
|
8
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Utilified/aemo-mdff-reader)
|
|
7
9
|
|
|
8
10
|
Fast, zero-dependency streaming reader for AEMO **NEM12** and **NEM13**
|
|
9
11
|
metering files. Implements AEMO MDFF (Meter Data File Format) v2.6.
|
|
@@ -190,10 +192,16 @@ pip install -e .[dev]
|
|
|
190
192
|
pytest
|
|
191
193
|
```
|
|
192
194
|
|
|
193
|
-
CI runs ruff, mypy --strict, the test matrix on Python 3.
|
|
194
|
-
Linux / macOS / Windows, `pip-audit`, `bandit`,
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
CI runs ruff, mypy --strict, the test matrix on Python 3.10 → 3.12 /
|
|
196
|
+
Linux / macOS / Windows, `pip-audit`, `bandit`, CodeQL, OpenSSF
|
|
197
|
+
Scorecard, and a wheel-install smoke test.
|
|
198
|
+
|
|
199
|
+
Releases are automated by [release-please](https://github.com/googleapis/release-please)
|
|
200
|
+
from [Conventional Commits](https://www.conventionalcommits.org/) on
|
|
201
|
+
`main`, then signed with sigstore, attested with SLSA build provenance
|
|
202
|
+
and a CycloneDX SBOM, and published to PyPI via Trusted Publishing.
|
|
203
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the contributor commit
|
|
204
|
+
conventions and the full release flow.
|
|
197
205
|
|
|
198
206
|
## License
|
|
199
207
|
|
|
@@ -7,8 +7,14 @@ The dependency is only required when you actually instantiate
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
10
12
|
from .query import COLUMNS, QueryBuilder
|
|
11
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
# Visible to static analysers / IDEs without forcing pymysql to load.
|
|
16
|
+
from .store import DBCredentials, Storer
|
|
17
|
+
|
|
12
18
|
__all__ = ["COLUMNS", "DBCredentials", "QueryBuilder", "Storer"]
|
|
13
19
|
|
|
14
20
|
|
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
import pymysql.cursors
|
|
6
6
|
|
|
7
|
-
from .query import
|
|
7
|
+
from .query import (
|
|
8
|
+
CHANNEL_TABLE,
|
|
9
|
+
IMPORT_TABLE,
|
|
10
|
+
INTERVAL_DATA_TABLE,
|
|
11
|
+
INTERVAL_TABLE,
|
|
12
|
+
INTERVAL_TYPE_TABLE,
|
|
13
|
+
NMI_TABLE,
|
|
14
|
+
QueryBuilder,
|
|
15
|
+
)
|
|
8
16
|
|
|
9
17
|
# Load queries once session is imported
|
|
10
18
|
QUERY_FOLDER = "queries"
|
|
@@ -128,11 +136,11 @@ class Storer:
|
|
|
128
136
|
|
|
129
137
|
data_intervals.append(data_interval)
|
|
130
138
|
query = QueryBuilder.insert_query(NMI_TABLE, data_nmi)
|
|
131
|
-
|
|
139
|
+
cursor.execute(query)
|
|
132
140
|
|
|
133
141
|
for row in range(len(data_channel)):
|
|
134
142
|
query = QueryBuilder.insert_query(CHANNEL_TABLE, [data_channel[row]])
|
|
135
|
-
|
|
143
|
+
cursor.execute(query)
|
|
136
144
|
query = "SELECT channelID FROM `nem`.`channel` WHERE `NMI` = %s AND `NMISuffix` = %s AND `MeterSerialNumber` = %s"
|
|
137
145
|
cursor.execute(
|
|
138
146
|
query, (data_channel[row][0], data_channel[row][2], data_channel[row][4])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aemo-mdff-reader
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Fast streaming reader for AEMO MDFF NEM12 / NEM13 metering files. Zero required dependencies.
|
|
5
5
|
Author: Utilified Holdings Pty Ltd
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,7 +15,6 @@ Classifier: Intended Audience :: Information Technology
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -23,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
23
22
|
Classifier: Topic :: Office/Business :: Financial
|
|
24
23
|
Classifier: Topic :: Scientific/Engineering
|
|
25
24
|
Classifier: Topic :: Utilities
|
|
26
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.10
|
|
27
26
|
Description-Content-Type: text/markdown
|
|
28
27
|
License-File: LICENSE
|
|
29
28
|
Provides-Extra: pandas
|
|
@@ -49,8 +48,10 @@ Dynamic: license-file
|
|
|
49
48
|
|
|
50
49
|
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/ci.yml)
|
|
51
50
|
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
52
|
-
[](https://pypi.org/project/aemo-mdff-reader/)
|
|
53
52
|
[](LICENSE)
|
|
53
|
+
[](https://github.com/Utilified/aemo-mdff-reader/actions/workflows/codeql.yml)
|
|
54
|
+
[](https://scorecard.dev/viewer/?uri=github.com/Utilified/aemo-mdff-reader)
|
|
54
55
|
|
|
55
56
|
Fast, zero-dependency streaming reader for AEMO **NEM12** and **NEM13**
|
|
56
57
|
metering files. Implements AEMO MDFF (Meter Data File Format) v2.6.
|
|
@@ -237,10 +238,16 @@ pip install -e .[dev]
|
|
|
237
238
|
pytest
|
|
238
239
|
```
|
|
239
240
|
|
|
240
|
-
CI runs ruff, mypy --strict, the test matrix on Python 3.
|
|
241
|
-
Linux / macOS / Windows, `pip-audit`, `bandit`,
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
CI runs ruff, mypy --strict, the test matrix on Python 3.10 → 3.12 /
|
|
242
|
+
Linux / macOS / Windows, `pip-audit`, `bandit`, CodeQL, OpenSSF
|
|
243
|
+
Scorecard, and a wheel-install smoke test.
|
|
244
|
+
|
|
245
|
+
Releases are automated by [release-please](https://github.com/googleapis/release-please)
|
|
246
|
+
from [Conventional Commits](https://www.conventionalcommits.org/) on
|
|
247
|
+
`main`, then signed with sigstore, attested with SLSA build provenance
|
|
248
|
+
and a CycloneDX SBOM, and published to PyPI via Trusted Publishing.
|
|
249
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the contributor commit
|
|
250
|
+
conventions and the full release flow.
|
|
244
251
|
|
|
245
252
|
## License
|
|
246
253
|
|
|
@@ -11,14 +11,15 @@ build-backend = "setuptools.build_meta"
|
|
|
11
11
|
# Pillow / PIL precedent (``pip install Pillow`` → ``import PIL``)
|
|
12
12
|
# applies here.
|
|
13
13
|
name = "aemo-mdff-reader"
|
|
14
|
-
version = "2.0
|
|
14
|
+
version = "2.1.0"
|
|
15
15
|
description = "Fast streaming reader for AEMO MDFF NEM12 / NEM13 metering files. Zero required dependencies."
|
|
16
16
|
readme = "README.md"
|
|
17
17
|
license = "MIT"
|
|
18
18
|
license-files = ["LICENSE"]
|
|
19
|
-
# Python 3.
|
|
20
|
-
#
|
|
21
|
-
|
|
19
|
+
# Python 3.9 reached end-of-life in October 2025; CI hash-pinning of
|
|
20
|
+
# pandas/pyarrow/numpy no longer resolves cleanly against 3.9 wheels.
|
|
21
|
+
# 3.10 is the lowest supported runtime as of v3.0.
|
|
22
|
+
requires-python = ">=3.10"
|
|
22
23
|
authors = [
|
|
23
24
|
{ name = "Utilified Holdings Pty Ltd" },
|
|
24
25
|
]
|
|
@@ -30,7 +31,6 @@ classifiers = [
|
|
|
30
31
|
"Operating System :: OS Independent",
|
|
31
32
|
"Programming Language :: Python :: 3",
|
|
32
33
|
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
-
"Programming Language :: Python :: 3.9",
|
|
34
34
|
"Programming Language :: Python :: 3.10",
|
|
35
35
|
"Programming Language :: Python :: 3.11",
|
|
36
36
|
"Programming Language :: Python :: 3.12",
|
|
@@ -95,7 +95,7 @@ exclude_lines = [
|
|
|
95
95
|
|
|
96
96
|
[tool.ruff]
|
|
97
97
|
line-length = 100
|
|
98
|
-
target-version = "
|
|
98
|
+
target-version = "py310"
|
|
99
99
|
|
|
100
100
|
[tool.ruff.lint]
|
|
101
101
|
select = [
|
|
@@ -128,10 +128,6 @@ ignore = [
|
|
|
128
128
|
"aemo_mdff_reader/sql/*" = ["F401", "F403", "F405", "UP031"]
|
|
129
129
|
|
|
130
130
|
[tool.mypy]
|
|
131
|
-
# Lowest supported runtime is 3.9 (see ``requires-python``), but mypy
|
|
132
|
-
# 1.16+ no longer accepts ``<3.10`` here. Type-checking against 3.10
|
|
133
|
-
# still produces useful results — we don't use any 3.10-only typing
|
|
134
|
-
# features (no ``match`` statements, no PEP 604 ``X | Y`` at runtime).
|
|
135
131
|
python_version = "3.10"
|
|
136
132
|
strict = true
|
|
137
133
|
files = ["aemo_mdff_reader"]
|
|
@@ -127,7 +127,8 @@ def test_parse_to_columns_matches_to_columns():
|
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
def test_parse_to_columns_from_iterable():
|
|
130
|
-
|
|
130
|
+
with open(FIXTURE) as f:
|
|
131
|
+
rows = list(csv.reader(f))
|
|
131
132
|
a = parse_to_columns(FIXTURE)
|
|
132
133
|
b = parse_to_columns(rows)
|
|
133
134
|
assert a == b
|
|
@@ -178,7 +179,8 @@ def test_header_repr():
|
|
|
178
179
|
|
|
179
180
|
|
|
180
181
|
def test_nem_reader_read_from_array():
|
|
181
|
-
|
|
182
|
+
with open(FIXTURE) as f:
|
|
183
|
+
rows = list(csv.reader(f))
|
|
182
184
|
rdr = NEMReader()
|
|
183
185
|
rdr.read_from_array(rows)
|
|
184
186
|
assert len(rdr.readings) == 3 * 48
|
|
@@ -188,7 +190,8 @@ def test_nem_reader_read_from_array():
|
|
|
188
190
|
def test_nem_reader_to_columns_without_filename():
|
|
189
191
|
# NEMReader.to_columns falls through the Reading-iterable branch
|
|
190
192
|
# when no source filename is buffered.
|
|
191
|
-
|
|
193
|
+
with open(FIXTURE) as f:
|
|
194
|
+
rows = list(csv.reader(f))
|
|
192
195
|
rdr = NEMReader()
|
|
193
196
|
rdr.read_from_array(rows)
|
|
194
197
|
cols = rdr.to_columns()
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from urllib.parse import urlparse
|
|
6
|
+
|
|
5
7
|
import aemo_mdff_reader
|
|
6
|
-
|
|
8
|
+
|
|
9
|
+
spec = aemo_mdff_reader.spec
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
def test_spec_module_is_re_exported():
|
|
@@ -16,7 +19,9 @@ def test_spec_version_metadata():
|
|
|
16
19
|
# ISO-8601 effective date keeps callers parseable.
|
|
17
20
|
assert spec.SPEC_EFFECTIVE_DATE == "2024-09-29"
|
|
18
21
|
assert "Meter Data File Format" in spec.SPEC_DOCUMENT_TITLE
|
|
19
|
-
|
|
22
|
+
parsed = urlparse(spec.SPEC_URL)
|
|
23
|
+
assert parsed.scheme == "https"
|
|
24
|
+
assert parsed.hostname == "www.aemo.com.au"
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
def test_allowed_interval_lengths_match_spec():
|
|
@@ -43,7 +43,7 @@ def test_storer_attribute_lazy_loads():
|
|
|
43
43
|
# If pymysql is not installed, accessing Storer should raise ImportError
|
|
44
44
|
# only at access time, not at module import time.
|
|
45
45
|
pytest.importorskip("aemo_mdff_reader.sql")
|
|
46
|
-
import
|
|
46
|
+
from aemo_mdff_reader import sql as sql_mod
|
|
47
47
|
|
|
48
48
|
if "pymysql" in sys.modules:
|
|
49
49
|
# If pymysql is available in the test env, we can at least confirm
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
Thanks for your interest in improving aemo-mdff-reader. The repository
|
|
4
|
-
is small and the bar for contributions is straightforward: a pull
|
|
5
|
-
request that passes CI and doesn't regress the public benchmark is
|
|
6
|
-
welcome.
|
|
7
|
-
|
|
8
|
-
Naming: everything (GitHub repo `Utilified/aemo-mdff-reader`, PyPI
|
|
9
|
-
distribution `aemo-mdff-reader`, Python import `aemo_mdff_reader`,
|
|
10
|
-
CLI `aemo-mdff-reader`) is consistently named after the AEMO spec —
|
|
11
|
-
MDFF, the Meter Data File Format that covers both NEM12 (interval) and
|
|
12
|
-
NEM13 (accumulation) formats. GitHub serves redirects from the
|
|
13
|
-
previous `Utilified/nem12-reader` repo URL so existing git pins
|
|
14
|
-
continue to work; v1 callers importing `from nem12_reader …` need to
|
|
15
|
-
update to `from aemo_mdff_reader …`.
|
|
16
|
-
|
|
17
|
-
## Setup
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
git clone https://github.com/Utilified/aemo-mdff-reader.git
|
|
21
|
-
cd aemo-mdff-reader
|
|
22
|
-
python -m venv .venv && source .venv/bin/activate
|
|
23
|
-
pip install -e .[dev]
|
|
24
|
-
pytest
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Running the test suite
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
pytest -v
|
|
31
|
-
pytest --cov=aemo_mdff_reader --cov-report=term-missing
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
A small, sanitized NEM12 sample lives at
|
|
35
|
-
`tests/fixtures/sample_nem12.csv`. To generate larger synthetic files
|
|
36
|
-
for ad-hoc testing or benchmarking:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
python tests/fixtures/generate.py /tmp/big.csv --nmis 4 --days 365 --interval-minutes 5
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Performance
|
|
43
|
-
|
|
44
|
-
`benchmarks/bench_parser.py` is the canonical performance test. Please
|
|
45
|
-
run it before and after changes that touch the hot path
|
|
46
|
-
(`parser.py::_emit_intervals`, `parse_to_columns`, `to_columns`):
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
python benchmarks/bench_parser.py --nmis 4 --days 365 --interval-minutes 5
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
The streaming and columnar fast paths must remain at or above the
|
|
53
|
-
current published throughput.
|
|
54
|
-
|
|
55
|
-
## Code style
|
|
56
|
-
|
|
57
|
-
- Pure stdlib in the core. **No** new required runtime dependencies.
|
|
58
|
-
Optional features go behind `[project.optional-dependencies]`.
|
|
59
|
-
- Type hints on all public symbols.
|
|
60
|
-
- Keep `aemo_mdff_reader.types` slots-based — per-row allocation is on
|
|
61
|
-
the hot path.
|
|
62
|
-
|
|
63
|
-
## Reporting issues
|
|
64
|
-
|
|
65
|
-
Please open an issue with:
|
|
66
|
-
|
|
67
|
-
1. The Python version and OS.
|
|
68
|
-
2. A minimal reproducer (a few NEM12 rows is usually enough).
|
|
69
|
-
3. The expected vs actual behaviour.
|
|
70
|
-
|
|
71
|
-
If you can share a sanitized sample file (no real NMIs / meter
|
|
72
|
-
serials), please attach it to the issue.
|
|
73
|
-
|
|
74
|
-
## Releasing
|
|
75
|
-
|
|
76
|
-
Maintainers only. Releases are tagged and pushed to GitHub; the
|
|
77
|
-
`Release` workflow then builds, signs (sigstore), publishes to PyPI
|
|
78
|
-
(via Trusted Publishing), and attaches signatures to the GitHub Release.
|
|
79
|
-
|
|
80
|
-
### One-time setup (per project)
|
|
81
|
-
|
|
82
|
-
Before the first release, configure these on PyPI / GitHub:
|
|
83
|
-
|
|
84
|
-
1. **PyPI Trusted Publishing**: register the project at
|
|
85
|
-
https://pypi.org/manage/account/publishing/ with:
|
|
86
|
-
- PyPI project name: `aemo-mdff-reader`
|
|
87
|
-
- Owner: `Utilified`
|
|
88
|
-
- Repository: `aemo-mdff-reader`
|
|
89
|
-
- Workflow filename: `release.yml`
|
|
90
|
-
- Environment name: `pypi`
|
|
91
|
-
2. **GitHub Environment**: in *Settings → Environments*, create an
|
|
92
|
-
environment named `pypi`. Add required reviewers if you want
|
|
93
|
-
manual approval before publish (recommended for the first few
|
|
94
|
-
releases). Without this environment, the publish job will fail with
|
|
95
|
-
a confusing "environment not found" error.
|
|
96
|
-
|
|
97
|
-
### Cutting a release
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
# Bump version in pyproject.toml AND aemo_mdff_reader/__init__.py.
|
|
101
|
-
# Update CHANGELOG.md with the new section.
|
|
102
|
-
git commit -am "release: vX.Y.Z"
|
|
103
|
-
git tag vX.Y.Z
|
|
104
|
-
git push origin main vX.Y.Z
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
The `Release` workflow takes over from here. Verify the published
|
|
108
|
-
artefact at https://pypi.org/project/aemo-mdff-reader/ and the
|
|
109
|
-
GitHub Release at https://github.com/Utilified/aemo-mdff-reader/releases.
|
|
110
|
-
|
|
111
|
-
### Local dry run
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
python -m build
|
|
115
|
-
twine check --strict dist/*
|
|
116
|
-
python -m venv /tmp/smoke && /tmp/smoke/bin/pip install dist/*.whl
|
|
117
|
-
/tmp/smoke/bin/aemo-mdff-reader --version
|
|
118
|
-
```
|
|
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
|
{aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{aemo_mdff_reader-2.0.2 → aemo_mdff_reader-2.1.0}/aemo_mdff_reader.egg-info/entry_points.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|