diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 2d2c544..cd8061b 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -10,22 +10,27 @@ concurrency: env: UV_VERSION: "0.9.4" +permissions: {} + jobs: - pre-commit: + prek: runs-on: ubuntu-latest - name: Pre-commit hooks (lint/format/spell/type, all files) + name: Prek hooks (lint/format/spell/type, all files) + permissions: + contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version-file: "pyproject.toml" - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 with: enable-cache: true version: ${{ env.UV_VERSION }} @@ -33,14 +38,16 @@ jobs: - name: Install dependencies run: uv sync --all-groups - - name: Run pre-commit - run: uv run pre-commit run --show-diff-on-failure --color=always --all-files --hook-stage push + - name: Run prek + run: uv run prek run --show-diff-on-failure --color=always --all-files --hook-stage pre-push pytest: name: Tests ${{ matrix.os }} / py${{ matrix.python }} - needs: pre-commit + needs: prek runs-on: ${{ matrix.os }} + permissions: + contents: read strategy: fail-fast: false matrix: @@ -50,10 +57,12 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 with: enable-cache: true version: ${{ env.UV_VERSION }} @@ -69,23 +78,25 @@ jobs: uv run pytest --cov --cov-report=xml - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5 with: token: ${{ secrets.CODECOV_TOKEN }} benchmarks: name: Benchmarks - needs: pre-commit + needs: prek runs-on: ubuntu-latest continue-on-error: true permissions: contents: read pull-requests: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 with: enable-cache: true version: ${{ env.UV_VERSION }} @@ -100,7 +111,7 @@ jobs: run: uv run pytest benchmarks/ -k "not xlarge_300k" --benchmark-only --benchmark-json=benchmark-results.json --no-cov - name: Download previous benchmark data - uses: actions/cache@v5 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 with: path: ./cache key: ${{ runner.os }}-benchmark-${{ github.head_ref || github.ref_name }}-${{ github.run_id }} @@ -112,7 +123,7 @@ jobs: run: mkdir -p cache && test -f cache/benchmark-data.json || echo '[]' > cache/benchmark-data.json - name: Publish benchmark results - uses: benchmark-action/github-action-benchmark@v1 + uses: benchmark-action/github-action-benchmark@a7bc2366eda11037936ea57d811a43b3418d3073 # v1 with: tool: pytest output-file-path: benchmark-results.json @@ -127,17 +138,21 @@ jobs: name: Package smoke test needs: pytest runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version-file: "pyproject.toml" - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 with: version: ${{ env.UV_VERSION }} enable-cache: true diff --git a/.github/workflows/commit.yaml b/.github/workflows/commit.yaml index 941a51f..73fc81f 100644 --- a/.github/workflows/commit.yaml +++ b/.github/workflows/commit.yaml @@ -4,18 +4,23 @@ on: pull_request: types: [opened, reopened, synchronize] +permissions: {} + jobs: lint-commit-messages: name: lint commit message runs-on: [ubuntu-latest] + permissions: + contents: read steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: + persist-credentials: false ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 - name: Commitizen check run: | uvx --from commitizen cz check --rev-range HEAD^! @@ -26,6 +31,6 @@ jobs: permissions: pull-requests: read steps: - - uses: amannn/action-semantic-pull-request@v6.1.1 + - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 601da5a..cde29f9 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -10,13 +10,18 @@ on: workflow_dispatch: +permissions: + contents: write + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 with: version: "latest" @@ -30,7 +35,7 @@ jobs: run: uv run sphinx-build docs/source/ docs/_build/ - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 + uses: peaceiris/actions-gh-pages@e9c66a37f080288a11235e32cbe2dc5fb3a679cc # v4 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} with: publish_branch: gh-pages diff --git a/.github/workflows/labeler.yaml b/.github/workflows/labeler.yaml index 46e6446..a867d60 100644 --- a/.github/workflows/labeler.yaml +++ b/.github/workflows/labeler.yaml @@ -1,7 +1,7 @@ name: labeler on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] types: [opened, reopened, synchronize] jobs: @@ -13,8 +13,10 @@ jobs: issues: write runs-on: [ubuntu-latest] steps: - - uses: actions/checkout@v6 - - uses: actions/labeler@v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + persist-credentials: false + - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/labeler.yaml diff --git a/.github/workflows/publish_pypi.yaml b/.github/workflows/publish_pypi.yaml deleted file mode 100644 index df2826b..0000000 --- a/.github/workflows/publish_pypi.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Upload to PyPi - -on: - release: - types: [published] - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install build - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }} - TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} - run: | - python -m build - twine upload dist/* diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 70bd63c..e05c39d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -8,16 +8,16 @@ concurrency: group: release-please cancel-in-progress: true -permissions: - contents: write - pull-requests: write - id-token: write +permissions: {} env: UV_VERSION: "0.9.4" jobs: release-please: + permissions: + contents: write + pull-requests: write outputs: release_created: ${{ steps.release.outputs.release_created }} release_tag: ${{ steps.release.outputs.tag_name }} @@ -25,7 +25,7 @@ jobs: steps: - name: Run release-please id: release - uses: googleapis/release-please-action@v4 + uses: googleapis/release-please-action@c3fc4de07084f75a2b61a5b933069bda6edf3d5c # v4 with: token: ${{ secrets.GITHUB_TOKEN }} config-file: .release-please-config.json @@ -34,26 +34,24 @@ jobs: build: name: Build + permissions: + contents: read needs: release-please if: needs.release-please.outputs.release_created runs-on: ubuntu-latest steps: - name: Checkout release commit - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ needs.release-please.outputs.release_tag }} fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version-file: "pyproject.toml" + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 - name: Install uv - uses: astral-sh/setup-uv@v7 - with: - version: ${{ env.UV_VERSION }} - enable-cache: true + uses: astral-sh/setup-uv@b75dde52aef63a238519e7aecbbe79a4a52e4315 # v7 - name: Install dependencies run: uv sync --all-groups @@ -62,12 +60,14 @@ jobs: run: uv build - name: Store the distribution packages - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 with: name: python-package-distributions path: dist/ publish-testpypi: + permissions: + id-token: write runs-on: ubuntu-latest needs: build environment: @@ -75,17 +75,16 @@ jobs: url: https://test.pypi.org/p/plexosdb steps: - name: Download all the dists - uses: actions/download-artifact@v8 - with: - name: python-package-distributions - path: dist/ + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 - name: Publish package to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@106e0b0b7c337fa67ed433972f777c6357f78598 # v1.13.0 with: repository-url: https://test.pypi.org/legacy/ publish-pypi: + permissions: + id-token: write needs: - build - publish-testpypi @@ -95,9 +94,9 @@ jobs: url: https://pypi.org/p/plexosdb steps: - name: Download all the dists - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: python-package-distributions path: dist/ - name: Publish distribution 📦 to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@106e0b0b7c337fa67ed433972f777c6357f78598 # v1.13.0 diff --git a/.gitignore b/.gitignore index ff77ed1..d604692 100644 --- a/.gitignore +++ b/.gitignore @@ -163,6 +163,9 @@ instance/ # Sphinx documentation docs/_build/ +# Implementation plans (local only) +docs/plans/ + # PyBuilder .pybuilder/ target/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a42f6f2..02e3fb1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,17 +21,32 @@ repos: language: system types_or: [python, pyi] - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + - repo: local + hooks: + - id: prettier + name: prettier + entry: prettier --write --ignore-unknown + language: node + additional_dependencies: ["prettier@3"] + types: [markdown] + + - repo: builtin hooks: - - id: end-of-file-fixer - id: trailing-whitespace - id: check-added-large-files - - id: check-merge-conflict - - id: check-yaml - - id: check-toml - - id: check-json + - id: end-of-file-fixer - id: check-case-conflict + - id: fix-byte-order-marker + - id: check-json + - id: check-toml + - id: check-yaml + - id: check-xml + - id: mixed-line-ending + - id: check-symlinks + - id: check-merge-conflict + - id: detect-private-key + - id: no-commit-to-branch + - id: check-executables-have-shebangs - repo: https://github.com/commitizen-tools/commitizen rev: v4.10.0 @@ -50,9 +65,7 @@ repos: pass_filenames: false stages: [pre-push] - - repo: https://github.com/astral-sh/uv-pre-commit - # uv version. rev: 0.9.4 hooks: - id: uv-lock diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..ed01e55 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,2 @@ +printWidth: 80 +proseWrap: "always" diff --git a/CHANGELOG.md b/CHANGELOG.md index 72a401d..2687f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,87 +4,122 @@ All notable changes to this project will be documented in this file. ## [1.3.2](https://github.com/NatLabRockies/plexosdb/compare/v1.3.1...v1.3.2) (2026-02-12) - ### 🐛 Bug Fixes -* Add capability of having a system object name different than system ([#96](https://github.com/NatLabRockies/plexosdb/issues/96)) ([6f3e408](https://github.com/NatLabRockies/plexosdb/commit/6f3e40827b2cc39445761a0822d31a58e4e7f126)) -* Propagate `parent_class_enum` when it is not the system get_object_properties() and iterate_properties() reject valid properties when parent_class_enum is not System. ([#100](https://github.com/NatLabRockies/plexosdb/issues/100)) ([7200897](https://github.com/NatLabRockies/plexosdb/commit/72008973493d086ba1901c6a4e88f3a68da135dd)) +- Add capability of having a system object name different than system + ([#96](https://github.com/NatLabRockies/plexosdb/issues/96)) + ([6f3e408](https://github.com/NatLabRockies/plexosdb/commit/6f3e40827b2cc39445761a0822d31a58e4e7f126)) +- Propagate `parent_class_enum` when it is not the system + get_object_properties() and iterate_properties() reject valid properties when + parent_class_enum is not System. + ([#100](https://github.com/NatLabRockies/plexosdb/issues/100)) + ([7200897](https://github.com/NatLabRockies/plexosdb/commit/72008973493d086ba1901c6a4e88f3a68da135dd)) ## [1.3.1](https://github.com/NatLabRockies/plexosdb/compare/v1.3.0...v1.3.1) (2026-02-10) - ### 🐛 Bug Fixes -* copy_object and list_objects_by_class ([#90](https://github.com/NatLabRockies/plexosdb/issues/90)) ([a11783e](https://github.com/NatLabRockies/plexosdb/commit/a11783edda469f5ad8f0dc6a5185139ce51fc1b7)) - +- copy_object and list_objects_by_class + ([#90](https://github.com/NatLabRockies/plexosdb/issues/90)) + ([a11783e](https://github.com/NatLabRockies/plexosdb/commit/a11783edda469f5ad8f0dc6a5185139ce51fc1b7)) ### 📦 Build -* **deps-dev:** bump ipython from 9.7.0 to 9.8.0 ([#86](https://github.com/NatLabRockies/plexosdb/issues/86)) ([50c97c5](https://github.com/NatLabRockies/plexosdb/commit/50c97c59e169860e9eace86dfaf0aeb62f795de2)) -* **deps-dev:** bump pytest from 9.0.1 to 9.0.2 ([#87](https://github.com/NatLabRockies/plexosdb/issues/87)) ([07e697b](https://github.com/NatLabRockies/plexosdb/commit/07e697b6e142521e84394901e8360cf28d8b95d1)) -* **deps:** bump actions/download-artifact from 6 to 7 ([#89](https://github.com/NatLabRockies/plexosdb/issues/89)) ([41ab2b4](https://github.com/NatLabRockies/plexosdb/commit/41ab2b47bbee8371aab0ca8a88a7dfcb5fa544d6)) -* **deps:** bump actions/upload-artifact from 5 to 6 ([#88](https://github.com/NatLabRockies/plexosdb/issues/88)) ([fc840f8](https://github.com/NatLabRockies/plexosdb/commit/fc840f85991f803817a7910a09ca0ff06c6f4713)) +- **deps-dev:** bump ipython from 9.7.0 to 9.8.0 + ([#86](https://github.com/NatLabRockies/plexosdb/issues/86)) + ([50c97c5](https://github.com/NatLabRockies/plexosdb/commit/50c97c59e169860e9eace86dfaf0aeb62f795de2)) +- **deps-dev:** bump pytest from 9.0.1 to 9.0.2 + ([#87](https://github.com/NatLabRockies/plexosdb/issues/87)) + ([07e697b](https://github.com/NatLabRockies/plexosdb/commit/07e697b6e142521e84394901e8360cf28d8b95d1)) +- **deps:** bump actions/download-artifact from 6 to 7 + ([#89](https://github.com/NatLabRockies/plexosdb/issues/89)) + ([41ab2b4](https://github.com/NatLabRockies/plexosdb/commit/41ab2b47bbee8371aab0ca8a88a7dfcb5fa544d6)) +- **deps:** bump actions/upload-artifact from 5 to 6 + ([#88](https://github.com/NatLabRockies/plexosdb/issues/88)) + ([fc840f8](https://github.com/NatLabRockies/plexosdb/commit/fc840f85991f803817a7910a09ca0ff06c6f4713)) ## [1.3.0](https://github.com/NREL/plexosdb/compare/v1.2.2...v1.3.0) (2025-12-11) - ### 🚀 Features -* Making add_from_records more robust ([#85](https://github.com/NREL/plexosdb/issues/85)) ([827b2dd](https://github.com/NREL/plexosdb/commit/827b2ddaa24cd5c9531d4f78fab8f4e1cb441ff2)) - +- Making add_from_records more robust + ([#85](https://github.com/NREL/plexosdb/issues/85)) + ([827b2dd](https://github.com/NREL/plexosdb/commit/827b2ddaa24cd5c9531d4f78fab8f4e1cb441ff2)) ### 📦 Build -* **deps:** bump pre-commit from 4.2.0 to 4.5.0 ([#82](https://github.com/NREL/plexosdb/issues/82)) ([a590ce9](https://github.com/NREL/plexosdb/commit/a590ce949bef17e8bfa81fe70bf75293d2e88aa8)) -* **deps:** bump ruff from 0.14.7 to 0.14.8 ([#83](https://github.com/NREL/plexosdb/issues/83)) ([c4123e1](https://github.com/NREL/plexosdb/commit/c4123e13f38d43586e1ba306b09b7b73c04b7b59)) +- **deps:** bump pre-commit from 4.2.0 to 4.5.0 + ([#82](https://github.com/NREL/plexosdb/issues/82)) + ([a590ce9](https://github.com/NREL/plexosdb/commit/a590ce949bef17e8bfa81fe70bf75293d2e88aa8)) +- **deps:** bump ruff from 0.14.7 to 0.14.8 + ([#83](https://github.com/NREL/plexosdb/issues/83)) + ([c4123e1](https://github.com/NREL/plexosdb/commit/c4123e13f38d43586e1ba306b09b7b73c04b7b59)) ## [1.2.2](https://github.com/NREL/plexosdb/compare/v1.2.1...v1.2.2) (2025-12-06) - ### 🐛 Bug Fixes -* Update battery collection enum naming and add increment to rank for same class enum ([#80](https://github.com/NREL/plexosdb/issues/80)) ([e247e67](https://github.com/NREL/plexosdb/commit/e247e6731f05eeef792cf8de09f0123e6f9d2995)) +- Update battery collection enum naming and add increment to rank for same class + enum ([#80](https://github.com/NREL/plexosdb/issues/80)) + ([e247e67](https://github.com/NREL/plexosdb/commit/e247e6731f05eeef792cf8de09f0123e6f9d2995)) ## [1.2.1](https://github.com/NREL/plexosdb/compare/v1.2.0...v1.2.1) (2025-12-04) - ### 🐛 Bug Fixes -* handle property related attributes on "add_properties_from_records" method ([#78](https://github.com/NREL/plexosdb/issues/78)) ([1776d2a](https://github.com/NREL/plexosdb/commit/1776d2a614facef29d5a2a3df1f3a27dd154e359)) +- handle property related attributes on "add_properties_from_records" method + ([#78](https://github.com/NREL/plexosdb/issues/78)) + ([1776d2a](https://github.com/NREL/plexosdb/commit/1776d2a614facef29d5a2a3df1f3a27dd154e359)) ## [1.2.0](https://github.com/NREL/plexosdb/compare/v1.1.3...v1.2.0) (2025-12-02) - ### 🚀 Features -* Adding method `add_datafile_tag` and refactor add_properties/add_properties_from_records ([#69](https://github.com/NREL/plexosdb/issues/69)) ([1e6e018](https://github.com/NREL/plexosdb/commit/1e6e01852e46fba89b16120c07d472f4c84f94ab)) -* Adding new fixtures for cleaner testing. ([#68](https://github.com/NREL/plexosdb/issues/68)) ([9062baa](https://github.com/NREL/plexosdb/commit/9062baab8db1eb611dcb7364e952bbdb898fe36a)) -* Adding query date_from and date_to to properties ([#67](https://github.com/NREL/plexosdb/issues/67)) ([00d533b](https://github.com/NREL/plexosdb/commit/00d533b4b547822a09984cf59e40738fea330f4a)) - +- Adding method `add_datafile_tag` and refactor + add_properties/add_properties_from_records + ([#69](https://github.com/NREL/plexosdb/issues/69)) + ([1e6e018](https://github.com/NREL/plexosdb/commit/1e6e01852e46fba89b16120c07d472f4c84f94ab)) +- Adding new fixtures for cleaner testing. + ([#68](https://github.com/NREL/plexosdb/issues/68)) + ([9062baa](https://github.com/NREL/plexosdb/commit/9062baab8db1eb611dcb7364e952bbdb898fe36a)) +- Adding query date_from and date_to to properties + ([#67](https://github.com/NREL/plexosdb/issues/67)) + ([00d533b](https://github.com/NREL/plexosdb/commit/00d533b4b547822a09984cf59e40738fea330f4a)) ### 🐛 Bug Fixes -* Adding new release-please workflow ([#71](https://github.com/NREL/plexosdb/issues/71)) ([1f8da38](https://github.com/NREL/plexosdb/commit/1f8da384a9deb3edfa7a343e91999d3d37e07b17)) - +- Adding new release-please workflow + ([#71](https://github.com/NREL/plexosdb/issues/71)) + ([1f8da38](https://github.com/NREL/plexosdb/commit/1f8da384a9deb3edfa7a343e91999d3d37e07b17)) ### 📦 Build -* **deps:** bump actions/checkout from 4 to 6 ([#74](https://github.com/NREL/plexosdb/issues/74)) ([bb7be8d](https://github.com/NREL/plexosdb/commit/bb7be8d0e36c332051ec1a1767b8862f4baec359)) -* **deps:** bump actions/setup-python from 5 to 6 ([#73](https://github.com/NREL/plexosdb/issues/73)) ([18a0d9d](https://github.com/NREL/plexosdb/commit/18a0d9d26db2056d79bbdda6cec168e895abe0e9)) -* **deps:** bump furo from 2024.8.6 to 2025.9.25 ([#77](https://github.com/NREL/plexosdb/issues/77)) ([3dd6463](https://github.com/NREL/plexosdb/commit/3dd64632666e31a38f6ed8f8bb15f9d333e64791)) -* **deps:** bump ipython from 9.4.0 to 9.7.0 ([#76](https://github.com/NREL/plexosdb/issues/76)) ([ca687df](https://github.com/NREL/plexosdb/commit/ca687dfa466990e59c273c26908496c1fd5a8878)) -* **deps:** bump pytest from 8.4.1 to 9.0.1 ([#75](https://github.com/NREL/plexosdb/issues/75)) ([5864d85](https://github.com/NREL/plexosdb/commit/5864d85e69e5e6cc865fc389e6b15f8e63785001)) +- **deps:** bump actions/checkout from 4 to 6 + ([#74](https://github.com/NREL/plexosdb/issues/74)) + ([bb7be8d](https://github.com/NREL/plexosdb/commit/bb7be8d0e36c332051ec1a1767b8862f4baec359)) +- **deps:** bump actions/setup-python from 5 to 6 + ([#73](https://github.com/NREL/plexosdb/issues/73)) + ([18a0d9d](https://github.com/NREL/plexosdb/commit/18a0d9d26db2056d79bbdda6cec168e895abe0e9)) +- **deps:** bump furo from 2024.8.6 to 2025.9.25 + ([#77](https://github.com/NREL/plexosdb/issues/77)) + ([3dd6463](https://github.com/NREL/plexosdb/commit/3dd64632666e31a38f6ed8f8bb15f9d333e64791)) +- **deps:** bump ipython from 9.4.0 to 9.7.0 + ([#76](https://github.com/NREL/plexosdb/issues/76)) + ([ca687df](https://github.com/NREL/plexosdb/commit/ca687dfa466990e59c273c26908496c1fd5a8878)) +- **deps:** bump pytest from 8.4.1 to 9.0.1 + ([#75](https://github.com/NREL/plexosdb/issues/75)) + ([5864d85](https://github.com/NREL/plexosdb/commit/5864d85e69e5e6cc865fc389e6b15f8e63785001)) ## [0.0.1] - 2024-08-21 ### 🐛 Bug Fixes -- *(get_memberships)* Updated `get_membership` function (#6) +- _(get_memberships)_ Updated `get_membership` function (#6) ### ⚙️ Miscellaneous Tasks -- *(actions)* Adding first version of GitHub actions (#5) -- *(actions)* Fixing GitHub Actions and refactoring API (#7) +- _(actions)_ Adding first version of GitHub actions (#5) +- _(actions)_ Fixing GitHub Actions and refactoring API (#7) - Removing trailwhitespace diff --git a/README.md b/README.md index 09f022f..6f0c468 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,103 @@ -### Database Manager for use with PLEXOS XML files -[![image](https://img.shields.io/pypi/v/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) -[![image](https://img.shields.io/pypi/l/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) -[![image](https://img.shields.io/pypi/pyversions/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) -[![CI](https://github.com/NREL/plexosdb/actions/workflows/CI.yaml/badge.svg)](https://github.com/NREL/plexosdb/actions/workflows/CI.yaml) -[![codecov](https://codecov.io/gh/NREL/plexosdb/branch/main/graph/badge.svg)](https://codecov.io/gh/NREL/plexosdb) -[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) -
+### plexosdb + +> SQLite-backed Python API for reading, building, and writing PLEXOS XML models +> +> [![image](https://img.shields.io/pypi/v/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) +> [![image](https://img.shields.io/pypi/l/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) +> [![image](https://img.shields.io/pypi/pyversions/plexosdb.svg)](https://pypi.python.org/pypi/plexosdb) +> [![CI](https://github.com/NatLabRockies/plexosdb/actions/workflows/CI.yaml/badge.svg)](https://github.com/NatLabRockies/plexosdb/actions/workflows/CI.yaml) +> [![codecov](https://codecov.io/gh/NatLabRockies/plexosdb/branch/main/graph/badge.svg)](https://codecov.io/gh/NatLabRockies/plexosdb) +> [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) +> [![Documentation](https://github.com/NatLabRockies/plexosdb/actions/workflows/docs.yaml/badge.svg?branch=main)](https://natlabrockies.github.io/plexosdb/) + +plexosdb converts PLEXOS XML input files into an in-memory SQLite database, +giving you a fast, typed Python API to query, create, and modify power system +models programmatically, then write them back to XML. ## Installation ```console -python -m pip install plexosdb +pip install plexosdb ``` -## Developer installation +Or with [uv](https://docs.astral.sh/uv/): ```console -$ pip install -e ".[dev]" +uv add plexosdb +``` + +**Python version support:** 3.11, 3.12, 3.13, 3.14 + +## Quick Start + +```python +from plexosdb import PlexosDB, ClassEnum, CollectionEnum + +# Load a PLEXOS XML file into an in-memory SQLite database +db = PlexosDB.from_xml("model.xml") + +# Query existing objects +generators = db.get_object_names(ClassEnum.Generator) + +# Add new objects +db.add_object(ClassEnum.Generator, name="SolarPV_01", category="Renewables") +db.add_object(ClassEnum.Node, name="Bus_1") + +# Create memberships between objects +db.add_membership( + CollectionEnum.GeneratorNodes, + parent_class=ClassEnum.Generator, + parent_name="SolarPV_01", + child_class=ClassEnum.Node, + child_name="Bus_1", +) + +# Export the modified model back to XML +db.to_xml("modified_model.xml") ``` -Please install `pre-commit` so that your code is checked before making commits. +## Documentation + +Full documentation is available at +[natlabrockies.github.io/plexosdb](https://natlabrockies.github.io/plexosdb/). + +## Developer Setup + +plexosdb uses [uv](https://docs.astral.sh/uv/) for dependency management. + +```console +git clone https://github.com/NatLabRockies/plexosdb.git +cd plexosdb +uv sync --all-groups +``` + +Install the git hooks so your code is checked before making commits: ```console -pre-commit install +uv run prek install +``` + +Run the test suite: + +```console +uv run pytest ``` ## License This software is released under a BSD-3-Clause -[License](https://github.com/NREL/plexosdb/blob/main/LICENSE.txt). - -This software was developed under software record SWR-24-90 at the National Renewable Energy Laboratory -([NREL](https://www.nrel.gov)). +[License](https://github.com/NatLabRockies/plexosdb/blob/main/LICENSE.txt). +This software was developed under software record SWR-24-90 at the National +Renewable Energy Laboratory ([NREL](https://www.nrel.gov)). ## Disclaimer -PLEXOS is a registered trademark of Energy Exemplar Pty Ltd. Energy Exemplar Pty Ltd. has no affiliation to or participation in this software. Reference herein to any specific commercial products, process, or service by trade name, trademark, manufacturer, or otherwise, does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or Alliance for Sustainable Energy, LLC ("Alliance"). The views and opinions of authors expressed in the available or referenced documents do not necessarily state or reflect those of the United States Government or Alliance. +PLEXOS is a registered trademark of Energy Exemplar Pty Ltd. Energy Exemplar Pty +Ltd. has no affiliation to or participation in this software. Reference herein +to any specific commercial products, process, or service by trade name, +trademark, manufacturer, or otherwise, does not necessarily constitute or imply +its endorsement, recommendation, or favoring by the United States Government or +Alliance for Sustainable Energy, LLC ("Alliance"). The views and opinions of +authors expressed in the available or referenced documents do not necessarily +state or reflect those of the United States Government or Alliance. diff --git a/docs/source/CHANGELOG.md b/docs/source/CHANGELOG.md index c0ed571..e5d936e 100644 --- a/docs/source/CHANGELOG.md +++ b/docs/source/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - Consolidate code structure (#26) - Adding support for adding attributes (#27) -- *(scenarios)* Adding scenario manipulation. (#28) +- _(scenarios)_ Adding scenario manipulation. (#28) - Adding report writing capability (#29) - Adding bulk operations to plexosdb (#30) @@ -48,7 +48,8 @@ All notable changes to this project will be documented in this file. ### 🚀 Features -- Enable capability of find enums with spaces and new methods for easy interaction (#17) +- Enable capability of find enums with spaces and new methods for easy + interaction (#17) ## [0.0.3] - 2024-09-17 @@ -77,7 +78,7 @@ All notable changes to this project will be documented in this file. ### ⚙️ Miscellaneous Tasks -- Fixing pre-commit errors and adding more workflows (#9) +- Fixing pre-commit errors and adding more workflows (#9) - Initial test PR (#10) - Fixing actions and coverage (#11) @@ -85,12 +86,12 @@ All notable changes to this project will be documented in this file. ### 🐛 Bug Fixes -- *(get_memberships)* Updated `get_membership` function (#6) +- _(get_memberships)_ Updated `get_membership` function (#6) ### ⚙️ Miscellaneous Tasks -- *(actions)* Adding first version of GitHub actions (#5) -- *(actions)* Fixing GitHub Actions and refactoring API (#7) +- _(actions)_ Adding first version of GitHub actions (#5) +- _(actions)_ Fixing GitHub Actions and refactoring API (#7) - Removing trailwhitespace diff --git a/docs/source/api/index.md b/docs/source/api/index.md index af2a0df..a885ae3 100644 --- a/docs/source/api/index.md +++ b/docs/source/api/index.md @@ -1,7 +1,11 @@ (api)= + # API Reference -This section provides comprehensive reference documentation for all PlexosDB classes, methods, and modules. Use this section when you need detailed information about specific functions, their parameters, return values, and behavior. +This section provides comprehensive reference documentation for all PlexosDB +classes, methods, and modules. Use this section when you need detailed +information about specific functions, their parameters, return values, and +behavior. ## Core Components diff --git a/docs/source/howtos/add_attributes.md b/docs/source/howtos/add_attributes.md index 8ae2850..d1481c7 100644 --- a/docs/source/howtos/add_attributes.md +++ b/docs/source/howtos/add_attributes.md @@ -6,6 +6,7 @@ table. ## Listing available attributes per `ClassEnum` To see the list of available attributes per `ClassEnum` use: + ```python from plexosdb import PlexosDB, ClassEnum db = PlexosDB.from_xml("/path/to/your/xml") diff --git a/docs/source/howtos/add_objects.md b/docs/source/howtos/add_objects.md index 3c52851..232bbf1 100644 --- a/docs/source/howtos/add_objects.md +++ b/docs/source/howtos/add_objects.md @@ -1,6 +1,7 @@ # Adding Objects to the Database -Objects in PlexosDB represent entities in your PLEXOS model like generators, regions, and nodes. +Objects in PlexosDB represent entities in your PLEXOS model like generators, +regions, and nodes. ## Basic Object Creation diff --git a/docs/source/howtos/add_properties.md b/docs/source/howtos/add_properties.md index b7bd253..c3f60c8 100644 --- a/docs/source/howtos/add_properties.md +++ b/docs/source/howtos/add_properties.md @@ -1,6 +1,7 @@ # Adding Properties to Objects -Properties define attributes of objects in your PLEXOS model, such as a generator's capacity or a node's location. +Properties define attributes of objects in your PLEXOS model, such as a +generator's capacity or a node's location. ## Basic Property Addition @@ -82,7 +83,8 @@ db.add_property( ## Bulk Adding Properties -For efficiency when adding many properties at once (use the flat format; the nested format is accepted but deprecated and will emit a warning): +For efficiency when adding many properties at once (use the flat format; the +nested format is accepted but deprecated and will emit a warning): ```python # Flat format (recommended) diff --git a/docs/source/howtos/add_reports.md b/docs/source/howtos/add_reports.md index 4b8b281..4133b6f 100644 --- a/docs/source/howtos/add_reports.md +++ b/docs/source/howtos/add_reports.md @@ -1,10 +1,13 @@ # How to Add Report Configurations -This guide demonstrates how to add report configurations to your PLEXOS model using the PlexosDB API. +This guide demonstrates how to add report configurations to your PLEXOS model +using the PlexosDB API. ## Basic Report Configuration -Reports in PLEXOS define what data will be available for post-processing after simulation runs. Each report must be associated with a Report object and specify which properties should be reported from which collections. +Reports in PLEXOS define what data will be available for post-processing after +simulation runs. Each report must be associated with a Report object and specify +which properties should be reported from which collections. ```python from plexosdb import PlexosDB @@ -87,7 +90,8 @@ for prop in ["Generation", "Available Capacity"]: ## Understanding Phase IDs -The `phase_id` parameter specifies which simulation phase to create the report for: +The `phase_id` parameter specifies which simulation phase to create the report +for: - `1`: ST (Short Term) - `2`: MT (Medium Term) diff --git a/docs/source/howtos/bulk_operations.md b/docs/source/howtos/bulk_operations.md index 4b08bcc..3ddb074 100644 --- a/docs/source/howtos/bulk_operations.md +++ b/docs/source/howtos/bulk_operations.md @@ -1,10 +1,14 @@ # Bulk Operations with PlexosDB -This guide demonstrates how to efficiently perform bulk operations using PlexosDB, which can significantly improve performance when working with large datasets. +This guide demonstrates how to efficiently perform bulk operations using +PlexosDB, which can significantly improve performance when working with large +datasets. ## Bulk Inserting Properties -When you need to add multiple properties to multiple objects, using individual `add_property` calls can be inefficient. The `add_properties_from_records` method provides a much more efficient approach. +When you need to add multiple properties to multiple objects, using individual +`add_property` calls can be inefficient. The `add_properties_from_records` +method provides a much more efficient approach. ### Basic Usage @@ -54,9 +58,13 @@ db.add_properties_from_records( ### Performance Considerations -The `add_properties_from_records` method processes records in batches (default 10,000 records per batch) and uses SQLite transactions to maximize performance. This makes it much faster than individual property insertions, especially for large datasets. +The `add_properties_from_records` method processes records in batches (default +10,000 records per batch) and uses SQLite transactions to maximize performance. +This makes it much faster than individual property insertions, especially for +large datasets. Key performance features: + - Single transaction for all insertions (atomic operations) - Batch processing to control memory usage - Direct SQL execution with prepared statements @@ -106,13 +114,16 @@ db.add_properties_from_records( ### Data Validation The method automatically validates: + - All objects exist before attempting inserts - All property names are valid for the collection - All required fields are present ## Bulk Inserting Memberships -Creating relationships between many objects can be time-consuming when done individually. The `add_memberships_from_records` method allows you to efficiently create multiple memberships in a single operation. +Creating relationships between many objects can be time-consuming when done +individually. The `add_memberships_from_records` method allows you to +efficiently create multiple memberships in a single operation. ### Basic Usage @@ -155,24 +166,26 @@ membership_records = create_membership_record( db.add_memberships_from_records(membership_records) ``` - -To identify the correct `CollectionEnum` for your relationship, use the `list_collections` method: +To identify the correct `CollectionEnum` for your relationship, use the +`list_collections` method: ```python collection_list = db.list_collections(parent_class=ClassEnum.Region, child_class=ClassEnum.Node) print(collection_list) # Shows available collections for Region-Node relationships ``` -This ensures you're using the exact collection name that exists in your database schema. - +This ensures you're using the exact collection name that exists in your database +schema. ### Performance Benefits -Using `add_memberships_from_records` offers several advantages over individual `add_membership` calls: +Using `add_memberships_from_records` offers several advantages over individual +`add_membership` calls: - Significantly reduced execution time for large datasets - Lower overhead from fewer database operations -- Optional chunking for very large datasets (controlled by the `chunksize` parameter) +- Optional chunking for very large datasets (controlled by the `chunksize` + parameter) - Efficient batch SQL execution ### Manual Record Creation @@ -196,6 +209,7 @@ db.add_memberships_from_records(records) ``` Each record must contain these fields: + - `parent_class_id`: ID of the parent class - `parent_object_id`: ID of the parent object - `collection_id`: ID of the collection @@ -204,10 +218,12 @@ Each record must contain these fields: ## Combined Bulk Operations -For complex model creation, you can combine bulk operations to efficiently build your model: +For complex model creation, you can combine bulk operations to efficiently build +your model: 1. First create all objects using `add_objects` (bulk object creation) 2. Add memberships between objects with `add_memberships_from_records` 3. Add properties to the objects using `add_properties_from_records` -This approach can dramatically improve performance when creating large, complex models. +This approach can dramatically improve performance when creating large, complex +models. diff --git a/docs/source/howtos/copy_objects.md b/docs/source/howtos/copy_objects.md index 948d42a..9a227bf 100644 --- a/docs/source/howtos/copy_objects.md +++ b/docs/source/howtos/copy_objects.md @@ -1,6 +1,7 @@ # Copying Objects -PlexosDB allows you to create copies of existing objects along with their properties, memberships, and related property records. +PlexosDB allows you to create copies of existing objects along with their +properties, memberships, and related property records. ## Basic Object Copying @@ -70,7 +71,8 @@ new_object_id = db.copy_object( ## Copying Memberships -When copying an object, PlexosDB also attempts to copy its memberships (except any that cannot be recreated due to model constraints): +When copying an object, PlexosDB also attempts to copy its memberships (except +any that cannot be recreated due to model constraints): ```python # First create some objects with memberships diff --git a/docs/source/howtos/create_db.md b/docs/source/howtos/create_db.md index ed2148f..f796fae 100644 --- a/docs/source/howtos/create_db.md +++ b/docs/source/howtos/create_db.md @@ -1,6 +1,7 @@ # Creating a database from an existing XML file -PlexosDB allows you to create a database from an existing XML file using a few simple steps. +PlexosDB allows you to create a database from an existing XML file using a few +simple steps. ## Basic Usage diff --git a/docs/source/howtos/delete_objects.md b/docs/source/howtos/delete_objects.md index b2f8062..a7f4d10 100644 --- a/docs/source/howtos/delete_objects.md +++ b/docs/source/howtos/delete_objects.md @@ -1,10 +1,13 @@ # Deleting Objects and Properties from the Database -This guide demonstrates how to delete objects and properties from the PlexosDB database. +This guide demonstrates how to delete objects and properties from the PlexosDB +database. ## Deleting Objects -When you delete an object, all its associated data (properties, memberships, etc.) are automatically removed due to foreign key constraints with cascade deletion. +When you delete an object, all its associated data (properties, memberships, +etc.) are automatically removed due to foreign key constraints with cascade +deletion. ```python from plexosdb import PlexosDB @@ -28,7 +31,8 @@ db.delete_object(ClassEnum.Generator, name="TestGenerator") ## Deleting Properties -You can delete specific properties from objects without removing the object itself. This provides fine-grained control over data management. +You can delete specific properties from objects without removing the object +itself. This provides fine-grained control over data management. ### Basic Property Deletion @@ -52,7 +56,8 @@ db.delete_property(ClassEnum.Generator, "PowerPlant1", property_name="Min Stable ### Scenario-Specific Property Deletion -When properties have scenario-specific values, you can delete only the property data associated with a particular scenario: +When properties have scenario-specific values, you can delete only the property +data associated with a particular scenario: ```python # Add properties with different scenarios @@ -92,9 +97,12 @@ db.delete_property( ### Cascade Deletion Behavior -- **Object deletion**: Removes the object and ALL associated data (properties, memberships, text data, etc.) -- **Property deletion**: Removes only the specified property data, including associated text, tags, and date ranges -- **Scenario-specific deletion**: Removes only property data tagged with the specified scenario +- **Object deletion**: Removes the object and ALL associated data (properties, + memberships, text data, etc.) +- **Property deletion**: Removes only the specified property data, including + associated text, tags, and date ranges +- **Scenario-specific deletion**: Removes only property data tagged with the + specified scenario ### Error Handling @@ -122,9 +130,12 @@ except NameError as e: ## Best Practices 1. **Backup data**: Always backup your database before performing bulk deletions -2. **Verify existence**: Check that objects and properties exist before attempting deletion -3. **Use transactions**: For complex operations, wrap deletions in database transactions -4. **Scenario management**: Be specific about scenarios when deleting scenario-based properties +2. **Verify existence**: Check that objects and properties exist before + attempting deletion +3. **Use transactions**: For complex operations, wrap deletions in database + transactions +4. **Scenario management**: Be specific about scenarios when deleting + scenario-based properties ```python # Example of safe deletion with verification diff --git a/docs/source/howtos/import_export.md b/docs/source/howtos/import_export.md index a203007..aaca443 100644 --- a/docs/source/howtos/import_export.md +++ b/docs/source/howtos/import_export.md @@ -1,6 +1,7 @@ # Importing and Exporting Data -PlexosDB provides methods for importing data from XML files and exporting to XML or CSV formats. +PlexosDB provides methods for importing data from XML files and exporting to XML +or CSV formats. ## Importing from XML diff --git a/docs/source/howtos/manage_relationships.md b/docs/source/howtos/manage_relationships.md index 139609f..4b22b9f 100644 --- a/docs/source/howtos/manage_relationships.md +++ b/docs/source/howtos/manage_relationships.md @@ -1,6 +1,7 @@ # Managing Object Relationships -In PLEXOS, objects can have relationships with each other. These relationships are managed through memberships in PlexosDB. +In PLEXOS, objects can have relationships with each other. These relationships +are managed through memberships in PlexosDB. ## Creating Relationships (Memberships) diff --git a/docs/source/howtos/query_database.md b/docs/source/howtos/query_database.md index 9145971..d92b084 100644 --- a/docs/source/howtos/query_database.md +++ b/docs/source/howtos/query_database.md @@ -1,6 +1,7 @@ # Querying the Database -PlexosDB provides various methods to efficiently retrieve data from your PLEXOS model. +PlexosDB provides various methods to efficiently retrieve data from your PLEXOS +model. ## Getting Object Properties diff --git a/docs/source/howtos/work_with_scenarios.md b/docs/source/howtos/work_with_scenarios.md index 677cd35..6392a7a 100644 --- a/docs/source/howtos/work_with_scenarios.md +++ b/docs/source/howtos/work_with_scenarios.md @@ -17,7 +17,6 @@ db.create_schema() db.add_scenario("TestScenario") ``` - ## Creating Scenario Properties Scenarios are automatically created when adding properties with a scenario name: diff --git a/docs/source/index.md b/docs/source/index.md index 3637026..3fccd3b 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -1,6 +1,7 @@ # PlexosDB Documentation -PlexosDB is a Python library for working with PLEXOS energy market simulation models. +PlexosDB is a Python library for working with PLEXOS energy market simulation +models. ```{toctree} :maxdepth: 2 @@ -15,29 +16,40 @@ CHANGELOG ## About PlexosDB -PlexosDB provides a Python interface for working with PLEXOS energy market simulation models. The library converts PLEXOS XML files into SQLite databases and offers a comprehensive API for creating, querying, and manipulating energy system models. +PlexosDB provides a Python interface for working with PLEXOS energy market +simulation models. The library converts PLEXOS XML files into SQLite databases +and offers a comprehensive API for creating, querying, and manipulating energy +system models. ### Key Features PlexosDB offers the following capabilities: -- Complete support for PLEXOS model components including generators, regions, lines, and transmission networks -- Optimized SQLite backend with transaction support and bulk operations for handling large datasets efficiently -- Seamless bidirectional conversion between PLEXOS XML format and database representation -- Scenario management system for creating and comparing different model configurations -- Memory-efficient iterators and chunked processing for working with large models +- Complete support for PLEXOS model components including generators, regions, + lines, and transmission networks +- Optimized SQLite backend with transaction support and bulk operations for + handling large datasets efficiently +- Seamless bidirectional conversion between PLEXOS XML format and database + representation +- Scenario management system for creating and comparing different model + configurations +- Memory-efficient iterators and chunked processing for working with large + models ## Getting Started -To begin using PlexosDB, start with the [installation guide](installation) and then follow the step-by-step [tutorial](tutorial). +To begin using PlexosDB, start with the [installation guide](installation) and +then follow the step-by-step [tutorial](tutorial). ## How-to Guides -Task-oriented guides for specific workflows can be found in the [How-to Guides](howtos/index) section. +Task-oriented guides for specific workflows can be found in the +[How-to Guides](howtos/index) section. ## Reference -Complete API documentation is available in the [API Reference](api/index) section. +Complete API documentation is available in the [API Reference](api/index) +section. ## Release Notes @@ -45,6 +57,6 @@ Track changes and updates in the [Release Notes](CHANGELOG). ## Indices and Tables -* {ref}`genindex` -* {ref}`modindex` -* {ref}`search` +- {ref}`genindex` +- {ref}`modindex` +- {ref}`search` diff --git a/docs/source/installation.md b/docs/source/installation.md index 3bf4599..49e2f6a 100644 --- a/docs/source/installation.md +++ b/docs/source/installation.md @@ -28,7 +28,8 @@ pip install git+https://github.com/NREL/plexosdb.git ## Using uv -[uv](https://github.com/astral-sh/uv) is a new, fast Python package installer and resolver. To install plexosdb using uv: +[uv](https://github.com/astral-sh/uv) is a new, fast Python package installer +and resolver. To install plexosdb using uv: ```bash # Install uv if you haven't already @@ -50,7 +51,8 @@ plexosdb requires: ## Verification -After installation, you can verify that plexosdb was installed correctly by running: +After installation, you can verify that plexosdb was installed correctly by +running: ```python import plexosdb diff --git a/docs/source/tutorial.md b/docs/source/tutorial.md index 22515a2..7db629a 100644 --- a/docs/source/tutorial.md +++ b/docs/source/tutorial.md @@ -1,6 +1,8 @@ # Tutorial -This tutorial provides a step-by-step introduction to PlexosDB, guiding you through the essential concepts and operations for working with PLEXOS energy market simulation models. +This tutorial provides a step-by-step introduction to PlexosDB, guiding you +through the essential concepts and operations for working with PLEXOS energy +market simulation models. ## Prerequisites @@ -38,7 +40,8 @@ This creates an empty database with the PLEXOS schema structure ready for data. ## Working with Objects -Objects represent entities in your energy model such as generators, nodes, and regions. +Objects represent entities in your energy model such as generators, nodes, and +regions. ### Adding Objects @@ -58,7 +61,8 @@ print(f"Generators: {generators}") ### Adding Properties -Properties define characteristics of objects like capacity, cost, or operational parameters: +Properties define characteristics of objects like capacity, cost, or operational +parameters: ```python # Add capacity property to the generator @@ -88,7 +92,8 @@ for prop in properties: ## Working with XML Files -PlexosDB can import existing PLEXOS XML files and export databases back to XML format. +PlexosDB can import existing PLEXOS XML files and export databases back to XML +format. ### Importing from XML @@ -110,7 +115,8 @@ db.to_xml("/path/to/output_model.xml") ## Working with Scenarios -Scenarios allow you to model different operational conditions or future projections: +Scenarios allow you to model different operational conditions or future +projections: ```python # Add a scenario diff --git a/pyproject.toml b/pyproject.toml index d9d9834..257df7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,10 +38,10 @@ dependencies = [ ] [project.urls] -Documentation = "https://github.com/NREL/plexosdb#readme" -Issues = "https://github.com/NREL/plexosdb/issues" -Source = "https://github.com/NREL/plexosdb" -Changelog = "https://github.com/NREL/plexosdb/blob/master/CHANGELOG.md" +Documentation = "https://natlabrockies.github.io/plexosdb/" +Issues = "https://github.com/NatLabRockies/plexosdb/issues" +Source = "https://github.com/NatLabRockies/plexosdb" +Changelog = "https://github.com/NatLabRockies/plexosdb/blob/main/CHANGELOG.md" [build-system] requires = ["uv_build>=0.8.22,<0.9.0"] @@ -64,7 +64,7 @@ docs = [ dev = [ "ipython>=9.2.0", "mypy>=1.15.0", - "pre-commit>=4.2.0", + "prek>=0.3.3", "pytest>=8.3.5", "pytest-benchmark>=5.1.0", "pytest-coverage>=0.0", diff --git a/uv.lock b/uv.lock index 01bcc3c..68e846c 100644 --- a/uv.lock +++ b/uv.lock @@ -77,15 +77,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/66/f3/80a3f974c8b535d394ff960a11ac20368e06b736da395b551a49ce950cce/certifi-2025.7.9-py3-none-any.whl", hash = "sha256:d842783a14f8fdd646895ac26f719a061408834473cfc10203f6a575beb15d39", size = 159230, upload-time = "2025-07-09T02:13:57.007Z" }, ] -[[package]] -name = "cfgv" -version = "3.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, -] - [[package]] name = "charset-normalizer" version = "3.4.2" @@ -232,15 +223,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, ] -[[package]] -name = "distlib" -version = "0.3.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, -] - [[package]] name = "docstr-coverage" version = "2.3.2" @@ -273,15 +255,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, ] -[[package]] -name = "filelock" -version = "3.18.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, -] - [[package]] name = "furo" version = "2025.9.25" @@ -319,15 +292,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, ] -[[package]] -name = "identify" -version = "2.6.12" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, -] - [[package]] name = "idna" version = "3.10" @@ -647,15 +611,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579, upload-time = "2025-02-12T10:53:02.078Z" }, ] -[[package]] -name = "nodeenv" -version = "1.9.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, -] - [[package]] name = "packaging" version = "25.0" @@ -695,15 +650,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, ] -[[package]] -name = "platformdirs" -version = "4.3.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, -] - [[package]] name = "plexosdb" version = "1.3.2" @@ -716,7 +662,7 @@ dependencies = [ dev = [ { name = "ipython" }, { name = "mypy" }, - { name = "pre-commit" }, + { name = "prek" }, { name = "pytest" }, { name = "pytest-benchmark" }, { name = "pytest-coverage" }, @@ -743,7 +689,7 @@ requires-dist = [{ name = "loguru" }] dev = [ { name = "ipython", specifier = ">=9.2.0" }, { name = "mypy", specifier = ">=1.15.0" }, - { name = "pre-commit", specifier = ">=4.2.0" }, + { name = "prek", specifier = ">=0.3.3" }, { name = "pytest", specifier = ">=8.3.5" }, { name = "pytest-benchmark", specifier = ">=5.1.0" }, { name = "pytest-coverage", specifier = ">=0.0" }, @@ -773,19 +719,27 @@ wheels = [ ] [[package]] -name = "pre-commit" -version = "4.5.0" +name = "prek" +version = "0.3.5" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cfgv" }, - { name = "identify" }, - { name = "nodeenv" }, - { name = "pyyaml" }, - { name = "virtualenv" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f4/9b/6a4ffb4ed980519da959e1cf3122fc6cb41211daa58dbae1c73c0e519a37/pre_commit-4.5.0.tar.gz", hash = "sha256:dc5a065e932b19fc1d4c653c6939068fe54325af8e741e74e88db4d28a4dd66b", size = 198428, upload-time = "2025-11-22T21:02:42.304Z" } +sdist = { url = "https://files.pythonhosted.org/packages/46/d6/277e002e56eeab3a9d48f1ca4cc067d249d6326fc1783b770d70ad5ae2be/prek-0.3.5.tar.gz", hash = "sha256:ca40b6685a4192256bc807f32237af94bf9b8799c0d708b98735738250685642", size = 374806, upload-time = "2026-03-09T10:35:18.842Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/c4/b2d28e9d2edf4f1713eb3c29307f1a63f3d67cf09bdda29715a36a68921a/pre_commit-4.5.0-py2.py3-none-any.whl", hash = "sha256:25e2ce09595174d9c97860a95609f9f852c0614ba602de3561e267547f2335e1", size = 226429, upload-time = "2025-11-22T21:02:40.836Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a9/16dd8d3a50362ebccffe58518af1f1f571c96f0695d7fcd8bbd386585f58/prek-0.3.5-py3-none-linux_armv6l.whl", hash = "sha256:44b3e12791805804f286d103682b42a84e0f98a2687faa37045e9d3375d3d73d", size = 5105604, upload-time = "2026-03-09T10:35:00.332Z" }, + { url = "https://files.pythonhosted.org/packages/e4/74/bc6036f5bf03860cda66ab040b32737e54802b71a81ec381839deb25df9e/prek-0.3.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3cb451cc51ac068974557491beb4c7d2d41dfde29ed559c1694c8ce23bf53e8", size = 5506155, upload-time = "2026-03-09T10:35:17.64Z" }, + { url = "https://files.pythonhosted.org/packages/02/d9/a3745c2a10509c63b6a118ada766614dd705efefd08f275804d5c807aa4a/prek-0.3.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ad8f5f0d8da53dc94d00b76979af312b3dacccc9dcbc6417756c5dca3633c052", size = 5100383, upload-time = "2026-03-09T10:35:13.302Z" }, + { url = "https://files.pythonhosted.org/packages/43/8e/de965fc515d39309a332789cd3778161f7bc80cde15070bedf17f9f8cb93/prek-0.3.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:4511e15d34072851ac88e4b2006868fbe13655059ad941d7a0ff9ee17138fd9f", size = 5334913, upload-time = "2026-03-09T10:35:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8c/44f07e8940256059cfd82520e3cbe0764ab06ddb4aa43148465db00b39ad/prek-0.3.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc0b63b8337e2046f51267facaac63ba755bc14aad53991840a5eccba3e5c28", size = 5033825, upload-time = "2026-03-09T10:35:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/94/85/3ff0f96881ff2360c212d310ff23c3cf5a15b223d34fcfa8cdcef203be69/prek-0.3.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5fc0d78c3896a674aeb8247a83bbda7efec85274dbdfbc978ceff8d37e4ed20", size = 5438586, upload-time = "2026-03-09T10:34:58.779Z" }, + { url = "https://files.pythonhosted.org/packages/79/a5/c6d08d31293400fcb5d427f8e7e6bacfc959988e868ad3a9d97b4d87c4b7/prek-0.3.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64cad21cb9072d985179495b77b312f6b81e7b45357d0c68dc1de66e0408eabc", size = 6359714, upload-time = "2026-03-09T10:34:57.454Z" }, + { url = "https://files.pythonhosted.org/packages/ba/18/321dcff9ece8065d42c8c1c7a53a23b45d2b4330aa70993be75dc5f2822f/prek-0.3.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45ee84199bb48e013bdfde0c84352c17a44cc42d5792681b86d94e9474aab6f8", size = 5717632, upload-time = "2026-03-09T10:35:08.634Z" }, + { url = "https://files.pythonhosted.org/packages/a3/7f/1288226aa381d0cea403157f4e6b64b356e1a745f2441c31dd9d8a1d63da/prek-0.3.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:f43275e5d564e18e52133129ebeb5cb071af7ce4a547766c7f025aa0955dfbb6", size = 5339040, upload-time = "2026-03-09T10:35:03.665Z" }, + { url = "https://files.pythonhosted.org/packages/22/94/cfec83df9c2b8e7ed1608087bcf9538a6a77b4c2e7365123e9e0a3162cd1/prek-0.3.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:abcee520d31522bcbad9311f21326b447694cd5edba33618c25fd023fc9865ec", size = 5162586, upload-time = "2026-03-09T10:35:11.564Z" }, + { url = "https://files.pythonhosted.org/packages/13/b7/741d62132f37a5f7cc0fad1168bd31f20dea9628f482f077f569547e0436/prek-0.3.5-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:499c56a94a155790c75a973d351a33f8065579d9094c93f6d451ada5d1e469be", size = 5002933, upload-time = "2026-03-09T10:35:16.347Z" }, + { url = "https://files.pythonhosted.org/packages/6f/83/630a5671df6550fcfa67c54955e8a8174eb9b4d97ac38fb05a362029245b/prek-0.3.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:de1065b59f194624adc9dea269d4ff6b50e98a1b5bb662374a9adaa496b3c1eb", size = 5304934, upload-time = "2026-03-09T10:35:09.975Z" }, + { url = "https://files.pythonhosted.org/packages/de/79/67a7afd0c0b6c436630b7dba6e586a42d21d5d6e5778fbd9eba7bbd3dd26/prek-0.3.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a1c4869e45ee341735d07179da3a79fa2afb5959cef8b3c8a71906eb52dc6933", size = 5829914, upload-time = "2026-03-09T10:35:05.39Z" }, + { url = "https://files.pythonhosted.org/packages/37/47/e2fe13b33e7b5fdd9dd1a312f5440208bfe1be6183e54c5c99c10f27d848/prek-0.3.5-py3-none-win32.whl", hash = "sha256:70b2152ecedc58f3f4f69adc884617b0cf44259f7414c44d6268ea6f107672eb", size = 4836910, upload-time = "2026-03-09T10:35:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ab/dc2a139fd4896d11f39631479ed385e86307af7f54059ebe9414bb0d00c6/prek-0.3.5-py3-none-win_amd64.whl", hash = "sha256:01d031b684f7e1546225393af1268d9b4451a44ef6cb9be4101c85c7862e08db", size = 5234234, upload-time = "2026-03-09T10:35:20.193Z" }, + { url = "https://files.pythonhosted.org/packages/ed/38/f7256b4b7581444f658e909c3b566f51bfabe56c03e80d107a6932d62040/prek-0.3.5-py3-none-win_arm64.whl", hash = "sha256:aa774168e3d868039ff79422bdef2df8d5a016ed804a9914607dcdd3d41da053", size = 5083330, upload-time = "2026-03-09T10:34:55.469Z" }, ] [[package]] @@ -1360,20 +1314,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, ] -[[package]] -name = "virtualenv" -version = "20.31.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "distlib" }, - { name = "filelock" }, - { name = "platformdirs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, -] - [[package]] name = "watchfiles" version = "1.1.0"