diff --git a/.badgery.yaml b/.badgery.yaml new file mode 100644 index 00000000..99bcdc1c --- /dev/null +++ b/.badgery.yaml @@ -0,0 +1,72 @@ +default_branch: master +develop_branch: develop + +cards: + - group: Tests + type: gh_action + title: Code/package tests (GitHub) + file: test.yml + enabled: true + - group: Tests + type: gh_action + title: Tutorial tests (GitHub) + file: tutorial-tests.yml + enabled: true + + - group: Tests + type: gh_action + title: Package tests (PyPI) + file: pypi-test.yml + enabled: true + + - group: Code Quality + type: codefactor + title: Code quality (CodeFactor) + enabled: true + + - group: Code Quality + type: radon_mi + title: Maintainability index (radon) + report: reports/{branch}/maintainability-index.json + enabled: true + + - group: Code Quality + type: radon_cc + title: Cyclomatic complexity (radon) + report: reports/{branch}/cyclomatic-complexity.json + enabled: true + + - group: Size + type: radon_loc + title: Source/Logical lines of code (radon) + report: reports/{branch}/raw-metrics.json + enabled: true + + - group: Size + type: radon_ff + title: Functions/Files count (radon) + report: reports/{branch}/cyclomatic-complexity.json + enabled: true + + - group: Coverage + type: codecov + title: Unit test coverage (Codecov) + flag: unittests + enabled: true + + - group: Coverage + type: interrogate + title: Docstring coverage (interrogate) + report: reports/{branch}/coverage-docstring.txt + enabled: true + - group: Build & Release + type: gh_action + title: Publishing (PyPI) + workflow: pypi-publish.yml + enabled: true + + - group: Build & Release + type: gh_action + title: Docs build/deployment + workflow: docs.yml + enabled: true diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 00000000..a8e73301 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,20 @@ +# WARNING: Do not edit this file manually. +# Any changes will be overwritten by Copier. +_commit: v0.11.0 +_src_path: gh:easyscience/templates +lib_docs_url: https://easyscience.github.io/gui-components +lib_doi: 10.5281/zenodo.18163581 +lib_package_name: EasyApplication +lib_python_max: '3.14' +lib_python_min: '3.12' +lib_repo_name: gui-components +project_contact_email: support@easyscience.org +project_copyright_years: 2021-2026 +project_extended_description: A collection of Qt/QML graphical components to create + cross-platform applications with intuitive graphical interface based on the EasyScience + framework +project_name: EasyApplication +project_short_description: Qt/QML components for building graphical applications +project_shortcut: EA +project_type: lib +template_type: lib diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml new file mode 100644 index 00000000..e4fd62f5 --- /dev/null +++ b/.github/actions/download-artifact/action.yml @@ -0,0 +1,50 @@ +name: 'Download artifact' +description: 'Generic wrapper for actions/download-artifact' +inputs: + name: + description: 'Name of the artifact to download' + required: true + + path: + description: 'Destination path' + required: false + default: '.' + + pattern: + description: 'Glob pattern to match artifact names (optional)' + required: false + default: '' + + merge-multiple: + description: 'Merge multiple artifacts into the same directory' + required: false + default: 'false' + + github-token: + description: 'GitHub token for cross-repo download (optional)' + required: false + default: '' + + repository: + description: 'owner/repo for cross-repo download (optional)' + required: false + default: '' + + run-id: + description: 'Workflow run ID for cross-run download (optional)' + required: false + default: '' + +runs: + using: 'composite' + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + pattern: ${{ inputs.pattern }} + merge-multiple: ${{ inputs.merge-multiple }} + github-token: ${{ inputs.github-token }} + repository: ${{ inputs.repository }} + run-id: ${{ inputs.run-id }} diff --git a/.github/actions/github-script/action.yml b/.github/actions/github-script/action.yml new file mode 100644 index 00000000..ab32da56 --- /dev/null +++ b/.github/actions/github-script/action.yml @@ -0,0 +1,19 @@ +name: 'GitHub Script' +description: 'Wrapper for actions/github-script' +inputs: + script: + description: 'JavaScript to run' + required: true + + github-token: + description: 'GitHub token (defaults to github.token)' + required: false + default: ${{ github.token }} + +runs: + using: 'composite' + steps: + - uses: actions/github-script@v8 + with: + script: ${{ inputs.script }} + github-token: ${{ inputs.github-token }} diff --git a/.github/actions/setup-easyscience-bot/action.yml b/.github/actions/setup-easyscience-bot/action.yml new file mode 100644 index 00000000..4b28eaf8 --- /dev/null +++ b/.github/actions/setup-easyscience-bot/action.yml @@ -0,0 +1,40 @@ +name: 'Setup EasyScience bot for pushing' +description: 'Create GitHub App token and configure git identity + origin remote' +inputs: + app-id: + description: 'GitHub App ID' + required: true + private-key: + description: 'GitHub App private key (PEM)' + required: true + repositories: + description: 'Additional repositories to grant access to (newline-separated)' + required: false + default: '' + +outputs: + token: + description: 'Installation access token' + value: ${{ steps.app-token.outputs.token }} + +runs: + using: 'composite' + steps: + - name: Create GitHub App installation token + id: app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ inputs.app-id }} + private-key: ${{ inputs.private-key }} + repositories: ${{ inputs.repositories }} + + - name: Configure git for pushing + shell: bash + run: | + git config user.name "easyscience[bot]" + git config user.email "${{ inputs.app-id }}+easyscience[bot]@users.noreply.github.com" + + - name: Configure origin remote to use the bot token + shell: bash + run: | + git remote set-url origin https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git diff --git a/.github/actions/setup-pixi/action.yml b/.github/actions/setup-pixi/action.yml new file mode 100644 index 00000000..167ee623 --- /dev/null +++ b/.github/actions/setup-pixi/action.yml @@ -0,0 +1,44 @@ +name: 'Setup Pixi Environment' +description: 'Sets up pixi with common configuration' +inputs: + environments: + description: 'Pixi environments to setup' + required: false + default: 'default' + activate-environment: + description: 'Environment to activate' + required: false + default: 'default' + run-install: + description: 'Whether to run pixi install' + required: false + default: 'true' + locked: + description: 'Whether to run pixi install --locked' + required: false + default: 'false' + frozen: + description: 'Whether to run pixi install --frozen' + required: false + default: 'true' + cache: + description: 'Whether to use cache' + required: false + default: 'false' + post-cleanup: + description: 'Whether to run post cleanup' + required: false + default: 'false' + +runs: + using: 'composite' + steps: + - uses: prefix-dev/setup-pixi@v0.9.4 + with: + environments: ${{ inputs.environments }} + activate-environment: ${{ inputs.activate-environment }} + run-install: ${{ inputs.run-install }} + locked: ${{ inputs.locked }} + frozen: ${{ inputs.frozen }} + cache: ${{ inputs.cache }} + post-cleanup: ${{ inputs.post-cleanup }} diff --git a/.github/actions/upload-artifact/action.yml b/.github/actions/upload-artifact/action.yml new file mode 100644 index 00000000..825ac396 --- /dev/null +++ b/.github/actions/upload-artifact/action.yml @@ -0,0 +1,49 @@ +name: 'Upload artifact' +description: 'Generic wrapper for actions/upload-artifact' +inputs: + name: + description: 'Artifact name' + required: true + + path: + description: 'File(s)/dir(s)/glob(s) to upload (newline-separated)' + required: true + + include-hidden-files: + description: 'Include hidden files' + required: false + default: 'true' + + if-no-files-found: + description: 'warn | error | ignore' + required: false + default: 'error' + + compression-level: + description: '0-9 (0 = no compression)' + required: false + default: '0' + + retention-days: + description: 'Retention in days (optional)' + required: false + default: '' + + overwrite: + description: 'Overwrite an existing artifact with the same name' + required: false + default: 'false' + +runs: + using: 'composite' + steps: + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + include-hidden-files: ${{ inputs.include-hidden-files }} + if-no-files-found: ${{ inputs.if-no-files-found }} + compression-level: ${{ inputs.compression-level }} + retention-days: ${{ inputs.retention-days }} + overwrite: ${{ inputs.overwrite }} diff --git a/.github/actions/upload-codecov/action.yml b/.github/actions/upload-codecov/action.yml new file mode 100644 index 00000000..37d6298a --- /dev/null +++ b/.github/actions/upload-codecov/action.yml @@ -0,0 +1,42 @@ +name: 'Upload coverage to Codecov' +description: 'Generic wrapper for codecov/codecov-action@v5' + +inputs: + name: + description: 'Codecov upload name' + required: true + + flags: + description: 'Codecov flags' + required: false + default: '' + + files: + description: 'Coverage report files' + required: true + + fail_ci_if_error: + description: 'Fail CI if upload fails' + required: false + default: 'true' + + verbose: + description: 'Enable verbose output' + required: false + default: 'true' + + token: + description: 'Codecov token' + required: true + +runs: + using: composite + steps: + - uses: codecov/codecov-action@v5 + with: + name: ${{ inputs.name }} + flags: ${{ inputs.flags }} + files: ${{ inputs.files }} + fail_ci_if_error: ${{ inputs.fail_ci_if_error }} + verbose: ${{ inputs.verbose }} + token: ${{ inputs.token }} diff --git a/.github/configs/pages-deployment.json b/.github/configs/pages-deployment.json new file mode 100644 index 00000000..c0d3fbee --- /dev/null +++ b/.github/configs/pages-deployment.json @@ -0,0 +1,6 @@ +{ + "source": { + "branch": "gh-pages", + "path": "/" + } +} diff --git a/.github/configs/rulesets-develop.json b/.github/configs/rulesets-develop.json new file mode 100644 index 00000000..04489e52 --- /dev/null +++ b/.github/configs/rulesets-develop.json @@ -0,0 +1,37 @@ +{ + "name": "develop branch", + "target": "branch", + "enforcement": "active", + "conditions": { + "ref_name": { + "include": ["refs/heads/develop"], + "exclude": [] + } + }, + "bypass_actors": [ + { + "actor_id": 2476259, + "actor_type": "Integration", + "bypass_mode": "always" + } + ], + "rules": [ + { + "type": "non_fast_forward" + }, + { + "type": "deletion" + }, + { + "type": "pull_request", + "parameters": { + "allowed_merge_methods": ["squash"], + "dismiss_stale_reviews_on_push": false, + "require_code_owner_review": false, + "require_last_push_approval": false, + "required_approving_review_count": 0, + "required_review_thread_resolution": false + } + } + ] +} diff --git a/.github/configs/rulesets-gh-pages.json b/.github/configs/rulesets-gh-pages.json new file mode 100644 index 00000000..ebf38928 --- /dev/null +++ b/.github/configs/rulesets-gh-pages.json @@ -0,0 +1,19 @@ +{ + "name": "gh-pages branch", + "target": "branch", + "enforcement": "active", + "conditions": { + "ref_name": { + "include": ["refs/heads/gh-pages"], + "exclude": [] + } + }, + "rules": [ + { + "type": "non_fast_forward" + }, + { + "type": "deletion" + } + ] +} diff --git a/.github/configs/rulesets-master.json b/.github/configs/rulesets-master.json new file mode 100644 index 00000000..f658a5c6 --- /dev/null +++ b/.github/configs/rulesets-master.json @@ -0,0 +1,30 @@ +{ + "name": "master branch", + "target": "branch", + "enforcement": "active", + "conditions": { + "ref_name": { + "include": ["~DEFAULT_BRANCH"], + "exclude": [] + } + }, + "rules": [ + { + "type": "non_fast_forward" + }, + { + "type": "deletion" + }, + { + "type": "pull_request", + "parameters": { + "allowed_merge_methods": ["merge"], + "dismiss_stale_reviews_on_push": false, + "require_code_owner_review": false, + "require_last_push_approval": false, + "required_approving_review_count": 0, + "required_review_thread_resolution": false + } + } + ] +} diff --git a/.github/scripts/backmerge-conflict-issue.js b/.github/scripts/backmerge-conflict-issue.js new file mode 100644 index 00000000..f6bd98b5 --- /dev/null +++ b/.github/scripts/backmerge-conflict-issue.js @@ -0,0 +1,69 @@ +module.exports = async ({ github, context, core }) => { + // Repo context + const owner = context.repo.owner + const repo = context.repo.repo + + // Link to the exact workflow run that detected the conflict + const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}` + + // We use a *stable title* so we can find/reuse the same "conflict tracker" issue + // instead of creating a new issue on every failed run. + const title = 'Backmerge conflict: master → develop' + + // Comment/issue body includes the run URL so maintainers can jump straight to logs. + const body = [ + 'Automatic backmerge failed due to merge conflicts.', + '', + `Workflow run: ${runUrl}`, + '', + 'Manual resolution required.', + ].join('\n') + + // Label applied to the tracker issue (assumed to already exist in the repo). + const label = '[bot] backmerge' + + // Search issues by title across *open and closed* issues. + // Why: if the conflict was resolved previously and the issue was closed, + // we prefer to reopen it and append a new comment instead of creating duplicates. + const q = `repo:${owner}/${repo} is:issue in:title "${title}"` + const search = await github.rest.search.issuesAndPullRequests({ + q, + per_page: 10, + }) + + // Pick the first exact-title match (search can return partial matches). + const existing = search.data.items.find((i) => i.title === title) + + if (existing) { + // If a tracker issue exists, reuse it: + // - reopen it if needed + // - add a comment with the new run URL + if (existing.state === 'closed') { + await github.rest.issues.update({ + owner, + repo, + issue_number: existing.number, + state: 'open', + }) + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: existing.number, + body, + }) + + core.notice(`Conflict issue updated: #${existing.number}`) + return + } + + // No tracker issue exists yet -> create the first one. + await github.rest.issues.create({ + owner, + repo, + title, + body, + labels: [label], + }) +} diff --git a/.github/workflows/backmerge.yml b/.github/workflows/backmerge.yml new file mode 100644 index 00000000..d8569f05 --- /dev/null +++ b/.github/workflows/backmerge.yml @@ -0,0 +1,114 @@ +# This workflow automatically merges `master` into `develop` whenever a +# new version release with a tag is published. It can also be triggered +# manually via workflow_dispatch for cases where an automatic backmerge +# is needed outside of the standard release process. +# If a merge conflict occurs, the workflow creates an issue to notify +# maintainers for manual resolution. + +name: Backmerge (master → develop) + +on: + release: + types: [published, prereleased] + workflow_dispatch: + +permissions: + contents: write + issues: write + +concurrency: + group: backmerge-master-into-develop + cancel-in-progress: false + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + backmerge: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout repository (for local actions) + uses: actions/checkout@v5 + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + repositories: ${{ github.event.repository.name }} + + - name: Checkout repository (with bot token) + uses: actions/checkout@v5 + with: + fetch-depth: 0 + token: ${{ steps.bot.outputs.token }} + + - name: Configure git identity + run: | + git config user.name "easyscience[bot]" + git config user.email "${{ vars.EASYSCIENCE_APP_ID }}+easyscience[bot]@users.noreply.github.com" + + - name: Set merge message + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + MESSAGE="Backmerge: master into develop (manual) [skip ci]" + else + TAG="${{ github.event.release.tag_name }}" + MESSAGE="Backmerge: master (${TAG}) into develop [skip ci]" + fi + + echo "MESSAGE=$MESSAGE" >> "$GITHUB_ENV" + echo "message=$MESSAGE" >> "$GITHUB_OUTPUT" + echo "📝 Merge message: $MESSAGE" | tee -a "$GITHUB_STEP_SUMMARY" + + - name: Prepare branches + run: | + git fetch origin master develop + git checkout -B develop origin/develop + + - name: Check if develop is already up-to-date + id: up_to_date + run: | + if git merge-base --is-ancestor origin/master develop; then + echo "value=true" >> "$GITHUB_OUTPUT" + echo "ℹ️ Develop is already up-to-date with master" | tee -a "$GITHUB_STEP_SUMMARY" + else + echo "value=false" >> "$GITHUB_OUTPUT" + fi + + - name: Try merge master into develop + id: merge + if: steps.up_to_date.outputs.value == 'false' + continue-on-error: true + run: | + if ! git merge origin/master --no-ff -m "${MESSAGE}"; then + echo "conflict=true" >> "$GITHUB_OUTPUT" + echo "❌ Backmerge conflict detected." | tee -a "$GITHUB_STEP_SUMMARY" + git status --porcelain || true + exit 0 + fi + + echo "conflict=false" >> "$GITHUB_OUTPUT" + echo "✅ Merge commit created." | tee -a "$GITHUB_STEP_SUMMARY" + + - name: Push to develop (if merge succeeded) + if: + steps.up_to_date.outputs.value == 'false' && steps.merge.outputs.conflict == + 'false' + run: | + git push origin develop + echo "🚀 Backmerge successful: master → develop" | tee -a "$GITHUB_STEP_SUMMARY" + + - name: Create issue (if merge failed with conflicts) + if: steps.merge.outputs.conflict == 'true' + uses: ./.github/actions/github-script + with: + github-token: ${{ steps.bot.outputs.token }} + script: | + const run = require('./.github/scripts/backmerge-conflict-issue.js') + await run({ github, context, core }) diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml new file mode 100644 index 00000000..d3ebf3a2 --- /dev/null +++ b/.github/workflows/cleanup.yml @@ -0,0 +1,89 @@ +# This workflow will delete old workflow runs based on the input +# parameters. +# https://github.com/Mattraks/delete-workflow-runs + +name: Old workflow runs cleanup + +on: + # Run monthly, at 00:00 on the 1st day of month. + schedule: + - cron: '0 0 1 * *' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + inputs: + days: + description: 'Number of days.' + required: true + default: 30 + minimum_runs: + description: 'The minimum runs to keep for each workflow.' + required: true + default: 6 + delete_workflow_pattern: + description: + 'The name or filename of the workflow. if not set then it will target all + workflows.' + required: false + delete_workflow_by_state_pattern: + description: + 'Remove workflow by state: active, deleted, disabled_fork, + disabled_inactivity, disabled_manually' + required: true + default: 'All' + type: choice + options: + - 'All' + - active + - deleted + - disabled_inactivity + - disabled_manually + delete_run_by_conclusion_pattern: + description: + 'Remove workflow by conclusion: action_required, cancelled, failure, skipped, + success' + required: true + default: 'All' + type: choice + options: + - 'All' + - action_required + - cancelled + - failure + - skipped + - success + dry_run: + description: 'Only log actions, do not perform any delete operations (dry run).' + required: false + default: 'false' + type: choice + options: + - 'false' + - 'true' + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + del-runs: + runs-on: ubuntu-latest + + permissions: + actions: write + + steps: + - name: Delete workflow runs + uses: Mattraks/delete-workflow-runs@v2 + with: + token: ${{ github.token }} + repository: ${{ github.repository }} + retain_days: ${{ github.event.inputs.days }} + keep_minimum_runs: ${{ github.event.inputs.minimum_runs }} + delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }} + delete_workflow_by_state_pattern: + ${{ github.event.inputs.delete_workflow_by_state_pattern }} + delete_run_by_conclusion_pattern: + ${{ github.event.inputs.delete_run_by_conclusion_pattern }} + dry_run: ${{ github.event.inputs.dry_run }} diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..1ad93139 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,99 @@ +name: Coverage checks + +on: + # Trigger the workflow on push to develop + push: + branches: + - develop + # Do not run on version tags (those are handled by other workflows) + tags-ignore: ['v*'] + # Trigger the workflow on pull request + pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Need permissions to trigger the dashboard build workflow +permissions: + actions: write + contents: read + +# Allow only one concurrent workflow per PR or branch ref. +# Cancel in-progress runs only for pull requests, but let branch push runs finish. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # Job 1: Run docstring coverage + docstring-coverage: + runs-on: ubuntu-latest + + steps: + - name: Check-out repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Run docstring coverage + run: pixi run docstring-coverage + + # Job 2: Run unit tests with coverage and upload to Codecov + unit-tests-coverage: + runs-on: ubuntu-latest + + steps: + - name: Check-out repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Run unit tests with coverage + run: pixi run unit-tests-coverage --cov-report=xml:coverage-unit.xml + + - name: Upload unit tests coverage to Codecov + if: ${{ !cancelled() }} + uses: ./.github/actions/upload-codecov + with: + name: unit-tests-job + flags: unittests + files: ./coverage-unit.xml + token: ${{ secrets.CODECOV_TOKEN }} + + # Job 2: Run integration tests with coverage and upload to Codecov + integration-tests-coverage: + runs-on: ubuntu-latest + + steps: + - name: Check-out repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Run integration tests with coverage + run: + pixi run integration-tests-coverage --cov-report=xml:coverage-integration.xml + + - name: Upload integration tests coverage to Codecov + if: ${{ !cancelled() }} + uses: ./.github/actions/upload-codecov + with: + name: integration-tests-job + flags: integration + files: ./coverage-integration.xml + token: ${{ secrets.CODECOV_TOKEN }} + + # Job 4: Build and publish dashboard (reusable workflow) + run-reusable-workflows: + needs: [docstring-coverage, unit-tests-coverage, integration-tests-coverage] # depend on the previous jobs + uses: ./.github/workflows/dashboard.yml + secrets: inherit diff --git a/.github/workflows/dashboard.yml b/.github/workflows/dashboard.yml new file mode 100644 index 00000000..68513427 --- /dev/null +++ b/.github/workflows/dashboard.yml @@ -0,0 +1,107 @@ +name: Dashboard build and publish + +on: + workflow_dispatch: + workflow_call: + +permissions: + contents: read + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + DEVELOP_BRANCH: develop + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + dashboard: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Install badgery + shell: bash + run: pixi add --pypi --git https://github.com/enhantica/badgery badgery + + - name: Run docstring coverage and code complexity/maintainability checks + run: | + for BRANCH in $DEFAULT_BRANCH $DEVELOP_BRANCH $CI_BRANCH; do + echo + echo "🔹🔸🔹🔸🔹 Processing branch $BRANCH 🔹🔸🔹🔸🔹" + if [ -d "../$BRANCH" ]; then + echo "Branch $BRANCH already processed, skipping" + continue + fi + + git worktree add ../$BRANCH origin/$BRANCH + mkdir -p reports/$BRANCH + + echo "Docstring coverage for branch $BRANCH" + pixi run interrogate -c pyproject.toml --fail-under=0 ../$BRANCH/src > reports/$BRANCH/coverage-docstring.txt + + echo "Cyclomatic complexity for branch $BRANCH" + pixi run radon cc -s -j ../$BRANCH/src > reports/$BRANCH/cyclomatic-complexity.json + + echo "Maintainability index for branch $BRANCH" + pixi run radon mi -j ../$BRANCH/src > reports/$BRANCH/maintainability-index.json + + echo "Raw metrics for branch $BRANCH" + pixi run radon raw -s -j ../$BRANCH/src > reports/$BRANCH/raw-metrics.json + done + + - name: Generate dashboard HTML + run: > + pixi run python -m badgery --config .badgery.yaml --repo ${{ github.repository + }} --branch ${{ env.CI_BRANCH }} --output index.html + + - name: Prepare publish directory + run: | + mkdir -p _dashboard_publish/${{ env.REPO_NAME }}/${{ env.CI_BRANCH }} + cp index.html _dashboard_publish/${{ env.REPO_NAME }}/${{ env.CI_BRANCH }} + + # Create GitHub App token for pushing to external dashboard repo. + # The 'repositories' parameter is required to grant access to repos + # other than the one where the workflow is running. + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + repositories: | + ${{ github.event.repository.name }} + dashboard + + # Publish to external dashboard repository with retry logic. + # Retry is needed to handle transient GitHub API/authentication issues + # that occasionally cause 403 errors when multiple workflows push concurrently. + # Uses personal_token (not github_token) as GITHUB_TOKEN cannot access external repos. + - name: Publish to main branch of ${{ github.repository }} + uses: Wandalen/wretry.action@v3.8.0 + with: + attempt_limit: 3 + attempt_delay: 15000 # 15 seconds between retries + action: peaceiris/actions-gh-pages@v4 + with: | + publish_dir: ./_dashboard_publish + keep_files: true + external_repository: ${{ env.REPO_OWNER }}/dashboard + publish_branch: master + personal_token: ${{ steps.bot.outputs.token }} + + - name: Add dashboard link to summary + run: | + URL="https://${{ env.REPO_OWNER }}.github.io/dashboard/${{ env.REPO_NAME }}/${{ env.CI_BRANCH }}" + echo "Dashboard link: [$URL]($URL)" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..b60bbe40 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,187 @@ +# This workflow builds and deploys documentation for the project. +# +# Overview: +# - Converts tutorial Python scripts to Jupyter notebooks and executes them. +# - Builds the documentation site using MkDocs with the Material theme. +# - Uploads the built site as an artifact for local inspection. +# - Deploys versioned documentation to the gh-pages branch using Mike: +# - For release tags (v*): deploys to a versioned folder (e.g., /0.9.1/) and updates /latest/. +# - For branches: deploys to /dev/. +# +# The action summary page will contain a link to the built artifact for downloading +# and inspecting, as well as a link to the deployed documentation site. + +name: Docs build and deployment + +on: + # Trigger the workflow on push + push: + # Selected branches + branches: [develop] # master and main are already verified in PR + # Runs on creating a new tag starting with 'v', e.g. 'v1.0.3' + tags: ['v*'] + # Trigger the workflow on pull request + pull_request: + # Selected branches + branches: [master, main, develop] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Allow only one concurrent deployment to gh-pages at a time. +# All docs workflows share the same concurrency group to prevent race conditions +# when multiple branches/tags trigger simultaneous deployments. +concurrency: + group: docs-gh-pages-deploy + cancel-in-progress: false + +# Set the environment variables to be used in all jobs defined in this workflow +env: + # CI_BRANCH - the branch name (used in mkdocs.yml) + # For PRs: github.head_ref is the source branch + # For pushes: github.ref_name is the branch + # For tags: github.ref_name is the tag name + # GITHUB_REPOSITORY - the repository name (used in mkdocs.yml) + # NOTEBOOKS_DIR - the directory containing the Jupyter notebooks (used in mkdocs.yml) + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + DEVELOP_BRANCH: develop + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + IS_RELEASE_TAG: ${{ startsWith(github.ref, 'refs/tags/v') }} + GITHUB_REPOSITORY: ${{ github.repository }} + NOTEBOOKS_DIR: tutorials + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # Single job that builds and deploys documentation. + # Uses macOS runner for consistent Plotly chart rendering. + build-deploy-docs: + runs-on: ubuntu-latest # macos-latest + + permissions: + contents: write # Required for pushing to the gh-pages branch + + steps: + # Setting DOCS_VERSION to be used in mkdocs.yml, and then in the + # main.html template. It defines the versioned docs subfolder name + # in the gh-pages branch. If it's a release tag, use the version + # number without the 'v' prefix, otherwise use 'dev'. + # Setting RELEASE_VERSION to be used in mkdocs.yml to show + # the latest release version in the index.md file. If it's a + # release tag, use the tag name, otherwise use the branch name + # for development builds. + - name: Set extra env variables + shell: bash + run: | + if [[ "${IS_RELEASE_TAG}" == "true" ]]; then + RELEASE_VERSION="${GITHUB_REF_NAME}" + DOCS_VERSION="${RELEASE_VERSION#v}" + else + RELEASE_VERSION="${CI_BRANCH}" + DOCS_VERSION="dev" + fi + echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "$GITHUB_ENV" + echo "DOCS_VERSION=${DOCS_VERSION}" >> "$GITHUB_ENV" + + # Check out the repository source code. + # Note: The gh-pages branch is fetched separately later for mike deployment. + - name: Checkout repository + uses: actions/checkout@v5 + + # Activate dark mode to create documentation with Plotly charts in dark mode + # Need a better solution to automatically switch the chart colour theme based on the mkdocs material switcher + # Something similar to mkdocs_plotly_plugin https://haoda-li.github.io/mkdocs-plotly-plugin/, + # but for generating documentation from notepads + #- name: Activate dark mode + # run: | + # brew install dark-mode + # dark-mode status + # dark-mode on + # dark-mode status + + # Set up the pixi package manager and install dependencies from pixi.toml. + # Uses frozen lockfile to ensure reproducible builds. + - name: Set up pixi + uses: ./.github/actions/setup-pixi + # Pre-import the main package to exclude info messages from the docs + # E.g., Matplotlib may print messages to stdout/stderr when first + # imported. This step allows to avoid "Matplotlib is building the font + # cache" messages during notebook execution. + - name: Pre-build site step + run: pixi run python -c "import EasyApplication" + + # Prepare the Jupyter notebooks for documentation (strip output, etc.). + - name: Prepare notebooks + run: pixi run notebook-prepare + + # Execute all Jupyter notebooks to generate output cells (plots, tables, etc.). + # Uses multiple cores for parallel execution to speed up the process. + - name: Run notebooks + # if: false # Temporarily disabled to speed up the docs build + run: pixi run notebook-exec + + # Build the static files for the documentation site for local inspection + # Input: docs/ directory containing the Markdown files + # Output: site/ directory containing the generated HTML files + - name: Build site for local check + run: pixi run docs-build-local + + # Upload the static files from the site/ directory to be used for + # local check + - name: Upload built site as artifact + uses: ./.github/actions/upload-artifact + with: + name: site-local_easyapplication-lib-${{ env.RELEASE_VERSION }} + path: docs/site/ + + # Create GitHub App token for pushing to gh-pages as easyscience[bot]. + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + # Configure git identity and remote URL so mike pushes as easyscience[bot]. + - name: Configure git for pushing + run: | + set -euo pipefail + git config user.name "easyscience[bot]" + git config user.email "${{ vars.EASYSCIENCE_APP_ID }}+easyscience[bot]@users.noreply.github.com" + git remote set-url origin "https://x-access-token:${{ steps.bot.outputs.token }}@github.com/${{ github.repository }}.git" + + # Fetch the gh-pages branch to ensure mike has the latest remote state. + # This is required because the checkout step only fetches the source branch, + # not the gh-pages branch that mike needs to update. + - name: Fetch gh-pages branch + run: | + git fetch origin gh-pages:gh-pages 2>/dev/null || true + + # Deploy versioned documentation using mike (MkDocs plugin for versioning). + # - For release tags (v*): deploys to versioned folder (e.g., /0.9.1/) and aliases to /latest/. + # - For branches: deploys to /dev/. + # The "${RELEASE_VERSION#v}" syntax strips the 'v' prefix (v0.9.1 -> 0.9.1). + # Also sets 'latest' as the default version for the version selector. + - name: Rebuild and deploy docs with mike + run: | + # Exit on error (-e), undefined vars (-u), and pipeline failures (pipefail) + set -euo pipefail + + REPO_NAME="${{ github.event.repository.name }}" + BASE_URL="https://easyscience.github.io/${REPO_NAME}" + + # Deploy the release version and update the "latest" alias + if [[ "${IS_RELEASE_TAG}" == "true" ]]; then + pixi run docs-deploy-pre "${RELEASE_VERSION#v}" latest + pixi run docs-set-default-pre latest + DEPLOYMENT_URL="${BASE_URL}/latest" + + # Deploy/update the "dev" alias (or whatever your convention is) + else + pixi run docs-deploy-pre dev + DEPLOYMENT_URL="${BASE_URL}/dev" + + fi + + # Add links to the action summary page for easy access + echo "🔗 deployment url [${DEPLOYMENT_URL}](${DEPLOYMENT_URL})" >> "${GITHUB_STEP_SUMMARY}" diff --git a/.github/workflows/issues-labels.yml b/.github/workflows/issues-labels.yml new file mode 100644 index 00000000..ed9d1c8b --- /dev/null +++ b/.github/workflows/issues-labels.yml @@ -0,0 +1,56 @@ +# Verifies if an issue has at least one of the `[scope]` and one of the +# `[priority]` labels. If not, the bot adds labels with a warning emoji +# to indicate that those labels need to be added. + +name: Issue labels check + +on: + issues: + types: [opened, labeled, unlabeled] + +permissions: + issues: write + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + check-labels: + if: github.actor != 'easyscience[bot]' + + runs-on: ubuntu-latest + + concurrency: + group: issue-labels-${{ github.event.issue.number }} + cancel-in-progress: true + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + - name: Check for required [scope] label + uses: trstringer/require-label-prefix@v1 + with: + secret: ${{ steps.bot.outputs.token }} + prefix: '[scope]' + labelSeparator: ' ' + addLabel: true + defaultLabel: '[scope] ⚠️ label needed' + + - name: Check for required [priority] label + uses: trstringer/require-label-prefix@v1 + with: + secret: ${{ steps.bot.outputs.token }} + prefix: '[priority]' + labelSeparator: ' ' + addLabel: true + defaultLabel: '[priority] ⚠️ label needed' diff --git a/.github/workflows/lint-format.yml b/.github/workflows/lint-format.yml new file mode 100644 index 00000000..720c9a4a --- /dev/null +++ b/.github/workflows/lint-format.yml @@ -0,0 +1,127 @@ +# The workflow checks +# - the validity of pyproject.toml, +# - the presence and correctness of SPDX license headers, +# - linting and formatting of Python code, +# - linting and formatting of docstrings in Python code, +# - formatting of non-Python files (like markdown and toml). +# - linting of Python code in Jupyter notebooks (for library template). +# +# A summary of the checks is added to the GitHub Actions summary. + +name: Lint and format checks + +on: + # Trigger the workflow on push + push: + branches-ignore: [master, main] # Already verified in PR + # Do not run this workflow on creating a new tag starting with + # 'v', e.g. 'v1.0.3' (see publish-pypi.yml) + tags-ignore: ['v*'] + # Trigger the workflow on pull request + pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Allow only one concurrent workflow, skipping runs queued between the run +# in-progress and latest queued. And cancel in-progress runs. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + lint-format: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Run post-install developer steps + run: pixi run post-install + + - name: Check validity of pyproject.toml + id: pyproject + continue-on-error: true + shell: bash + run: pixi run pyproject-check + + - name: Check SPDX license headers + id: license_headers + continue-on-error: true + shell: bash + run: pixi run license-check + + - name: Check linting of Python code + id: py_lint + continue-on-error: true + shell: bash + run: pixi run py-lint-check + + - name: Check formatting of Python code + id: py_format + continue-on-error: true + shell: bash + run: pixi run py-format-check + + - name: Check linting of docstrings in Python code + id: docstring_lint + continue-on-error: true + shell: bash + run: pixi run docstring-lint-check + + - name: Check formatting of non-Python files (md, toml, etc.) + id: nonpy_format + continue-on-error: true + shell: bash + run: pixi run nonpy-format-check + + - name: Check linting of Python code in Jupyter notebooks (ipynb) + id: notebook_lint + continue-on-error: true + shell: bash + run: pixi run notebook-lint-check + + # Add summary + - name: Add quality checks summary + if: always() + shell: bash + run: | + { + echo "## 🧪 Checks Summary" + echo "" + echo "| Check | Status |" + echo "|-------|--------|" + echo "| pyproject.toml | ${{ steps.pyproject.outcome == 'success' && '✅' || '❌' }} |" + echo "| license headers | ${{ steps.license_headers.outcome == 'success' && '✅' || '❌' }} |" + echo "| py lint | ${{ steps.py_lint.outcome == 'success' && '✅' || '❌' }} |" + echo "| py format | ${{ steps.py_format.outcome == 'success' && '✅' || '❌' }} |" + echo "| docstring lint | ${{ steps.docstring_lint.outcome == 'success' && '✅' || '❌' }} |" + echo "| nonpy format | ${{ steps.nonpy_format.outcome == 'success' && '✅' || '❌' }} |" + echo "| notebooks lint | ${{ steps.notebook_lint.outcome == 'success' && '✅' || '❌' }} |" + } >> "$GITHUB_STEP_SUMMARY" + + # Fail job if any check failed + - name: Fail job if any check failed + if: | + steps.pyproject.outcome == 'failure' + || steps.license_headers.outcome == 'failure' + || steps.py_lint.outcome == 'failure' + || steps.py_format.outcome == 'failure' + || steps.docstring_lint.outcome == 'failure' + || steps.nonpy_format.outcome == 'failure' + || steps.notebook_lint.outcome == 'failure' + shell: bash + run: exit 1 diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml new file mode 100644 index 00000000..642cd318 --- /dev/null +++ b/.github/workflows/pr-labels.yml @@ -0,0 +1,56 @@ +# Verifies if a pull request has at least one label from a set of valid +# labels before it can be merged. +# +# NOTE: +# This workflow may be triggered twice in quick succession when a PR is +# created: +# 1) `opened` — when the pull request is initially created +# 2) `labeled` — if labels are added immediately after creation +# (e.g. by manual labeling, another workflow, or GitHub App). +# +# These are separate GitHub events, so two workflow runs can be started. + +name: PR labels check + +on: + pull_request_target: + types: [opened, labeled, unlabeled, synchronize] + +permissions: + pull-requests: read + +jobs: + check-labels: + runs-on: ubuntu-latest + + steps: + - name: Check for valid labels + run: | + PR_LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r '.[]') + + echo "Current PR labels: $PR_LABELS" + VALID_LABELS=( + "[bot] release" + "[scope] bug" + "[scope] documentation" + "[scope] enhancement" + "[scope] maintenance" + "[scope] significant" + ) + + found=false + for label in "${VALID_LABELS[@]}"; do + if echo "$PR_LABELS" | grep -Fxq "$label"; then + echo "✅ Found valid label: $label" + found=true + break + fi + done + + if [ "$found" = false ]; then + echo "ERROR: PR must have at least one of the following labels:" + for label in "${VALID_LABELS[@]}"; do + echo " - $label" + done + exit 1 + fi diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml new file mode 100644 index 00000000..b03a4859 --- /dev/null +++ b/.github/workflows/pypi-publish.yml @@ -0,0 +1,51 @@ +# Builds a Python package and publish it to PyPI when a new tag is +# created. + +name: PyPI publishing + +on: + # Runs on creating a new tag starting with 'v', e.g. 'v1.0.3' + push: + tags: ['v*'] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + pypi-publish: + runs-on: ubuntu-latest + + permissions: + contents: read + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + + steps: + - name: Check-out repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 # full history with tags to get the version number by versioningit + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + # Build the Python package (to dist/ folder) + - name: Create Python package + run: pixi run default-build + + # Publish the package to PyPI (from dist/ folder) + # Instead of publishing with personal access token, we use + # GitHub Actions OIDC to get a short-lived token from PyPI. + # New publisher must be previously configured in PyPI at + # https://pypi.org/manage/project/EasyApplication/settings/publishing/ + # Use the following data: + # Owner: easyscience + # Repository name: gui-components + # Workflow name: pypi-publish.yml + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: 'dist' diff --git a/.github/workflows/pypi-test.yml b/.github/workflows/pypi-test.yml new file mode 100644 index 00000000..6c3cb94e --- /dev/null +++ b/.github/workflows/pypi-test.yml @@ -0,0 +1,83 @@ +name: PyPI package tests + +on: + # Run daily, at 00:00. + schedule: + - cron: '0 0 * * *' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Allow only one concurrent workflow, skipping runs queued between the run +# in-progress and latest queued. And cancel in-progress runs. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # Job 1: Test installation from PyPI on multiple OS + pypi-package-tests: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + with: + environments: '' + activate-environment: '' + run-install: false + frozen: false + + - name: Init pixi project + run: pixi init EasyApplication + + - name: Set the minimum system requirements + working-directory: EasyApplication + run: pixi project system-requirements add macos 14.0 + + - name: Add Python 3.14 from Conda + working-directory: EasyApplication + run: pixi add "python=3.14" + + - name: Add other Conda dependencies + working-directory: EasyApplication + run: pixi add gsl + + - name: Add EasyApplication (with dev dependencies) from PyPI + working-directory: EasyApplication + run: pixi add --pypi "EasyApplication[dev]" + + - name: Run unit tests to verify the installation + working-directory: EasyApplication + run: pixi run python -m pytest ../tests/unit/ --color=yes -v + + - name: Run functional tests to verify the installation + working-directory: EasyApplication + run: pixi run python -m pytest ../tests/functional/ --color=yes -v + + - name: Run integration tests to verify the installation + working-directory: EasyApplication + run: pixi run python -m pytest ../tests/integration/ --color=yes -n auto + + # Job 2: Build and publish dashboard (reusable workflow) + run-reusable-workflows: + needs: pypi-package-tests # depend on previous job + uses: ./.github/workflows/dashboard.yml + secrets: inherit diff --git a/.github/workflows/release-notes.yml b/.github/workflows/release-notes.yml new file mode 100644 index 00000000..cdc0330c --- /dev/null +++ b/.github/workflows/release-notes.yml @@ -0,0 +1,76 @@ +# Drafts your next Release notes as pull requests are merged into +# default branch + +name: Release draft update + +on: + # Runs on pushes targeting the default branch (updates the real draft release) + push: + branches: [master, main] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + draft-release-notes: + permissions: + # write permission is required to create a github release + contents: write + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 # full history with tags to get the version number + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + - name: Drafts the next release notes + id: draft + uses: enhantica/drafterino@v2 + with: + config: | + title: 'easyapplication $COMPUTED_VERSION' + tag: 'v$COMPUTED_VERSION' + note-template: '- $PR_TITLE (#$PR_NUMBER)' + + default-bump: post + + major-bump-labels: ['[scope] significant'] + minor-bump-labels: ['[scope] enhancement'] + patch-bump-labels: ['[scope] bug', '[scope] maintenance'] + post-bump-labels: ['[scope] documentation'] + + release-notes: + - title: 'Added' + labels: ['[scope] significant', '[scope] enhancement'] + - title: 'Fixed' + labels: ['[scope] bug'] + - title: 'Changed' + labels: ['[scope] maintenance', '[scope] documentation'] + env: + GITHUB_TOKEN: ${{ steps.bot.outputs.token }} + + - name: Create GitHub draft release + uses: softprops/action-gh-release@v2 + with: + draft: true + tag_name: ${{ steps.draft.outputs.tag_name }} + name: ${{ steps.draft.outputs.release_name }} + body: ${{ steps.draft.outputs.release_notes }} + env: + GITHUB_TOKEN: ${{ steps.bot.outputs.token }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml new file mode 100644 index 00000000..5694a2a0 --- /dev/null +++ b/.github/workflows/release-pr.yml @@ -0,0 +1,58 @@ +# This workflow creates an automated release PR from a source branch into the default branch. +# +# Usage: +# - Triggered manually via workflow_dispatch. +# - Creates a PR titled "Release: merge into ". +# - Adds the label "[bot] release" so it is excluded from changelogs. +# - The PR body makes clear that this is automation only (no review needed). + +name: 'Release PR (develop → master)' + +on: + workflow_dispatch: + inputs: + source_branch: + description: 'Source branch to create PR from' + required: false + default: 'develop' + type: string + +permissions: + contents: read + pull-requests: write + +env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + SOURCE_BRANCH: ${{ inputs.source_branch || 'develop' }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + create-pull-request: + runs-on: ubuntu-latest + steps: + - name: Checkout ${{ env.SOURCE_BRANCH }} branch + uses: actions/checkout@v5 + with: + ref: ${{ env.SOURCE_BRANCH }} + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + - name: Create PR from ${{ env.SOURCE_BRANCH }} to ${{ env.DEFAULT_BRANCH }} + env: + GH_TOKEN: ${{ steps.bot.outputs.token }} + run: | + gh pr create \ + --base ${{ env.DEFAULT_BRANCH }} \ + --head ${{ env.SOURCE_BRANCH }} \ + --title "Release: merge ${{ env.SOURCE_BRANCH }} into ${{ env.DEFAULT_BRANCH }}" \ + --label "[bot] release" \ + --body "This PR is created automatically to trigger the release pipeline. It merges the accumulated changes from \`${{ env.SOURCE_BRANCH }}\` into \`${{ env.DEFAULT_BRANCH }}\`. + + ⚠️ It is labeled \`[bot] release\` and is excluded from release notes and version bump logic." diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 00000000..a53e9afc --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,98 @@ +# Code scanning (CodeQL) for vulnerabilities and insecure coding patterns. +# +# What this workflow does +# - Runs GitHub CodeQL analysis and uploads results to your repository's Security tab. +# - Triggers on PRs (so findings appear as PR checks) and on pushes to `develop`. +# - Runs on a weekly schedule. +# +# Where to find results on GitHub +# - Repository → Security → Code scanning alerts +# (You can filter by tool = CodeQL and by branch.) +# +# Where to configure on GitHub +# - Repository → Settings → Advanced Security +# Enable "GitHub Advanced Security" (if available) and configure CodeQL there. +# - Repository → Security → Code scanning alerts +# This page shows findings produced by this workflow. +# +# Notes about the scheduled run +# - Scheduled workflows are triggered from the repository's *default branch*. +# If your default branch is `master` but you want the scheduled scan to analyze +# `develop`, this workflow checks out `develop` explicitly for scheduled runs. +# +# References +# - CodeQL Action: https://github.com/github/codeql-action +# - Advanced setup docs: https://docs.github.com/en/code-security/code-scanning + +name: Security scans with CodeQL + +on: + # Run on pull requests so results show up as PR checks and code + # scanning alerts. + pull_request: + branches: [master, main, develop] + + # Run on pushes (e.g., after merging PRs). + push: + branches: [master, main, develop] + + # Run weekly. (Cron is in UTC.) + schedule: + - cron: '0 3 * * 1' + +permissions: + contents: read + security-events: write + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + codeql: + name: Code scanning + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Keep this list tight to avoid noise and speed up runs. + language: [python, actions] + + steps: + # Scheduled workflows run from the default branch. + # We explicitly analyze `develop` on the schedule to keep the scan + # focused on the active dev branch. + - name: Checkout repository (scheduled → develop) + if: ${{ github.event_name == 'schedule' }} + uses: actions/checkout@v5 + with: + ref: develop + + - name: Checkout repository + if: ${{ github.event_name != 'schedule' }} + uses: actions/checkout@v5 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + + print-link: + name: Print results link + runs-on: ubuntu-latest + + needs: codeql + permissions: {} # no special perms needed just to print links + + steps: + - name: Add Code Scanning link to job summary + run: | + echo "## 🔎 CodeQL Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "View Code Scanning alerts here:" >> $GITHUB_STEP_SUMMARY + echo "${{ github.server_url }}/${{ github.repository }}/security/code-scanning" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test-trigger.yml b/.github/workflows/test-trigger.yml new file mode 100644 index 00000000..f4a39e93 --- /dev/null +++ b/.github/workflows/test-trigger.yml @@ -0,0 +1,45 @@ +name: Scheduled code tests trigger + +on: + # Run daily, at 00:00. + schedule: + - cron: '0 0 * * *' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + code-tests-trigger: + runs-on: ubuntu-latest + + steps: + - name: Checkout develop branch + uses: actions/checkout@v5 + with: + ref: develop + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + - name: Dispatch code tests workflow + uses: ./.github/actions/github-script + with: + github-token: ${{ steps.bot.outputs.token }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: "test.yml", + ref: "develop" + }); diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..313d9552 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,305 @@ +# This is the main workflow for testing the code before and after +# packaging it. +# The workflow is divided into three jobs: +# 1. env-prepare: +# - Prepare the environment for testing +# 2. source-test: +# - Test the code base against the latest code in the repository +# - Create the Python package +# - Upload the Python package for the next job +# 3. package-test: +# - Download the Python package (including extra files) from the previous job +# - Install the downloaded Python package +# - Test the code base against the installed package +# 4. dashboard-build-trigger: +# - Trigger the dashboard build workflow to update the code quality +# metrics on the dashboard + +name: Code and package tests + +on: + # Trigger the workflow on push + push: + branches-ignore: [master, main] # Already verified in PR + # But do not run this workflow on creating a new tag starting with + # 'v', e.g. 'v1.0.3' (see publish-pypi.yml) + tags-ignore: ['v*'] + # Trigger the workflow on pull request + pull_request: + branches: ['**'] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Need permissions to trigger the dashboard build workflow +permissions: + actions: write + contents: read + +# Allow only one concurrent workflow, skipping runs queued between the run +# in-progress and latest queued. And cancel in-progress runs. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + PY_VERSIONS: '3.12 3.14' + PIXI_ENVS: 'py-312-env py-314-env' + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # Job 1: Set up environment variables + env-prepare: + runs-on: [ubuntu-latest] + + outputs: + pytest-marks: ${{ steps.set-mark.outputs.pytest_marks }} + + steps: + # Determine if integration tests should be run fully or only the fast ones + # (to save time on branches other than master and develop) + - name: Set mark for integration tests + id: set-mark + run: | + if [[ "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then + echo "pytest_marks=" >> $GITHUB_OUTPUT + else + echo "pytest_marks=-m fast" >> $GITHUB_OUTPUT + fi + + # Job 2: Test code + source-test: + needs: env-prepare # depend on previous job + + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, macos-15, windows-2022] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + with: + environments: ${{ env.PIXI_ENVS }} + + - name: Run unit tests + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env + + echo "Running tests in environment: $env" + pixi run --environment $env unit-tests + done + + - name: Run functional tests + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env + + echo "Running tests in environment: $env" + pixi run --environment $env functional-tests + done + + - name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }} + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env + + echo "Running tests in environment: $env" + pixi run --environment $env integration-tests ${{ needs.env-prepare.outputs.pytest-marks }} + done + + # Delete all local tags when not on a tagged commit to force versioningit + # to fall back to the configured default-tag, which is '999.0.0' in our case. + # This is needed for testing the package in the next job, as its version + # must be higher than the PyPI version for pip to prefer the local version. + - name: Force using versioningit default tag (non tagged release) + if: startsWith(github.ref , 'refs/tags/v') != true + run: git tag --delete $(git tag) + + - name: Build package wheels for all Python versions + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.11 -> py-311-env + + echo "Building wheel in environment: $env" + pixi run --environment $env dist-build + + echo "Moving built wheel to dist/py$py_ver/" + pixi run mkdir -p dist/py$py_ver + pixi run mv dist/*.whl dist/py$py_ver/ + done + + - name: Remove Python cache files before uploading + shell: bash + run: pixi run clean-pycache + + # More than one file/dir need to be specified in 'path', to preserve the + # structure of the dist/ directory, not only its contents. + - name: Upload package (incl. extras) for next job + uses: ./.github/actions/upload-artifact + with: + name: easyapplication_${{ matrix.os }}_${{ runner.arch }} + path: dist/ + + # Job 3: Test the package + package-test: + needs: source-test # depend on previous job + + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, macos-15, windows-2022] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Download package (incl. extras) from previous job + uses: ./.github/actions/download-artifact + with: + # name and path should be taken from the upload step of the previous job + name: easyapplication_${{ matrix.os }}_${{ runner.arch }} + path: dist/ + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + with: + environments: '' + activate-environment: '' + run-install: false + frozen: false + + - name: Install EasyApplication from the built wheel + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + echo "Initializing pixi project" + pixi init EasyApplication_py$py_ver + cd EasyApplication_py$py_ver + + echo "Adding Python $py_ver" + pixi add "python=$py_ver" + + echo "Setting macOS 14.0 as minimum required" + pixi project system-requirements add macos 14.0 + + echo "Looking for wheel in ../dist/py$py_ver/" + ls -l "../dist/py$py_ver/" + + whl_path=(../dist/"py$py_ver"/*.whl) + if [[ ! -f "${whl_path[0]}" ]]; then + echo "❌ No wheel found in ../dist/py$py_ver/" + exit 1 + fi + + whl_url="file://$(python -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "${whl_path[0]}")" + + echo "Adding EasyApplication from: $whl_url" + pixi add --pypi "EasyApplication[dev] @ ${whl_url}" + + echo "Exiting pixi project directory" + cd .. + done + + - name: Run unit tests + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + echo "Entering pixi project directory EasyApplication_py$py_ver" + cd EasyApplication_py$py_ver + + echo "Running tests" + pixi run python -m pytest ../tests/unit/ --color=yes -v + + echo "Exiting pixi project directory" + cd .. + done + + - name: Run functional tests + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + echo "Entering pixi project directory EasyApplication_py$py_ver" + cd EasyApplication_py$py_ver + + echo "Running tests" + pixi run python -m pytest ../tests/functional/ --color=yes -v + + echo "Exiting pixi project directory" + cd .. + done + + - name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }} + shell: bash + run: | + set -euo pipefail + + for py_ver in $PY_VERSIONS; do + echo + echo "🔹🔸🔹🔸🔹 Python: $py_ver 🔹🔸🔹🔸🔹" + + echo "Entering pixi project directory EasyApplication_py$py_ver" + cd EasyApplication_py$py_ver + + echo "Running tests" + pixi run python -m pytest ../tests/integration/ --color=yes -n auto -v ${{ needs.env-prepare.outputs.pytest-marks }} + + echo "Exiting pixi project directory" + cd .. + done + + # Job 4: Build and publish dashboard (reusable workflow) + run-reusable-workflows: + needs: package-test # depend on previous job + uses: ./.github/workflows/dashboard.yml + secrets: inherit diff --git a/.github/workflows/tutorial-tests-trigger.yml b/.github/workflows/tutorial-tests-trigger.yml new file mode 100644 index 00000000..f28d6527 --- /dev/null +++ b/.github/workflows/tutorial-tests-trigger.yml @@ -0,0 +1,45 @@ +name: Scheduled tutorial tests trigger + +on: + # Run daily, at 00:00. + schedule: + - cron: '0 0 * * *' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + +# Opt into Node.js 24 for all JavaScript actions. +# Remove once all referenced actions natively target Node 24. +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + tutorial-tests-trigger: + runs-on: ubuntu-latest + + steps: + - name: Checkout develop branch + uses: actions/checkout@v5 + with: + ref: develop + + - name: Setup easyscience[bot] + id: bot + uses: ./.github/actions/setup-easyscience-bot + with: + app-id: ${{ vars.EASYSCIENCE_APP_ID }} + private-key: ${{ secrets.EASYSCIENCE_APP_KEY }} + + - name: Dispatch tutorial tests workflow + uses: ./.github/actions/github-script + with: + github-token: ${{ steps.bot.outputs.token }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: "tutorial-tests.yml", + ref: "develop" + }); diff --git a/.github/workflows/tutorial-tests.yml b/.github/workflows/tutorial-tests.yml new file mode 100644 index 00000000..66ff6921 --- /dev/null +++ b/.github/workflows/tutorial-tests.yml @@ -0,0 +1,63 @@ +name: Tutorial tests + +on: + # Trigger the workflow on push + push: + # Selected branches + branches: [develop] # master and main are already verified in PR + # Trigger the workflow on pull request + pull_request: + branches: ['**'] + # Trigger the workflow on workflow_call (to be called from other workflows) + # Needed, as standard schedule triggers the master branch only, but we want + # to run this workflow on develop branch. + workflow_call: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + +# Allow only one concurrent workflow, skipping runs queued between the run +# in-progress and latest queued. And cancel in-progress runs. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +# Set the environment variables to be used in all jobs defined in this workflow +env: + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + # Opt into Node.js 24 for all JavaScript actions. + # Remove once all referenced actions natively target Node 24. + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + # Job 1: Test tutorials as scripts and notebooks on multiple OS + tutorial-tests: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up pixi + uses: ./.github/actions/setup-pixi + + - name: Prepare notebooks + shell: bash + run: pixi run notebook-prepare + + - name: Test tutorials as notebooks + shell: bash + run: pixi run notebook-tests + + # Job 2: Build and publish dashboard (reusable workflow) + run-reusable-workflows: + needs: tutorial-tests # depend on previous job + uses: ./.github/workflows/dashboard.yml + secrets: inherit diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 38d48eb2..a5b4578c 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -125,9 +125,9 @@ jobs: - name: Upload the zipped wasm folder uses: actions/upload-artifact@v4 with: - name: wasm # name of the zip file to be created and uploaded - path: build/wasm # directory whose content is to be zipped - compression-level: 0 # no compression + name: wasm # name of the zip file to be created and uploaded + path: build/wasm # directory whose content is to be zipped + compression-level: 0 # no compression if-no-files-found: error - name: Push the built wasm to the webapp branch @@ -136,4 +136,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_API_PERSONAL_ACESS_TOKEN }} REPO: self BRANCH: webapp - FOLDER: build/wasm # directory whose content is to be pushed + FOLDER: build/wasm # directory whose content is to be pushed diff --git a/.gitignore b/.gitignore index cebd2acc..6dc595c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,46 +1,39 @@ -# Qt Creator -*.autosave +# Python +__pycache__/ +.venv/ +.coverage +.pyc + +# Pixi +.pixi/ + +# PyInstaller +dist/ +build/ +*.spec -# Qt Creator Qml +# MkDocs +docs/site/ + +# Jupyter Notebooks +.ipynb_checkpoints + +# Node +node_modules/ + +# QtCreator +*.autosave *.qmlproject.user *.qmlproject.user.* - -# Qt Creator Python *.pyproject.user *.pyproject.user.* - -# Qt Creator C++ -*.pro.user -*.pro.user.* - -# Qt Creator CMake CMakeLists.txt.user* -# VS Code -.vscode/ - # PyCharm .idea/ -# Fortran -fort.1 - -# Python -__pycache__ -.venv -.coverage -.pyc - -# Poetry -dist -*.egg-info - -# PyInstaller -build -*.spec - -# Jupyter -.ipynb_checkpoints +# VS Code +.vscode/ # macOS .DS_Store @@ -48,9 +41,6 @@ build *.dmg # Misc -..* +.cache/ *.log *.zip -settings.ini* -temp.cif -.ci/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..9a3855f4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,61 @@ +repos: + - repo: local + hooks: + # ------------- + # Manual checks + # ------------- + - id: pixi-pyproject-check + name: pixi run pyproject-check + entry: pixi run pyproject-check + language: system + pass_filenames: false + stages: [manual] + + - id: license-headers-check + name: pixi run license-check + entry: pixi run license-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-py-lint-check + name: pixi run py-lint-check + entry: pixi run py-lint-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-py-format-check + name: pixi run py-format-check + entry: pixi run py-format-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-docstring-lint-check + name: pixi run docstring-lint-check + entry: pixi run docstring-lint-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-nonpy-format-check + name: pixi run nonpy-format-check + entry: pixi run nonpy-format-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-notebook-lint-check + name: pixi run notebook-lint-check + entry: pixi run notebook-lint-check + language: system + pass_filenames: false + stages: [manual] + + - id: pixi-unit-tests + name: pixi run unit-tests + entry: pixi run unit-tests + language: system + pass_filenames: false + stages: [manual] diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..71d6c650 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,36 @@ +# Git +.git/ + +# Copier +.copier-answers*.yml + +# Pixi +.pixi +pixi.lock + +# MkDocs +docs/overrides/ +docs/site/ +docs/docs/assets/ + +# Python +.pytest_cache/ + +# MyPy +.mypy_cache/ + +# Ruff +.ruff_cache/ + +# Node +node_modules + +# Minified files +*.min.js +*.min.css + +# Misc +.benchmarks +.cache +deps/ +tmp/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..0476c549 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,446 @@ +# Contributing to EasyApplication + +Thank you for your interest in contributing to **EasyApplication**! + +This guide explains how you can: + +- Report issues +- Contribute code +- Improve documentation +- Suggest enhancements +- Interact with the EasyScience community + +Whether you are an experienced developer or contributing for the first +time, this document walks you through the entire process step by step. + +Please make sure you follow the EasyScience organization-wide +[Code of Conduct](https://github.com/easyscience/.github/blob/master/CODE_OF_CONDUCT.md). + +--- + +## Table of Contents + +- [How to Interact With This Project](#how-to-interact-with-this-project) +- [1. Understanding the Development Model](#1-understanding-the-development-model) +- [2. Getting the Code](#2-getting-the-code) +- [3. Setting Up the Development Environment](#3-setting-up-the-development-environment) +- [4. Creating a Branch](#4-creating-a-branch) +- [5. Implementing Your Changes](#5-implementing-your-changes) +- [6. Code Quality Checks](#6-code-quality-checks) +- [7. Opening a Pull Request](#7-opening-a-pull-request) +- [8. Continuous Integration (CI)](#8-continuous-integration-ci) +- [9. Code Review](#9-code-review) +- [10. Documentation Contributions](#10-documentation-contributions) +- [11. Reporting Issues](#11-reporting-issues) +- [12. Security Issues](#12-security-issues) +- [13. Releases](#13-releases) + +--- + +## How to Interact With This Project + +If you are not planning to contribute code, you may want to: + +- 🐞 Report a bug — see [Reporting Issues](#11-reporting-issues) +- 🛡 Report a security issue — see + [Security Issues](#12-security-issues) +- 💬 Ask a question or start a discussion at + [Project Discussions](https://github.com/easyscience/gui-components/discussions) + +If you plan to contribute code or documentation, continue below. + +--- + +## 1. Understanding the Development Model + +Before you start coding, it is important to understand how development +works in this project. + +### Branching Strategy + +We use the following branches: + +- `master` — stable releases only +- `develop` — active development branch +- Short-lived branches — feature or fix branches created for a single + contribution and deleted after merge + +> [!IMPORTANT] +> +> All normal contributions must target the `develop` branch. +> +> - Do **not** open Pull Requests against `master` +> - Always create your branch from `develop` +> - Always target `develop` when opening a Pull Request + +See ADR easyscience/.github#12 for more details on the branching +strategy. + +--- + +## 2. Getting the Code + +### 2.1. If You Are an External Contributor + +If you are not a core maintainer of this repository, follow these steps. + +1. Open the repository page: + `https://github.com/easyscience/gui-components` + +2. Click the **Fork** button (top-right corner). This creates your own + copy of the repository. + +3. Clone your fork locally: + + ```bash + git clone https://github.com//gui-components.git + cd gui-components + ``` + +4. Add the original repository as `upstream`: + + ```bash + git remote add upstream https://github.com/easyscience/gui-components.git + ``` + +5. Switch to the `develop` branch and update it: + + ```bash + git fetch upstream + git checkout develop + git pull upstream develop + ``` + +If you have contributed before, make sure your local `develop` branch is +up to date before starting new work. You can update it with: + +```bash +git fetch upstream +git pull upstream develop +``` + +This ensures you are working on the latest version of the project. + +### 2.2. If You Are a Core Team Member + +Core team members can create branches directly in this repository and +therefore do not need to fork it, but the rest of the workflow remains +the same. + +--- + +## 3. Setting Up the Development Environment + +You need: + +- Git +- Pixi + +EasyScience projects use **Pixi** to manage the development environment. + +To install Pixi, follow the official instructions: +https://pixi.prefix.dev/latest/installation/ + +You do **not** need to manually install Python. Pixi automatically: + +- Creates the correct Python environment +- Installs all required dependencies +- Installs development tools (linters, formatters, test tools) + +Set up the environment: + +```bash +pixi install +pixi run post-install # Install additional tooling +``` + +After this step, your development environment is ready. + +See ADR easyscience/.github#63 for more details about using Pixi for +development. + +--- + +## 4. Creating a Branch + +Never work directly on `develop`. + +Create a new branch: + +```bash +git checkout -b my-change develop +``` + +> [!IMPORTANT] +> +> Use a clear and descriptive name, for example: +> +> - `improve-solver-speed` +> - `fix-boundary-condition` +> - `add-tutorial-example` + +Clear branch names make reviews and history easier to understand. + +--- + +## 5. Implementing Your Changes + +While developing, make small, logical commits with clear messages. + +Example: + +```bash +git add . +git commit -m "Improve performance of time integrator for large systems" +``` + +--- + +## 6. Code Quality Checks + +> [!IMPORTANT] +> +> When adding new functionality or making changes, make sure to add or +> update the following as needed: +> +> - 📘 docstrings +> - 🧪 unit tests + +Before opening a Pull Request, always run: + +```bash +pixi run check +``` + +This command: + +- Validates the pyproject.toml file +- Checks for licence headers in code files +- Identifies linting and formatting issues in Python code +- Checks docstring linting and formatting issues in Python code +- Detects formatting issues in non-Python files (MD, YAML, TOML etc.) +- Checks linting issues in Jupyter notebooks (if applicable) +- Runs unit tests + +A successful run should look like this: + +```bash +pixi run pyproject-check.......................Passed +pixi run license-check.........................Passed +pixi run py-lint-check.........................Passed +pixi run py-format-check.......................Passed +pixi run docstring-lint-check..................Passed +pixi run nonpy-format-check....................Passed +pixi run notebook-lint-check...................Passed +pixi run unit-tests............................Passed +``` + +If something fails, read the error message carefully and fix the issue. + +You can run individual checks, for example, to run only unit tests: + +```bash +pixi run unit-tests +``` + +or to run only Python linting checks: + +```bash +pixi run py-lint-check +``` + +Some formatting issues can be fixed automatically: + +```bash +pixi run fix +``` + +If everything is correctly formatted, you will see: + +```text +✅ All auto-formatting steps completed successfully! +``` + +This indicates that the auto-formatting pipeline completed successfully. +If you do not see this message and no error messages appear, try running +the command again. + +If errors are reported, resolve them and re-run: + +```bash +pixi run check +``` + +> [!IMPORTANT] +> +> All checks must pass before your Pull Request can be merged. + +If you are unsure how to fix an issue, ask for help in your Pull Request +discussion. + +--- + +## 7. Opening a Pull Request + +Push your branch: + +```bash +git push origin my-change +``` + +On GitHub: + +- Click **Compare & Pull Request** +- Ensure the base branch is `develop` +- Write a clear and concise title +- Add a description explaining what changed and why +- Add the required `[scope]` label + +### Pull Request Title + +> [!IMPORTANT] +> +> The PR title appears in release notes and changelogs. It should be +> concise and informative. + +Good examples: + +- Improve performance of time integrator for large systems +- Fix incorrect boundary condition handling in solver +- Add adaptive step-size control to ODE solver +- Add tutorial for custom model configuration +- Refactor solver API for improved readability + +### Required `[scope]` Label + +> [!IMPORTANT] +> +> Each Pull Request must include a `[scope]` label, which is used for +> automatically suggesting version bumps when preparing a new release. + +The available scopes are: + +| Label | Description | +| ----------------------- | ----------------------------------------------------------------------- | +| `[scope] bug` | Bug report or fix (major.minor.**PATCH**) | +| `[scope] documentation` | Documentation-only changes (major.minor.patch.**POST**) | +| `[scope] enhancement` | Adds or improves features (major.**MINOR**.patch) | +| `[scope] maintenance` | Code/tooling cleanup without feature or bug fix (major.minor.**PATCH**) | +| `[scope] significant` | Breaking or major changes (**MAJOR**.minor.patch) | + +See ADR easyscience/.github#33 for more details on the standardized +labeling scheme. + +--- + +## 8. Continuous Integration (CI) + +After opening a Pull Request: + +- Automated checks run automatically +- You will see green checkmarks or red crosses + +If checks fail: + +1. Open the failing check +2. Read the logs +3. Fix the issue locally +4. Run `pixi run check` +5. Push your changes + +The Pull Request updates automatically. + +--- + +## 9. Code Review + +All Pull Requests are reviewed by at least one core team member. + +Code review is collaborative and aims to improve quality. + +Do not take comments personally — they are meant to help. + +To update your PR: + +```bash +git add . +git commit -m "Address review comments" +git push +``` + +--- + +## 10. Documentation Contributions + +> [!IMPORTANT] +> +> If your change affects user-facing functionality, update the project +> documentation accordingly — specifically the `nav:` (navigation) +> structure in `mkdocs.yml` and the relevant documentation Markdown +> files in `docs/docs/`. +> +> ```text +> 📁 docs +> ├── 📁 docs - Markdown files for documentation +> │ └── ... +> └── 📄 mkdocs.yml - Configuration file (navigation, theme, etc.) +> ``` + +This may include: + +- API documentation +- Examples +- Tutorials +- Jupyter notebooks + +Preview documentation locally: + +```bash +pixi run docs-serve +``` + +Open the URL shown in the terminal to review your changes. + +--- + +## 11. Reporting Issues + +If you find a bug but cannot work on a fix, please consider opening an +issue. + +When reporting an issue, it helps to: + +- Search existing issues first. +- Provide clear reproduction steps. +- Include logs, screenshots, and environment details. + +Clear and detailed reports help maintainers investigate and resolve +issues more effectively. + +--- + +## 12. Security Issues + +> [!IMPORTANT] +> +> Please do **not** report security vulnerabilities publicly. + +If you discover a potential vulnerability, please contact the +maintainers privately so the issue can be investigated and addressed +responsibly. + +--- + +## 13. Releases + +Once your contribution is merged into `develop`, it will eventually be +included in the next stable release. + +When enough changes have accumulated in `develop`, core team members +merge `develop` into `master` to prepare a new release. The release is +then tagged and published on GitHub and PyPI. + +--- + +Thank you for contributing to EasyApplication and the EasyScience +ecosystem! diff --git a/EXAMPLES.md b/EXAMPLES.md index 14f2bf93..6c59df26 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -1,6 +1,9 @@ ## Types of examples -Different types of examples are given here. All examples have a graphical frontend implemented in QML, but differ in the way the backend logic is implemented and the runtime used to run them. These examples can be categorised as shown in the following table: +Different types of examples are given here. All examples have a +graphical frontend implemented in QML, but differ in the way the backend +logic is implemented and the runtime used to run them. These examples +can be categorised as shown in the following table: | Example | Type | Frontend | Backend | Runtime | | -------------- | ---- | -------- | -------- | -------------------- | @@ -14,29 +17,29 @@ Different types of examples are given here. All examples have a graphical fronte ### Python environment -* Create and activate a python environment (_optional_) +- Create and activate a python environment (_optional_) - ***macOS and Linux*** + **_macOS and Linux_** ``` python3 -m venv .venv source .venv/bin/activate ``` - ***Windows*** + **_Windows_** ``` python3 -m venv .venv .venv\Scripts\activate ``` -* Upgrade PIP, the package installer for Python (_optional_) +- Upgrade PIP, the package installer for Python (_optional_) ``` pip install --upgrade pip ``` -* Install the Qt for Python `PySide6` package using PIP +- Install the Qt for Python `PySide6` package using PIP ``` pip install 'PySide6>=6.8,<6.9' @@ -46,65 +49,98 @@ Different types of examples are given here. All examples have a graphical fronte #### Qt Creator -Qt Creator is a prefered IDE for developing the GUI in QML. It allows to run QML code in debug mode with breakpoints, preview changes to QML code in live mode, has build in documentation for QML modules, has QML code auto-completion, and more unique feature related to the QML code. - -* Download Qt Online Installer from [qt.io](https://www.qt.io/download-qt-installer-oss). More info at [doc.qt.io](https://doc.qt.io/qt-6/qt-online-installation.html). -* Install Qt for desktop development using a custom installation that includes the following components: - * Qt - * [ ] Qt 6.8.z - * [x] Desktop (***macOS***) or MSVC 2019 64-bit (***Windows***) - * [ ] Additional Libraries - * [x] Qt Charts - * [x] Qt Shader Tools - * [ ] Developer and Designer Tools - * [x] Qt Creator x.y.z +Qt Creator is a prefered IDE for developing the GUI in QML. It allows to +run QML code in debug mode with breakpoints, preview changes to QML code +in live mode, has build in documentation for QML modules, has QML code +auto-completion, and more unique feature related to the QML code. + +- Download Qt Online Installer from + [qt.io](https://www.qt.io/download-qt-installer-oss). More info at + [doc.qt.io](https://doc.qt.io/qt-6/qt-online-installation.html). +- Install Qt for desktop development using a custom installation that + includes the following components: + - Qt + - [ ] Qt 6.8.z + - [x] Desktop (**_macOS_**) or MSVC 2019 64-bit (**_Windows_**) + - [ ] Additional Libraries + - [x] Qt Charts + - [x] Qt Shader Tools + - [ ] Developer and Designer Tools + - [x] Qt Creator x.y.z #### VS Code (_alternative to Qt Creator_) -VS Code is an alternative IDE to Qt Creator. It has a syntax highlighting plugin for QML code, but lacks some of the unique features of Qt Creator mentioned above to make QML development easier. +VS Code is an alternative IDE to Qt Creator. It has a syntax +highlighting plugin for QML code, but lacks some of the unique features +of Qt Creator mentioned above to make QML development easier. -* Download an install VS Code -* Add the python extension -* The initial launch configuration is in the `.vscode/launch.json` file, which should be automatically read by VS Code -* Select any python file in the repo and choose the desired python environment +- Download an install VS Code +- Add the python extension +- The initial launch configuration is in the `.vscode/launch.json` file, + which should be automatically read by VS Code +- Select any python file in the repo and choose the desired python + environment ## How to run ### Type I Examples: BasicQml (QML runtime with QML backend) -This example is located in `examples/BasicQml` and the source code is in the subfolder `src/BasicQml`. The example consists of a graphical QML frontend (`Gui/Application.qml`) and a QML backend (`Logic/Mock/BackendProxy.qml`). It is considered a mock backend as it only returns hardcoded values rather than providing the required functionality. The entry point for Qt is `main.qml`, which can be displayed using Qt `qml` viewer. +This example is located in `examples/BasicQml` and the source code is in +the subfolder `src/BasicQml`. The example consists of a graphical QML +frontend (`Gui/Application.qml`) and a QML backend +(`Logic/Mock/BackendProxy.qml`). It is considered a mock backend as it +only returns hardcoded values rather than providing the required +functionality. The entry point for Qt is `main.qml`, which can be +displayed using Qt `qml` viewer. #### Run using the QML Runtime ##### Run via the Qt Creator IDE -* Run Qt Creator -* Open the qml project file from the example folder `examples/BasicQml/src/BasicQml.qmlproject` -* Click Run (Green play button) +- Run Qt Creator +- Open the qml project file from the example folder + `examples/BasicQml/src/BasicQml.qmlproject` +- Click Run (Green play button) #### How to edit GUI elements in live mode -* In Qt Creator, select the `*.qml` file to be edited in live mode -* Click the `Design` button at the top of the left sidebar of `Qt Creator` - * _Note: If this button is disabled, find and click `About plugins...` in the `Qt Creator` menu, scroll down to the `Qt Quick` section and enable `QmlDesigner`._ -* In the `Design` window, click the `Show Live Preview` button in the top panel of the application (small play button in a circle). - * _Note: Showing the entire `main.qml` application window in live mode works best when the open `main.qml` is moved to another monitor and does not overlap with the `Qt Creator` window_. -* When the desired GUI component appears, you can click the `Edit` button at the top of the left sidebar of `Qt Creator` to return to the source code of that qml component and still see it live in a separate window. +- In Qt Creator, select the `*.qml` file to be edited in live mode +- Click the `Design` button at the top of the left sidebar of + `Qt Creator` + - _Note: If this button is disabled, find and click `About plugins...` + in the `Qt Creator` menu, scroll down to the `Qt Quick` section and + enable `QmlDesigner`._ +- In the `Design` window, click the `Show Live Preview` button in the + top panel of the application (small play button in a circle). + - _Note: Showing the entire `main.qml` application window in live mode + works best when the open `main.qml` is moved to another monitor and + does not overlap with the `Qt Creator` window_. +- When the desired GUI component appears, you can click the `Edit` + button at the top of the left sidebar of `Qt Creator` to return to the + source code of that qml component and still see it live in a separate + window. ### Type II Examples: BasicPy (Python runtime with QML backend) -This example is in the `examples/BasicPy` folder, and the source code is in the `examples/BasicPy/src/BasicPy` folder. This example serves to demonstrate how an application with a QML frontend and QML backend (similar to the Type I example) can be run from Python. The entry point for the Python application is the `main.py` file. To run it, follow the steps below: +This example is in the `examples/BasicPy` folder, and the source code is +in the `examples/BasicPy/src/BasicPy` folder. This example serves to +demonstrate how an application with a QML frontend and QML backend +(similar to the Type I example) can be run from Python. The entry point +for the Python application is the `main.py` file. To run it, follow the +steps below: #### Run using the Python interpreter ##### Run from the terminal -* Go to the example folder, e.g., +- Go to the example folder, e.g., ```sh $ cd examples/BasicPy/src/BasicPy ``` -* Run using Python (provided that the required python environment is activated as explained above) + +- Run using Python (provided that the required python environment is + activated as explained above) ```sh $ python main.py @@ -112,27 +148,41 @@ This example is in the `examples/BasicPy` folder, and the source code is in the ##### Run via the Qt Creator IDE (_alternative to run from the terminal_) -* Run Qt Creator -* Open the python project file from the example folder `examples/BasicPy/src/BasicPy.pyproject` -* Select the desired python environment with the Qt `PySide6` module installed -* Click Run (Green play button) +- Run Qt Creator +- Open the python project file from the example folder + `examples/BasicPy/src/BasicPy.pyproject` +- Select the desired python environment with the Qt `PySide6` module + installed +- Click Run (Green play button) ##### Run via the VS Code IDE (_alternative to run from the terminal or via the Qt Creator IDE_) -* Open the repo in VS Code -* Click on the debug extension and select which example to execute -![Debug dropdown window](resources/images/vscode_debug.jpg) +- Open the repo in VS Code +- Click on the debug extension and select which example to execute + ![Debug dropdown window](resources/images/vscode_debug.jpg) ### Type III Examples: IntermediatePy and AdvancedPy (Python runtime with Python backend) -These examples demonstrate how to use the Python runtime to run the QML GUI binded with the Python backend located in `Backends/real_backend.py`. These examples can be run through Python in the same way as Type II described above. In these examples, the Python-based backend is registered in `main.py` and then imported into QML. The Qt QML GUI then accesses the backend by calling the properties and methods of the classes defined in the `Backends/real_py` folder. +These examples demonstrate how to use the Python runtime to run the QML +GUI binded with the Python backend located in +`Backends/real_backend.py`. These examples can be run through Python in +the same way as Type II described above. In these examples, the +Python-based backend is registered in `main.py` and then imported into +QML. The Qt QML GUI then accesses the backend by calling the properties +and methods of the classes defined in the `Backends/real_py` folder. #### Possible Issues -* If in Qt Creator some components are highlighted and marked as "Unknown component. (M300)", try resetting via "Tools > QML/JS > Reset Code Model". +- If in Qt Creator some components are highlighted and marked as + "Unknown component. (M300)", try resetting via "Tools > QML/JS > Reset + Code Model". ### Type IV Examples: BasicC++ (QML backend) -This example can be run after compilation into an executable program. It only has a mock backend in QML (the C++ backend is not implemented). The minimum configuration requires a base `main.cpp` file and, if Qt Creator is used as the IDE, a `*.pro` file. +This example can be run after compilation into an executable program. It +only has a mock backend in QML (the C++ backend is not implemented). The +minimum configuration requires a base `main.cpp` file and, if Qt Creator +is used as the IDE, a `*.pro` file. -This example is currently used to create a WebAssembly application that can be run inside a web browser. +This example is currently used to create a WebAssembly application that +can be run inside a web browser. diff --git a/LICENSE b/LICENSE index 056a3c1e..c4e3e48e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,6 @@ BSD 3-Clause License -Copyright (c) 2024, EasyApp contributors (https://github.com/easyscience/EasyApp). -All rights reserved. +Copyright (c) 2021-2026 EasyScience contributors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index f519aa85..413b7359 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,51 @@ - +

+ + + + + + + EasyApplication + +

-EasyApp is a collection of Qt QML graphical components which allows one to quickly create cross-platform applications with an eye-catching and intuitive graphical interface based on the [EasyScience](http://github.com/EasyScience) framework. +**EasyApplication** is a collection of Qt/QML graphical components to +create cross-platform applications with intuitive graphical interface +based on the EasyScience framework. -* Website: https://app.easyscience.software -* Source code: https://github.com/EasyScience/EasyApp -* Bug reports: https://github.com/EasyScience/EasyApp/issues + -EasyApp is currently being used as the basis for the graphical interface in the following projects: +**EasyApplication** is developed as a Python library. -* [EasyDiffraction](http://github.com/EasyScience/EasyDiffraction) -* [EasyReflectometry](http://github.com/EasyScience/EasyReflectometry) -* [EasyTexture](http://github.com/EasyScience/EasyTextureApp) +License: +[BSD 3-Clause](https://github.com/easyscience/easyapp/blob/master/LICENSE) -More simple examples of how to use EasyApp are described in [EXAMPLES.md](https://github.com/EasyScience/EasyApp/blob/master/EXAMPLES.md) and presented in the project [examples](https://github.com/EasyScience/EasyApp/tree/master/examples) directory: +License: +[BSD 3-Clause](https://github.com/easyscience/gui-components/blob/master/LICENSE) -* [BasicQml](https://github.com/EasyScience/EasyApp/tree/master/examples/BasicQml) -* [BasicPy](https://github.com/EasyScience/EasyApp/tree/master/examples/BasicPy) -* [BasicC++](https://github.com/EasyScience/EasyApp/tree/master/examples/BasicC++) -* [IntermediatePy](https://github.com/EasyScience/EasyApp/tree/master/examples/IntermediatePy) -* [AdvancedPy](https://github.com/EasyScience/EasyApp/tree/master/examples/AdvancedPy) +## Useful Links -If you want to see what EasyApp looks like, you can try the web demo based on the [BasicC++](https://github.com/EasyScience/EasyApp/tree/master/examples/BasicC++) example at https://easyscience.github.io/EasyApp/BasicC++.html. +### For Users + +- 📖 + [Documentation](https://easyscience.github.io/gui-components/latest) +- 🚀 + [Getting Started](https://easyscience.github.io/gui-components/latest/introduction) +- 🧪 + [Tutorials](https://easyscience.github.io/gui-components/latest/tutorials) +- 💬 + [Get in Touch](https://easyscience.github.io/gui-components/latest/introduction/#get-in-touch) +- 🧾 + [Citation](https://easyscience.github.io/gui-components/latest/introduction/#citation) + +### For Contributors + +- 🧑‍💻 [Source Code](https://github.com/easyscience/gui-components) +- 🐞 + [Issue Tracker](https://github.com/easyscience/gui-components/issues) +- 💡 + [Discussions](https://github.com/easyscience/gui-components/discussions) +- 🤝 + [Contributing Guide](https://github.com/easyscience/gui-components/blob/master/CONTRIBUTING.md) +- 🛡 + [Code of Conduct](https://github.com/easyscience/.github/blob/master/CODE_OF_CONDUCT.md) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..f62b13ab --- /dev/null +++ b/codecov.yml @@ -0,0 +1,13 @@ +# Codecov configuration +# https://docs.codecov.com/docs/codecovyml-reference + +coverage: + status: + project: + default: + # Make project coverage informational (won't block PR) + informational: true + patch: + default: + # Require patch coverage but with threshold + threshold: 1% diff --git a/docs/docs/api-reference/index.md b/docs/docs/api-reference/index.md new file mode 100644 index 00000000..87933712 --- /dev/null +++ b/docs/docs/api-reference/index.md @@ -0,0 +1,8 @@ +--- +icon: material/code-braces-box +--- + +# :material-code-braces-box: API Reference + +This section contains the reference detailing the functions and modules +available in EasyApplication. diff --git a/docs/docs/assets/images/favicon.png b/docs/docs/assets/images/favicon.png new file mode 100644 index 00000000..27628988 Binary files /dev/null and b/docs/docs/assets/images/favicon.png differ diff --git a/docs/docs/assets/images/logo_dark.svg b/docs/docs/assets/images/logo_dark.svg new file mode 100644 index 00000000..766608a9 --- /dev/null +++ b/docs/docs/assets/images/logo_dark.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + Logo + + + Main circle + + + + + + + + + + + + + + + + Text + + + + + \ No newline at end of file diff --git a/docs/docs/assets/images/logo_light.svg b/docs/docs/assets/images/logo_light.svg new file mode 100644 index 00000000..ab2547d9 --- /dev/null +++ b/docs/docs/assets/images/logo_light.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + Logo + + + Main circle + + + + + + + + + + + + + + + + Text + + + + + \ No newline at end of file diff --git a/docs/docs/assets/javascripts/extra.js b/docs/docs/assets/javascripts/extra.js new file mode 100644 index 00000000..9596ee07 --- /dev/null +++ b/docs/docs/assets/javascripts/extra.js @@ -0,0 +1,27 @@ +;(function () { + 'use strict' + + // Variables + const header = document.getElementsByTagName('header')[0] + + console.log(window.pageYOffset) + + // Hide-show header shadow + function toggleHeaderShadow() { + if (window.pageYOffset <= 0) { + header.classList.remove('md-header--shadow') + } else { + header.classList.add('md-header--shadow') + } + } + + // Onload + window.onload = function () { + toggleHeaderShadow() + } + + // Onscroll + window.onscroll = function () { + toggleHeaderShadow() + } +})() diff --git a/docs/docs/assets/javascripts/mathjax.js b/docs/docs/assets/javascripts/mathjax.js new file mode 100644 index 00000000..333524ec --- /dev/null +++ b/docs/docs/assets/javascripts/mathjax.js @@ -0,0 +1,33 @@ +window.MathJax = { + tex: { + //inlineMath: [['\\(', '\\)']], + //displayMath: [['\\[', '\\]']], + // Add support for $...$ and \(...\) delimiters + inlineMath: [ + ['$', '$'], + ['\\(', '\\)'], + ], + // Add support for $$...$$ and \[...]\ delimiters + displayMath: [ + ['$$', '$$'], + ['\\[', '\\]'], + ], + processEscapes: true, + processEnvironments: true, + }, + options: { + //ignoreHtmlClass: ".*|", + //processHtmlClass: "arithmatex" + // Skip code blocks only + skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'], + // Only ignore explicit opt-out + ignoreHtmlClass: 'no-mathjax|tex2jax_ignore', + }, +} + +document$.subscribe(() => { + MathJax.startup.output.clearCache() + MathJax.typesetClear() + MathJax.texReset() + MathJax.typesetPromise() +}) diff --git a/docs/docs/assets/stylesheets/extra.css b/docs/docs/assets/stylesheets/extra.css new file mode 100644 index 00000000..a625be80 --- /dev/null +++ b/docs/docs/assets/stylesheets/extra.css @@ -0,0 +1,359 @@ +/*************/ +/* Variables */ +/*************/ + +:root { + --sz-link-color--lightmode: #0184c7; + --sz-hovered-link-color--lightmode: #37bdf9; + --sz-body-background-color--lightmode: #fafafa; + --sz-body-text-color--lightmode: #525252; + --sz-body-heading-color--lightmode: #434343; + --sz-code-background-color--lightmode: #ececec; + + --sz-link-color--darkmode: #37bdf9; + --sz-hovered-link-color--darkmode: #2890c0; + --sz-body-background-color--darkmode: #262626; + --sz-body-text-color--darkmode: #a3a3a3; + --sz-body-heading-color--darkmode: #e5e5e5; + --sz-code-background-color--darkmode: #212121; +} + +/****************/ +/* Color styles */ +/****************/ + +/* Default styles https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/main/_typeset.scss */ + +/* Light mode */ + +/* Default light mode https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/main/_colors.scss */ + +[data-md-color-scheme="default"] { + + /* Primary color shades */ + --md-primary-fg-color: var(--sz-body-background-color--lightmode); /* Navigation background */ + --md-primary-bg-color: var(--sz-body-text-color--lightmode); /* E.g., Header title and icons */ + --md-primary-bg-color--light: var(--sz-body-text-color--lightmode); /* E.g., Header search */ + + /* Accent color shades */ + --md-accent-fg-color: var(--sz-hovered-link-color--lightmode); /* E.g., Hovered `a` elements & copy icon in code */ + + /* Default color shades */ + --md-default-fg-color: var(--sz-body-text-color--lightmode); + --md-default-fg-color--light: var(--sz-body-heading-color--lightmode); /* E.g., `h1` color & TOC viewed items & `$` in code */ + --md-default-fg-color--lighter: var(--sz-body-text-color--lightmode); /* E.g., `¶` sign near `h1-h8` */ + --md-default-fg-color--lightest: var(--sz-body-text-color--lightmode); /* E.g., Copy icon in code */ + --md-default-bg-color: var(--sz-body-background-color--lightmode); + + /* Code color shades */ + --md-code-bg-color: var(--sz-code-background-color--lightmode); + + /* Typeset color shades */ + --md-typeset-color: var(--sz-body-text-color--lightmode); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--sz-link-color--lightmode); + + /* Footer color shades */ + --md-footer-fg-color: var(--sz-body-text-color--lightmode); /* E.g., Next -> */ + --md-footer-fg-color--light: var(--sz-body-text-color--lightmode); /* E.g., © 2022 EasyDiffraction, Material for MkDocs */ + --md-footer-fg-color--lighter: var(--sz-body-text-color--lightmode); /* E.g. Made with */ + --md-footer-bg-color: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., Next -> */ + --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., © 2022 EasyDiffraction */ + + /* Custom colors */ + --sz-red-color: #F44336; + --sz-blue-color: #03A9F4; + --sz-green-color: #4CAF50; + --sz-orange-color: #FF9800; + + /* Logo display */ + --md-footer-logo-dark-mode: none; + --md-footer-logo-light-mode: block; +} + +/* Dark mode */ + +/* Default dark mode: https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/palette/_scheme.scss */ + +[data-md-color-scheme="slate"] { + + /* Primary color shades */ + --md-primary-fg-color: var(--sz-body-background-color--darkmode); /* Navigation background */ + --md-primary-bg-color: var(--sz-body-text-color--darkmode); /* E.g., Header title and icons */ + --md-primary-bg-color--light: var(--sz-body-text-color--darkmode); /* E.g., Header search */ + + /* Accent color shades */ + --md-accent-fg-color: var(--sz-hovered-link-color--darkmode); /* E.g., Hovered `a` elements & copy icon in code */ + + /* Default color shades */ + --md-default-fg-color: var(--sz-body-text-color--darkmode); + --md-default-fg-color--light: var(--sz-body-heading-color--darkmode); /* E.g., `h1` color & TOC viewed items & `$` in code */ + --md-default-fg-color--lighter: var(--sz-body-text-color--darkmode); /* E.g., `¶` sign near `h1-h8` */ + --md-default-fg-color--lightest: var(--sz-body-text-color--darkmode); /* E.g., Copy icon in code */ + --md-default-bg-color: var(--sz-body-background-color--darkmode); + + /* Code color shades */ + --md-code-bg-color: var(--sz-code-background-color--darkmode); + + /* Typeset color shades */ + --md-typeset-color: var(--sz-body-text-color--darkmode); + + /* Typeset `a` color shades */ + --md-typeset-a-color: var(--sz-link-color--darkmode); + + /* Footer color shades */ + --md-footer-fg-color: var(--sz-body-text-color--darkmode); /* E.g., Next -> */ + --md-footer-fg-color--light: var(--sz-body-text-color--darkmode); /* E.g., © 2022 EasyDiffraction, Material for MkDocs */ + --md-footer-fg-color--lighter: var(--sz-body-text-color--darkmode); /* E.g. Made with */ + --md-footer-bg-color: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., Next -> */ + --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.0); /* Space with, e.g., © 2022 EasyDiffraction */ + + /* Custom colors */ + --sz-red-color: #EF9A9A; + --sz-blue-color: #81D4FA; + --sz-green-color: #A5D6A7; + --sz-orange-color: #FFCC80; + + /* Logo display */ + --md-footer-logo-dark-mode: block; + --md-footer-logo-light-mode: none; +} + +/*****************/ +/* Custom styles */ +/*****************/ + +/* Logo */ + +#logo_light_mode { + display: var(--md-footer-logo-light-mode); +} + +#logo_dark_mode { + display: var(--md-footer-logo-dark-mode); +} + +/* Customize default styles of MkDocs Material */ + +/* Hide navigation title */ +label.md-nav__title[for="__drawer"] { + height: 0; +} + +/* Hide site title (first topic) while keeping page title and version selector */ +.md-header__topic:first-child .md-ellipsis { + display: none; +} + +/* Increase logo size */ +.md-logo :is(img, svg) { + height: 1.8rem !important; +} + +/* Hide GH repo with counts (top right page corner) */ +.md-header__source { + display: none; +} + +/* Hide GH repo with counts (navigation bar in mobile view) */ +.md-nav__source { + display: none; +} + +/* Ensure all horizontal lines in the navigation list are removed or hidden */ +.md-nav__item { + /* Removes any border starting from the second level */ + border: none !important; + /* Modifies the background color to hide the first horizontal line */ + background-color: var(--md-default-bg-color); +} + +/* Increase TOC (on the right) width */ +.md-nav--secondary { + margin-left: -10px; + margin-right: -4px; +} + +/* */ +.md-nav__item > .md-nav__link { + padding-left: 0.5em; /* Default */ +} + +/* Change line height of the tabel cells */ +.md-typeset td, +.md-typeset th { + line-height: 1.25 !important; +} + +/* Change vertical alignment of the icon inside the tabel cells */ +.md-typeset td .twemoji { + vertical-align: sub !important; +} + +/* Change the width of the primary sidebar */ +/* +.md-sidebar--primary { + width: 240px; +} +*/ + +/* Change the overall width of the page */ +.md-grid { + max-width: 1280px; +} + +/* Needed for mkdocs-jupyter to show download and other buttons on top of the notebook */ +.md-content__button { + position: relative !important; +} + +/* Background color of the search input field */ +.md-search__input { + background-color: var(--md-code-bg-color) !important; +} + +/* Customize default style of mkdocs-jupyter plugin */ + +/* Set the width of the notebook to fill 100% and not reduce by the width of .md-content__button's +Adjust the margins and paddings to fit the defaults in MkDocs Material and do not crop the label in the header +*/ +.jupyter-wrapper { + width: 100% !important; + display: flex !important; +} + +.jp-Notebook { + padding: 0 !important; + margin-top: -3em !important; + + /* Ensure notebook content stretches across the page */ + width: 100% !important; + max-width: 100% !important; + + /* mkdocs-material + some notebook HTML end up as flex */ + align-items: stretch !important; +} + +.jp-Notebook .jp-Cell { + /* Key: flex children often need min-width: 0 to prevent weird shrink */ + width: 100% !important; + max-width: 100% !important; + min-width: 0 !important; + + /* Removes jupyter cell paddings */ + padding-left: 0 !important; +} + +/* Removes jupyter cell prefixes, like In[123]: */ +.prompt, +.jp-InputPrompt, +.jp-OutputPrompt { + display: none !important; +} + +/* Removes jupyter output cell padding to align with input cell text */ +.jp-RenderedText { + padding-left: 0.85em !important; +} + +/* Extra styling the panda dataframes, on top of the style included in the code */ +table.dataframe { + float: left; + margin-left: 0.75em !important; + margin-bottom: 0.5em !important; + font-size: var(--jp-code-font-size) !important; + color: var(--md-primary-bg-color) !important; + /* Allow table cell wrapping in MkDocs-Jupyter outputs */ + /* + table-layout: auto !important; + width: auto !important; + */ +} + +/* Allow wrap for the last column */ +/* +table.dataframe td:last-child, +table.dataframe th:last-child { + white-space: normal !important; + word-break: break-word !important; +} +*/ + +/* Custom styles for the CIF files */ + +.cif { + padding-left: 1em; + padding-right: 1em; + padding-top: 1px; + padding-bottom: 1px; + background-color: var(--md-code-bg-color); + font-size: small; +} +.red { + color: var(--sz-red-color); +} +.green { + color: var(--sz-green-color); +} +.blue { + color: var(--sz-blue-color); +} +.orange { + color: var(--sz-orange-color); +} +.grey { + color: grey; +} + +/**********/ +/* Labels */ +/**********/ + +.label-cif { + padding-top: 0.5ex; + padding-bottom: 0.5ex; + padding-left: 0.9ex; + padding-right: 0.9ex; + border-radius: 1ex; + color: var(--md-default-fg-color) !important; + background-color: var(--md-code-bg-color); +} + +p .label-cif, li .label-cif { + vertical-align: 5%; + font-size: 12px; +} + +.label-cif:hover { + color: white !important; +} + +.label-experiment { + padding-top: 0.25ex; + padding-bottom: 0.6ex; + padding-left: 0.9ex; + padding-right: 0.9ex; + border-radius: 1ex; + color: var(--md-default-fg-color) !important; + background-color: rgba(55, 189, 249, 0.1); +} + +p .label-experiment, li .label-experiment { + vertical-align: 5%; + font-size: 12px; +} + +h1 .label-experiment { + padding-top: 0.05ex; + padding-bottom: 0.4ex; + padding-left: 0.9ex; + padding-right: 0.9ex; + border-radius: 0.75ex; + color: var(--md-default-fg-color) !important; + background-color: rgba(55, 189, 249, 0.1); +} + +.label-experiment:hover { + color: white !important; +} diff --git a/docs/docs/index.md b/docs/docs/index.md new file mode 100644 index 00000000..5f267d9f --- /dev/null +++ b/docs/docs/index.md @@ -0,0 +1,21 @@ +![](assets/images/logo_dark.svg#gh-dark-mode-only)![](assets/images/logo_light.svg#gh-light-mode-only) + +# Qt/QML components for building graphical applications + +Here is a brief overview of the main documentation sections: + +- [:material-information-slab-circle: Introduction](introduction/index.md) + – Provides a description of EasyApplication, including its purpose, + licensing, latest release details, and contact information. +- [:material-cog-box: Installation & Setup](installation-and-setup/index.md) + – Guides users through system requirements, environment configuration, + and the installation process. +- [:material-book-open-variant: User Guide](user-guide/index.md) – + Covers core concepts, key terminology, workflow steps, and essential + parameters for effective use of EasyApplication. +- [:material-school: Tutorials](tutorials/index.md) – Offers practical, + step-by-step examples demonstrating common workflows and data analysis + tasks. +- [:material-code-braces-box: API Reference](api-reference/index.md) – + An auto-generated reference detailing the available functions and + modules in EasyApplication. diff --git a/docs/docs/installation-and-setup/index.md b/docs/docs/installation-and-setup/index.md new file mode 100644 index 00000000..ce61fd48 --- /dev/null +++ b/docs/docs/installation-and-setup/index.md @@ -0,0 +1,285 @@ +--- +icon: material/cog-box +--- + +# :material-cog-box: Installation & Setup + +**EasyApplication** is a cross-platform Python library compatible with +**Python 3.12** through **3.14**. + +To install and set up EasyApplication, we recommend using +[**Pixi**](https://pixi.prefix.dev), a modern package manager for +Windows, macOS, and Linux. + +??? note "Main benefits of using Pixi" + + - **Ease of use**: Pixi simplifies the installation process, making it + accessible even for users with limited experience in package management. + - **Python version control**: Pixi allows specifying and managing different + Python versions for each project, ensuring compatibility. + - **Isolated environments**: Pixi creates isolated environments for each + project, preventing conflicts between different package versions. + - **PyPI and Conda support**: Pixi can install packages from both PyPI and + Conda repositories, providing access to a wide range of libraries. + +An alternative installation method using the traditional **pip** package +manager is also provided. + +## Installing with Pixi recommended { #installing-with-pixi data-toc-label="Installing with Pixi" } + +This section describes the simplest way to set up EasyApplication using +**Pixi**. + +#### Installing Pixi + +- Install Pixi by following the instructions on the + [official Pixi Installation Guide](https://pixi.prefix.dev/latest/installation). + +#### Setting up EasyApplication with Pixi + + + +- Choose a project location (local drive recommended). + + ??? warning ":fontawesome-brands-windows: Windows + OneDrive" + + We **do not recommend creating a Pixi project inside OneDrive or other + synced folders**. + + By default, Pixi creates the virtual environment inside the project + directory (in `.pixi/`). On Windows, synced folders such as OneDrive + may cause file‑system issues (e.g., path-length limitations or + restricted link operations), which can lead to unexpected install + errors or environments being recreated. + + Instead, create your project in a **local directory on your drive** + where you have full write permissions. + + + +- Initialize a new Pixi project and navigate into it: + ```txt + pixi init EasyApplication + cd EasyApplication + ``` +- Set the Python version for the Pixi environment (e.g., 3.14): + ```txt + pixi add python=3.14 + ``` +- Add EasyApplication to the Pixi environment from PyPI: + ```txt + pixi add --pypi EasyApplication + ``` +- Add a Pixi task to run EasyApplication commands easily: + ```txt + pixi task add EasyApplication "python -m EasyApplication" + ``` + +#### Updating Pixi and EasyApplication + +- To update all packages in the Pixi environment, including + EasyApplication: + ```txt + pixi update + ``` +- To update Pixi itself to the latest version: + ```txt + pixi self-update + ``` + +#### Uninstalling Pixi + +- Follow the + [official Pixi Guide](https://pixi.prefix.dev/latest/installation/#uninstall). + +## Classical Installation + +This section describes how to install EasyApplication using the +traditional method with **pip**. It is assumed that you are familiar +with Python package management and virtual environments. + +### Environment Setup optional { #environment-setup data-toc-label="Environment Setup" } + +We recommend using a **virtual environment** to isolate dependencies and +avoid conflicts with system-wide packages. If any issues arise, you can +simply delete and recreate the environment. + +#### Creating and Activating a Virtual Environment: + + + +- Create a new virtual environment: + ```txt + python3 -m venv venv + ``` +- Activate the environment: + + === ":material-apple: macOS" + ```txt + . venv/bin/activate + ``` + === ":material-linux: Linux" + ```txt + . venv/bin/activate + ``` + === ":fontawesome-brands-windows: Windows" + ```txt + . venv/Scripts/activate # Windows with Unix-like shells + .\venv\Scripts\activate.bat # Windows with CMD + .\venv\Scripts\activate.ps1 # Windows with PowerShell + ``` + +- The terminal should now show `(venv)`, indicating that the virtual environment + is active. + + + +#### Deactivating and Removing the Virtual Environment: + + + +- Exit the environment: + ```txt + deactivate + ``` +- If this environment is no longer needed, delete it: + + === ":material-apple: macOS" + ```txt + rm -rf venv + ``` + === ":material-linux: Linux" + ```txt + rm -rf venv + ``` + === ":fontawesome-brands-windows: Windows" + ```txt + rmdir /s /q venv + ``` + + + +### Installing from PyPI { #from-pypi } + +EasyApplication is available on **PyPI (Python Package Index)** and can +be installed using `pip`. To do so, use the following command: + +```txt +pip install EasyApplication +``` + +To install a specific version of EasyApplication, e.g., 1.0.3: + +```txt +pip install 'EasyApplication==1.0.3' +``` + +To upgrade to the latest version: + +```txt +pip install --upgrade EasyApplication +``` + +To upgrade to the latest version and force reinstallation of all +dependencies (useful if files are corrupted): + +```txt +pip install --upgrade --force-reinstall EasyApplication +``` + +To check the installed version: + +```txt +pip show EasyApplication +``` + +### Installing from GitHub alternative { #from-github data-toc-label="Installing from GitHub" } + +Installing unreleased versions is generally not recommended but may be +useful for testing. + +To install EasyApplication from the `develop` branch of GitHub, for +example: + +```txt +pip install git+https://github.com/easyscience/gui-components@develop +``` + +To include extra dependencies (e.g., dev): + +```txt +pip install 'EasyApplication[dev] @ git+https://github.com/easyscience/gui-components@develop' +``` + +## How to Run Tutorials + +EasyApplication includes a collection of **Jupyter Notebook examples** +that demonstrate key functionality. These tutorials serve as +**step-by-step guides** to help users understand the data analysis +workflow. They are available as **static HTML pages** in the +[:material-school: Tutorials](../tutorials/index.md) section. + +In the next sections, we explain how to set up Jupyter and run the +tutorials interactively in two different ways: locally or online via +Google Colab. + +If you decide to run the tutorials locally, you need to download them +first. This can be done individually via the :material-download: +**Download Notebook** button available on each tutorial page, or all at +once using the command line, as shown below. + +### Run Tutorials Locally with Pixi recommended { #running-with-pixi data-toc-label="Run Tutorials Locally with Pixi" } + +- Navigate to your existing Pixi project, created as described in the + [Installing with Pixi](#installing-with-pixi) section. +- Add JupyterLab and the Pixi kernel for Jupyter: + ```txt + pixi add --pypi jupyterlab pixi-kernel + ``` +- Download all the EasyApplication tutorials to the `tutorials/` + directory: + ```txt + pixi run EasyApplication download-all-tutorials + ``` +- Start JupyterLab in the `tutorials/` directory to access the + notebooks: + ```txt + pixi run jupyter lab tutorials/ + ``` +- Your web browser should open automatically. Click on one of the + `*.ipynb` files and select the `Python (Pixi)` kernel to get started. + +### Classical Run Tutorials Locally + +- Install Jupyter Notebook and IPython kernel: + ```txt + pip install notebook ipykernel + ``` +- Add the virtual environment as a Jupyter kernel: + ```txt + python -m ipykernel install --user --name=venv --display-name "EasyApplication Python kernel" + ``` +- Download all the EasyApplication tutorials to the `tutorials/` + directory: + ```txt + python -m EasyApplication download-all-tutorials + ``` +- Launch the Jupyter Notebook server (opens browser automatically at + `http://localhost:8888/`): + ```txt + jupyter notebook tutorials/ + ``` +- Open one of the `*.ipynb` files and select the + `EasyApplication Python kernel` to get started. + +### Run Tutorials via Google Colab + +**Google Colab** lets you run Jupyter Notebooks in the cloud without any +local installation. This is the fastest way to start experimenting with +EasyApplication. + +- Ensure you have a **Google account**. +- Go to the **[:material-school: Tutorials](../tutorials/index.md)** + section. +- Click the :google-colab: **Open in Google Colab** button on any + tutorial. diff --git a/docs/docs/introduction/index.md b/docs/docs/introduction/index.md new file mode 100644 index 00000000..7395fa02 --- /dev/null +++ b/docs/docs/introduction/index.md @@ -0,0 +1,68 @@ +--- +icon: material/information-slab-circle +--- + +# :material-information-slab-circle: Introduction + +## Description + +**EasyApplication** is a collection of Qt/QML graphical components to +create cross-platform applications with intuitive graphical interface +based on the EasyScience framework. + +**EasyApplication** is developed as a Python library. + + + +## License + +**EasyApplication** library is released under the +[BSD 3-Clause License](https://raw.githubusercontent.com/easyscience/gui-components/master/LICENSE). + +## Releases + +The latest version of the **EasyApplication** library is +[{{ vars.release_version }}](https://github.com/easyscience/gui-components/releases/latest). + +For a complete list of new features, bug fixes, and improvements, see +the +[GitHub Releases page](https://github.com/easyscience/gui-components/releases). + +## Citation + +If you use **EasyApplication** library in your work, please cite the +specific version you used. + +All official releases of the **EasyApplication** library are archived on +Zenodo, each with a version-specific Digital Object Identifier (DOI). + +Citation details in various styles (e.g., APA, MLA) and formats (e.g., +BibTeX, JSON) are available on the +[Zenodo archive page](https://doi.org/10.5281/zenodo.18163581). + +## Contributing + +We welcome contributions of any kind! + +**EasyApplication** is intended to be a community-driven, open-source +project supported by a diverse group of contributors. + +The project is maintained by the +[European Spallation Source (ESS)](https://ess.eu). + +If you would like to report a bug or request a new feature, please use +the +[GitHub Issue Tracker](https://github.com/easyscience/gui-components/issues) +(A free GitHub account is required.) + +To contribute code, documentation, or tests, please see our +[:material-account-plus: Contributing Guidelines](https://github.com/easyscience/gui-components/blob/master/CONTRIBUTING.md) +for detailed development instructions. + +## Get in Touch + +For general questions or feedback, please contact us at +[support@easyscience.org](mailto:support@easyscience.org). diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md new file mode 100644 index 00000000..a57bbbf6 --- /dev/null +++ b/docs/docs/tutorials/index.md @@ -0,0 +1,21 @@ +--- +icon: material/school +--- + +# :material-school: Tutorials + +This section presents a collection of **Jupyter Notebook** tutorials +that demonstrate how to use EasyApplication for various tasks. These +tutorials serve as self-contained, step-by-step **guides** to help users +grasp the workflow of data analysis using EasyApplication. + +Instructions on how to run the tutorials are provided in the +[:material-cog-box: Installation & Setup](../installation-and-setup/index.md#how-to-run-tutorials) +section of the documentation. + +The tutorials are organized into the following categories: + +## Getting Started + +- [Dummy tutorial](tutorial.ipynb) – A dummy tutorial to ensure the + tutorial infrastructure is working correctly. diff --git a/docs/docs/tutorials/tutorial.ipynb b/docs/docs/tutorials/tutorial.ipynb new file mode 100644 index 00000000..ea07cddd --- /dev/null +++ b/docs/docs/tutorials/tutorial.ipynb @@ -0,0 +1,63 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Dummy Tutorial\n", + "\n", + "This is a dummy tutorial file to ensure that the tutorials section is\n", + "not empty. You can replace this file with actual tutorial content as\n", + "needed." + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": {}, + "source": [ + "## Import Library" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "import EasyApplication" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "## Step 1: Blah Blah Blah" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4", + "metadata": {}, + "outputs": [], + "source": [ + "# This is a placeholder for tutorial content.\n", + "print('This is a dummy tutorial.')\n", + "print('Imported library:', EasyApplication)" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "main_language": "python", + "notebook_metadata_filter": "-all" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/docs/tutorials/tutorial.py b/docs/docs/tutorials/tutorial.py new file mode 100644 index 00000000..200123db --- /dev/null +++ b/docs/docs/tutorials/tutorial.py @@ -0,0 +1,20 @@ +# %% [markdown] +# # Dummy Tutorial +# +# This is a dummy tutorial file to ensure that the tutorials section is +# not empty. You can replace this file with actual tutorial content as +# needed. + +# %% [markdown] +# ## Import Library + +# %% +import EasyApplication + +# %% [markdown] +# ## Step 1: Blah Blah Blah + +# %% +# This is a placeholder for tutorial content. +print('This is a dummy tutorial.') +print('Imported library:', EasyApplication) diff --git a/docs/docs/user-guide/index.md b/docs/docs/user-guide/index.md new file mode 100644 index 00000000..19b66f95 --- /dev/null +++ b/docs/docs/user-guide/index.md @@ -0,0 +1,24 @@ +--- +icon: material/book-open-variant +--- + +# :material-book-open-variant: User Guide + +This section provides an overview of the **core concepts**, **key +parameters** and **workflow steps** required for using EasyApplication +effectively. + +Here is a brief overview of the User Guide sections: + +- [Glossary](#) – Defines common terms and labels used throughout the + documentation. +- [Concept](#) – Introduces the overall idea behind data analysis in + EasyApplication. +- [Data Format](#) – Explains the data structures and file formats used + by EasyApplication. +- [Parameters](#) – Describes how parameters are structured, named, and + accessed within the EasyApplication. +- [First Steps](#) – Shows how to begin using EasyApplication in Python + or Jupyter notebooks. +- [Analysis Workflow](#) – Breaks down the data analysis pipeline into + practical, sequential steps. diff --git a/docs/includes/abbreviations.md b/docs/includes/abbreviations.md new file mode 100644 index 00000000..682f16ff --- /dev/null +++ b/docs/includes/abbreviations.md @@ -0,0 +1,15 @@ + + +*[CIF]: Crystallographic Information File. +*[curl]: Command-line tool for transferring data with URLs. +*[GitHub]: A web-based platform for version control and collaboration. +*[Google Colab]: Cloud service that allows you to run Jupyter Notebooks in the cloud. +*[IUCr]: International Union of Crystallography. +*[Jupyter Notebook]: An open-source web application that allows you to create and share documents that contain live code, equations, visualizations, and narrative text. +*[JupyterLab]: Web-based interactive development environment for notebooks, code, and data. +*[pip]: Package installer for Python. +*[PyPI]: The Python Package Index is a repository of software for the Python programming language. +*[Conda]: Conda is a cross-platform, language-agnostic binary package manager. +*[Pixi]: A modern package manager for Windows, macOS, and Linux. + + diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 00000000..2f581412 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,180 @@ +# Project information +site_name: EasyApplication Library +site_url: https://easyscience.github.io/gui-components + +# Repository +repo_url: https://github.com/easyscience/gui-components +edit_uri: edit/develop/docs/ + +# Copyright +copyright: © 2021-2026 EasyApplication + +# Sets the theme and theme-specific configuration +theme: + name: material + custom_dir: overrides + features: + #- content.action.edit # Temporary disable edit button (until decided on which branch to use and where to host the notebooks) + #- content.action.view + - content.code.annotate + - content.code.copy # Auto generated button to copy a code block's content + - content.tooltips + - navigation.footer + - navigation.indexes + #- navigation.instant # Instant loading, but it causes issues with rendering equations + #- navigation.sections + - navigation.top # Back-to-top button + - navigation.tracking # Anchor tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + palette: + # Palette toggle for light mode + - media: '(prefers-color-scheme: light)' + scheme: default + primary: custom + toggle: + icon: fontawesome/solid/sun + name: Switch to dark mode + # Palette toggle for dark mode + - media: '(prefers-color-scheme: dark)' + scheme: slate + primary: custom + toggle: + icon: fontawesome/solid/moon + name: Switch to light mode + font: + text: Mulish + code: Roboto Mono + icon: + edit: material/file-edit-outline + favicon: assets/images/favicon.png + logo_dark_mode: assets/images/logo_dark.svg + logo_light_mode: assets/images/logo_light.svg + +# A set of key-value pairs, where the values can be any valid YAML +# construct, that will be passed to the template +extra: + generator: false # Disable `Made with Material for MkDocs` (bottom left) + social: # Extra icons in the bottom right corner + - icon: easyscience # File: overrides/.icons/easyscience.svg + link: https://easyscience.org + name: EasyScience Framework Webpage + - icon: easyapplication # File: overrides/.icons/easyapplication.svg + link: https://easyscience.github.io/application + name: EasyApplication Main Webpage + - icon: fontawesome/brands/github # Name as in Font Awesome + link: https://github.com/easyscience/gui-components + name: EasyApplication Library Source Code on GitHub + # Set custom variables to be used in Markdown and HTML files + vars: + ci_branch: !ENV CI_BRANCH + github_repository: !ENV GITHUB_REPOSITORY + release_version: !ENV RELEASE_VERSION + docs_version: !ENV DOCS_VERSION + notebooks_dir: !ENV NOTEBOOKS_DIR + # Renders a version selector in the header + version: + provider: mike + +# Customization to be included by the theme +extra_css: + - assets/stylesheets/extra.css + +extra_javascript: + - assets/javascripts/extra.js + # MathJax for rendering mathematical expressions + - assets/javascripts/mathjax.js # Custom MathJax config to ensure compatibility with mkdocs-jupyter + - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js # Official MathJax CDN + +# A list of extensions beyond the ones that MkDocs uses by default (meta, toc, tables, and fenced_code) +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - pymdownx.arithmatex: # rendering of equations and integrates with MathJax or KaTeX + generic: true + - pymdownx.blocks.caption + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + options: + custom_icons: + - docs/overrides/.icons + - pymdownx.highlight: # whether highlighting should be carried out during build time by Pygments + use_pygments: true + pygments_lang_class: true + - pymdownx.snippets: + auto_append: + - docs/includes/abbreviations.md + - pymdownx.superfences: # whether highlighting should be carried out during build time by Pygments + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: # enables content tabs + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - toc: + toc_depth: 3 + +# A list of plugins (with optional configuration settings) to use when building the site +plugins: + - autorefs + - inline-svg + - markdownextradata # Plugin that injects the mkdocs.yml extra variables into the Markdown template + - mike # Plugin that makes it easy to deploy multiple versions of the docs + - mkdocs-jupyter: + include: ['*.ipynb'] # Default: ['*.py', '*.ipynb'] + execute: false # Do not execute notebooks during build. They are expected to be pre-executed. + allow_errors: false + include_source: true + include_requirejs: true # Required for Plotly + #custom_mathjax_url: 'https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js' # See 'extra_javascript' above + ignore_h1_titles: true # Use titles defined in the nav section below + remove_tag_config: + remove_input_tags: + - hide-in-docs + - mkdocstrings: + handlers: + python: + paths: ['src'] # Change 'src' to your actual sources directory + options: + docstring_style: numpy + group_by_category: false + heading_level: 1 + show_root_heading: true + show_root_full_path: false + show_submodules: true + show_source: true + - search + +# Determines additional directories to watch when running mkdocs serve +watch: + - includes + - overrides + - ../src + +# Exclude files and folders from the global navigation +not_in_nav: | + index.md + +# Format and layout of the global navigation for the site +nav: + - Introduction: + - Introduction: introduction/index.md + - Installation & Setup: + - Installation & Setup: installation-and-setup/index.md + - User Guide: + - User Guide: user-guide/index.md + - Tutorials: + - Tutorials: tutorials/index.md + - Getting Started: + - Dummy tutorial: tutorials/tutorial.ipynb + - API Reference: + - API Reference: api-reference/index.md diff --git a/docs/overrides/.icons/app.svg b/docs/overrides/.icons/app.svg new file mode 100644 index 00000000..b4fdd4f3 --- /dev/null +++ b/docs/overrides/.icons/app.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/overrides/.icons/easyapplication.svg b/docs/overrides/.icons/easyapplication.svg new file mode 100644 index 00000000..5813e570 --- /dev/null +++ b/docs/overrides/.icons/easyapplication.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/overrides/.icons/easyscience.svg b/docs/overrides/.icons/easyscience.svg new file mode 100644 index 00000000..fb514912 --- /dev/null +++ b/docs/overrides/.icons/easyscience.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/overrides/.icons/google-colab.svg b/docs/overrides/.icons/google-colab.svg new file mode 100644 index 00000000..9cd9d1b0 --- /dev/null +++ b/docs/overrides/.icons/google-colab.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 00000000..2e146827 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block content %} + +{% if page.nb_url %} + {# Parse notebook path/URL #} + {% set parts = page.nb_url.split('/') %} + {% set tutorial_name = parts[-2] %} + {% set filename = parts[-1] %} + + {# Colab url #} + {% set base_colab_url = "https://colab.research.google.com/github/" %} + {% set colab_url = + base_colab_url ~ config.extra.vars.github_repository ~ + "/blob/gh-pages/" ~ config.extra.vars.docs_version ~ + "/tutorials/" ~ tutorial_name ~ "/" ~ filename + %} + + {# Download link: relative to the current page #} + {% set file_url = filename %} + + {# Open in Colab (absolute GitHub URL; works anywhere) #} + + {% include ".icons/google-colab.svg" %} + + + {# Download: use a RELATIVE link to the file next to this page #} + + {% include ".icons/material/download.svg" %} + +{% endif %} + +{{ super() }} +{% endblock content %} diff --git a/docs/overrides/partials/logo.html b/docs/overrides/partials/logo.html new file mode 100644 index 00000000..78fa69ca --- /dev/null +++ b/docs/overrides/partials/logo.html @@ -0,0 +1,15 @@ +{% if ( config.theme.logo_light_mode and config.theme.logo_dark_mode ) %} +logo +logo +{% elif config.theme.logo %} +logo +{% else %} {% set icon = config.theme.icon.logo or "material/library" %} {% +include ".icons/" ~ icon ~ ".svg" %} {% endif %} diff --git a/examples/AdvancedPy/README.md b/examples/AdvancedPy/README.md index c36a7a12..11a1ff15 100644 --- a/examples/AdvancedPy/README.md +++ b/examples/AdvancedPy/README.md @@ -13,14 +13,14 @@ ├── AdvancedPy.pyproject # Python project for the Qt Creator IDE │ └── 🗂️ AdvancedPy # Directory with the name of the current Python package - ├── __init__.py # Executed when the current Python package is imported - ├── main.qml # Root QML component - ├── main.py # Root Python file + ├── __init__.py # Executed when the current Python package is imported + ├── main.qml # Root QML component + ├── main.py # Root Python file │ ├── 🗂️ Backends # Backend logic │ ├── MockBackend.qml # Parent object for all other objects with mock QML logic │ ├── 🗂️ MockQml # Mock QML backend to be used if no python backend is defined - │ │ ├── qmldir + │ │ ├── qmldir │ │ ├── Status.qml # Mock logic for the status bar │ │ ├── Project.qml # Mock logic for the application page 'Project' │ │ └── Report.qml # Mock logic for the application page 'Report' @@ -35,12 +35,12 @@ │ └── helpers.py # Some helper functions │ └── 🗂️ Gui # Frontend GUI components - ├── qmldir + ├── qmldir ├── ApplicationWindow.qml # Top-level application window - ├── StatusBar.qml # Status bar + ├── StatusBar.qml # Status bar │ ├── 🗂️ Globals # Globally accessible objects - │ ├── qmldir + │ ├── qmldir │ ├── ApplicationInfo.qml # Name, version and other information about the application │ ├── BackendWrapper.qml # Layer between the backend proxy and GUI objects │ └── References.qml # QML object ids to globally access the desired objects @@ -49,11 +49,11 @@ │ ├── 🗂️ Home # Components of the application page 'Home' │ ├── 🗂️ Project # Components of the application page 'Project' │ └── 🗂️ Report # Components of the application page 'Report' - │ + │ └── 🗂️ Resources └── 🗂️ Logos # Logos of the application and contributors -(*) Full structure of the 'Pages' directory is shown below +(*) Full structure of the 'Pages' directory is shown below ``` ### Structure of the application pages only @@ -64,7 +64,7 @@ ├── 🗂️ Home # Components of the application 'Home' page │ ├── Content.qml │ │ -│ └── 🗂️ Popups +│ └── 🗂️ Popups │ └── About.qml │ ├── 🗂️ Project # Components of the application 'Project' page @@ -76,25 +76,25 @@ │ └── 🗂️ Sidebar # Tabs of the sidebar │ │ │ ├── 🗂️ Basic # Components of the sidebar tab with basic controls -│ │ ├── Layout.qml +│ │ ├── Layout.qml │ │ │ -│ │ ├── 🗂️ Groups +│ │ ├── 🗂️ Groups │ │ │ ├── GetStarted.qml │ │ │ ├── Examples.qml │ │ │ └── Recent.qml │ │ │ -│ │ └── 🗂️ Popups +│ │ └── 🗂️ Popups │ │ ├── OpenCifFile.qml │ │ └── ProjectDescription.qml │ │ │ ├── 🗂️ Extra # Components of the sidebar tab with extra controls -│ │ ├── Layout.qml +│ │ ├── Layout.qml │ │ │ -│ │ └── 🗂️ Groups +│ │ └── 🗂️ Groups │ │ └── Scrolling.qml │ │ │ └── 🗂️ Text # Components of the sidebar tab with text mode controls -│ └── Layout.qml +│ └── Layout.qml │ └── 🗂️ Report # Components of the application 'Report' page ├── Layout.qml # Layout of the whole page @@ -105,19 +105,21 @@ └── 🗂️ Sidebar # Tabs of the sidebar │ ├── 🗂️ Basic # Components of the sidebar tab with basic controls - │ ├── Layout.qml - │ │ - │ └── 🗂️ Groups + │ ├── Layout.qml + │ │ + │ └── 🗂️ Groups │ └── Export.qml │ └── 🗂️ Extra # Components of the sidebar tab with extra controls - ├── Layout.qml + ├── Layout.qml │ - └── 🗂️ Groups + └── 🗂️ Groups └── Empty.qml ``` ### Glossary -* qmldir - Declares objects that can then be imported into other qml files. See -[doc.qt.io](https://doc.qt.io/qt-6/qtqml-modules-qmldir.html) for more details. +- qmldir - Declares objects that can then be imported into other qml + files. See + [doc.qt.io](https://doc.qt.io/qt-6/qtqml-modules-qmldir.html) for more + details. diff --git a/examples/AdvancedPy/pyproject.toml b/examples/AdvancedPy/pyproject.toml index 6e7dcf64..21e4c9d9 100644 --- a/examples/AdvancedPy/pyproject.toml +++ b/examples/AdvancedPy/pyproject.toml @@ -6,27 +6,19 @@ build-backend = 'hatchling.build' name = 'advancedpy' version = '1.0.0' description = 'Example of a desktop application of advanced complexity with Python backend and EasyApp-based GUI' -authors = [ - {name = 'Andrew Sazonov', email = 'andrew.sazonov@ess.eu'} -] +authors = [{ name = 'Andrew Sazonov', email = 'andrew.sazonov@ess.eu' }] readme = 'README.md' -license = {file = 'LICENSE'} +license = { file = 'LICENSE' } classifiers = [ 'Development Status :: 4 - Beta', 'License :: OSI Approved :: BSD License', - 'Programming Language :: Python :: 3' + 'Programming Language :: Python :: 3', ] requires-python = '>=3.11' -dependencies = [ - 'numpy<2' -] +dependencies = ['numpy<2'] [project.optional-dependencies] -ci = [ - 'validate-pyproject[all]', - 'build', - 'wheel' -] +ci = ['validate-pyproject[all]', 'build', 'wheel'] [project.urls] homepage = 'https://github.com/EasyScience/EasyApp/tree/master/examples/AdvancedPy' diff --git a/pixi.lock b/pixi.lock index cbcfe22e..e602a80a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -5,105 +5,2121 @@ environments: - url: https://conda.anaconda.org/conda-forge/ indexes: - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit packages: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda - - pypi: https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/34/0e/1e9841cc46196c55ac3eac0b8e08044a88cc70c8cc29e9dc1e33b2ced2b7/pyside6-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/17/fe/d5c67665f866b8859d02aa1a859f101a1b2fd348cb61746a3e16fd98fb20/pyside6_addons-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/85/e8/9396cf11a60f80175bb3c5c1d498d84e87b7af653ab4ea001acf821a3981/pyside6_essentials-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/be/82/c1c6932f9849bc5e75c93c38a29419505a6e3e0037261e28f3e7ecbf2751/shiboken6-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - - pypi: ./ - osx-64: - - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.1-h21dd04a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-h750e83c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.50.4-h39a8b3b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.5.4-h230baf5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h17c18a5_101_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - - pypi: https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/98/84b16f78b5d92dd234fb1eb9890a350a5b0c83d985bb8c44a92f813a2d02/pyside6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/47/23/9fbdec2ce16244ac3fe28e6d44c39c70465c93a03325939a792fd00fde7f/pyside6_addons-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/e5/55/bad02ab890c8b8101abef0db4a2e5304be78a69e23a438e4d8555b664467/pyside6_essentials-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/fd/78/3e730aea82089dd82b1e092bc265778bda329459e6ad9b7134eec5fff3f2/shiboken6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl - pypi: ./ osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.1-hec049ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.4-h4237e3c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.4-h5503f6c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-hfc2f54d_101_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - - pypi: https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e6/98/84b16f78b5d92dd234fb1eb9890a350a5b0c83d985bb8c44a92f813a2d02/pyside6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/47/23/9fbdec2ce16244ac3fe28e6d44c39c70465c93a03325939a792fd00fde7f/pyside6_addons-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/e5/55/bad02ab890c8b8101abef0db4a2e5304be78a69e23a438e4d8555b664467/pyside6_essentials-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - - pypi: https://files.pythonhosted.org/packages/fd/78/3e730aea82089dd82b1e092bc265778bda329459e6ad9b7134eec5fff3f2/shiboken6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz - pypi: ./ win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-h4c7d964_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.1-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.50.4-hf5d6505_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.5.4-h725018a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-h09917c8_101_cp313.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h2c6b04d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h2b53caa_32.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_32.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_32.conda - - pypi: https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/43/67/94794ebaf198bbdb35cb77f19f38370f9b323b036ab149874bc33c38faab/pyside6-6.10.0-cp39-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/7d/5d/a3c32f85ac7f905c95679967c0ddda0ba043c273b75623cc90d8185064e4/pyside6_addons-6.10.0-cp39-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/bb/3a/d8211d17e6ca70f641c6ebd309f08ef18930acda60e74082c75875a274da/pyside6_essentials-6.10.0-cp39-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/11/30/e4624a7e3f0dc9796b701079b77defcce0d32d1afc86bb1d0df04bc3d9e2/shiboken6-6.10.0-cp39-abi3-win_amd64.whl + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl + - pypi: ./ + py-312-env: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py312h8285ef7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + - pypi: ./ + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.3.0-py312h44dc372_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl + - pypi: ./ + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py312h06d0912_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl + - pypi: ./ + py-314-env: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + - pypi: ./ + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz + - pypi: ./ + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.0-hf5d6505_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl - pypi: ./ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 @@ -113,6 +2129,20 @@ packages: purls: [] size: 2562 timestamp: 1578324546067 +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28948 + timestamp: 1770939786096 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 build_number: 16 sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 @@ -127,6 +2157,457 @@ packages: purls: [] size: 23621 timestamp: 1650670423406 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 + md5: aaa2a381ccc56eac91d63b6c1240312f + depends: + - cpython + - python-gil + license: MIT + license_family: MIT + purls: [] + size: 8191 + timestamp: 1744137672556 +- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + name: annotated-types + version: 0.7.0 + sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 + requires_dist: + - typing-extensions>=4.0.0 ; python_full_version < '3.9' + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.13.0-pyhcf101f3_0.conda + sha256: f09aed24661cd45ba54a43772504f05c0698248734f9ae8cd289d314ac89707e + md5: af2df4b9108808da3dc76710fe50eae2 + depends: + - exceptiongroup >=1.0.2 + - idna >=2.8 + - python >=3.10 + - typing_extensions >=4.5 + - python + constrains: + - trio >=0.32.0 + - uvloop >=0.22.1 + - winloop >=0.2.3 + license: MIT + license_family: MIT + purls: + - pkg:pypi/anyio?source=compressed-mapping + size: 146764 + timestamp: 1774359453364 +- conda: https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.4-pyhd8ed1ab_1.conda + sha256: 8f032b140ea4159806e4969a68b4a3c0a7cab1ad936eb958a2b5ffe5335e19bf + md5: 54898d0f524c9dee622d44bbb081a8ab + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/appnope?source=hash-mapping + size: 10076 + timestamp: 1733332433806 +- conda: https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-25.1.0-pyhd8ed1ab_0.conda + sha256: bea62005badcb98b1ae1796ec5d70ea0fc9539e7d59708ac4e7d41e2f4bb0bad + md5: 8ac12aff0860280ee0cff7fa2cf63f3b + depends: + - argon2-cffi-bindings + - python >=3.9 + - typing-extensions + constrains: + - argon2_cffi ==999 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi?source=hash-mapping + size: 18715 + timestamp: 1749017288144 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + sha256: 7988c207b2b766dad5ebabf25a92b8d75cb8faed92f256fd7a4e0875c9ec6d58 + md5: 1567f06d717246abab170736af8bad1b + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.0.1 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 35646 + timestamp: 1762509443854 +- conda: https://conda.anaconda.org/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py314h5bd0f2a_2.conda + sha256: 39234a99df3d2e3065383808ed8bfda36760de5ef590c54c3692bb53571ef02b + md5: 3cca1b74b2752917b5b65b81f61f0553 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=2.0.0b1 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 35598 + timestamp: 1762509505285 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py312h4409184_2.conda + sha256: 24c475f6f7abf03ef3cc2ac572b7a6d713bede00ef984591be92cdc439b09fbc + md5: 0a2a07b42db3f92b8dccf0f60b5ebee8 + depends: + - __osx >=11.0 + - cffi >=1.0.1 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 34224 + timestamp: 1762509989973 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/argon2-cffi-bindings-25.1.0-py314h0612a62_2.conda + sha256: aab60bbaea5cc49dff37438d1ad469d64025cda2ce58103cf68da61701ed2075 + md5: a240a79a49a95b388ef81ccda27a5e51 + depends: + - __osx >=11.0 + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 34218 + timestamp: 1762509977830 +- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda + sha256: 38c5e43d991b0c43713fa2ceba3063afa4ccad2dd4c8eb720143de54d461a338 + md5: 5dc3781bbc4ddce0bf250a04c1a192c2 + depends: + - cffi >=1.0.1 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 38535 + timestamp: 1762509763237 +- conda: https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-25.1.0-py314h5a2d7ad_2.conda + sha256: a742e7cd0d5534bfff3fd550a0c1e430411fad60a24f88930d261056ab08096f + md5: ffa247e46f47e157851dc547f4c513e4 + depends: + - cffi >=2.0.0b1 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/argon2-cffi-bindings?source=hash-mapping + size: 38653 + timestamp: 1762509771011 +- conda: https://conda.anaconda.org/conda-forge/noarch/arrow-1.4.0-pyhcf101f3_0.conda + sha256: 792da8131b1b53ff667bd6fc617ea9087b570305ccb9913deb36b8e12b3b5141 + md5: 85c4f19f377424eafc4ed7911b291642 + depends: + - python >=3.10 + - python-dateutil >=2.7.0 + - python-tzdata + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/arrow?source=hash-mapping + size: 113854 + timestamp: 1760831179410 +- conda: https://conda.anaconda.org/conda-forge/noarch/asttokens-3.0.1-pyhd8ed1ab_0.conda + sha256: ee4da0f3fe9d59439798ee399ef3e482791e48784873d546e706d0935f9ff010 + md5: 9673a61a297b00016442e022d689faa6 + depends: + - python >=3.10 + constrains: + - astroid >=2,<5 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/asttokens?source=hash-mapping + size: 28797 + timestamp: 1763410017955 +- conda: https://conda.anaconda.org/conda-forge/noarch/async-lru-2.3.0-pyhcf101f3_0.conda + sha256: ea8486637cfb89dc26dc9559921640cd1d5fd37e5e02c33d85c94572139f2efe + md5: b85e84cb64c762569cc1a760c2327e0a + depends: + - python >=3.10 + - typing_extensions >=4.0.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/async-lru?source=hash-mapping + size: 22949 + timestamp: 1773926359134 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda + sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab + md5: c6b0543676ecb1fb2d7643941fe375f2 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/attrs?source=hash-mapping + size: 64927 + timestamp: 1773935801332 +- pypi: https://files.pythonhosted.org/packages/9e/43/53afb8ba17218f19b77c7834128566c5bbb100a0ad9ba2e8e89d089d7079/autopep8-2.3.2-py2.py3-none-any.whl + name: autopep8 + version: 2.3.2 + sha256: ce8ad498672c845a0c3de2629c15b635ec2b05ef8177a6e7c91c74f3e9b51128 + requires_dist: + - pycodestyle>=2.12.0 + - tomli ; python_full_version < '3.11' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.18.0-pyhcf101f3_1.conda + sha256: a14a9ad02101aab25570543a59c5193043b73dc311a25650134ed9e6cb691770 + md5: f1976ce927373500cc19d3c0b2c85177 + depends: + - python >=3.10 + - python + constrains: + - pytz >=2015.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/babel?source=compressed-mapping + size: 7684321 + timestamp: 1772555330347 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda + sha256: d77a24be15e283d83214121428290dbe55632a6e458378205b39c550afa008cf + md5: 5b8c55fed2e576dde4b0b33693a4fdb1 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 237970 + timestamp: 1767045004512 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda + noarch: generic + sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 + md5: a2ac7763a9ac75055b68f325d3255265 + depends: + - python >=3.14 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: [] + size: 7514 + timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/backports.zstd-1.3.0-py312h44dc372_0.conda + sha256: aee745bfca32f7073d3298157bbb2273d6d83383cb266840cf0a7862b3cd8efc + md5: c2d5961bfd98504b930e704426d16572 + depends: + - python + - python 3.12.* *_cpython + - __osx >=11.0 + - zstd >=1.5.7,<1.6.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 241051 + timestamp: 1767045000787 +- conda: https://conda.anaconda.org/conda-forge/win-64/backports.zstd-1.3.0-py312h06d0912_0.conda + sha256: c9c97cd644faa6c4fb38017c5ecfd082f56a3126af5925d246364fa4a22b2a74 + md5: 2db2b356f08f19ce4309a79a9ee6b9d8 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 236635 + timestamp: 1767045021157 +- pypi: https://files.pythonhosted.org/packages/36/da/87912ddec6e06feffbaa3d7aa18fc6352bee2e8f1fee185d7d1690f8f4e8/backrefs-7.0-py312-none-any.whl + name: backrefs + version: '7.0' + sha256: ca42ce6a49ace3d75684dfa9937f3373902a63284ecb385ce36d15e5dcb41c12 + requires_dist: + - regex ; extra == 'extras' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/3e/5c/fb93d3092640a24dfb7bd7727a24016d7c01774ca013e60efd3f683c8002/backrefs-7.0-py314-none-any.whl + name: backrefs + version: '7.0' + sha256: a6448b28180e3ca01134c9cf09dcebafad8531072e09903c5451748a05f24bc9 + requires_dist: + - regex ; extra == 'extras' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.14.3-pyha770c72_0.conda + sha256: bf1e71c3c0a5b024e44ff928225a0874fc3c3356ec1a0b6fe719108e6d1288f6 + md5: 5267bef8efea4127aacd1f4e1f149b6e + depends: + - python >=3.10 + - soupsieve >=1.2 + - typing-extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/beautifulsoup4?source=hash-mapping + size: 90399 + timestamp: 1764520638652 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-6.3.0-pyhcf101f3_1.conda + sha256: f8ff1f98423674278964a46c93a1766f9e91960d44efd91c6c3ed56a33813f46 + md5: 7c5ebdc286220e8021bf55e6384acd67 + depends: + - python >=3.10 + - webencodings + - python + constrains: + - tinycss2 >=1.1.0,<1.5 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/bleach?source=hash-mapping + size: 142008 + timestamp: 1770719370680 +- conda: https://conda.anaconda.org/conda-forge/noarch/bleach-with-css-6.3.0-hbca2aae_1.conda + sha256: 7c07a865e5e4cca233cc4e0eb3f0f5ff6c90776461687b4fb0b1764133e1fd61 + md5: f11a319b9700b203aa14c295858782b6 + depends: + - bleach ==6.3.0 pyhcf101f3_1 + - tinycss2 + license: Apache-2.0 AND MIT + purls: [] + size: 4409 + timestamp: 1770719370682 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda + sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 + md5: 64088dffd7413a2dd557ce837b4cbbdb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 368300 + timestamp: 1764017300621 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda + sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 + md5: 8910d2c46f7e7b519129f486e0fe927a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 367376 + timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py312h0dfefe5_1.conda + sha256: 6178775a86579d5e8eec6a7ab316c24f1355f6c6ccbe84bb341f342f1eda2440 + md5: 311fcf3f6a8c4eb70f912798035edd35 + depends: + - __osx >=11.0 + - libcxx >=19 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 359503 + timestamp: 1764018572368 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.2.0-py314h3daef5d_1.conda + sha256: 5c2e471fd262fcc3c5a9d5ea4dae5917b885e0e9b02763dbd0f0d9635ed4cb99 + md5: f9501812fe7c66b6548c7fcaa1c1f252 + depends: + - __osx >=11.0 + - libcxx >=19 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 359854 + timestamp: 1764018178608 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py312hc6d9e41_1.conda + sha256: 2bb6f384a51929ef2d5d6039fcf6c294874f20aaab2f63ca768cbe462ed4b379 + md5: e8e7a6346a9e50d19b4daf41f367366f + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335482 + timestamp: 1764018063640 +- conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.2.0-py314he701e3d_1.conda + sha256: 6854ee7675135c57c73a04849c29cbebc2fb6a3a3bfee1f308e64bf23074719b + md5: 1302b74b93c44791403cbeee6a0f62a3 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - libbrotlicommon 1.2.0 hfd05255_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=hash-mapping + size: 335782 + timestamp: 1764018443683 +- pypi: https://files.pythonhosted.org/packages/fa/88/6764e7a109dd84294850741501145da90d13cdeac9d4e614929464a37420/build-1.4.4-py3-none-any.whl + name: build + version: 1.4.4 + sha256: 8c3f48a6090b39edec1a273d2d57949aaf13723b01e02f9d518396887519f64d + requires_dist: + - packaging>=24.0 + - pyproject-hooks + - colorama ; os_name == 'nt' + - importlib-metadata>=4.6 ; python_full_version < '3.10.2' + - tomli>=1.1.0 ; python_full_version < '3.11' + - keyring ; extra == 'keyring' + - uv>=0.1.18 ; extra == 'uv' + - virtualenv>=20.11 ; python_full_version < '3.10' and extra == 'virtualenv' + - virtualenv>=20.17 ; python_full_version >= '3.10' and python_full_version < '3.14' and extra == 'virtualenv' + - virtualenv>=20.31 ; python_full_version >= '3.14' and extra == 'virtualenv' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 md5: 51a19bba1b8ebfb60df25cde030b7ebc @@ -138,16 +2619,17 @@ packages: purls: [] size: 260341 timestamp: 1757437258798 -- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_8.conda - sha256: 8f50b58efb29c710f3cecf2027a8d7325ba769ab10c746eff75cea3ac050b10c - md5: 97c4b3bd8a90722104798175a1bdddbf +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 depends: - - __osx >=10.13 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 license: bzip2-1.0.6 license_family: BSD purls: [] - size: 132607 - timestamp: 1757437730085 + size: 260182 + timestamp: 1771350215188 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_8.conda sha256: b456200636bd5fecb2bec63f7e0985ad2097cf1b83d60ce0b6968dffa6d02aa1 md5: 58fd217444c2a5701a44244faf518206 @@ -158,6 +2640,16 @@ packages: purls: [] size: 125061 timestamp: 1757437486465 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df + md5: 620b85a3f45526a8bc4d23fd78fc22f0 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 124834 + timestamp: 1771350416561 - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_8.conda sha256: d882712855624641f48aa9dc3f5feea2ed6b4e6004585d3616386a18186fe692 md5: 1077e9333c41ff0be8edd1a5ec0ddace @@ -170,6 +2662,39 @@ packages: purls: [] size: 55977 timestamp: 1757437738856 +- conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h0ad9c76_9.conda + sha256: 76dfb71df5e8d1c4eded2dbb5ba15bb8fb2e2b0fe42d94145d5eed4c75c35902 + md5: 4cb8e6b48f67de0b018719cdf1136306 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 56115 + timestamp: 1771350256444 +- conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.34.6-hb03c661_0.conda + sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e + md5: 920bb03579f15389b9e512095ad995b7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 207882 + timestamp: 1765214722852 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.34.6-hc919400_0.conda + sha256: 2995f2aed4e53725e5efbc28199b46bf311c3cab2648fc4f10c2227d6d5fa196 + md5: bcb3cba70cf1eec964a03b4ba7775f01 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 180327 + timestamp: 1765215064054 - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-h4c7d964_0.conda sha256: bfb7f9f242f441fdcd80f1199edd2ecf09acea0f2bcef6f07d7cbb1a8131a345 md5: e54200a1cd1fe33d61c9df8d3b00b743 @@ -188,671 +2713,4178 @@ packages: purls: [] size: 155907 timestamp: 1759649036195 -- pypi: ./ - name: easyapp - version: 0.8.0 - sha256: 9a70274e50d805916093ff0760fe747728bce9023b76cb802b1feba354b24fd6 - requires_dist: - - pyside6 - requires_python: '>=3.10' - editable: true -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda - sha256: 9ba12c93406f3df5ab0a43db8a4b4ef67a5871dfd401010fbe29b218b2cbe620 - md5: 5eb22c1d7b3fc4abb50d92d621583137 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-h4c7d964_0.conda + sha256: 6f4ff81534c19e76acf52fcabf4a258088a932b8f1ac56e9a59e98f6051f8e46 + md5: 56fb2c6c73efc627b40c77d14caecfba depends: - - __osx >=11.0 - license: MIT - license_family: MIT + - __win + license: ISC purls: [] - size: 11857802 - timestamp: 1720853997952 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda - sha256: 96b6900ca0489d9e5d0318a6b49f8eff43fd85fef6e07cb0c25344ee94cd7a3a - md5: c94ab6ff54ba5172cf1c58267005670f + size: 131388 + timestamp: 1776865633471 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda + sha256: c9dbcc8039a52023660d6d1bbf87594a93dd69c6ac5a2a44323af2c92976728d + md5: e18ad67cf881dcadee8b8d9e2f8e5f73 depends: - - __glibc >=2.17,<3.0.a0 - - zstd >=1.5.7,<1.6.0a0 - constrains: - - binutils_impl_linux-64 2.44 - license: GPL-3.0-only - license_family: GPL + - __unix + license: ISC purls: [] - size: 742501 - timestamp: 1761335175964 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - sha256: da2080da8f0288b95dd86765c801c6e166c4619b910b11f9a8446fb852438dc2 - md5: 4211416ecba1866fab0c6470986c22d6 + size: 131039 + timestamp: 1776865545798 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached-property-1.5.2-hd8ed1ab_1.tar.bz2 + noarch: python + sha256: 561e6660f26c35d137ee150187d89767c988413c978e1b712d53f27ddf70ea17 + md5: 9b347a7ec10940d3f7941ff6c460b551 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - constrains: - - expat 2.7.1.* - license: MIT - license_family: MIT + - cached_property >=1.5.2,<1.5.3.0a0 + license: BSD-3-Clause + license_family: BSD purls: [] - size: 74811 - timestamp: 1752719572741 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.1-h21dd04a_0.conda - sha256: 689862313571b62ee77ee01729dc093f2bf25a2f99415fcfe51d3a6cd31cce7b - md5: 9fdeae0b7edda62e989557d645769515 + size: 4134 + timestamp: 1615209571450 +- conda: https://conda.anaconda.org/conda-forge/noarch/cached_property-1.5.2-pyha770c72_1.tar.bz2 + sha256: 6dbf7a5070cc43d90a1e4c2ec0c541c69d8e30a0e25f50ce9f6e4a432e42c5d7 + md5: 576d629e47797577ab0f1b351297ef4a depends: - - __osx >=10.13 - constrains: - - expat 2.7.1.* - license: MIT - license_family: MIT - purls: [] - size: 72450 - timestamp: 1752719744781 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.1-hec049ff_0.conda - sha256: 8fbb17a56f51e7113ed511c5787e0dec0d4b10ef9df921c4fd1cccca0458f648 - md5: b1ca5f21335782f71a8bd69bdc093f67 + - python >=3.6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cached-property?source=hash-mapping + size: 11065 + timestamp: 1615209567874 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda + sha256: 989db6e5957c4b44fa600c68c681ec2f36a55e48f7c7f1c073d5e91caa8cd878 + md5: 929471569c93acefb30282a22060dcd5 depends: - - __osx >=11.0 - constrains: - - expat 2.7.1.* - license: MIT - license_family: MIT - purls: [] - size: 65971 - timestamp: 1752719657566 -- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.1-hac47afa_0.conda - sha256: 8432ca842bdf8073ccecf016ccc9140c41c7114dc4ec77ca754551c01f780845 - md5: 3608ffde260281fa641e70d6e34b1b96 + - python >=3.10 + license: ISC + purls: + - pkg:pypi/certifi?source=compressed-mapping + size: 135656 + timestamp: 1776866680878 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + sha256: 7dafe8173d5f94e46cf9cd597cc8ff476a8357fbbd4433a8b5697b2864845d9c + md5: 648ee28dcd4e07a1940a17da62eccd40 depends: - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - constrains: - - expat 2.7.1.* + - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - pycparser + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 license: MIT license_family: MIT - purls: [] - size: 141322 - timestamp: 1752719767870 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54 - md5: 35f29eec58405aaf55e01cb470d8c26a + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 295716 + timestamp: 1761202958833 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py314h4a8dc5f_1.conda + sha256: c6339858a0aaf5d939e00d345c98b99e4558f285942b27232ac098ad17ac7f8e + md5: cf45f4278afd6f4e6d03eda0f435d527 depends: - __glibc >=2.17,<3.0.a0 + - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 license: MIT license_family: MIT - purls: [] - size: 57821 - timestamp: 1760295480630 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-h750e83c_0.conda - sha256: 277dc89950f5d97f1683f26e362d6dca3c2efa16cb2f6fdb73d109effa1cd3d0 - md5: d214916b24c625bcc459b245d509f22e + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 300271 + timestamp: 1761203085220 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py312h1b4d9a2_1.conda + sha256: 597e986ac1a1bd1c9b29d6850e1cdea4a075ce8292af55568952ec670e7dd358 + md5: 503ac138ad3cfc09459738c0f5750705 depends: - - __osx >=10.13 + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 license: MIT license_family: MIT - purls: [] - size: 52573 - timestamp: 1760295626449 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f - md5: 411ff7cd5d1472bba0f55c0faf04453b + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 288080 + timestamp: 1761203317419 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/cffi-2.0.0-py314h44086f9_1.conda + sha256: 5b5ee5de01eb4e4fd2576add5ec9edfc654fbaf9293e7b7ad2f893a67780aa98 + md5: 10dd19e4c797b8f8bdb1ec1fbb6821d7 depends: - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pycparser + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 license: MIT license_family: MIT - purls: [] - size: 40251 - timestamp: 1760295839166 -- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda - sha256: ddff25aaa4f0aa535413f5d831b04073789522890a4d8626366e43ecde1534a3 - md5: ba4ad812d2afc22b9a34ce8327a0930f + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 292983 + timestamp: 1761203354051 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py312he06e257_1.conda + sha256: 3e3bdcb85a2e79fe47d9c8ce64903c76f663b39cb63b8e761f6f884e76127f82 + md5: 46f7dccfee37a52a97c0ed6f33fcf0a3 depends: + - pycparser + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 license: MIT license_family: MIT - purls: [] - size: 44866 + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 291324 + timestamp: 1761203195397 +- conda: https://conda.anaconda.org/conda-forge/win-64/cffi-2.0.0-py314h5a2d7ad_1.conda + sha256: 924f2f01fa7a62401145ef35ab6fc95f323b7418b2644a87fea0ea68048880ed + md5: c360170be1c9183654a240aadbedad94 + depends: + - pycparser + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/cffi?source=hash-mapping + size: 294731 + timestamp: 1761203441365 +- pypi: https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl + name: cfgv + version: 3.5.0 + sha256: a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl + name: chardet + version: 7.4.3 + sha256: 4b2799bd58e7245cfa8d4ab2e8ad1d76a5c3a5b1f32318eb6acca4c69a3e7101 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/51/ac/b9d68ebddfe1b02c77af5bf81120e12b036b4432dc6af7a303d90e2bc38b/chardet-7.4.3-cp314-cp314-macosx_11_0_arm64.whl + name: chardet + version: 7.4.3 + sha256: acc46d1b8b7d5783216afe15db56d1c179b9a40e5a1558bc13164c4fd20674c4 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl + name: chardet + version: 7.4.3 + sha256: 29af5999f654e8729d251f1724a62b538b1262d9292cccaefddf8a02aae1ef6a + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b1/2c/cad8b5e3623a987f3c930b68e2bdd06cfc388cd91cd42ed05f1227701b73/chardet-7.4.3-cp314-cp314-win_amd64.whl + name: chardet + version: 7.4.3 + sha256: b95c934b9ad59e2ba8abb9be49df70d3ad1b0d95d864b9fdb7588d4fa8bd921c + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/c2/20/193faab46a68ea550587331a698c3dca8099f8901d10937c4443135c7ed9/chardet-7.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: chardet + version: 7.4.3 + sha256: 6e3bd9f936e04bae89c254262af08d9e5b98f805175ba1e29d454e6cba3107b7 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: chardet + version: 7.4.3 + sha256: 9a4904dd5f071b7a7d7f50b4a67a86db3c902d243bf31708f1d5cde2f68239cb + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda + sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 + md5: a9167b9571f3baa9d448faa2139d1089 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=compressed-mapping + size: 58872 + timestamp: 1775127203018 +- pypi: https://files.pythonhosted.org/packages/ae/44/c1221527f6a71a01ec6fbad7fa78f1d50dfa02217385cf0fa3eec7087d59/click-8.3.3-py3-none-any.whl + name: click + version: 8.3.3 + sha256: a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613 + requires_dist: + - colorama ; sys_platform == 'win32' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + name: colorama + version: 0.4.6 + sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/comm-0.2.3-pyhe01879c_0.conda + sha256: 576a44729314ad9e4e5ebe055fbf48beb8116b60e58f9070278985b2b634f212 + md5: 2da13f2b299d8e1995bafbbe9689a2f7 + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/comm?source=hash-mapping + size: 14690 + timestamp: 1753453984907 +- pypi: https://files.pythonhosted.org/packages/75/3f/aa2458b3b88e59b0be1a06685f237c944375186f4652eb9b5d43bb5ebe21/copier-9.14.3-py3-none-any.whl + name: copier + version: 9.14.3 + sha256: b237bb8a7fba91fbe0580ee54292e7a4c915028f08389f1ee99332fb70d2cab1 + requires_dist: + - colorama>=0.4.6 + - dunamai>=1.7.0 + - funcy>=1.17 + - jinja2-ansible-filters>=1.3.1 + - jinja2>=3.1.5 + - packaging>=23.0 + - pathspec>=0.9.0 + - platformdirs>=4.3.6 + - plumbum>=1.6.9 + - pydantic>=2.4.2 + - pygments>=2.7.1 + - pyyaml>=5.3.1 + - questionary>=1.8.1 + - typing-extensions>=4.0.0,<5.0.0 ; python_full_version < '3.11' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: coverage + version: 7.13.5 + sha256: 6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl + name: coverage + version: 7.13.5 + sha256: d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: coverage + version: 7.13.5 + sha256: 03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl + name: coverage + version: 7.13.5 + sha256: 2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl + name: coverage + version: 7.13.5 + sha256: 0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422 + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl + name: coverage + version: 7.13.5 + sha256: 9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e + requires_dist: + - tomli ; python_full_version <= '3.11' and extra == 'toml' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda + noarch: generic + sha256: d3e9bbd7340199527f28bbacf947702368f31de60c433a16446767d3c6aaf6fe + md5: f54c1ffb8ecedb85a8b7fcde3a187212 + depends: + - python >=3.12,<3.13.0a0 + - python_abi * *_cp312 + license: Python-2.0 + purls: [] + size: 46463 + timestamp: 1772728929620 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda + noarch: generic + sha256: 40dc224f2b718e5f034efd2332bc315a719063235f63673468d26a24770094ee + md5: f111d4cfaf1fe9496f386bc98ae94452 + depends: + - python >=3.14,<3.15.0a0 + - python_abi * *_cp314 + license: Python-2.0 + purls: [] + size: 49809 + timestamp: 1775614256655 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py312h8285ef7_0.conda + sha256: f20121b67149ff80bf951ccae7442756586d8789204cd08ade59397b22bfd098 + md5: ee1b48795ceb07311dd3e665dd4f5f33 + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2858582 + timestamp: 1769744978783 +- conda: https://conda.anaconda.org/conda-forge/linux-64/debugpy-1.8.20-py314h42812f9_0.conda + sha256: d9e89e351d7189c41615cfceca76b3bcacaa9c81d9945ac1caa6fb9e5184f610 + md5: 57e6fad901c05754d5256fe3ab9f277b + depends: + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2886804 + timestamp: 1769744977998 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py312h6510ced_0.conda + sha256: f0ca130b5ffd6949673d3c61d7b8562ab76ad8debafb83f8b3443d30c172f5eb + md5: da3b5efcb0caabcede61a6ce4e0a7669 + depends: + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - libcxx >=19 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2752978 + timestamp: 1769744996462 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/debugpy-1.8.20-py314he609de1_0.conda + sha256: 7736a82ebe75c0f3ea6991298363d1f2edb34291f8616c1d3719862881c3a167 + md5: 407c74dc27356ba6bf3a0191070e3ac0 + depends: + - python + - python 3.14.* *_cp314 + - __osx >=11.0 + - libcxx >=19 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 2778080 + timestamp: 1769745040206 +- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py312ha1a9051_0.conda + sha256: 5a886b1af3c66bf58213c7f3d802ea60fe8218313d9072bc1c9e8f7840548ba0 + md5: 032746a0b0663920f0afb18cec61062b + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 3996113 + timestamp: 1769745013982 +- conda: https://conda.anaconda.org/conda-forge/win-64/debugpy-1.8.20-py314hb98de8c_0.conda + sha256: ece1d8299ad081edaf1e5279f2a900bdedddb2c795ac029a06401543cd7610ad + md5: 48ae8370a4562f7049d587d017792a3a + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/debugpy?source=hash-mapping + size: 4026404 + timestamp: 1769745008861 +- conda: https://conda.anaconda.org/conda-forge/noarch/decorator-5.2.1-pyhd8ed1ab_0.conda + sha256: c17c6b9937c08ad63cb20a26f403a3234088e57d4455600974a0ce865cb14017 + md5: 9ce473d1d1be1cc3810856a48b3fab32 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/decorator?source=hash-mapping + size: 14129 + timestamp: 1740385067843 +- conda: https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 + sha256: 9717a059677553562a8f38ff07f3b9f61727bd614f505658b0a5ecbcf8df89be + md5: 961b3a227b437d82ad7054484cfa71b2 + depends: + - python >=3.6 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/defusedxml?source=hash-mapping + size: 24062 + timestamp: 1615232388757 +- pypi: https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl + name: distlib + version: 0.4.0 + sha256: 9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16 +- pypi: https://files.pythonhosted.org/packages/bf/50/98b146aea0f1cd7531d25f12bea69fa9ce8d1662124f93fb30dc4511b65e/docstring_parser_fork-0.0.14-py3-none-any.whl + name: docstring-parser-fork + version: 0.0.14 + sha256: 4c544f234ef2cc2749a3df32b70c437d77888b1099143a1ad5454452c574b9af + requires_dist: + - docstring-parser[docs] ; extra == 'dev' + - docstring-parser[test] ; extra == 'dev' + - pre-commit>=2.16.0 ; python_full_version >= '3.9' and extra == 'dev' + - pydoctor>=25.4.0 ; extra == 'docs' + - pytest ; extra == 'test' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/85/d7/9b6ac05350ab7f7d3a730ff143ff3e2cada54514117c37be37e26dc91242/docstripy-0.7.2-py3-none-any.whl + name: docstripy + version: 0.7.2 + sha256: c4ba35de6c1b1c51f7afad4a46d8953aad55dce1a490d198f7e98c8c63efefda + requires_dist: + - nbformat + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/fa/bc/8b8ec5a4bfc5b9cf3ce27a118339e994f88410be5677c96493e0ea28e76d/dunamai-1.26.1-py3-none-any.whl + name: dunamai + version: 1.26.1 + sha256: 2727d939c5b4257cb01ea404372803b477f5176e5a347c43beaf89cd5072e853 + requires_dist: + - importlib-metadata>=1.6.0 ; python_full_version < '3.8' + - packaging>=20.9 + requires_python: '>=3.5' +- pypi: ./ + name: easyapplication + version: 0.8.0+devdirty37 + sha256: 07cc2d7d4f893a9ef373e240902c667f8e8199338ae0340222e652dce6d225ab + requires_dist: + - pooch + - build ; extra == 'dev' + - copier ; extra == 'dev' + - docstripy ; extra == 'dev' + - format-docstring ; extra == 'dev' + - gitpython ; extra == 'dev' + - interrogate ; extra == 'dev' + - jinja2 ; extra == 'dev' + - jupyterquiz ; extra == 'dev' + - jupytext ; extra == 'dev' + - mike ; extra == 'dev' + - mkdocs ; extra == 'dev' + - mkdocs-autorefs ; extra == 'dev' + - mkdocs-jupyter ; extra == 'dev' + - mkdocs-markdownextradata-plugin ; extra == 'dev' + - mkdocs-material ; extra == 'dev' + - mkdocs-plugin-inline-svg ; extra == 'dev' + - mkdocstrings-python ; extra == 'dev' + - nbmake ; extra == 'dev' + - nbqa ; extra == 'dev' + - nbstripout ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pydoclint ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - pyyaml ; extra == 'dev' + - radon ; extra == 'dev' + - ruff ; extra == 'dev' + - spdx-headers ; extra == 'dev' + - validate-pyproject[all] ; extra == 'dev' + - versioningit ; extra == 'dev' + requires_python: '>=3.12' +- conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.1-pyhd8ed1ab_0.conda + sha256: ee6cf346d017d954255bbcbdb424cddea4d14e4ed7e9813e429db1d795d01144 + md5: 8e662bd460bda79b1ea39194e3c4c9ab + depends: + - python >=3.10 + - typing_extensions >=4.6.0 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup?source=hash-mapping + size: 21333 + timestamp: 1763918099466 +- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + name: execnet + version: 2.1.2 + sha256: 67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec + requires_dist: + - hatch ; extra == 'testing' + - pre-commit ; extra == 'testing' + - pytest ; extra == 'testing' + - tox ; extra == 'testing' + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda + sha256: 210c8165a58fdbf16e626aac93cc4c14dbd551a01d1516be5ecad795d2422cad + md5: ff9efb7f7469aed3c4a8106ffa29593c + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/executing?source=hash-mapping + size: 30753 + timestamp: 1756729456476 +- pypi: https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl + name: filelock + version: 3.29.0 + sha256: 96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/33/b2/986d1220f6ee931e338d272bc1f3ec02cfe5f9b5fad84e95afdad57f1ebc/format_docstring-0.2.7-py3-none-any.whl + name: format-docstring + version: 0.2.7 + sha256: c9d50eafebe0f260e3270ca662ff3a0ed4050f64d95e352f8c5f88d9aede42d6 + requires_dist: + - click>=8.0 + - jupyter-notebook-parser>=0.1.4 + - tomli>=1.1.0 ; python_full_version < '3.11' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/fqdn-1.5.1-pyhd8ed1ab_1.conda + sha256: 2509992ec2fd38ab27c7cdb42cf6cadc566a1cc0d1021a2673475d9fa87c6276 + md5: d3549fd50d450b6d9e7dddff25dd2110 + depends: + - cached-property >=1.3.0 + - python >=3.9,<4 + license: MPL-2.0 + license_family: MOZILLA + purls: + - pkg:pypi/fqdn?source=hash-mapping + size: 16705 + timestamp: 1733327494780 +- pypi: https://files.pythonhosted.org/packages/d5/08/c2409cb01d5368dcfedcbaffa7d044cc8957d57a9d0855244a5eb4709d30/funcy-2.0-py2.py3-none-any.whl + name: funcy + version: '2.0' + sha256: 53df23c8bb1651b12f095df764bfb057935d49537a56de211b098f4c79614bb0 +- pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + name: ghp-import + version: 2.1.0 + sha256: 8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 + requires_dist: + - python-dateutil>=2.8.1 + - twine ; extra == 'dev' + - markdown ; extra == 'dev' + - flake8 ; extra == 'dev' + - wheel ; extra == 'dev' +- pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl + name: gitdb + version: 4.0.12 + sha256: 67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf + requires_dist: + - smmap>=3.0.1,<6 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/fd/6f/b842bfa6f21d6f87c57f9abf7194225e55279d96d869775e19e9f7236fc5/gitpython-3.1.49-py3-none-any.whl + name: gitpython + version: 3.1.49 + sha256: 024b0422d7f84d15cd794844e029ffebd4c5d42a7eb9b936b458697ef550a02c + requires_dist: + - gitdb>=4.0.1,<5 + - typing-extensions>=3.10.0.2 ; python_full_version < '3.10' + - coverage[toml] ; extra == 'test' + - ddt>=1.1.1,!=1.4.3 ; extra == 'test' + - mock ; python_full_version < '3.8' and extra == 'test' + - mypy==1.18.2 ; python_full_version >= '3.9' and extra == 'test' + - pre-commit ; extra == 'test' + - pytest>=7.3.1 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-instafail ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-sugar ; extra == 'test' + - typing-extensions ; python_full_version < '3.11' and extra == 'test' + - sphinx>=7.4.7,<8 ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - sphinx-autodoc-typehints ; extra == 'doc' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl + name: griffelib + version: 2.0.2 + sha256: 925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1 + requires_dist: + - pip>=24.0 ; extra == 'pypi' + - platformdirs>=4.2 ; extra == 'pypi' + - wheel>=0.42 ; extra == 'pypi' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/h11-0.16.0-pyhcf101f3_1.conda + sha256: 96cac6573fd35ae151f4d6979bab6fbc90cb6b1fb99054ba19eb075da9822fcb + md5: b8993c19b0c32a2f7b66cbb58ca27069 + depends: + - python >=3.10 + - typing_extensions + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h11?source=compressed-mapping + size: 39069 + timestamp: 1767729720872 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 + md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 + depends: + - python >=3.10 + - hyperframe >=6.1,<7 + - hpack >=4.1,<5 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h2?source=hash-mapping + size: 95967 + timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba + md5: 0a802cb9888dd14eeefc611f05c40b6e + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hpack?source=hash-mapping + size: 30731 + timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpcore-1.0.9-pyh29332c3_0.conda + sha256: 04d49cb3c42714ce533a8553986e1642d0549a05dc5cc48e0d43ff5be6679a5b + md5: 4f14640d58e2cc0aa0819d9d8ba125bb + depends: + - python >=3.9 + - h11 >=0.16 + - h2 >=3,<5 + - sniffio 1.* + - anyio >=4.0,<5.0 + - certifi + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpcore?source=hash-mapping + size: 49483 + timestamp: 1745602916758 +- conda: https://conda.anaconda.org/conda-forge/noarch/httpx-0.28.1-pyhd8ed1ab_0.conda + sha256: cd0f1de3697b252df95f98383e9edb1d00386bfdd03fdf607fa42fe5fcb09950 + md5: d6989ead454181f4f9bc987d3dc4e285 + depends: + - anyio + - certifi + - httpcore 1.* + - idna + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/httpx?source=hash-mapping + size: 63082 + timestamp: 1733663449209 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hyperframe?source=hash-mapping + size: 17397 + timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a + md5: c80d8a3b84358cb967fa81e7075fbc8a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12723451 + timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5 + md5: f1182c91c0de31a7abd40cedf6a5ebef + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12361647 + timestamp: 1773822915649 +- pypi: https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl + name: identify + version: 2.6.19 + sha256: 20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a + requires_dist: + - ukkonen ; extra == 'license' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda + sha256: 9ab620e6f64bb67737bd7bc1ad6f480770124e304c6710617aba7fe60b089f48 + md5: fb7130c190f9b4ec91219840a05ba3ac + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/idna?source=compressed-mapping + size: 59038 + timestamp: 1776947141407 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda + sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 + md5: 080594bf4493e6bae2607e65390c520a + depends: + - python >=3.10 + - zipp >=3.20 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/importlib-metadata?source=compressed-mapping + size: 34387 + timestamp: 1773931568510 +- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + name: iniconfig + version: 2.3.0 + sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/12/c9/6869a1dcf4aaf309b9543ec070be3ec3adebee7c9bec9af8c230494134b9/interrogate-1.7.0-py3-none-any.whl + name: interrogate + version: 1.7.0 + sha256: b13ff4dd8403369670e2efe684066de9fcb868ad9d7f2b4095d8112142dc9d12 + requires_dist: + - attrs + - click>=7.1 + - colorama + - py + - tabulate + - tomli ; python_full_version < '3.11' + - cairosvg ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-autobuild ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-mock ; extra == 'dev' + - coverage[toml] ; extra == 'dev' + - wheel ; extra == 'dev' + - pre-commit ; extra == 'dev' + - sphinx ; extra == 'docs' + - sphinx-autobuild ; extra == 'docs' + - cairosvg ; extra == 'png' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-mock ; extra == 'tests' + - coverage[toml] ; extra == 'tests' + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh5552912_1.conda + sha256: 5c1f3e874adaf603449f2b135d48f168c5d510088c78c229bda0431268b43b27 + md5: 4b53d436f3fbc02ce3eeaf8ae9bebe01 + depends: + - appnope + - __osx + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 132260 + timestamp: 1770566135697 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyh6dadd2b_1.conda + sha256: 9cdadaeef5abadca4113f92f5589db19f8b7df5e1b81cb0225f7024a3aedefa3 + md5: b3a7d5842f857414d9ae831a799444dd + depends: + - __win + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 132382 + timestamp: 1770566174387 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipykernel-7.2.0-pyha191276_1.conda + sha256: b77ed58eb235e5ad80e742b03caeed4bbc2a2ef064cb9a2deee3b75dfae91b2a + md5: 8b267f517b81c13594ed68d646fd5dcb + depends: + - __linux + - comm >=0.1.1 + - debugpy >=1.6.5 + - ipython >=7.23.1 + - jupyter_client >=8.8.0 + - jupyter_core >=5.1,!=6.0.* + - matplotlib-inline >=0.1 + - nest-asyncio >=1.4 + - packaging >=22 + - psutil >=5.7 + - python >=3.10 + - pyzmq >=25 + - tornado >=6.4.1 + - traitlets >=5.4.0 + - python + constrains: + - appnope >=0.1.2 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipykernel?source=hash-mapping + size: 133644 + timestamp: 1770566133040 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyh53cf698_0.conda + sha256: a0af49948a1842dfd15a0b0b2fd56c94ddbd07e07a6c8b4bc70d43015eafaff0 + md5: 73e9657cd19605740d21efb14d8d0cb9 + depends: + - __unix + - decorator >=5.1.0 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - pexpect >4.6 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=compressed-mapping + size: 651632 + timestamp: 1777038396606 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython-9.13.0-pyhe2676ad_0.conda + sha256: f252ec33597115ff21cbb31051f6f9be34ca36cbbbf3d266b597660d8d8edde9 + md5: 5631ab99e902463d9dd4221e5b4eab6d + depends: + - __win + - decorator >=5.1.0 + - ipython_pygments_lexers >=1.0.0 + - jedi >=0.18.2 + - matplotlib-inline >=0.1.6 + - prompt-toolkit >=3.0.41,<3.1.0 + - psutil >=7 + - pygments >=2.14.0 + - python >=3.11 + - stack_data >=0.6.0 + - traitlets >=5.13.0 + - typing_extensions >=4.6 + - colorama >=0.4.4 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython?source=compressed-mapping + size: 650593 + timestamp: 1777038425499 +- conda: https://conda.anaconda.org/conda-forge/noarch/ipython_pygments_lexers-1.1.1-pyhd8ed1ab_0.conda + sha256: 894682a42a7d659ae12878dbcb274516a7031bbea9104e92f8e88c1f2765a104 + md5: bd80ba060603cc228d9d81c257093119 + depends: + - pygments + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/ipython-pygments-lexers?source=hash-mapping + size: 13993 + timestamp: 1737123723464 +- conda: https://conda.anaconda.org/conda-forge/noarch/isoduration-20.11.0-pyhd8ed1ab_1.conda + sha256: 08e838d29c134a7684bca0468401d26840f41c92267c4126d7b43a6b533b0aed + md5: 0b0154421989637d424ccf0f104be51a + depends: + - arrow >=0.15.0 + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/isoduration?source=hash-mapping + size: 19832 + timestamp: 1733493720346 +- conda: https://conda.anaconda.org/conda-forge/noarch/jedi-0.19.2-pyhd8ed1ab_1.conda + sha256: 92c4d217e2dc68983f724aa983cca5464dcb929c566627b26a2511159667dba8 + md5: a4f4c5dc9b80bc50e0d3dc4e6e8f1bd9 + depends: + - parso >=0.8.3,<0.9.0 + - python >=3.9 + license: Apache-2.0 AND MIT + purls: + - pkg:pypi/jedi?source=hash-mapping + size: 843646 + timestamp: 1733300981994 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d + depends: + - markupsafe >=2.0 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jinja2?source=compressed-mapping + size: 120685 + timestamp: 1764517220861 +- pypi: https://files.pythonhosted.org/packages/72/b9/313e8f2f2e9517ae050a692ae7b3e4b3f17cc5e6dfea0db51fe14e586580/jinja2_ansible_filters-1.3.2-py3-none-any.whl + name: jinja2-ansible-filters + version: 1.3.2 + sha256: e1082f5564917649c76fed239117820610516ec10f87735d0338688800a55b34 + requires_dist: + - jinja2 + - pyyaml + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' +- conda: https://conda.anaconda.org/conda-forge/noarch/json5-0.14.0-pyhd8ed1ab_0.conda + sha256: 9daa95bd164c8fa23b3ab196e906ef806141d749eddce2a08baa064f722d25fa + md5: 1269891272187518a0a75c286f7d0bbf + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/json5?source=compressed-mapping + size: 34731 + timestamp: 1774655440045 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonpointer-3.1.1-pyhcf101f3_0.conda + sha256: a3d10301b6ff399ba1f3d39e443664804a3d28315a4fb81e745b6817845f70ae + md5: 89bf346df77603055d3c8fe5811691e6 + depends: + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jsonpointer?source=hash-mapping + size: 14190 + timestamp: 1774311356147 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda + sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 + md5: ada41c863af263cc4c5fcbaff7c3e4dc + depends: + - attrs >=22.2.0 + - jsonschema-specifications >=2023.3.6 + - python >=3.10 + - referencing >=0.28.4 + - rpds-py >=0.25.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/jsonschema?source=hash-mapping + size: 82356 + timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda + sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 + md5: 439cd0f567d697b20a8f45cb70a1005a + depends: + - python >=3.10 + - referencing >=0.31.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/jsonschema-specifications?source=hash-mapping + size: 19236 + timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-with-format-nongpl-4.26.0-hcf101f3_0.conda + sha256: 6886fc61e4e4edd38fd38729976b134e8bd2143f7fce56cc80d7ac7bac99bce1 + md5: 8368d58342d0825f0843dc6acdd0c483 + depends: + - jsonschema >=4.26.0,<4.26.1.0a0 + - fqdn + - idna + - isoduration + - jsonpointer >1.13 + - rfc3339-validator + - rfc3986-validator >0.1.0 + - rfc3987-syntax >=1.1.0 + - uri-template + - webcolors >=24.6.0 + license: MIT + license_family: MIT + purls: [] + size: 4740 + timestamp: 1767839954258 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter-lsp-2.3.1-pyhcf101f3_0.conda + sha256: 3766e2ae59641c172cec8a821528bfa6bf9543ffaaeb8b358bfd5259dcf18e4e + md5: 0c3b465ceee138b9c39279cc02e5c4a0 + depends: + - importlib-metadata >=4.8.3 + - jupyter_server >=1.1.2 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-lsp?source=compressed-mapping + size: 61633 + timestamp: 1775136333147 +- pypi: https://files.pythonhosted.org/packages/f4/a4/61adb19f3c74b0dc0e411de4f06ebef564b1f179928f9dffcbd4b378f2ef/jupyter_notebook_parser-0.1.4-py2.py3-none-any.whl + name: jupyter-notebook-parser + version: 0.1.4 + sha256: 27b3b67cf898684e646d569f017cb27046774ad23866cb0bdf51d5f76a46476b + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.8.0-pyhcf101f3_0.conda + sha256: e402bd119720862a33229624ec23645916a7d47f30e1711a4af9e005162b84f3 + md5: 8a3d6d0523f66cf004e563a50d9392b3 + depends: + - jupyter_core >=5.1 + - python >=3.10 + - python-dateutil >=2.8.2 + - pyzmq >=25.0 + - tornado >=6.4.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-client?source=hash-mapping + size: 112785 + timestamp: 1767954655912 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyh6dadd2b_0.conda + sha256: ed709a6c25b731e01563521ef338b93986cd14b5bc17f35e9382000864872ccc + md5: a8db462b01221e9f5135be466faeb3e0 + depends: + - __win + - pywin32 + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + size: 64679 + timestamp: 1760643889625 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_core-5.9.1-pyhc90fa1f_0.conda + sha256: 1d34b80e5bfcd5323f104dbf99a2aafc0e5d823019d626d0dce5d3d356a2a52a + md5: b38fe4e78ee75def7e599843ef4c1ab0 + depends: + - __unix + - python + - platformdirs >=2.5 + - python >=3.10 + - traitlets >=5.3 + - python + constrains: + - pywin32 >=300 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-core?source=hash-mapping + size: 65503 + timestamp: 1760643864586 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.12.1-pyhcf101f3_0.conda + sha256: c7edb5682c6316a95ad781dccb1b6589cd2ec0bf94f23c21152974eb0363b5d7 + md5: bf42ee94c750c0b2e7e998b79ac299ea + depends: + - jsonschema-with-format-nongpl >=4.18.0 + - packaging + - python >=3.10 + - python-json-logger >=2.0.4 + - pyyaml >=5.3 + - referencing + - rfc3339-validator + - rfc3986-validator >=0.1.1 + - traitlets >=5.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-events?source=compressed-mapping + size: 24002 + timestamp: 1776861872237 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.17.0-pyhcf101f3_0.conda + sha256: 74c4e642be97c538dae1895f7052599dfd740d8bd251f727bce6453ce8d6cd9a + md5: d79a87dcfa726bcea8e61275feed6f83 + depends: + - anyio >=3.1.0 + - argon2-cffi >=21.1 + - jinja2 >=3.0.3 + - jupyter_client >=7.4.4 + - jupyter_core >=4.12,!=5.0.* + - jupyter_events >=0.11.0 + - jupyter_server_terminals >=0.4.4 + - nbconvert-core >=6.4.4 + - nbformat >=5.3.0 + - overrides >=5.0 + - packaging >=22.0 + - prometheus_client >=0.9 + - python >=3.10 + - pyzmq >=24 + - send2trash >=1.8.2 + - terminado >=0.8.3 + - tornado >=6.2.0 + - traitlets >=5.6.0 + - websocket-client >=1.7 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server?source=hash-mapping + size: 347094 + timestamp: 1755870522134 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.5.4-pyhcf101f3_0.conda + sha256: 5eda79ed9f53f590031d29346abd183051263227dd9ee667b5ca1133ce297654 + md5: 7b8bace4943e0dc345fc45938826f2b8 + depends: + - python >=3.10 + - terminado >=0.8.3 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyter-server-terminals?source=hash-mapping + size: 22052 + timestamp: 1768574057200 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.5.6-pyhd8ed1ab_0.conda + sha256: 436a70259a9b4e13ce8b15faa8b37342835954d77a0a74d21dd24547e0871088 + md5: bcbb401d6fa84e0cee34d4926b0e9e93 + depends: + - async-lru >=1.0.0 + - httpx >=0.25.0,<1 + - ipykernel >=6.5.0,!=6.30.0 + - jinja2 >=3.0.3 + - jupyter-lsp >=2.0.0 + - jupyter_core + - jupyter_server >=2.4.0,<3 + - jupyterlab_server >=2.28.0,<3 + - notebook-shim >=0.2 + - packaging + - python >=3.10 + - setuptools >=41.1.0 + - tomli >=1.2.2 + - tornado >=6.2.0 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab?source=hash-mapping + size: 8245973 + timestamp: 1773240966438 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.3.0-pyhd8ed1ab_2.conda + sha256: dc24b900742fdaf1e077d9a3458fd865711de80bca95fe3c6d46610c532c6ef0 + md5: fd312693df06da3578383232528c468d + depends: + - pygments >=2.4.1,<3 + - python >=3.9 + constrains: + - jupyterlab >=4.0.8,<5.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-pygments?source=hash-mapping + size: 18711 + timestamp: 1733328194037 +- conda: https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.28.0-pyhcf101f3_0.conda + sha256: 381d2d6a259a3be5f38a69463e0f6c5dcf1844ae113058007b51c3bef13a7cee + md5: a63877cb23de826b1620d3adfccc4014 + depends: + - babel >=2.10 + - jinja2 >=3.0.3 + - json5 >=0.9.0 + - jsonschema >=4.18 + - jupyter_server >=1.21,<3 + - packaging >=21.3 + - python >=3.10 + - requests >=2.31 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jupyterlab-server?source=hash-mapping + size: 51621 + timestamp: 1761145478692 +- pypi: https://files.pythonhosted.org/packages/b3/52/bc858b1665d0dec3a2511f4e6f5c18ea85c0977563d624d597c95d6d0fd7/jupyterquiz-2.9.6.4-py2.py3-none-any.whl + name: jupyterquiz + version: 2.9.6.4 + sha256: f8c4418f6c827454523fc882a30d744b585cb58ac1ae277769c3059d04fc272b +- pypi: https://files.pythonhosted.org/packages/16/5a/736dd2f4535dbf3bf26523f9158c011389ef88dd06ec2eef67fd744f1c7b/jupytext-1.19.1-py3-none-any.whl + name: jupytext + version: 1.19.1 + sha256: d8975035155d034bdfde5c0c37891425314b7ea8d3a6c4b5d18c294348714cd9 + requires_dist: + - markdown-it-py>=1.0 + - mdit-py-plugins + - nbformat + - packaging + - pyyaml + - tomli ; python_full_version < '3.11' + - autopep8 ; extra == 'dev' + - black ; extra == 'dev' + - flake8 ; extra == 'dev' + - gitpython ; extra == 'dev' + - ipykernel ; extra == 'dev' + - isort ; extra == 'dev' + - jupyter-fs[fs]>=1.0 ; extra == 'dev' + - jupyter-server!=2.11 ; extra == 'dev' + - marimo>=0.17.6,<=0.19.4 ; extra == 'dev' + - nbconvert ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-asyncio ; extra == 'dev' + - pytest-cov>=2.6.1 ; extra == 'dev' + - pytest-randomly ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-gallery>=0.8 ; extra == 'dev' + - myst-parser ; extra == 'docs' + - sphinx ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest ; extra == 'test' + - pytest-asyncio ; extra == 'test' + - pytest-randomly ; extra == 'test' + - pytest-xdist ; extra == 'test' + - black ; extra == 'test-cov' + - ipykernel ; extra == 'test-cov' + - jupyter-server!=2.11 ; extra == 'test-cov' + - nbconvert ; extra == 'test-cov' + - pytest ; extra == 'test-cov' + - pytest-asyncio ; extra == 'test-cov' + - pytest-cov>=2.6.1 ; extra == 'test-cov' + - pytest-randomly ; extra == 'test-cov' + - pytest-xdist ; extra == 'test-cov' + - autopep8 ; extra == 'test-external' + - black ; extra == 'test-external' + - flake8 ; extra == 'test-external' + - gitpython ; extra == 'test-external' + - ipykernel ; extra == 'test-external' + - isort ; extra == 'test-external' + - jupyter-fs[fs]>=1.0 ; extra == 'test-external' + - jupyter-server!=2.11 ; extra == 'test-external' + - marimo>=0.17.6,<=0.19.4 ; extra == 'test-external' + - nbconvert ; extra == 'test-external' + - pre-commit ; extra == 'test-external' + - pytest ; extra == 'test-external' + - pytest-asyncio ; extra == 'test-external' + - pytest-randomly ; extra == 'test-external' + - pytest-xdist ; extra == 'test-external' + - sphinx ; extra == 'test-external' + - sphinx-gallery>=0.8 ; extra == 'test-external' + - black ; extra == 'test-functional' + - pytest ; extra == 'test-functional' + - pytest-asyncio ; extra == 'test-functional' + - pytest-randomly ; extra == 'test-functional' + - pytest-xdist ; extra == 'test-functional' + - black ; extra == 'test-integration' + - ipykernel ; extra == 'test-integration' + - jupyter-server!=2.11 ; extra == 'test-integration' + - nbconvert ; extra == 'test-integration' + - pytest ; extra == 'test-integration' + - pytest-asyncio ; extra == 'test-integration' + - pytest-randomly ; extra == 'test-integration' + - pytest-xdist ; extra == 'test-integration' + - bash-kernel ; extra == 'test-ui' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda + sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 + md5: b38117a3c920364aff79f870c984b4a3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-or-later + purls: [] + size: 134088 + timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 + depends: + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1386730 + timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.22.2-h385eeb1_0.conda + sha256: c0a0bf028fe7f3defcdcaa464e536cf1b202d07451e18ad83fdd169d15bef6ed + md5: e446e1822f4da8e5080a9de93474184d + depends: + - __osx >=11.0 + - libcxx >=19 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 1160828 + timestamp: 1769770119811 +- conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.22.2-h0ea6238_0.conda + sha256: eb60f1ad8b597bcf95dee11bc11fe71a8325bc1204cf51d2bb1f2120ffd77761 + md5: 4432f52dc0c8eb6a7a6abc00a037d93c + depends: + - openssl >=3.5.5,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 751055 + timestamp: 1769769688841 +- conda: https://conda.anaconda.org/conda-forge/noarch/lark-1.3.1-pyhd8ed1ab_0.conda + sha256: 49570840fb15f5df5d4b4464db8ee43a6d643031a2bc70ef52120a52e3809699 + md5: 9b965c999135d43a3d0f7bd7d024e26a + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/lark?source=compressed-mapping + size: 94312 + timestamp: 1761596921009 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-h1aa0949_4.conda + sha256: 96b6900ca0489d9e5d0318a6b49f8eff43fd85fef6e07cb0c25344ee94cd7a3a + md5: c94ab6ff54ba5172cf1c58267005670f + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.44 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 742501 + timestamp: 1761335175964 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c + md5: 18335a698559cdbcd86150a48bf54ba6 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 728002 + timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20260107.1-cxx17_h7b12aa8_0.conda + sha256: a7a4481a4d217a3eadea0ec489826a69070fcc3153f00443aa491ed21527d239 + md5: 6f7b4302263347698fd24565fbf11310 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + constrains: + - libabseil-static =20260107.1=cxx17* + - abseil-cpp =20260107.1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 1384817 + timestamp: 1770863194876 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20260107.1-cxx17_h2062a1b_0.conda + sha256: 756611fbb8d2957a5b4635d9772bd8432cb6ddac05580a6284cca6fdc9b07fca + md5: bb65152e0d7c7178c0f1ee25692c9fd1 + depends: + - __osx >=11.0 + - libcxx >=19 + constrains: + - abseil-cpp =20260107.1 + - libabseil-static =20260107.1=cxx17* + license: Apache-2.0 + license_family: Apache + purls: [] + size: 1229639 + timestamp: 1770863511331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda + sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e + md5: 72c8fd1af66bd67bf580645b426513ed + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 79965 + timestamp: 1764017188531 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.2.0-hc919400_1.conda + sha256: a7cb9e660531cf6fbd4148cff608c85738d0b76f0975c5fc3e7d5e92840b7229 + md5: 006e7ddd8a110771134fcc4e1e3a6ffa + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 79443 + timestamp: 1764017945924 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda + sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b + md5: 366b40a69f0ad6072561c1d09301c886 + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 34632 + timestamp: 1764017199083 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.2.0-hc919400_1.conda + sha256: 2eae444039826db0454b19b52a3390f63bfe24f6b3e63089778dd5a5bf48b6bf + md5: 079e88933963f3f149054eec2c487bc2 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: [] + size: 29452 + timestamp: 1764017979099 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda + sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d + md5: 4ffbb341c8b616aa2494b6afb26a0c5f + depends: + - __glibc >=2.17,<3.0.a0 + - libbrotlicommon 1.2.0 hb03c661_1 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 298378 + timestamp: 1764017210931 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.2.0-hc919400_1.conda + sha256: 01436c32bb41f9cb4bcf07dda647ce4e5deb8307abfc3abdc8da5317db8189d1 + md5: b2b7c8288ca1a2d71ff97a8e6a1e8883 + depends: + - __osx >=11.0 + - libbrotlicommon 1.2.0 hc919400_1 + license: MIT + license_family: MIT + purls: [] + size: 290754 + timestamp: 1764018009077 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-22.1.4-h55c6f16_0.conda + sha256: 25a0d02148a39b665d9c2957676faf62a4d2a58494d53b201151199a197db4b0 + md5: 448a1af83a9205655ee1cf48d3875ca3 + depends: + - __osx >=11.0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 569927 + timestamp: 1776816293111 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda + sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 + md5: c277e0a4d549b03ac1e9d6cbbe3d017b + depends: + - ncurses + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 134676 + timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20250104-pl5321hafb1f1b_0.conda + sha256: 66aa216a403de0bb0c1340a88d1a06adaff66bae2cfd196731aa24db9859d631 + md5: 44083d2d2c2025afca315c7a172eab2b + depends: + - ncurses + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107691 + timestamp: 1738479560845 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 + md5: 172bf1cd1ff8629f2b1179945ed45055 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 112766 + timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + sha256: 95cecb3902fbe0399c3a7e67a5bed1db813e5ab0e22f4023a5e0f722f2cc214f + md5: 36d33e440c31857372a72137f78bacf5 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 107458 + timestamp: 1702146414478 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + sha256: e8c2b57f6aacabdf2f1b0924bd4831ce5071ba080baa4a9e8c0d720588b6794c + md5: 49f570f3bc4c874a06ea69b7225753af + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 76624 + timestamp: 1774719175983 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + sha256: 06780dec91dd25770c8cf01e158e1062fbf7c576b1406427475ce69a8af75b7e + md5: a32123f93e168eaa4080d87b0fb5da8a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 68192 + timestamp: 1774719211725 +- conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.7.5-hac47afa_0.conda + sha256: 6850c3a4d5dc215b86f58518cfb8752998533d6569b08da8df1da72e7c68e571 + md5: bfb43f52f13b7c56e7677aa7a8efdf0c + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 70609 + timestamp: 1774719377850 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda + sha256: 25cbdfa65580cfab1b8d15ee90b4c9f1e0d72128f1661449c9a999d341377d54 + md5: 35f29eec58405aaf55e01cb470d8c26a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 57821 + timestamp: 1760295480630 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 + md5: 43c04d9cb46ef176bb2a4c77e324d599 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda + sha256: 9b8acdf42df61b7bfe8bdc545c016c29e61985e79748c64ad66df47dbc2e295f + md5: 411ff7cd5d1472bba0f55c0faf04453b + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40251 + timestamp: 1760295839166 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h3d046cb_0.conda + sha256: 59d01f2dfa8b77491b5888a5ab88ff4e1574c9359f7e229da254cdfe27ddc190 + md5: 720b39f5ec0610457b725eb3f396219a + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 45831 + timestamp: 1769456418774 +- conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.5.2-h52bdfb6_0.conda + sha256: ddff25aaa4f0aa535413f5d831b04073789522890a4d8626366e43ecde1534a3 + md5: ba4ad812d2afc22b9a34ce8327a0930f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: [] + size: 44866 timestamp: 1760295760649 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda sha256: 08f9b87578ab981c7713e4e6a7d935e40766e10691732bba376d4964562bcb45 md5: c0374badb3a5d4b1372db28d19462c53 depends: - __glibc >=2.17,<3.0.a0 - - _openmp_mutex >=4.5 - constrains: - - libgomp 15.2.0 h767d61c_7 - - libgcc-ng ==15.2.0=*_7 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL + - _openmp_mutex >=4.5 + constrains: + - libgomp 15.2.0 h767d61c_7 + - libgcc-ng ==15.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 822552 + timestamp: 1759968052178 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 + md5: d5e96b1ed75ca01906b3d2469b4ce493 + depends: + - libgcc 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27526 + timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda + sha256: 2045066dd8e6e58aaf5ae2b722fb6dfdbb57c862b5f34ac7bfb58c40ef39b6ad + md5: 280ea6eee9e2ddefde25ff799c4f0363 + depends: + - libgcc 15.2.0 h767d61c_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 29313 + timestamp: 1759968065504 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda + sha256: e9fb1c258c8e66ee278397b5822692527c5f5786d372fe7a869b900853f3f5ca + md5: f7b4d76975aac7e5d9e6ad13845f92fe + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 447919 + timestamp: 1759967942498 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda + sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d + md5: b88d90cad08e6bc8ad540cb310a761fb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 113478 + timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.3-h8088a28_0.conda + sha256: 34878d87275c298f1a732c6806349125cebbf340d24c6c23727268184bba051e + md5: b1fd823b5ae54fbec272cea0811bd8a9 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 92472 + timestamp: 1775825802659 +- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.3-hfd05255_0.conda + sha256: d636d1a25234063642f9c531a7bb58d84c1c496411280a36ea000bd122f078f1 + md5: 8f83619ab1588b98dd99c90b0bfc5c6d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - xz 5.8.3.* + license: 0BSD + purls: [] + size: 106486 + timestamp: 1775825663227 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 92400 + timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda + sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee + md5: c7e925f37e3b40d893459e625f6a53f1 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 91183 + timestamp: 1748393666725 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda + sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2 + md5: 85ccccb47823dd9f7a99d2c7f530342f + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 71829 + timestamp: 1748393749336 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2 + md5: 57c4be259f5e0b99a5983799a228ae55 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 73690 + timestamp: 1769482560514 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda + sha256: fc529fc82c7caf51202cc5cec5bb1c2e8d90edbac6d0a4602c966366efe3c7bf + md5: 74860100b2029e2523cf480804c76b9b + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 88657 + timestamp: 1723861474602 +- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-hfd05255_1.conda + sha256: 40dcd0b9522a6e0af72a9db0ced619176e7cfdb114855c7a64f278e73f8a7514 + md5: e4a9fc2bba3b022dad998c78856afe47 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 89411 + timestamp: 1769482314283 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda + sha256: 663444d77a42f2265f54fb8b48c5450bfff4388d9c0f8253dd7855f0d993153f + md5: 2a45e7f8af083626f009645a6481f12d + depends: + - __glibc >=2.17,<3.0.a0 + - c-ares >=1.34.6,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc >=14 + - libstdcxx >=14 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 663344 + timestamp: 1773854035739 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.68.1-h8f3e76b_0.conda + sha256: 2bc7bc3978066f2c274ebcbf711850cc9ab92e023e433b9631958a098d11e10a + md5: 6ea18834adbc3b33df9bd9fb45eaf95b + depends: + - __osx >=11.0 + - c-ares >=1.34.6,<2.0a0 + - libcxx >=19 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + license: MIT + license_family: MIT + purls: [] + size: 576526 + timestamp: 1773854624224 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 + md5: 7af961ef4aa2c1136e11dd43ded245ab + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: ISC + purls: [] + size: 277661 + timestamp: 1772479381288 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.21-h1a92334_3.conda + sha256: df603472ea1ebd8e7d4fb71e4360fe48d10b11c240df51c129de1da2ff9e8227 + md5: 7cc5247987e6d115134ebab15186bc13 + depends: + - __osx >=11.0 + license: ISC + purls: [] + size: 248039 + timestamp: 1772479570912 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.21-h6a83c73_3.conda + sha256: d915f4fa8ebbf237c7a6e511ed458f2cfdc7c76843a924740318a15d0dd33d6d + md5: da2aa614d16a795b3007b6f4a1318a81 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: ISC + purls: [] + size: 276860 + timestamp: 1772479407566 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda + sha256: ec37c79f737933bbac965f5dc0f08ef2790247129a84bb3114fad4900adce401 + md5: 810d83373448da85c3f673fbcb7ad3a3 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.3,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 958864 + timestamp: 1775753750179 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.53.0-h1b79a29_0.conda + sha256: 1a9d1e3e18dbb0b87cff3b40c3e42703730d7ac7ee9b9322c2682196a81ba0c3 + md5: 8423c008105df35485e184066cad4566 + depends: + - __osx >=11.0 + - libzlib >=1.3.2,<2.0a0 + license: blessing + purls: [] + size: 920039 + timestamp: 1775754485962 +- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.53.0-hf5d6505_0.conda + sha256: 7a6256ea136936df4c4f3b227ba1e273b7d61152f9811b52157af497f07640b0 + md5: 4152b5a8d2513fd7ae9fb9f221a5595d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: blessing + purls: [] + size: 1301855 + timestamp: 1775753831574 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda + sha256: 1b981647d9775e1cdeb2fab0a4dd9cd75a6b0de2963f6c3953dbd712f78334b3 + md5: 5b767048b1b3ee9a954b06f4084f93dc + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 h767d61c_7 + constrains: + - libstdcxx-ng ==15.2.0=*_7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 3898269 + timestamp: 1759968103436 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 + md5: 38ffe67b78c9d4de527be8315e5ada2c + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40297 + timestamp: 1775052476770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.51.0-hb03c661_1.conda + sha256: c180f4124a889ac343fc59d15558e93667d894a966ec6fdb61da1604481be26b + md5: 0f03292cc56bf91a077a134ea8747118 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 895108 + timestamp: 1753948278280 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.51.0-h6caf38d_1.conda + sha256: 042c7488ad97a5629ec0a991a8b2a3345599401ecc75ad6a5af73b60e6db9689 + md5: c0d87c3c8e075daf1daf6c31b53e8083 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 421195 + timestamp: 1753948426421 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 + md5: d87ff7921124eccd67248aa483c23fec + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 63629 + timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05 + md5: bc5a5721b6439f2f62a84f2548136082 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 47759 + timestamp: 1774072956767 +- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.2-hfd05255_2.conda + sha256: 88609816e0cc7452bac637aaf65783e5edf4fee8a9f8e22bdc3a75882c536061 + md5: dbabbd6234dea34040e631f87676292f + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 58347 + timestamp: 1774072851498 +- pypi: https://files.pythonhosted.org/packages/d2/f0/834e479e47e499b6478e807fb57b31cc2db696c4db30557bb6f5aea4a90b/mando-0.7.1-py2.py3-none-any.whl + name: mando + version: 0.7.1 + sha256: 26ef1d70928b6057ee3ca12583d73c63e05c49de8972d620c278a7b206581a8a + requires_dist: + - six + - argparse ; python_full_version < '2.7' + - funcsigs ; python_full_version < '3.3' + - rst2ansi ; extra == 'restructuredtext' +- pypi: https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl + name: markdown + version: 3.10.2 + sha256: e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36 + requires_dist: + - coverage ; extra == 'testing' + - pyyaml ; extra == 'testing' + - mkdocs>=1.6 ; extra == 'docs' + - mkdocs-nature>=0.6 ; extra == 'docs' + - mdx-gh-links>=0.2 ; extra == 'docs' + - mkdocstrings[python]>=0.28.3 ; extra == 'docs' + - mkdocs-gen-files ; extra == 'docs' + - mkdocs-section-index ; extra == 'docs' + - mkdocs-literate-nav ; extra == 'docs' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + name: markdown-it-py + version: 4.0.0 + sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147 + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=3.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - markdown-it-pyrs ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins>=0.5.0 ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins>=0.5.0 ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme~=1.0 ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - ipykernel ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - requests ; extra == 'testing' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda + sha256: 5f3aad1f3a685ed0b591faad335957dbdb1b73abfd6fc731a0d42718e0653b33 + md5: 93a4752d42b12943a355b682ee43285b + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 26057 + timestamp: 1772445297924 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda + sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf + md5: 9a17c4307d23318476d7fbf0fedc0cde + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 27424 + timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py312h04c11ed_1.conda + sha256: 330394fb9140995b29ae215a19fad46fcc6691bdd1b7654513d55a19aaa091c1 + md5: 11d95ab83ef0a82cc2de12c1e0b47fe4 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 25564 + timestamp: 1772445846939 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.3-py314h6e9b3f0_1.conda + sha256: 411153d14ee0d98be6e3751cf5cc0502db17bce2deebebb8779e33d29d0e525f + md5: d33c0a15882b70255abdd54711b06a45 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=compressed-mapping + size: 27256 + timestamp: 1772445397216 +- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py312h05f76fc_1.conda + sha256: b744287a780211ac4595126ef96a44309c791f155d4724021ef99092bae4aace + md5: a73298d225c7852f97403ca105d10a13 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=compressed-mapping + size: 28510 + timestamp: 1772445175216 +- conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-3.0.3-py314h2359020_1.conda + sha256: 02805a0f3cd168dbf13afc5e4aed75cc00fe538ce143527a6471485b36f5887c + md5: 8de7b40f8b30a8fcaa423c2537fe4199 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe?source=hash-mapping + size: 30022 + timestamp: 1772445159549 +- conda: https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.2.1-pyhd8ed1ab_0.conda + sha256: 9d690334de0cd1d22c51bc28420663f4277cfa60d34fa5cad1ce284a13f1d603 + md5: 00e120ce3e40bad7bfc78861ce3c4a25 + depends: + - python >=3.10 + - traitlets + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/matplotlib-inline?source=hash-mapping + size: 15175 + timestamp: 1761214578417 +- pypi: https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl + name: mdit-py-plugins + version: 0.5.0 + sha256: 07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f + requires_dist: + - markdown-it-py>=2.0.0,<5.0.0 + - pre-commit ; extra == 'code-style' + - myst-parser ; extra == 'rtd' + - sphinx-book-theme ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + name: mdurl + version: 0.1.2 + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + name: mergedeep + version: 1.3.4 + sha256: 70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/76/8e/56ccb09c7232a55403a7637caa21922f3b65901a37f5e8bdb405d0de0946/mike-2.2.0-py3-none-any.whl + name: mike + version: 2.2.0 + sha256: e1f4981c1152eec7c2490a3401142292cc47d686194188416db2648fdfe1d040 + requires_dist: + - jinja2>=2.7 + - mkdocs~=1.0 + - pyparsing>=3.0 + - pyyaml>=5.1 + - pyyaml-env-tag + - verspec + - importlib-metadata ; python_full_version < '3.10' + - importlib-resources ; python_full_version < '3.10' + - coverage ; extra == 'dev' + - flake8-quotes ; extra == 'dev' + - flake8>=3.0 ; extra == 'dev' + - shtab ; extra == 'dev' + - coverage ; extra == 'test' + - flake8-quotes ; extra == 'test' + - flake8>=3.0 ; extra == 'test' + - shtab ; extra == 'test' +- conda: https://conda.anaconda.org/conda-forge/noarch/mistune-3.2.0-pyhcf101f3_0.conda + sha256: d3fb4beb5e0a52b6cc33852c558e077e1bfe44df1159eb98332d69a264b14bae + md5: b11e360fc4de2b0035fc8aaa74f17fd6 + depends: + - python >=3.10 + - typing_extensions + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/mistune?source=hash-mapping + size: 74250 + timestamp: 1766504456031 +- pypi: https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl + name: mkdocs + version: 1.6.1 + sha256: db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + requires_dist: + - click>=7.0 + - colorama>=0.4 ; sys_platform == 'win32' + - ghp-import>=1.0 + - importlib-metadata>=4.4 ; python_full_version < '3.10' + - jinja2>=2.11.1 + - markdown>=3.3.6 + - markupsafe>=2.0.1 + - mergedeep>=1.3.4 + - mkdocs-get-deps>=0.2.0 + - packaging>=20.5 + - pathspec>=0.11.1 + - pyyaml-env-tag>=0.1 + - pyyaml>=5.1 + - watchdog>=2.0 + - babel>=2.9.0 ; extra == 'i18n' + - babel==2.9.0 ; extra == 'min-versions' + - click==7.0 ; extra == 'min-versions' + - colorama==0.4 ; sys_platform == 'win32' and extra == 'min-versions' + - ghp-import==1.0 ; extra == 'min-versions' + - importlib-metadata==4.4 ; python_full_version < '3.10' and extra == 'min-versions' + - jinja2==2.11.1 ; extra == 'min-versions' + - markdown==3.3.6 ; extra == 'min-versions' + - markupsafe==2.0.1 ; extra == 'min-versions' + - mergedeep==1.3.4 ; extra == 'min-versions' + - mkdocs-get-deps==0.2.0 ; extra == 'min-versions' + - packaging==20.5 ; extra == 'min-versions' + - pathspec==0.11.1 ; extra == 'min-versions' + - pyyaml-env-tag==0.1 ; extra == 'min-versions' + - pyyaml==5.1 ; extra == 'min-versions' + - watchdog==2.0 ; extra == 'min-versions' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/28/de/a3e710469772c6a89595fc52816da05c1e164b4c866a89e3cb82fb1b67c5/mkdocs_autorefs-1.4.4-py3-none-any.whl + name: mkdocs-autorefs + version: 1.4.4 + sha256: 834ef5408d827071ad1bc69e0f39704fa34c7fc05bc8e1c72b227dfdc5c76089 + requires_dist: + - markdown>=3.3 + - markupsafe>=2.0.1 + - mkdocs>=1.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/88/29/744136411e785c4b0b744d5413e56555265939ab3a104c6a4b719dad33fd/mkdocs_get_deps-0.2.2-py3-none-any.whl + name: mkdocs-get-deps + version: 0.2.2 + sha256: e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650 + requires_dist: + - importlib-metadata>=4.3 ; python_full_version < '3.10' + - mergedeep>=1.3.4 + - platformdirs>=2.2.0 + - pyyaml>=5.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/13/95/cf3f7fe4910cf0365fa8ea0c731f4b8a624d97cd76ea777913ac8d0868e2/mkdocs_jupyter-0.26.3-py3-none-any.whl + name: mkdocs-jupyter + version: 0.26.3 + sha256: cd6644fb578131157194d750fd4d10fc2fd8f1e84e00036ee62df3b5b4b84c82 + requires_dist: + - ipykernel>6.0.0,<8 + - jupytext>1.13.8,<2 + - mkdocs-material>9.0.0 + - mkdocs>=1.4.0,<2 + - nbconvert>=7.2.9,<8 + - pygments>2.12.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a8/4e/c09876f08fa9faaa5e1178f3d77b7af3f343258689bd6f3b72593b2f74e3/mkdocs_markdownextradata_plugin-0.2.6-py3-none-any.whl + name: mkdocs-markdownextradata-plugin + version: 0.2.6 + sha256: 34dd40870781784c75809596b2d8d879da783815b075336d541de1f150c94242 + requires_dist: + - mkdocs + - pyyaml + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/2c/01/bc663630c510822c95c47a66af9fa7a443c295b47d5f041e5e6ae62ef659/mkdocs_material-9.7.6-py3-none-any.whl + name: mkdocs-material + version: 9.7.6 + sha256: 71b84353921b8ea1ba84fe11c50912cc512da8fe0881038fcc9a0761c0e635ba + requires_dist: + - babel>=2.10 + - backrefs>=5.7.post1 + - colorama>=0.4 + - jinja2>=3.1 + - markdown>=3.2 + - mkdocs-material-extensions>=1.3 + - mkdocs>=1.6,<2 + - paginate>=0.5 + - pygments>=2.16 + - pymdown-extensions>=10.2 + - requests>=2.30 + - mkdocs-git-committers-plugin-2>=1.1 ; extra == 'git' + - mkdocs-git-revision-date-localized-plugin>=1.2.4 ; extra == 'git' + - cairosvg>=2.6 ; extra == 'imaging' + - pillow>=10.2 ; extra == 'imaging' + - mkdocs-minify-plugin>=0.7 ; extra == 'recommended' + - mkdocs-redirects>=1.2 ; extra == 'recommended' + - mkdocs-rss-plugin>=1.6 ; extra == 'recommended' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl + name: mkdocs-material-extensions + version: 1.3.1 + sha256: adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/c6/3d/020a6b6248c3d4a37797db068256f0b3f15b01bc481327ba888c50309aa8/mkdocs_plugin_inline_svg-0.1.0-py3-none-any.whl + name: mkdocs-plugin-inline-svg + version: 0.1.0 + sha256: a5aab2d98a19b24019f8e650f54fc647c2f31e7d0e36fc5cf2d2161acc0ea49a + requires_dist: + - mkdocs + requires_python: '>=3.5' +- pypi: https://files.pythonhosted.org/packages/6e/94/be70f8ee9c45f2f62b39a1f0e9303bc20e138a8f3b8e50ffd89498e177e1/mkdocstrings-1.0.4-py3-none-any.whl + name: mkdocstrings + version: 1.0.4 + sha256: 63464b4b29053514f32a1dbbf604e52876d5e638111b0c295ab7ed3cac73ca9b + requires_dist: + - jinja2>=3.1 + - markdown>=3.6 + - markupsafe>=1.1 + - mkdocs>=1.6 + - mkdocs-autorefs>=1.4 + - pymdown-extensions>=6.3 + - mkdocstrings-crystal>=0.3.4 ; extra == 'crystal' + - mkdocstrings-python-legacy>=0.2.1 ; extra == 'python-legacy' + - mkdocstrings-python>=1.16.2 ; extra == 'python' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/32/28/79f0f8de97cce916d5ae88a7bee1ad724855e83e6019c0b4d5b3fabc80f3/mkdocstrings_python-2.0.3-py3-none-any.whl + name: mkdocstrings-python + version: 2.0.3 + sha256: 0b83513478bdfd803ff05aa43e9b1fca9dd22bcd9471f09ca6257f009bc5ee12 + requires_dist: + - mkdocstrings>=0.30 + - mkdocs-autorefs>=1.4 + - griffelib>=2.0 + - typing-extensions>=4.0 ; python_full_version < '3.11' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py312h4c3975b_0.conda + sha256: 25eb262c378a922eeed85c941ab7de2687ea842daed80521b861b7472b5a7f9a + md5: 5e07dc45b4458c19fdc085bd6c1aa51f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 218330 + timestamp: 1776337395109 +- conda: https://conda.anaconda.org/conda-forge/linux-64/msgspec-0.21.1-py314h5bd0f2a_0.conda + sha256: 52565ceea81e801c59dcaeaf5a9c77fba2fade445e67e0864fda50d4b944e15b + md5: 4a8ea416a56e58f012e445f7af2bbcc8 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 220990 + timestamp: 1776337508167 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py312h2bbb03f_0.conda + sha256: 50e284832520f08ef1e37e0ca20459f5df2c048f59dfba1f2e3ee0ccfe7be317 + md5: ae340bdc5bdf5abd3183c5962517cbde + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 212357 + timestamp: 1776338798628 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/msgspec-0.21.1-py314h6c2aa35_0.conda + sha256: 24a9105921e94fa526ffde1e956fa550c48ddb9ce4b0cf19ae22e79ed267261e + md5: 26fce586b13842a0f9f9a3aabae3e943 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 216965 + timestamp: 1776338889692 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py312he06e257_0.conda + sha256: 003de3343b481937b5eb500ecdbfc882e87cea608be3741dc1fb13d22f8ed95e + md5: 1f32f4f6aa595377a7e651e67ba53d30 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 199413 + timestamp: 1776337631789 +- conda: https://conda.anaconda.org/conda-forge/win-64/msgspec-0.21.1-py314h5a2d7ad_0.conda + sha256: 6a076225fa315d29c5d556e3912a6319aea60b4f458c23f23f5ce66495cb9414 + md5: a4b20f401c93cf8651093fcc8380e3c9 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/msgspec?source=hash-mapping + size: 201836 + timestamp: 1776337750218 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda + sha256: 1b66960ee06874ddceeebe375d5f17fb5f393d025a09e15b830ad0c4fffb585b + md5: 00f5b8dafa842e0c27c1cd7296aa4875 + depends: + - jupyter_client >=6.1.12 + - jupyter_core >=4.12,!=5.0.* + - nbformat >=5.1 + - python >=3.8 + - traitlets >=5.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbclient?source=compressed-mapping + size: 28473 + timestamp: 1766485646962 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.1-pyhcf101f3_0.conda + sha256: ab2ac79c5892c5434d50b3542d96645bdaa06d025b6e03734be29200de248ac2 + md5: 2bce0d047658a91b99441390b9b27045 + depends: + - beautifulsoup4 + - bleach-with-css !=5.0.0 + - defusedxml + - importlib-metadata >=3.6 + - jinja2 >=3.0 + - jupyter_core >=4.7 + - jupyterlab_pygments + - markupsafe >=2.0 + - mistune >=2.0.3,<4 + - nbclient >=0.5.0 + - nbformat >=5.7 + - packaging + - pandocfilters >=1.4.1 + - pygments >=2.4.1 + - python >=3.10 + - traitlets >=5.1 + - python + constrains: + - pandoc >=2.9.2,<4.0.0 + - nbconvert ==7.17.1 *_0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbconvert?source=compressed-mapping + size: 202229 + timestamp: 1775615493260 +- conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda + sha256: 7a5bd30a2e7ddd7b85031a5e2e14f290898098dc85bea5b3a5bf147c25122838 + md5: bbe1963f1e47f594070ffe87cdf612ea + depends: + - jsonschema >=2.6 + - jupyter_core >=4.12,!=5.0.* + - python >=3.9 + - python-fastjsonschema >=2.15 + - traitlets >=5.1 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/nbformat?source=hash-mapping + size: 100945 + timestamp: 1733402844974 +- pypi: https://files.pythonhosted.org/packages/eb/be/b257e12f9710819fde40adc972578bee6b72c5992da1bc8369bef2597756/nbmake-1.5.5-py3-none-any.whl + name: nbmake + version: 1.5.5 + sha256: c6fbe6e48b60cacac14af40b38bf338a3b88f47f085c54ac5b8639ff0babaf4b + requires_dist: + - ipykernel>=5.4.0 + - nbclient>=0.6.6 + - nbformat>=5.0.4 + - pygments>=2.7.3 + - pytest>=6.1.0 + requires_python: '>=3.8.0' +- pypi: https://files.pythonhosted.org/packages/28/88/4789719fbbe166d12d345b3ac66b96105f10001b16e00a9765ba29261a21/nbqa-1.9.1-py3-none-any.whl + name: nbqa + version: 1.9.1 + sha256: 95552d2f6c2c038136252a805aa78d85018aef922586270c3a074332737282e5 + requires_dist: + - autopep8>=1.5 + - ipython>=7.8.0 + - tokenize-rt>=3.2.0 + - tomli + - black ; extra == 'toolchain' + - blacken-docs ; extra == 'toolchain' + - flake8 ; extra == 'toolchain' + - isort ; extra == 'toolchain' + - jupytext ; extra == 'toolchain' + - mypy ; extra == 'toolchain' + - pylint ; extra == 'toolchain' + - pyupgrade ; extra == 'toolchain' + - ruff ; extra == 'toolchain' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/20/16/e777eadfa0c0305878c36fae1d5e6db474fbb15dae202b9ec378809dfb4d/nbstripout-0.9.1-py3-none-any.whl + name: nbstripout + version: 0.9.1 + sha256: ca027ee45742ee77e4f8e9080254f9a707f1161ba11367b82fdf4a29892c759e + requires_dist: + - nbformat + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: X11 AND BSD-3-Clause purls: [] - size: 822552 - timestamp: 1759968052178 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - sha256: e9fb1c258c8e66ee278397b5822692527c5f5786d372fe7a869b900853f3f5ca - md5: f7b4d76975aac7e5d9e6ad13845f92fe + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda + sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 + md5: fc21868a1a5aacc937e7a18747acb8a5 depends: - __glibc >=2.17,<3.0.a0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL + - libgcc >=14 + license: X11 AND BSD-3-Clause purls: [] - size: 447919 - timestamp: 1759967942498 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8 - md5: 1a580f7796c7bf6393fddb8bbbde58dc + size: 918956 + timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 797030 + timestamp: 1738196177597 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.6-h1d4f5a5_0.conda + sha256: 4ea6c620b87bd1d42bb2ccc2c87cd2483fa2d7f9e905b14c223f11ff3f4c455d + md5: 343d10ed5b44030a2f67193905aea159 + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 805509 + timestamp: 1777423252320 +- conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda + sha256: bb7b21d7fd0445ddc0631f64e66d91a179de4ba920b8381f29b9d006a42788c0 + md5: 598fd7d4d0de2455fb74f56063969a97 + depends: + - python >=3.9 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/nest-asyncio?source=hash-mapping + size: 11543 + timestamp: 1733325673691 +- pypi: https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl + name: nodeenv + version: 1.10.0 + sha256: 5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.8.2-he4ff34a_0.conda + sha256: d1a673d1418d9e956b6e4e46c23e72a511c5c1d45dc5519c947457427036d5e2 + md5: baffb1570b3918c784d4490babc52fbf + depends: + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.28,<3.0.a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libuv >=1.51.0,<2.0a0 + - c-ares >=1.34.6,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - libsqlite >=3.52.0,<4.0a0 + - icu >=78.3,<79.0a0 + - libzlib >=1.3.2,<2.0a0 + - libabseil >=20260107.1,<20260108.0a0 + - libabseil * cxx17* + - zstd >=1.5.7,<1.6.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + license: MIT + license_family: MIT + purls: [] + size: 18829340 + timestamp: 1774514313036 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.8.2-h7039424_0.conda + sha256: 4782b172b3b8a557b60bf5f591821cf100e2092ba7a5494ce047dfa41626de26 + md5: ca8277c52fdface8bb8ebff7cd9a6f56 + depends: + - libcxx >=19 + - __osx >=11.0 + - icu >=78.3,<79.0a0 + - libbrotlicommon >=1.2.0,<1.3.0a0 + - libbrotlienc >=1.2.0,<1.3.0a0 + - libbrotlidec >=1.2.0,<1.3.0a0 + - libnghttp2 >=1.68.1,<2.0a0 + - libuv >=1.51.0,<2.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - zstd >=1.5.7,<1.6.0a0 + - c-ares >=1.34.6,<2.0a0 + - libabseil >=20260107.1,<20260108.0a0 + - libabseil * cxx17* + license: MIT + license_family: MIT + purls: [] + size: 17101803 + timestamp: 1774517834028 +- conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-25.8.2-h80d1838_0.conda + sha256: 5e38e51da1aa4bc352db9b4cec1c3e25811de0f4408edaa24e009a64de6dbfdf + md5: e626ee7934e4b7cb21ce6b721cff8677 + license: MIT + license_family: MIT + purls: [] + size: 31271315 + timestamp: 1774517904472 +- conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda + sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 + md5: e7f89ea5f7ea9401642758ff50a2d9c1 + depends: + - jupyter_server >=1.8,<3 + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/notebook-shim?source=hash-mapping + size: 16817 + timestamp: 1733408419340 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda + sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb + md5: da1b85b6a87e141f5140bb9924cecab0 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3167099 + timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.2-hd24854e_0.conda + sha256: c91bf510c130a1ea1b6ff023e28bac0ccaef869446acd805e2016f69ebdc49ea + md5: 25dcccd4f80f1638428613e0d7c9b4e1 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3106008 + timestamp: 1775587972483 +- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.6.2-hf411b9b_0.conda + sha256: feb5815125c60f2be4a411e532db1ed1cd2d7261a6a43c54cb6ae90724e2e154 + md5: 05c7d624cff49dbd8db1ad5ba537a8a3 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 9410183 + timestamp: 1775589779763 +- conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda + sha256: 1840bd90d25d4930d60f57b4f38d4e0ae3f5b8db2819638709c36098c6ba770c + md5: e51f1e4089cad105b6cac64bd8166587 + depends: + - python >=3.9 + - typing_utils + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/overrides?source=hash-mapping + size: 30139 + timestamp: 1734587755455 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda + sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 + md5: 4c06a92e74452cfa53623a81592e8934 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=compressed-mapping + size: 91574 + timestamp: 1777103621679 +- pypi: https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl + name: paginate + version: 0.5.7 + sha256: b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 + requires_dist: + - pytest ; extra == 'dev' + - tox ; extra == 'dev' + - black ; extra == 'lint' +- conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 + sha256: 2bb9ba9857f4774b85900c2562f7e711d08dd48e2add9bee4e1612fbee27e16f + md5: 457c2c8c08e54905d6954e79cb5b5db9 + depends: + - python !=3.0,!=3.1,!=3.2,!=3.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pandocfilters?source=hash-mapping + size: 11627 + timestamp: 1631603397334 +- conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda + sha256: 42b2d77ccea60752f3aa929a6413a7835aaacdbbde679f2f5870a744fa836b94 + md5: 97c1ce2fffa1209e7afb432810ec6e12 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/parso?source=hash-mapping + size: 82287 + timestamp: 1770676243987 +- pypi: https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl + name: pathspec + version: 1.1.1 + sha256: a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + requires_dist: + - hyperscan>=0.7 ; extra == 'hyperscan' + - typing-extensions>=4 ; extra == 'optional' + - google-re2>=1.1 ; extra == 're2' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda + sha256: 202af1de83b585d36445dc1fda94266697341994d1a3328fabde4989e1b3d07a + md5: d0d408b1f18883a944376da5cf8101ea + depends: + - ptyprocess >=0.5 + - python >=3.9 + license: ISC + purls: + - pkg:pypi/pexpect?source=hash-mapping + size: 53561 + timestamp: 1733302019362 +- conda: https://conda.anaconda.org/conda-forge/noarch/pixi-kernel-0.7.1-pyhbbac1ac_0.conda + sha256: 506c9330b8dc5ae98f4c32629fa59fa40e6bdd42a681c48d2f9554693dd01156 + md5: d57ef7cb7ad6b5d62cef8b9bdf1d400b + depends: + - ipykernel >=6 + - jupyter_client >=7 + - jupyter_server >=2.4 + - msgspec >=0.18 + - python >=3.10 + - returns >=0.23 + - tomli >=2 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pixi-kernel?source=hash-mapping + size: 39509 + timestamp: 1764156429044 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.6-pyhcf101f3_0.conda + sha256: 8f29915c172f1f7f4f7c9391cd5dac3ebf5d13745c8b7c8006032615246345a5 + md5: 89c0b6d1793601a2a3a3f7d2d3d8b937 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/platformdirs?source=compressed-mapping + size: 25862 + timestamp: 1775741140609 +- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + name: pluggy + version: 1.6.0 + sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 + requires_dist: + - pre-commit ; extra == 'dev' + - tox ; extra == 'dev' + - pytest ; extra == 'testing' + - pytest-benchmark ; extra == 'testing' + - coverage ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/79/ad/45312df6b63ba64ea35b8d8f5f0c577aac16e6b416eafe8e1cb34e03f9a7/plumbum-1.10.0-py3-none-any.whl + name: plumbum + version: 1.10.0 + sha256: 9583d737ac901c474d99d030e4d5eec4c4e6d2d7417b1cf49728cf3be34f6dc8 + requires_dist: + - pywin32 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32' + - paramiko ; extra == 'ssh' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2a/2d/d4bf65e47cea8ff2c794a600c4fd1273a7902f268757c531e0ee9f18aa58/pooch-1.9.0-py3-none-any.whl + name: pooch + version: 1.9.0 + sha256: f265597baa9f760d25ceb29d0beb8186c243d6607b0f60b83ecf14078dbc703b + requires_dist: + - platformdirs>=2.5.0 + - packaging>=20.0 + - requests>=2.19.0 + - tqdm>=4.41.0,<5.0.0 ; extra == 'progress' + - paramiko>=2.7.0 ; extra == 'sftp' + - xxhash>=1.4.3 ; extra == 'xxhash' + - pytest-httpserver ; extra == 'test' + - pytest-localftpserver ; extra == 'test' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl + name: pre-commit + version: 4.6.0 + sha256: e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b + requires_dist: + - cfgv>=2.0.0 + - identify>=1.0.0 + - nodeenv>=0.11.1 + - pyyaml>=5.1 + - virtualenv>=20.10.0 + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.25.0-pyhd8ed1ab_0.conda + sha256: 4d7ec90d4f9c1f3b4a50623fefe4ebba69f651b102b373f7c0e9dbbfa43d495c + md5: a11ab1f31af799dd93c3a39881528884 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/prometheus-client?source=compressed-mapping + size: 57113 + timestamp: 1775771465170 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.51-pyha770c72_0.conda + sha256: ebc1bb62ac612af6d40667da266ff723662394c0ca78935340a5b5c14831227b + md5: d17ae9db4dc594267181bd199bf9a551 + depends: + - python >=3.9 + - wcwidth constrains: - - xz 5.8.1.* - license: 0BSD + - prompt_toolkit 3.0.51 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/prompt-toolkit?source=hash-mapping + size: 271841 + timestamp: 1744724188108 +- conda: https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.52-pyha770c72_0.conda + sha256: 4817651a276016f3838957bfdf963386438c70761e9faec7749d411635979bae + md5: edb16f14d920fb3faf17f5ce582942d6 + depends: + - python >=3.10 + - wcwidth + constrains: + - prompt_toolkit 3.0.52 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/prompt-toolkit?source=hash-mapping + size: 273927 + timestamp: 1756321848365 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py312h5253ce2_0.conda + sha256: d834fd656133c9e4eaf63ffe9a117c7d0917d86d89f7d64073f4e3a0020bd8a7 + md5: dd94c506b119130aef5a9382aed648e7 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=compressed-mapping + size: 225545 + timestamp: 1769678155334 +- conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-7.2.2-py314h0f05182_0.conda + sha256: f15574ed6c8c8ed8c15a0c5a00102b1efe8b867c0bd286b498cd98d95bd69ae5 + md5: 4f225a966cfee267a79c5cb6382bd121 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 231303 + timestamp: 1769678156552 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py312hb3ab3e3_0.conda + sha256: 6d0e21c76436374635c074208cfeee62a94d3c37d0527ad67fd8a7615e546a05 + md5: fd856899666759403b3c16dcba2f56ff + depends: + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 239031 + timestamp: 1769678393511 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-7.2.2-py314ha14b1ff_0.conda + sha256: e0f31c053eb11803d63860c213b2b1b57db36734f5f84a3833606f7c91fedff9 + md5: fc4c7ab223873eee32080d51600ce7e7 + depends: + - python + - __osx >=11.0 + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 245502 + timestamp: 1769678303655 +- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py312he5662c2_0.conda + sha256: edffc84c001a05b996b5f8607c8164432754e86ec9224e831cd00ebabdec04e7 + md5: a2724c93b745fc7861948eb8b9f6679a + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 242769 + timestamp: 1769678170631 +- conda: https://conda.anaconda.org/conda-forge/win-64/psutil-7.2.2-py314hc5dbbe4_0.conda + sha256: 17c8274ce5a32c9793f73a5a0094bd6188f3a13026a93147655143d4df034214 + md5: fd539ac231820f64066839251aa9fa48 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil?source=hash-mapping + size: 249950 + timestamp: 1769678167309 +- conda: https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd8ed1ab_1.conda + sha256: a7713dfe30faf17508ec359e0bc7e0983f5d94682492469bd462cdaae9c64d83 + md5: 7d9daffbb8d8e0af0f769dbbcd173a54 + depends: + - python >=3.9 + license: ISC + purls: + - pkg:pypi/ptyprocess?source=hash-mapping + size: 19457 + timestamp: 1733302371990 +- conda: https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.3-pyhd8ed1ab_1.conda + sha256: 71bd24600d14bb171a6321d523486f6a06f855e75e547fa0cb2a0953b02047f0 + md5: 3bfdfb8dbcdc4af1ae3f9a8eb3948f04 + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pure-eval?source=hash-mapping + size: 16668 + timestamp: 1733569518868 +- pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + name: py + version: 1.11.0 + sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' +- pypi: https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl + name: pycodestyle + version: 2.14.0 + sha256: dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda + sha256: 79db7928d13fab2d892592223d7570f5061c192f27b9febd1a418427b719acc6 + md5: 12c566707c80111f9799308d9e265aef + depends: + - python >=3.9 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pycparser?source=hash-mapping + size: 110100 + timestamp: 1733195786147 +- pypi: https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl + name: pydantic + version: 2.13.3 + sha256: 6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927 + requires_dist: + - annotated-types>=0.6.0 + - pydantic-core==2.46.3 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 + - email-validator>=2.0.0 ; extra == 'email' + - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl + name: pydantic-core + version: 2.46.3 + sha256: 8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.46.3 + sha256: ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/57/be/6b5e757b859013ebfbd7adba02f23b428f37c86dcbf78b5bb0b4ffd36e99/pydantic_core-2.46.3-cp312-cp312-win_amd64.whl + name: pydantic-core + version: 2.46.3 + sha256: c3212fda0ee959c1dd04c60b601ec31097aaa893573a3a1abd0a47bcac2968c1 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5e/d5/e3d9717c9eba10855325650afd2a9cba8e607321697f18953af9d562da2f/pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.46.3 + sha256: fb528e295ed31570ac3dcc9bfdd6e0150bc11ce6168ac87a8082055cf1a67395 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a1/4f/2fb62c2267cae99b815bbf4a7b9283812c88ca3153ef29f7707200f1d4e5/pydantic_core-2.46.3-cp312-cp312-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.46.3 + sha256: af8653713055ea18a3abc1537fe2ebc42f5b0bbb768d1eb79fd74eb47c0ac089 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.46.3 + sha256: ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/87/6f/cc2b231dc78d8c3aaa674a676db190b8f8071c50134af8f8cf39b9b8e8df/pydoclint-0.8.3-py3-none-any.whl + name: pydoclint + version: 0.8.3 + sha256: 5fc9b82d0d515afce0908cb70e8ff695a68b19042785c248c4f227ad66b4a164 + requires_dist: + - click>=8.1.0 + - docstring-parser-fork>=0.0.12 + - tomli>=2.0.1 ; python_full_version < '3.11' + - flake8>=4 ; extra == 'flake8' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda + sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 + md5: 16c18772b340887160c79a6acc022db0 + depends: + - python >=3.10 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pygments?source=compressed-mapping + size: 893031 + timestamp: 1774796815820 +- pypi: https://files.pythonhosted.org/packages/f7/27/a2fc51a4a122dfd1015e921ae9d22fee3d20b0b8080d9a704578bf9deece/pymdown_extensions-10.21.2-py3-none-any.whl + name: pymdown-extensions + version: 10.21.2 + sha256: 5c0fd2a2bea14eb39af8ff284f1066d898ab2187d81b889b75d46d4348c01638 + requires_dist: + - markdown>=3.6 + - pyyaml + - pygments>=2.19.1 ; extra == 'extra' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py312h19bbe71_0.conda + sha256: b015f430fe9ea2c53e14be13639f1b781f68deaa5ae74cd8c1d07720890cd02a + md5: c65d7abdc9e60fd3af0ed852591adf1b + depends: + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-core?source=hash-mapping + size: 476750 + timestamp: 1763151865523 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-core-12.1-py314h3a4d195_0.conda + sha256: df5af268c5a74b7160d772c263ece6f43257faff571783443e34b5f1d5a61cf2 + md5: 75a84fc8337557347252cc4fd3ba2a93 + depends: + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - setuptools + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-core?source=hash-mapping + size: 483374 + timestamp: 1763151489724 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py312h1de3e18_0.conda + sha256: 3710f5ae09c2ea77ba4d82cc51e876d9fc009b878b197a40d3c6347c09ae7d7c + md5: f0bae1b67ece138378923e340b940051 + depends: + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pyobjc-core 12.1.* + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping + size: 377723 + timestamp: 1763160705325 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyobjc-framework-cocoa-12.1-py314h36abed7_0.conda + sha256: aa76ee4328d0514d7c1c455dcd2d3b547db1c59797e54ce0a3f27de5b970e508 + md5: 4219bb3408016e22316cf8b443b5ef93 + depends: + - __osx >=11.0 + - libffi >=3.5.2,<3.6.0a0 + - pyobjc-core 12.1.* + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyobjc-framework-cocoa?source=hash-mapping + size: 374792 + timestamp: 1763160601898 +- pypi: https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl + name: pyparsing + version: 3.3.2 + sha256: 850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d + requires_dist: + - railroad-diagrams ; extra == 'diagrams' + - jinja2 ; extra == 'diagrams' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl + name: pyproject-hooks + version: 1.2.0 + sha256: 9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913 + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh09c184e_7.conda + sha256: d016e04b0e12063fbee4a2d5fbb9b39a8d191b5a0042f0b8459188aedeabb0ca + md5: e2fd202833c4a981ce8a65974fe4abd1 + depends: + - __win + - python >=3.9 + - win_inet_pton + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21784 + timestamp: 1733217448189 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 + md5: 461219d1a5bd61342293efa2c0c90eac + depends: + - __unix + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21085 + timestamp: 1733217331982 +- pypi: https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl + name: pytest + version: 9.0.3 + sha256: 2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9 + requires_dist: + - colorama>=0.4 ; sys_platform == 'win32' + - exceptiongroup>=1 ; python_full_version < '3.11' + - iniconfig>=1.0.1 + - packaging>=22 + - pluggy>=1.5,<2 + - pygments>=2.7.2 + - tomli>=1 ; python_full_version < '3.11' + - argcomplete ; extra == 'dev' + - attrs>=19.2 ; extra == 'dev' + - hypothesis>=3.56 ; extra == 'dev' + - mock ; extra == 'dev' + - requests ; extra == 'dev' + - setuptools ; extra == 'dev' + - xmlschema ; extra == 'dev' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl + name: pytest-cov + version: 7.1.0 + sha256: a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 + requires_dist: + - coverage[toml]>=7.10.6 + - pluggy>=1.2 + - pytest>=7 + - process-tests ; extra == 'testing' + - pytest-xdist ; extra == 'testing' + - virtualenv ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + name: pytest-xdist + version: 3.8.0 + sha256: 202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88 + requires_dist: + - execnet>=2.1 + - pytest>=7.0.0 + - filelock ; extra == 'testing' + - psutil>=3.0 ; extra == 'psutil' + - setproctitle ; extra == 'setproctitle' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e + md5: 7eccb41177e15cc672e1babe9056018e + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 31608571 + timestamp: 1772730708989 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda + build_number: 100 + sha256: dec247c5badc811baa34d6085df9d0465535883cf745e22e8d79092ad54a3a7b + md5: a443f87920815d41bfe611296e507995 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libuuid >=2.42,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 purls: [] - size: 112894 - timestamp: 1749230047870 -- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.1-hd471939_2.conda - sha256: 7e22fd1bdb8bf4c2be93de2d4e718db5c548aa082af47a7430eb23192de6bb36 - md5: 8468beea04b9065b9807fc8b9cdc5894 + size: 36705460 + timestamp: 1775614357822 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.13-h8561d8f_0_cpython.conda + sha256: e658e647a4a15981573d6018928dec2c448b10c77c557c29872043ff23c0eb6a + md5: 8e7608172fa4d1b90de9a745c2fd2b81 depends: - - __osx >=10.13 + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata constrains: - - xz 5.8.1.* - license: 0BSD + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 12127424 + timestamp: 1772730755512 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.4-h4c637c5_100_cp314.conda + build_number: 100 + sha256: 27e7d6cbe021f37244b643f06a98e46767255f7c2907108dd3736f042757ddad + md5: e1bc5a3015a4bbeb304706dba5a32b7f + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 purls: [] - size: 104826 - timestamp: 1749230155443 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.1-h39f12f2_2.conda - sha256: 0cb92a9e026e7bd4842f410a5c5c665c89b2eb97794ffddba519a626b8ce7285 - md5: d6df911d4564d77c4374b02552cb17d1 + size: 13533346 + timestamp: 1775616188373 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.13-h0159041_0_cpython.conda + sha256: a02b446d8b7b167b61733a3de3be5de1342250403e72a63b18dac89e99e6180e + md5: 2956dff38eb9f8332ad4caeba941cfe7 depends: - - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - openssl >=3.5.5,<4.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 constrains: - - xz 5.8.1.* - license: 0BSD + - python_abi 3.12.* *_cp312 + license: Python-2.0 purls: [] - size: 92286 - timestamp: 1749230283517 -- conda: https://conda.anaconda.org/conda-forge/win-64/liblzma-5.8.1-h2466b09_2.conda - sha256: 55764956eb9179b98de7cc0e55696f2eff8f7b83fc3ebff5e696ca358bca28cc - md5: c15148b2e18da456f5108ccb5e411446 + size: 15840187 + timestamp: 1772728877265 +- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.14.4-h4b44e0e_100_cp314.conda + build_number: 100 + sha256: e258d626b0ba778abb319f128de4c1211306fe86fe0803166817b1ce2514c920 + md5: 40b6a8f438afb5e7b314cc5c4a43cd84 depends: + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.5,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.52.0,<4.0a0 + - libzlib >=1.3.2,<2.0a0 + - openssl >=3.5.6,<4.0a0 + - python_abi 3.14.* *_cp314 + - tk >=8.6.13,<8.7.0a0 + - tzdata - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - xz 5.8.1.* - license: 0BSD + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 purls: [] - size: 104935 - timestamp: 1749230611612 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb9d3cd8_0.conda - sha256: 3aa92d4074d4063f2a162cd8ecb45dccac93e543e565c01a787e16a43501f7ee - md5: c7e925f37e3b40d893459e625f6a53f1 + size: 18055445 + timestamp: 1775615317758 + python_site_packages_path: Lib/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda + sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 + md5: 5b8d21249ff20967101ffa321cab24e8 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - license: BSD-2-Clause + - python >=3.9 + - six >=1.5 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-dateutil?source=hash-mapping + size: 233310 + timestamp: 1751104122689 +- pypi: https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl + name: python-discovery + version: 1.2.2 + sha256: e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a + requires_dist: + - filelock>=3.15.4 + - platformdirs>=4.3.6,<5 + - furo>=2025.12.19 ; extra == 'docs' + - sphinx-autodoc-typehints>=3.6.3 ; extra == 'docs' + - sphinx>=9.1 ; extra == 'docs' + - sphinxcontrib-mermaid>=2 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'testing' + - coverage>=7.5.4 ; extra == 'testing' + - pytest-mock>=3.14 ; extra == 'testing' + - pytest>=8.3.5 ; extra == 'testing' + - setuptools>=75.1 ; extra == 'testing' + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda + sha256: df9aa74e9e28e8d1309274648aac08ec447a92512c33f61a8de0afa9ce32ebe8 + md5: 23029aae904a2ba587daba708208012f + depends: + - python >=3.9 + - python + license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/fastjsonschema?source=hash-mapping + size: 244628 + timestamp: 1755304154927 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + sha256: 97327b9509ae3aae28d27217a5d7bd31aff0ab61a02041e9c6f98c11d8a53b29 + md5: 32780d6794b8056b78602103a04e90ef + depends: + - cpython 3.12.13.* + - python_abi * *_cp312 + license: Python-2.0 purls: [] - size: 91183 - timestamp: 1748393666725 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-h6e16a3a_0.conda - sha256: 98299c73c7a93cd4f5ff8bb7f43cd80389f08b5a27a296d806bdef7841cc9b9e - md5: 18b81186a6adb43f000ad19ed7b70381 + size: 46449 + timestamp: 1772728979370 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda + sha256: 36ff7984e4565c85149e64f8206303d412a0652e55cf806dcb856903fa056314 + md5: e4e60721757979d01d3964122f674959 depends: - - __osx >=10.13 - license: BSD-2-Clause - license_family: BSD + - cpython 3.14.4.* + - python_abi * *_cp314 + license: Python-2.0 purls: [] - size: 77667 - timestamp: 1748393757154 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h5505292_0.conda - sha256: 0a1875fc1642324ebd6c4ac864604f3f18f57fbcf558a8264f6ced028a3c75b2 - md5: 85ccccb47823dd9f7a99d2c7f530342f + size: 49806 + timestamp: 1775614307464 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-3.2.1-pyh332efcf_0.conda + sha256: 1c55116c22512cef7b01d55ae49697707f2c1fd829407183c19817e2d300fd8d + md5: 1cd2f3e885162ee1366312bd1b1677fd depends: - - __osx >=11.0 + - python >=3.10 + - typing_extensions license: BSD-2-Clause license_family: BSD + purls: + - pkg:pypi/python-json-logger?source=compressed-mapping + size: 18969 + timestamp: 1777318679482 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2026.2-pyhd8ed1ab_0.conda + sha256: e943f9c15a6bdba2e1b9f423ab913b3f6b02197b0ef9f8e6b7464d78b59965b9 + md5: f6ad7450fc21e00ecc23812baed6d2e4 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/tzdata?source=compressed-mapping + size: 146639 + timestamp: 1777068997932 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda + build_number: 8 + sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 + md5: c3efd25ac4d74b1584d2f7a57195ddf1 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD purls: [] - size: 71829 - timestamp: 1748393749336 -- conda: https://conda.anaconda.org/conda-forge/win-64/libmpdec-4.0.0-h2466b09_0.conda - sha256: fc529fc82c7caf51202cc5cec5bb1c2e8d90edbac6d0a4602c966366efe3c7bf - md5: 74860100b2029e2523cf480804c76b9b + size: 6958 + timestamp: 1752805918820 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6989 + timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py312h829343e_1.conda + sha256: a7505522048dad63940d06623f07eb357b9b65510a8d23ff32b99add05aac3a1 + md5: 64cbe4ecbebe185a2261d3f298a60cde + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/pywin32?source=hash-mapping + size: 6684490 + timestamp: 1756487136116 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywin32-311-py314h8f8f202_1.conda + sha256: 6918a8067f296f3c65d43e84558170c9e6c3f4dd735cfe041af41a7fdba7b171 + md5: 2d7b7ba21e8a8ced0eca553d4d53f773 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/pywin32?source=hash-mapping + size: 6713155 + timestamp: 1756487145487 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py312h275cf98_1.conda + sha256: 61cc6c2c712ab4d2b8e7a73d884ef8d3262cb80cc93a4aa074e8b08aa7ddd648 + md5: 66255d136bd0daa41713a334db41d9f0 depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 - license: BSD-2-Clause - license_family: BSD - purls: [] - size: 88657 - timestamp: 1723861474602 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - sha256: 6d9c32fc369af5a84875725f7ddfbfc2ace795c28f246dc70055a79f9b2003da - md5: 0b367fad34931cb79e0d6b7e5c06bb1c + - winpty + license: MIT + license_family: MIT + purls: + - pkg:pypi/pywinpty?source=hash-mapping + size: 215371 + timestamp: 1759557609855 +- conda: https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.15-py314h51f0985_1.conda + sha256: 048e20641da680aedaab285640a2aca56b7b5baf7a18f8f164f2796e13628c1f + md5: dd84e8748bd3c85a5c751b0576488080 + depends: + - python >=3.14.0rc3,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - winpty + license: MIT + license_family: MIT + purls: + - pkg:pypi/pywinpty?source=hash-mapping + size: 216325 + timestamp: 1759557436167 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + sha256: cb142bfd92f6e55749365ddc244294fa7b64db6d08c45b018ff1c658907bfcbf + md5: 15878599a87992e44c059731771591cb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - - libzlib >=1.3.1,<2.0a0 - license: blessing - purls: [] - size: 932581 - timestamp: 1753948484112 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.50.4-h39a8b3b_0.conda - sha256: 466366b094c3eb4b1d77320530cbf5400e7a10ab33e4824c200147488eebf7a6 - md5: 156bfb239b6a67ab4a01110e6718cbc4 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 198293 + timestamp: 1770223620706 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda + sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d + md5: 2035f68f96be30dc60a5dfd7452c7941 depends: - - __osx >=10.13 - - libzlib >=1.3.1,<2.0a0 - license: blessing - purls: [] - size: 980121 - timestamp: 1753948554003 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.50.4-h4237e3c_0.conda - sha256: 802ebe62e6bc59fc26b26276b793e0542cfff2d03c086440aeaf72fb8bbcec44 - md5: 1dcb0468f5146e38fae99aef9656034b + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=compressed-mapping + size: 202391 + timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py312h04c11ed_1.conda + sha256: 737959262d03c9c305618f2d48c7f1691fb996f14ae420bfd05932635c99f873 + md5: 95a5f0831b5e0b1075bbd80fcffc52ac depends: - __osx >=11.0 - - icu >=75.1,<76.0a0 - - libzlib >=1.3.1,<2.0a0 - license: blessing - purls: [] - size: 902645 - timestamp: 1753948599139 -- conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.50.4-hf5d6505_0.conda - sha256: 5dc4f07b2d6270ac0c874caec53c6984caaaa84bc0d3eb593b0edf3dc8492efa - md5: ccb20d946040f86f0c05b644d5eadeca + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 187278 + timestamp: 1770223990452 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.3-py314h6e9b3f0_1.conda + sha256: 95f385f9606e30137cf0b5295f63855fd22223a4cf024d306cf9098ea1c4a252 + md5: dcf51e564317816cb8d546891019b3ab + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 189475 + timestamp: 1770223788648 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py312h05f76fc_1.conda + sha256: 1cab6cbd6042b2a1d8ee4d6b4ec7f36637a41f57d2f5c5cf0c12b7c4ce6a62f6 + md5: 9f6ebef672522cb9d9a6257215ca5743 depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 - ucrt >=10.0.20348.0 - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - license: blessing - purls: [] - size: 1288499 - timestamp: 1753948889360 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - sha256: 1b981647d9775e1cdeb2fab0a4dd9cd75a6b0de2963f6c3953dbd712f78334b3 - md5: 5b767048b1b3ee9a954b06f4084f93dc + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 179738 + timestamp: 1770223468771 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.3-py314h2359020_1.conda + sha256: a2aff34027aa810ff36a190b75002d2ff6f9fbef71ec66e567616ac3a679d997 + md5: 0cd9b88826d0f8db142071eb830bce56 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc 15.2.0 h767d61c_7 - constrains: - - libstdcxx-ng ==15.2.0=*_7 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 3898269 - timestamp: 1759968103436 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - sha256: e5ec6d2ad7eef538ddcb9ea62ad4346fde70a4736342c4ad87bd713641eb9808 - md5: 80c07c68d2f6870250959dcc95b209d1 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyyaml?source=hash-mapping + size: 181257 + timestamp: 1770223460931 +- pypi: https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl + name: pyyaml-env-tag + version: '1.1' + sha256: 17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 + requires_dist: + - pyyaml + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + noarch: python + sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 + md5: 082985717303dab433c976986c674b35 depends: - - __glibc >=2.17,<3.0.a0 + - python - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 license: BSD-3-Clause license_family: BSD - purls: [] - size: 37135 - timestamp: 1758626800002 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 - md5: edb0dca6bc32e4f4789199455a1dbeb8 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - purls: [] - size: 60963 - timestamp: 1727963148474 -- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.1-hd23fc13_2.conda - sha256: 8412f96504fc5993a63edf1e211d042a1fd5b1d51dedec755d2058948fcced09 - md5: 003a54a4e32b02f7355b50a837e699da - depends: - - __osx >=10.13 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - purls: [] - size: 57133 - timestamp: 1727963183990 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.1-h8359307_2.conda - sha256: ce34669eadaba351cd54910743e6a2261b67009624dbc7daeeafdef93616711b - md5: 369964e85dc26bfe78f41399b366c435 + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 211567 + timestamp: 1771716961404 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyzmq-27.1.0-py312h022ad19_2.conda + noarch: python + sha256: 2f31f799a46ed75518fae0be75ecc8a1b84360dbfd55096bc2fe8bd9c797e772 + md5: 2f6b79700452ef1e91f45a99ab8ffe5a depends: + - python + - libcxx >=19 - __osx >=11.0 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - purls: [] - size: 46438 - timestamp: 1727963202283 -- conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.3.1-h2466b09_2.conda - sha256: ba945c6493449bed0e6e29883c4943817f7c79cbff52b83360f7b341277c6402 - md5: 41fbfac52c601159df6c01f875de31b9 + - _python_abi3_support 1.* + - cpython >=3.12 + - zeromq >=4.3.5,<4.4.0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 191641 + timestamp: 1771717073430 +- conda: https://conda.anaconda.org/conda-forge/win-64/pyzmq-27.1.0-py312h343a6d4_2.conda + noarch: python + sha256: d84bcc19a945ca03d1fd794be3e9896ab6afc9f691d58d9c2da514abe584d4df + md5: eb1ec67a70b4d479f7dd76e6c8fe7575 depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - zlib 1.3.1 *_2 - license: Zlib - license_family: Other - purls: [] - size: 55476 - timestamp: 1727963768015 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 - md5: 47e340acb35de30501a76c7c799c41d7 + - zeromq >=4.3.5,<4.3.6.0a0 + - _python_abi3_support 1.* + - cpython >=3.12 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pyzmq?source=hash-mapping + size: 183235 + timestamp: 1771716967192 +- pypi: https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl + name: questionary + version: 2.1.1 + sha256: a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59 + requires_dist: + - prompt-toolkit>=2.0,<4.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/93/f7/d00d9b4a0313a6be3a3e0818e6375e15da6d7076f4ae47d1324e7ca986a1/radon-6.0.1-py2.py3-none-any.whl + name: radon + version: 6.0.1 + sha256: 632cc032364a6f8bb1010a2f6a12d0f14bc7e5ede76585ef29dc0cecf4cd8859 + requires_dist: + - mando>=0.6,<0.8 + - colorama==0.4.1 ; python_full_version < '3.5' + - colorama>=0.4.1 ; python_full_version >= '3.5' + - tomli>=2.0.1 ; extra == 'toml' +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 - license: X11 AND BSD-3-Clause - purls: [] - size: 891641 - timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda - sha256: ea4a5d27ded18443749aefa49dc79f6356da8506d508b5296f60b8d51e0c4bd9 - md5: ced34dd9929f491ca6dab6a2927aff25 - depends: - - __osx >=10.13 - license: X11 AND BSD-3-Clause + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL purls: [] - size: 822259 - timestamp: 1738196181298 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 - md5: 068d497125e4bf8a66bf707254fff5ae + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 depends: - __osx >=11.0 - license: X11 AND BSD-3-Clause + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL purls: [] - size: 797030 - timestamp: 1738196177597 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - sha256: e807f3bad09bdf4075dbb4168619e14b0c0360bacb2e12ef18641a834c8c5549 - md5: 14edad12b59ccbfa3910d42c72adc2a0 + size: 313930 + timestamp: 1765813902568 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda + sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 + md5: 870293df500ca7e18bedefa5838a22ab depends: - - __glibc >=2.17,<3.0.a0 - - ca-certificates - - libgcc >=14 - license: Apache-2.0 - license_family: Apache - purls: [] - size: 3119624 - timestamp: 1759324353651 -- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.5.4-h230baf5_0.conda - sha256: 3ce8467773b2472b2919412fd936413f05a9b10c42e52c27bbddc923ef5da78a - md5: 075eaad78f96bbf5835952afbe44466e + - attrs >=22.2.0 + - python >=3.10 + - rpds-py >=0.7.0 + - typing_extensions >=4.4.0 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/referencing?source=hash-mapping + size: 51788 + timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_1.conda + sha256: 7f2c24dd3bd3c104a1d2c9a10ead5ed6758b0976b74f972cfe9c19884ccc4241 + md5: 9659f587a8ceacc21864260acd02fc67 depends: - - __osx >=10.13 - - ca-certificates + - python >=3.10 + - certifi >=2023.5.7 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.26,<3 + - python + constrains: + - chardet >=3.0.2,<8 license: Apache-2.0 - license_family: Apache - purls: [] - size: 2747108 - timestamp: 1759326402264 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.5.4-h5503f6c_0.conda - sha256: f0512629f9589392c2fb9733d11e753d0eab8fc7602f96e4d7f3bd95c783eb07 - md5: 71118318f37f717eefe55841adb172fd + license_family: APACHE + purls: + - pkg:pypi/requests?source=compressed-mapping + size: 63728 + timestamp: 1777030058920 +- conda: https://conda.anaconda.org/conda-forge/noarch/returns-0.27.0-pyhc364b38_0.conda + sha256: 3b45efeae771f1a20307b36ecdb3a8911a89c05382836b50c62b0a99d8d3dfd8 + md5: da94ff04d97ec5efc42cbe5da3c43a84 depends: - - __osx >=11.0 - - ca-certificates - license: Apache-2.0 - license_family: Apache - purls: [] - size: 3067808 - timestamp: 1759324763146 -- conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.5.4-h725018a_0.conda - sha256: 5ddc1e39e2a8b72db2431620ad1124016f3df135f87ebde450d235c212a61994 - md5: f28ffa510fe055ab518cbd9d6ddfea23 + - python >=3.11 + - typing_extensions >=4.0,<5.0 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/returns?source=hash-mapping + size: 100559 + timestamp: 1776176903101 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda + sha256: 2e4372f600490a6e0b3bac60717278448e323cab1c0fecd5f43f7c56535a99c5 + md5: 36de09a8d3e5d5e6f4ee63af49e59706 depends: - - ca-certificates - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: Apache-2.0 - license_family: Apache - purls: [] - size: 9218823 - timestamp: 1759326176247 -- pypi: https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl - name: pip - version: '25.3' - sha256: 9655943313a94722b7774661c21049070f6bbb0a1516bf02f7c8d5d9201514cd - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/34/0e/1e9841cc46196c55ac3eac0b8e08044a88cc70c8cc29e9dc1e33b2ced2b7/pyside6-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - name: pyside6 - version: 6.9.3 - sha256: 6485aebec8eba4e55d1ec1cebe68ca1413589880cc8ccd8a49acae852ec6cfb3 - requires_dist: - - shiboken6==6.9.3 - - pyside6-essentials==6.9.3 - - pyside6-addons==6.9.3 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/43/67/94794ebaf198bbdb35cb77f19f38370f9b323b036ab149874bc33c38faab/pyside6-6.10.0-cp39-abi3-win_amd64.whl - name: pyside6 - version: 6.10.0 - sha256: 70a8bcc73ea8d6baab70bba311eac77b9a1d31f658d0b418e15eb6ea36c97e6f - requires_dist: - - shiboken6==6.10.0 - - pyside6-essentials==6.10.0 - - pyside6-addons==6.10.0 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/e6/98/84b16f78b5d92dd234fb1eb9890a350a5b0c83d985bb8c44a92f813a2d02/pyside6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - name: pyside6 - version: 6.10.0 - sha256: c2cbc5dc2a164e3c7c51b3435e24203e90e5edd518c865466afccbd2e5872bb0 - requires_dist: - - shiboken6==6.10.0 - - pyside6-essentials==6.10.0 - - pyside6-addons==6.10.0 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/17/fe/d5c67665f866b8859d02aa1a859f101a1b2fd348cb61746a3e16fd98fb20/pyside6_addons-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - name: pyside6-addons - version: 6.9.3 - sha256: 68932327e1c33d729d79b2b94242f97b77601efe0427e757cd3fd588939ea479 - requires_dist: - - shiboken6==6.9.3 - - pyside6-essentials==6.9.3 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/47/23/9fbdec2ce16244ac3fe28e6d44c39c70465c93a03325939a792fd00fde7f/pyside6_addons-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - name: pyside6-addons - version: 6.10.0 - sha256: 88e61e21ee4643cdd9efb39ec52f4dc1ac74c0b45c5b7fa453d03c094f0a8a5c - requires_dist: - - shiboken6==6.10.0 - - pyside6-essentials==6.10.0 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/7d/5d/a3c32f85ac7f905c95679967c0ddda0ba043c273b75623cc90d8185064e4/pyside6_addons-6.10.0-cp39-abi3-win_amd64.whl - name: pyside6-addons - version: 6.10.0 - sha256: 99d93a32c17c5f6d797c3b90dd58f2a8bae13abde81e85802c34ceafaee11859 - requires_dist: - - shiboken6==6.10.0 - - pyside6-essentials==6.10.0 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/85/e8/9396cf11a60f80175bb3c5c1d498d84e87b7af653ab4ea001acf821a3981/pyside6_essentials-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - name: pyside6-essentials - version: 6.9.3 - sha256: c70d5544e892b201a677b615156fab6a0fef865e7fc287f55a0eae00a682e83f - requires_dist: - - shiboken6==6.9.3 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/bb/3a/d8211d17e6ca70f641c6ebd309f08ef18930acda60e74082c75875a274da/pyside6_essentials-6.10.0-cp39-abi3-win_amd64.whl - name: pyside6-essentials - version: 6.10.0 - sha256: fc167eb211dd1580e20ba90d299e74898e7a5a1306d832421e879641fc03b6fe - requires_dist: - - shiboken6==6.10.0 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/e5/55/bad02ab890c8b8101abef0db4a2e5304be78a69e23a438e4d8555b664467/pyside6_essentials-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - name: pyside6-essentials - version: 6.10.0 - sha256: 003e871effe1f3e5b876bde715c15a780d876682005a6e989d89f48b8b93e93a - requires_dist: - - shiboken6==6.10.0 - requires_python: '>=3.9,<3.14' -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.9-hc97d973_101_cp313.conda - build_number: 101 - sha256: e89da062abd0d3e76c8d3b35d3cafc5f0d05914339dcb238f9e3675f2a58d883 - md5: 4780fe896e961722d0623fa91d0d3378 + - python >=3.9 + - six + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3339-validator?source=hash-mapping + size: 10209 + timestamp: 1733600040800 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 + sha256: 2a5b495a1de0f60f24d8a74578ebc23b24aa53279b1ad583755f223097c41c37 + md5: 912a71cc01012ee38e6b90ddd561e36f + depends: + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3986-validator?source=hash-mapping + size: 7818 + timestamp: 1598024297745 +- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda + sha256: 70001ac24ee62058557783d9c5a7bbcfd97bd4911ef5440e3f7a576f9e43bc92 + md5: 7234f99325263a5af6d4cd195035e8f2 + depends: + - python >=3.9 + - lark >=1.2.2 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/rfc3987-syntax?source=hash-mapping + size: 22913 + timestamp: 1752876729969 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py312h868fb18_0.conda + sha256: 62f46e85caaba30b459da7dfcf3e5488ca24fd11675c33ce4367163ab191a42c + md5: 3ffc5a3572db8751c2f15bacf6a0e937 depends: + - python - __glibc >=2.17,<3.0.a0 - - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.1,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 - - libuuid >=2.41.2,<3.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.13.* *_cp313 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - license: Python-2.0 - purls: [] - size: 37174029 - timestamp: 1761178179147 - python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.13.9-h17c18a5_101_cp313.conda - build_number: 101 - sha256: b56484229cf83f6c84e8b138dc53f7f2fa9ee850f42bf1f6d6fa1c03c044c2d3 - md5: fb1e51574ce30d2a4d5e4facb9b2cbd5 + - python_abi 3.12.* *_cp312 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 383750 + timestamp: 1764543174231 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda + sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 + md5: c1c368b5437b0d1a68f372ccf01cb133 depends: - - __osx >=10.13 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.1,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.13.* *_cp313 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - license: Python-2.0 - purls: [] - size: 17521522 - timestamp: 1761177097697 - python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.13.9-hfc2f54d_101_cp313.conda - build_number: 101 - sha256: 516229f780b98783a5ef4112a5a4b5e5647d4f0177c4621e98aa60bb9bc32f98 - md5: a4241bce59eecc74d4d2396e108c93b8 + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.14.* *_cp314 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 376121 + timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py312h6ef9ec0_0.conda + sha256: ea06f6f66b1bea97244c36fd2788ccd92fd1fb06eae98e469dd95ee80831b057 + md5: a7cfbbdeb93bb9a3f249bc4c3569cd4c + depends: + - python + - __osx >=11.0 + - python 3.12.* *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 358853 + timestamp: 1764543161524 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.30.0-py314haad56a0_0.conda + sha256: e161dd97403b8b8a083d047369a5cf854557dba1204d29e2f0250f5ac4403925 + md5: 76a4f88d1b7748c477abf3c341edc64c depends: + - python - __osx >=11.0 - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.1,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.13.* *_cp313 - - readline >=8.2,<9.0a0 - - tk >=8.6.13,<8.7.0a0 - - tzdata - license: Python-2.0 - purls: [] - size: 11915380 - timestamp: 1761176793936 - python_site_packages_path: lib/python3.13/site-packages -- conda: https://conda.anaconda.org/conda-forge/win-64/python-3.13.9-h09917c8_101_cp313.conda - build_number: 101 - sha256: bc855b513197637c2083988d5cbdcc407a23151cdecff381bd677df33d516a01 - md5: 89d992b9d4b9e88ed54346c9c4a24c1c + - python 3.14.* *_cp314 + - python_abi 3.14.* *_cp314 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 350976 + timestamp: 1764543169524 +- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py312hdabe01f_0.conda + sha256: faad05e6df2fc15e3ae06fdd71a36e17ff25364777aa4c40f2ec588740d64091 + md5: 2c51baeda0a355b0a5e7b6acb28cf02d depends: - - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.7.1,<3.0a0 - - libffi >=3.5.2,<3.6.0a0 - - liblzma >=5.8.1,<6.0a0 - - libmpdec >=4.0.0,<5.0a0 - - libsqlite >=3.50.4,<4.0a0 - - libzlib >=1.3.1,<2.0a0 - - openssl >=3.5.4,<4.0a0 - - python_abi 3.13.* *_cp313 - - tk >=8.6.13,<8.7.0a0 - - tzdata + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 - ucrt >=10.0.20348.0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 243577 + timestamp: 1764543069837 +- conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.30.0-py314h9f07db2_0.conda + sha256: e4435368c5c25076dc0f5918ba531c5a92caee8e0e2f9912ef6810049cf00db2 + md5: e86531e278ad304438e530953cd55d14 + depends: + - python - vc >=14.3,<15 - vc14_runtime >=14.44.35208 - license: Python-2.0 - purls: [] - size: 16613183 - timestamp: 1761175050438 - python_site_packages_path: Lib/site-packages -- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.13-8_cp313.conda - build_number: 8 - sha256: 210bffe7b121e651419cb196a2a63687b087497595c9be9d20ebe97dd06060a7 - md5: 94305520c52a4aa3f6c2b1ff6008d9f8 - constrains: - - python 3.13.* *_cp313 + - ucrt >=10.0.20348.0 + - python_abi 3.14.* *_cp314 + license: MIT + license_family: MIT + purls: + - pkg:pypi/rpds-py?source=hash-mapping + size: 235780 + timestamp: 1764543046065 +- pypi: https://files.pythonhosted.org/packages/33/f1/9614e03e1cdcbf9437570b5400ced8a720b5db22b28d8e0f1bda429f660d/ruff-0.15.12-py3-none-win_amd64.whl + name: ruff + version: 0.15.12 + sha256: c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/aa/a4/f828e9718d3dce1f5f11c39c4f65afd32783c8b2aebb2e3d259e492c47bd/ruff-0.15.12-py3-none-macosx_11_0_arm64.whl + name: ruff + version: 0.15.12 + sha256: fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/e8/39/c61d193b8a1daaa8977f7dea9e8d8ba866e02ea7b65d32f6861693aa4c12/ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: ruff + version: 0.15.12 + sha256: 83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0 + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh5552912_1.conda + sha256: 8fc024bf1a7b99fc833b131ceef4bef8c235ad61ecb95a71a6108be2ccda63e8 + md5: b70e2d44e6aa2beb69ba64206a16e4c6 + depends: + - __osx + - pyobjc-framework-cocoa + - python >=3.10 + - python license: BSD-3-Clause license_family: BSD - purls: [] - size: 7002 - timestamp: 1752805902938 -- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - sha256: 2d6d0c026902561ed77cd646b5021aef2d4db22e57a5b0178dfc669231e06d2c - md5: 283b96675859b20a825f8fa30f311446 + purls: + - pkg:pypi/send2trash?source=hash-mapping + size: 22519 + timestamp: 1770937603551 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyh6dadd2b_1.conda + sha256: 305446a0b018f285351300463653d3d3457687270e20eda37417b12ee386ef76 + md5: 6ac53f3fff2c416d63511843a04646fa depends: - - libgcc >=13 - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - purls: [] - size: 282480 - timestamp: 1740379431762 -- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h7cca4af_2.conda - sha256: 53017e80453c4c1d97aaf78369040418dea14cf8f46a2fa999f31bd70b36c877 - md5: 342570f8e02f2f022147a7f841475784 + - __win + - pywin32 + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + size: 22864 + timestamp: 1770937641143 +- conda: https://conda.anaconda.org/conda-forge/noarch/send2trash-2.1.0-pyha191276_1.conda + sha256: 59656f6b2db07229351dfb3a859c35e57cc8e8bcbc86d4e501bff881a6f771f1 + md5: 28eb91468df04f655a57bcfbb35fc5c5 depends: - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL - purls: [] - size: 256712 - timestamp: 1740379577668 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h1d1bf99_2.conda - sha256: 7db04684d3904f6151eff8673270922d31da1eea7fa73254d01c437f49702e34 - md5: 63ef3f6e6d6d5c589e64f11263dc5676 + - __linux + - python >=3.10 + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/send2trash?source=hash-mapping + size: 24108 + timestamp: 1770937597662 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.1-pyh332efcf_0.conda + sha256: 82088a6e4daa33329a30bc26dc19a98c7c1d3f05c0f73ce9845d4eab4924e9e1 + md5: 8e194e7b992f99a5015edbd4ebd38efd depends: - - ncurses >=6.5,<7.0a0 - license: GPL-3.0-only - license_family: GPL + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools?source=hash-mapping + size: 639697 + timestamp: 1773074868565 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda + sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d + md5: 3339e3b65d58accf4ca4fb8748ab16b3 + depends: + - python >=3.9 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/six?source=hash-mapping + size: 18455 + timestamp: 1753199211006 +- pypi: https://files.pythonhosted.org/packages/c1/d4/59e74daffcb57a07668852eeeb6035af9f32cbfd7a1d2511f17d2fe6a738/smmap-5.0.3-py3-none-any.whl + name: smmap + version: 5.0.3 + sha256: c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f + requires_python: '>=3.7' +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda + sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad + md5: 03fe290994c5e4ec17293cfb6bdce520 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/sniffio?source=hash-mapping + size: 15698 + timestamp: 1762941572482 +- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda + sha256: 23b71ecf089967d2900126920e7f9ff18cdcef82dbff3e2f54ffa360243a17ac + md5: 18de09b20462742fe093ba39185d9bac + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/soupsieve?source=hash-mapping + size: 38187 + timestamp: 1769034509657 +- pypi: https://files.pythonhosted.org/packages/3e/17/1f31d8562e6f970d64911f1abc330d233bc0c0601411cf7e19c1292be6da/spdx_headers-1.5.1-py3-none-any.whl + name: spdx-headers + version: 1.5.1 + sha256: 73bcb1ed087824b55ccaa497d03d8f0f0b0eaf30e5f0f7d5bbd29d2c4fe78fcf + requires_dist: + - chardet>=5.2.0 + - requests>=2.32.3 + - black>=23.0.0 ; extra == 'dev' + - build>=0.10.0 ; extra == 'dev' + - hatch>=1.9.0 ; extra == 'dev' + - isort>=5.12.0 ; extra == 'dev' + - mypy>=1.0.0 ; extra == 'dev' + - pre-commit>=4.3.0 ; extra == 'dev' + - pytest-cov>=4.0.0 ; extra == 'dev' + - pytest>=7.0.0 ; extra == 'dev' + - ruff>=0.5.0 ; extra == 'dev' + - twine>=4.0.0 ; extra == 'dev' + - types-requests>=2.31.0.6 ; extra == 'dev' + - pytest-cov>=4.0.0 ; extra == 'test' + - pytest-mock>=3.10.0 ; extra == 'test' + - pytest>=7.0.0 ; extra == 'test' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda + sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 + md5: b1b505328da7a6b246787df4b5a49fbc + depends: + - asttokens + - executing + - pure_eval + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/stack-data?source=hash-mapping + size: 26988 + timestamp: 1733569565672 +- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + name: tabulate + version: 0.10.0 + sha256: f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 + requires_dist: + - wcwidth ; extra == 'widechars' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyh6dadd2b_1.conda + sha256: b375e8df0d5710717c31e7c8e93c025c37fa3504aea325c7a55509f64e5d4340 + md5: e43ca10d61e55d0a8ec5d8c62474ec9e + depends: + - __win + - pywinpty >=1.1.0 + - python >=3.10 + - tornado >=6.1.0 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/terminado?source=hash-mapping + size: 23665 + timestamp: 1766513806974 +- conda: https://conda.anaconda.org/conda-forge/noarch/terminado-0.18.1-pyhc90fa1f_1.conda + sha256: 6b6727a13d1ca6a23de5e6686500d0669081a117736a87c8abf444d60c1e40eb + md5: 17b43cee5cc84969529d5d0b0309b2cb + depends: + - __unix + - ptyprocess + - python >=3.10 + - tornado >=6.1.0 + - python + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/terminado?source=hash-mapping + size: 24749 + timestamp: 1766513766867 +- conda: https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.4.0-pyhd8ed1ab_0.conda + sha256: cad582d6f978276522f84bd209a5ddac824742fe2d452af6acf900f8650a73a2 + md5: f1acf5fdefa8300de697982bcb1761c9 + depends: + - python >=3.5 + - webencodings >=0.4 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/tinycss2?source=hash-mapping + size: 28285 + timestamp: 1729802975370 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD purls: [] - size: 252359 - timestamp: 1740379663071 -- pypi: https://files.pythonhosted.org/packages/be/82/c1c6932f9849bc5e75c93c38a29419505a6e3e0037261e28f3e7ecbf2751/shiboken6-6.9.3-cp39-abi3-manylinux_2_28_x86_64.whl - name: shiboken6 - version: 6.9.3 - sha256: f3f5337a3a8fc660ba1462265bd9a2bdda9588f8d90fbc3d5ac4ce3134c11e59 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/11/30/e4624a7e3f0dc9796b701079b77defcce0d32d1afc86bb1d0df04bc3d9e2/shiboken6-6.10.0-cp39-abi3-win_amd64.whl - name: shiboken6 - version: 6.10.0 - sha256: 0bc5631c1bf150cbef768a17f5f289aae1cb4db6c6b0c19b2421394e27783717 - requires_python: '>=3.9,<3.14' -- pypi: https://files.pythonhosted.org/packages/fd/78/3e730aea82089dd82b1e092bc265778bda329459e6ad9b7134eec5fff3f2/shiboken6-6.10.0-cp39-abi3-macosx_13_0_universal2.whl - name: shiboken6 - version: 6.10.0 - sha256: 7a5f5f400ebfb3a13616030815708289c2154e701a60b9db7833b843e0bee543 - requires_python: '>=3.9,<3.14' + size: 3301196 + timestamp: 1769460227866 - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda sha256: a84ff687119e6d8752346d1d408d5cf360dee0badd487a472aa8ddedfdc219e1 md5: a0116df4f4ed05c303811a837d5b39d8 @@ -865,17 +6897,17 @@ packages: purls: [] size: 3285204 timestamp: 1748387766691 -- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hf689a15_2.conda - sha256: b24468006a96b71a5f4372205ea7ec4b399b0f2a543541e86f883de54cd623fc - md5: 9864891a6946c2fe037c02fca7392ab4 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 depends: - - __osx >=10.13 + - __osx >=11.0 - libzlib >=1.3.1,<2.0a0 license: TCL license_family: BSD purls: [] - size: 3259809 - timestamp: 1748387843735 + size: 3127137 + timestamp: 1769460817696 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h892fb3f_2.conda sha256: cb86c522576fa95c6db4c878849af0bccfd3264daf0cc40dd18e7f4a7bfced0e md5: 7362396c170252e7b7b0c8fb37fe9c78 @@ -899,6 +6931,176 @@ packages: purls: [] size: 3466348 timestamp: 1748388121356 +- conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h6ed50ae_3.conda + sha256: 0e79810fae28f3b69fe7391b0d43f5474d6bd91d451d5f2bde02f55ae481d5e3 + md5: 0481bfd9814bf525bd4b3ee4b51494c4 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: TCL + license_family: BSD + purls: [] + size: 3526350 + timestamp: 1769460339384 +- pypi: https://files.pythonhosted.org/packages/33/f0/3fe8c6e69135a845f4106f2ff8b6805638d4e85c264e70114e8126689587/tokenize_rt-6.2.0-py2.py3-none-any.whl + name: tokenize-rt + version: 6.2.0 + sha256: a152bf4f249c847a66497a4a95f63376ed68ac6abf092a2f7cfb29d044ecff44 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.4.1-pyhcf101f3_0.conda + sha256: 91cafdb64268e43e0e10d30bd1bef5af392e69f00edd34dfaf909f69ab2da6bd + md5: b5325cf06a000c5b14970462ff5e4d58 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli?source=hash-mapping + size: 21561 + timestamp: 1774492402955 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py312h4c3975b_0.conda + sha256: 4629b1c9139858fb08bb357df917ffc12e4d284c57ff389806bb3ae476ef4e0a + md5: 2b37798adbc54fd9e591d24679d2133a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=compressed-mapping + size: 859665 + timestamp: 1774358032165 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tornado-6.5.5-py314h5bd0f2a_0.conda + sha256: ed8d06093ff530a2dae9ed1e51eb6f908fbfd171e8b62f4eae782d67b420be5a + md5: dc1ff1e915ab35a06b6fa61efae73ab5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 912476 + timestamp: 1774358032579 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py312h2bbb03f_0.conda + sha256: 29edd36311b4a810a9e6208437bdbedb28c9ac15221caf812cb5c5cf48375dca + md5: 02cce5319b0f1317d9642dcb2e475379 + depends: + - __osx >=11.0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=compressed-mapping + size: 859155 + timestamp: 1774358568476 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tornado-6.5.5-py314h6c2aa35_0.conda + sha256: 4ccc4a20d676c0ba85adee9c99015bec7f5b685df0cf8006e34573f1d6c2ce75 + md5: 3f81f8b2fe2c26a82c0abf57ab2b9610 + depends: + - __osx >=11.0 + - python >=3.14,<3.15.0a0 + - python >=3.14,<3.15.0a0 *_cp314 + - python_abi 3.14.* *_cp314 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 910845 + timestamp: 1774358965067 +- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py312he06e257_0.conda + sha256: 1220c986664e9e8662e660dc64dd97ed823926b1ba05175771408cf1d6a46dd2 + md5: c6c66a64da3d2953c83ed2789a7f4bdb + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=compressed-mapping + size: 859726 + timestamp: 1774358173994 +- conda: https://conda.anaconda.org/conda-forge/win-64/tornado-6.5.5-py314h5a2d7ad_0.conda + sha256: 49d64837dd02475903479ca47b82669bd6c9f7e6afde61860c6f3f2bd57d8a03 + md5: 87b1215adf7f0ba1fb9250af9fc668e1 + depends: + - python >=3.14,<3.15.0a0 + - python_abi 3.14.* *_cp314 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/tornado?source=hash-mapping + size: 914835 + timestamp: 1774358183098 +- conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda + sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 + md5: 019a7385be9af33791c989871317e1ed + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/traitlets?source=hash-mapping + size: 110051 + timestamp: 1733367480074 +- pypi: https://files.pythonhosted.org/packages/d6/bb/fbdc4e57731efb86b4209ffdd2519520782bf27b3c961beac3e5c20d2b87/trove_classifiers-2026.4.28.13-py3-none-any.whl + name: trove-classifiers + version: 2026.4.28.13 + sha256: 8f4b1eb4e16296b57d612965444f87a83861cc989a0451ac97fe4265ddef03b8 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda + sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c + md5: edd329d7d3a4ab45dcf905899a7a6115 + depends: + - typing_extensions ==4.15.0 pyhcf101f3_0 + license: PSF-2.0 + license_family: PSF + purls: [] + size: 91383 + timestamp: 1756220668932 +- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + name: typing-inspection + version: 0.4.2 + sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 + requires_dist: + - typing-extensions>=4.12.0 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda + sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 + md5: 0caa1af407ecff61170c9437a808404d + depends: + - python >=3.10 + - python + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions?source=hash-mapping + size: 51692 + timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda + sha256: 3088d5d873411a56bf988eee774559335749aed6f6c28e07bf933256afb9eb6c + md5: f6d7aa696c67756a650e91e15e88223c + depends: + - python >=3.9 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/typing-utils?source=hash-mapping + size: 15183 + timestamp: 1733331395943 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda sha256: 5aaa366385d716557e365f0a4e9c3fca43ba196872abbbe3d56bb610d131e192 md5: 4222072737ccff51314b5ece9c7d6f5a @@ -906,6 +7108,13 @@ packages: purls: [] size: 122968 timestamp: 1742727099393 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.26100.0-h57928b3_0.conda sha256: 3005729dce6f3d3f5ec91dfc49fc75a0095f9cd23bab49efb899657297ac91a5 md5: 71b24316859acd00bdb8b38f5e2ce328 @@ -916,6 +7125,43 @@ packages: purls: [] size: 694692 timestamp: 1756385147981 +- conda: https://conda.anaconda.org/conda-forge/noarch/uri-template-1.3.0-pyhd8ed1ab_1.conda + sha256: e0eb6c8daf892b3056f08416a96d68b0a358b7c46b99c8a50481b22631a4dfc0 + md5: e7cb0f5745e4c5035a460248334af7eb + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/uri-template?source=hash-mapping + size: 23990 + timestamp: 1733323714454 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a + md5: 9272daa869e03efe68833e3dc7a02130 + depends: + - backports.zstd >=1.0.0 + - brotli-python >=1.2.0 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + size: 103172 + timestamp: 1767817860341 +- pypi: https://files.pythonhosted.org/packages/b7/ee/e9c95cda829131f71a8dff5ce0406059fd16e591c074414e31ada19ba7c3/validate_pyproject-0.25-py3-none-any.whl + name: validate-pyproject + version: '0.25' + sha256: f9d05e2686beff82f9ea954f582306b036ced3d3feb258c1110f2c2a495b1981 + requires_dist: + - fastjsonschema>=2.16.2,<=3 + - packaging>=24.2 ; extra == 'all' + - trove-classifiers>=2021.10.20 ; extra == 'all' + - tomli>=1.2.1 ; python_full_version < '3.11' and extra == 'all' + - validate-pyproject-schema-store ; extra == 'store' + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h2b53caa_32.conda sha256: 82250af59af9ff3c6a635dd4c4764c631d854feb334d6747d356d949af44d7cf md5: ef02bbe151253a72b8eda264a935db66 @@ -928,6 +7174,18 @@ packages: purls: [] size: 18861 timestamp: 1760418772353 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h41ae7f8_34.conda + sha256: 9dc40c2610a6e6727d635c62cced5ef30b7b30123f5ef67d6139e23d21744b3a + md5: 1e610f2416b6acdd231c5f573d754a0f + depends: + - vc14_runtime >=14.44.35208 + track_features: + - vc14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 19356 + timestamp: 1767320221521 - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_32.conda sha256: e3a3656b70d1202e0d042811ceb743bd0d9f7e00e2acdf824d231b044ef6c0fd md5: 378d5dcec45eaea8d303da6f00447ac0 @@ -941,6 +7199,19 @@ packages: purls: [] size: 682706 timestamp: 1760418629729 +- conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.44.35208-h818238b_34.conda + sha256: 02732f953292cce179de9b633e74928037fa3741eb5ef91c3f8bae4f761d32a5 + md5: 37eb311485d2d8b2c419449582046a42 + depends: + - ucrt >=10.0.20348.0 + - vcomp14 14.44.35208 h818238b_34 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 683233 + timestamp: 1767320219644 - conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_32.conda sha256: f3790c88fbbdc55874f41de81a4237b1b91eab75e05d0e58661518ff04d2a8a1 md5: 58f67b437acbf2764317ba273d731f1d @@ -953,6 +7224,240 @@ packages: purls: [] size: 114846 timestamp: 1760418593847 +- conda: https://conda.anaconda.org/conda-forge/win-64/vcomp14-14.44.35208-h818238b_34.conda + sha256: 878d5d10318b119bd98ed3ed874bd467acbe21996e1d81597a1dbf8030ea0ce6 + md5: 242d9f25d2ae60c76b38a5e42858e51d + depends: + - ucrt >=10.0.20348.0 + constrains: + - vs2015_runtime 14.44.35208.* *_34 + license: LicenseRef-MicrosoftVisualCpp2015-2022Runtime + license_family: Proprietary + purls: [] + size: 115235 + timestamp: 1767320173250 +- pypi: https://files.pythonhosted.org/packages/1c/59/964ecb8008722d27d8a835baea81f56a91cea8e097b3be992bc6ccde6367/versioningit-3.3.0-py3-none-any.whl + name: versioningit + version: 3.3.0 + sha256: 23b1db3c4756cded9bd6b0ddec6643c261e3d0c471707da3e0b230b81ce53e4b + requires_dist: + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - packaging>=17.1 + - tomli>=1.2,<3.0 ; python_full_version < '3.11' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + name: verspec + version: 0.1.0 + sha256: 741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 + requires_dist: + - coverage ; extra == 'test' + - flake8>=3.7 ; extra == 'test' + - mypy ; extra == 'test' + - pretend ; extra == 'test' + - pytest ; extra == 'test' +- pypi: https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl + name: virtualenv + version: 21.3.0 + sha256: 4d28ee41f6d9ec8f1f00cd472b9ffbcedda1b3d3b9a575b5c94a2d004fd51bd7 + requires_dist: + - distlib>=0.3.7,<1 + - filelock>=3.24.2,<4 ; python_full_version >= '3.10' + - filelock>=3.16.1,<=3.19.1 ; python_full_version < '3.10' + - importlib-metadata>=6.6 ; python_full_version < '3.8' + - platformdirs>=3.9.1,<5 + - python-discovery>=1.2.2 + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl + name: watchdog + version: 6.0.0 + sha256: 6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl + name: watchdog + version: 6.0.0 + sha256: 20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz + name: watchdog + version: 6.0.0 + sha256: 9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl + name: watchdog + version: 6.0.0 + sha256: cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 + requires_dist: + - pyyaml>=3.10 ; extra == 'watchmedo' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.6.0-pyhd8ed1ab_0.conda + sha256: e298b508b2473c4227206800dfb14c39e4b14fd79d4636132e9e1e4244cdf4aa + md5: c3197f8c0d5b955c904616b716aca093 + depends: + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wcwidth?source=hash-mapping + size: 71550 + timestamp: 1770634638503 +- conda: https://conda.anaconda.org/conda-forge/noarch/webcolors-25.10.0-pyhd8ed1ab_0.conda + sha256: 21f6c8a20fe050d09bfda3fb0a9c3493936ce7d6e1b3b5f8b01319ee46d6c6f6 + md5: 6639b6b0d8b5a284f027a2003669aa65 + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/webcolors?source=hash-mapping + size: 18987 + timestamp: 1761899393153 +- conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_3.conda + sha256: 19ff205e138bb056a46f9e3839935a2e60bd1cf01c8241a5e172a422fed4f9c6 + md5: 2841eb5bfc75ce15e9a0054b98dcd64d + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/webencodings?source=hash-mapping + size: 15496 + timestamp: 1733236131358 +- conda: https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.9.0-pyhd8ed1ab_0.conda + sha256: 42a2b61e393e61cdf75ced1f5f324a64af25f347d16c60b14117393a98656397 + md5: 2f1ed718fcd829c184a6d4f0f2e07409 + depends: + - python >=3.10 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/websocket-client?source=hash-mapping + size: 61391 + timestamp: 1759928175142 +- conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda + sha256: 93807369ab91f230cf9e6e2a237eaa812492fe00face5b38068735858fba954f + md5: 46e441ba871f524e2b067929da3051c2 + depends: + - __win + - python >=3.9 + license: LicenseRef-Public-Domain + purls: + - pkg:pypi/win-inet-pton?source=hash-mapping + size: 9555 + timestamp: 1733130678956 +- conda: https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2 + sha256: 9df10c5b607dd30e05ba08cbd940009305c75db242476f4e845ea06008b0a283 + md5: 1cee351bf20b830d991dbe0bc8cd7dfe + license: MIT + license_family: MIT + purls: [] + size: 1176306 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda + sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad + md5: a77f85f77be52ff59391544bfe73390a + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + license: MIT + license_family: MIT + purls: [] + size: 85189 + timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h925e9cb_3.conda + sha256: b03433b13d89f5567e828ea9f1a7d5c5d697bf374c28a4168d71e9464f5dafac + md5: 78a0fe9e9c50d2c381e8ee47e3ea437d + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 83386 + timestamp: 1753484079473 +- conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h6a83c73_3.conda + sha256: 80ee68c1e7683a35295232ea79bcc87279d31ffeda04a1665efdb43cbd50a309 + md5: 433699cba6602098ae8957a323da2664 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + license: MIT + license_family: MIT + purls: [] + size: 63944 + timestamp: 1753484092156 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 + md5: 755b096086851e1193f3b10347415d7c + depends: + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 311150 + timestamp: 1772476812121 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zeromq-4.3.5-h4818236_10.conda + sha256: 2705360c72d4db8de34291493379ffd13b09fd594d0af20c9eefa8a3f060d868 + md5: e85dcd3bde2b10081cdcaeae15797506 + depends: + - __osx >=11.0 + - libcxx >=19 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 245246 + timestamp: 1772476886668 +- conda: https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.5-h507cc87_10.conda + sha256: b8568dfde46edf3455458912ea6ffb760e4456db8230a0cf34ecbc557d3c275f + md5: 1ab0237036bfb14e923d6107473b0021 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libsodium >=1.0.21,<1.0.22.0a0 + - krb5 >=1.22.2,<1.23.0a0 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 265665 + timestamp: 1772476832995 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda + sha256: 523616c0530d305d2216c2b4a8dfd3872628b60083255b89c5e0d8c42e738cca + md5: e1c36c6121a7c9c76f2f148f1e83b983 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp?source=compressed-mapping + size: 24461 + timestamp: 1776131454755 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb8e6e7a_2.conda sha256: a4166e3d8ff4e35932510aaff7aa90772f84b4d07e9f6f83c614cba7ceefe0eb md5: 6432cb5d4ac0046c3ac0a8a0f95842f9 @@ -966,3 +7471,27 @@ packages: purls: [] size: 567578 timestamp: 1742433379869 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 433413 + timestamp: 1764777166076 +- conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.7-h534d264_6.conda + sha256: 368d8628424966fd8f9c8018326a9c779e06913dd39e646cf331226acc90e5b2 + md5: 053b84beec00b71ea8ff7a4f84b55207 + depends: + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 388453 + timestamp: 1764777142545 diff --git a/pixi.toml b/pixi.toml index 0faecf02..4d194291 100644 --- a/pixi.toml +++ b/pixi.toml @@ -5,7 +5,7 @@ # Platform-independent [activation.env] -PYTHONIOENCODING = "utf-8" +PYTHONIOENCODING = 'utf-8' # Platform-specific @@ -27,23 +27,46 @@ PYTHONPATH = "${PIXI_PROJECT_ROOT}/src;%PYTHONPATH%" ########### [workspace] + # Supported platforms for the lock file (pixi.lock) -platforms = ['win-64', 'linux-64', 'osx-64', 'osx-arm64'] +platforms = ['win-64', 'linux-64', 'osx-arm64'] # Channels for fetching packages channels = ['conda-forge'] +##################### +# SYSTEM REQUIREMENTS +##################### + +[system-requirements] + +# Set minimum supported version for macOS to be 14.0 to ensure packages +# like `skipp` that only have wheels for macOS 14.0+ (macosx_14_0_arm64) +# are used instead of building from source. This is a workaround for +# Pixi, see https://github.com/prefix-dev/pixi/issues/5667 +macos = '14.0' + ########## # FEATURES ########## -[dependencies] # == [feature.default.dependencies] -python = '3.13.*' +# Default feature configuration + +[dependencies] +nodejs = '*' # Required for Prettier (non-Python formatting) +jupyterlab = '*' # Jupyter notebooks +pixi-kernel = '*' # Pixi Jupyter kernel [pypi-dependencies] # == [feature.default.pypi-dependencies] -pip = '*' -easyapp = { path = ".", editable = true } +#pip = '*' # Native package installer +EasyApplication = { path = '.', editable = true, extras = ['dev'] } + +# Specific features: Set specific Python versions +[feature.py-min.dependencies] +python = '3.12.*' +[feature.py-max.dependencies] +python = '3.14.*' ############## # ENVIRONMENTS @@ -53,12 +76,200 @@ easyapp = { path = ".", editable = true } # The `default` feature is always included in all environments. # Additional features can be specified per environment. +py-312-env = { features = ['py-min'] } +py-314-env = { features = ['py-max'] } # The `default` environment is always created and includes the `default` feature. # It does not need to be specified explicitly unless non-default features are included. +default = { features = ['py-max'] } ####### # TASKS ####### -#[tasks] +[tasks] + +################## +# 🧪 Testing Tasks +################## + +unit-tests = 'python -m pytest tests/unit/ --color=yes -v' +functional-tests = 'python -m pytest tests/functional/ --color=yes -v' +integration-tests = 'python -m pytest tests/integration/ --color=yes -n auto -v' +notebook-tests = 'python -m pytest --nbmake docs/docs/tutorials/ --nbmake-timeout=1200 --color=yes -n auto -v' + +test = { depends-on = ['unit-tests'] } + +########### +# ✔️ Checks +########### + +pyproject-check = 'python -m validate_pyproject pyproject.toml' +docstring-lint-check = 'pydoclint --quiet src/' +notebook-lint-check = 'nbqa ruff docs/docs/tutorials/' +py-lint-check = 'ruff check src/ tests/ docs/docs/tutorials/' +py-format-check = 'ruff format --check src/ tests/ docs/docs/tutorials/' +nonpy-format-check = 'npx prettier --list-different --config=prettierrc.toml --ignore-unknown .' +nonpy-format-check-modified = 'python tools/nonpy_prettier_modified.py' + +check = 'pre-commit run --hook-stage manual --all-files' + +########## +# 🛠️ Fixes +########## + +docstring-transform = 'pixi run docstripy src/ -s=numpy -w' +docstring-format-fix = 'format-docstring src/' +notebook-lint-fix = 'nbqa ruff --fix docs/docs/tutorials/' +py-lint-fix = 'ruff check --fix src/ tests/ docs/docs/tutorials/' +py-lint-fix-unsafe = 'ruff check --fix --unsafe-fixes src/ tests/ docs/docs/tutorials/' +py-format-fix = 'ruff format src/ tests/ docs/docs/tutorials/' +nonpy-format-fix = 'npx prettier --write --list-different --config=prettierrc.toml --ignore-unknown .' +nonpy-format-fix-modified = 'python tools/nonpy_prettier_modified.py --write' +success-message = 'echo "✅ All auto-formatting steps completed successfully!"' + +fix = { depends-on = [ + 'docstring-format-fix', + 'py-format-fix', + 'py-lint-fix', + 'nonpy-format-fix', + 'notebook-lint-fix', + 'success-message', +] } + +#################### +# 🧮 Code Complexity +#################### + +complexity-check = 'radon cc -s src/' +complexity-check-json = 'radon cc -s -j src/' +maintainability-check = 'radon mi src/' +maintainability-check-json = 'radon mi -j src/' +raw-metrics = 'radon raw -s src/' +raw-metrics-json = 'radon raw -s -j src/' + +############# +# 📊 Coverage +############# + +unit-tests-coverage = 'pixi run unit-tests --cov=src/EasyApplication --cov-report=term-missing' +functional-tests-coverage = 'pixi run functional-tests --cov=src/EasyApplication --cov-report=term-missing' +integration-tests-coverage = 'pixi run integration-tests --cov=src/EasyApplication --cov-report=term-missing' +docstring-coverage = 'interrogate -c pyproject.toml src/EasyApplication' + +cov = { depends-on = [ + 'docstring-coverage', + 'unit-tests-coverage', + 'integration-tests-coverage', +] } + +######################## +# 📓 Notebook Management +######################## + +notebook-convert = 'jupytext docs/docs/tutorials/*.py --from py:percent --to ipynb' +notebook-strip = 'nbstripout docs/docs/tutorials/*.ipynb' +notebook-tweak = 'python tools/tweak_notebooks.py docs/docs/tutorials/' +notebook-exec = 'python -m pytest --nbmake docs/docs/tutorials/ --nbmake-timeout=1200 --overwrite --color=yes -n auto -v' + +notebook-prepare = { depends-on = [ + #'notebook-convert', + 'notebook-strip', + #'notebook-tweak', +] } + +######################## +# 📚 Documentation Tasks +######################## + +docs-vars = "JUPYTER_PLATFORM_DIRS=1 PYTHONWARNINGS='ignore::RuntimeWarning'" +docs-pre = 'pixi run docs-vars python -m mkdocs' +docs-serve = 'pixi run docs-pre serve -f docs/mkdocs.yml' +docs-serve-dirty = 'pixi run docs-serve --dirty' +docs-build = 'pixi run docs-pre build -f docs/mkdocs.yml' +docs-build-local = 'pixi run docs-build --no-directory-urls' + +docs-deploy-pre = 'mike deploy -F docs/mkdocs.yml --push --branch gh-pages --update-aliases --alias-type redirect' +docs-set-default-pre = 'mike set-default -F docs/mkdocs.yml --push --branch gh-pages' + +docs-update-assets = 'python tools/update_docs_assets.py' + +############################## +# 📦 Template Management Tasks +############################## + +copier-copy = 'copier copy gh:easyscience/templates . --data-file .copier-answers.yml --data template_type=lib' +copier-recopy = 'copier recopy --data-file .copier-answers.yml --data template_type=lib' +copier-update = 'copier update --data-file .copier-answers.yml --data template_type=lib' + +##################### +# 🪝 Pre-commit Hooks +##################### + +pre-commit-clean = 'pre-commit clean' +pre-commit-install = 'pre-commit install --hook-type pre-commit --hook-type pre-push --overwrite' +pre-commit-uninstall = 'pre-commit uninstall --hook-type pre-commit --hook-type pre-push' +pre-commit-setup = { depends-on = [ + 'pre-commit-clean', + 'pre-commit-uninstall', + 'pre-commit-install', +] } + +################# +# 🐙️ GitHub Tasks +################# + +repo-wiki = 'gh api -X PATCH repos/easyscience/gui-components -f has_wiki=false' +repo-discussions = 'gh api -X PATCH repos/easyscience/gui-components -f has_discussions=true' +repo-description = "gh api -X PATCH repos/easyscience/gui-components -f description='Qt/QML components for building graphical applications'" +repo-homepage = "gh api -X PATCH repos/easyscience/gui-components -f homepage='https://easyscience.github.io/gui-components'" +repo-config = { depends-on = [ + 'repo-wiki', + 'repo-discussions', + 'repo-description', + 'repo-homepage', +] } + +master-protection = 'gh api -X POST repos/easyscience/gui-components/rulesets --input .github/configs/rulesets-master.json' +develop-protection = 'gh api -X POST repos/easyscience/gui-components/rulesets --input .github/configs/rulesets-develop.json' +gh-pages-protection = 'gh api -X POST repos/easyscience/gui-components/rulesets --input .github/configs/rulesets-gh-pages.json' +branch-protection = { depends-on = [ + 'master-protection', + 'develop-protection', + 'gh-pages-protection', +] } + +pages-deployment = 'gh api -X POST repos/easyscience/gui-components/pages --input .github/configs/pages-deployment.json' + +github-labels = 'python tools/update_github_labels.py' + +######################### +# ⚖️ SPDX License Headers +######################### + +license-remove = 'python tools/license_headers.py remove src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude' +license-add = 'python tools/license_headers.py add src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude' +license-check = 'python tools/license_headers.py check src/ tests/ --exclude-from-pyproject-toml tool.ruff.exclude' + +#################################### +# 🚀 Other Development & Build Tasks +#################################### + +default-build = 'python -m build' +dist-build = 'python -m build --wheel --outdir dist' + +npm-config = 'npm config set registry https://registry.npmjs.org/' +prettier-install = 'npm install --no-save --no-audit --no-fund prettier prettier-plugin-toml' + +clean-pycache = "find . -type d -name '__pycache__' -prune -exec rm -rf '{}' +" + +post-install = { depends-on = [ + 'npm-config', + 'prettier-install', + #'pre-commit-setup', +] } + +########################## +# 🔗 Main Package Shortcut +########################## +EasyApplication = 'python -m EasyApplication' diff --git a/prettierrc.toml b/prettierrc.toml new file mode 100644 index 00000000..b98c86eb --- /dev/null +++ b/prettierrc.toml @@ -0,0 +1,22 @@ +plugins = [ + "prettier-plugin-toml", # use the TOML plugin +] + +endOfLine = 'lf' # change line endings to LF +proseWrap = 'always' # change wrapping in Markdown files +semi = false # remove semicolons +singleQuote = true # use single quotes instead of double quotes +tabWidth = 2 # change tab width to 2 spaces +useTabs = false # use spaces instead of tabs + +printWidth = 79 # wrap lines at 79 characters + +[[overrides]] +files = ["*.md"] +[overrides.options] +printWidth = 72 # wrap Markdown files at 72 characters + +[[overrides]] +files = ["*.yml", "*.yaml"] +[overrides.options] +printWidth = 88 # wrap YAML files at 88 characters diff --git a/pyproject.toml b/pyproject.toml index 7385333c..1c31277d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,33 +1,335 @@ -[build-system] -requires = ['hatchling'] -build-backend = 'hatchling.build' +############################### +# Configuration for the project +############################### [project] -name = 'EasyApp' -version = '0.8.0' -description = 'Collection of graphical components to quickly create cross-platform applications in the EasyScience universe.' -authors = [ - {name = 'Andrew Sazonov', email = 'andrew.sazonov@ess.eu'} -] -license = {file = 'LICENSE'} +name = 'EasyApplication' +dynamic = ['version'] # Use versioningit to manage the version +description = 'Qt/QML components for building graphical applications' +authors = [{ name = 'EasyScience contributors' }] +readme = 'README.md' +license = 'BSD-3-Clause' +license-files = ['LICENSE'] classifiers = [ - 'Development Status :: 4 - Beta', + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering', 'License :: OSI Approved :: BSD License', - 'Programming Language :: Other', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3', - 'Operating System :: MacOS', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux' + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', ] -requires-python = '>=3.11' +requires-python = '>=3.12' dependencies = [ - 'PySide6' + #'easyscience', # The base library of the EasyScience framework + 'pooch', # Data downloader +] + +[project.optional-dependencies] +dev = [ + 'GitPython', # Interact with Git repositories + 'build', # Building the package + 'pre-commit', # Pre-commit hooks + 'jinja2', # Templating + 'nbmake', # Building notebooks + 'nbstripout', # Strip output from notebooks + 'nbqa', # Linting and formatting notebooks + 'pytest', # Testing + 'pytest-cov', # Test coverage + 'pytest-xdist', # Enable parallel testing + 'ruff', # Linting and formatting code + 'radon', # Code complexity and maintainability + 'validate-pyproject[all]', # Validate pyproject.toml + 'versioningit', # Automatic versioning from git tags + 'jupytext', # Jupyter notebook text format support + 'jupyterquiz', # Quizzes in Jupyter notebooks + 'pydoclint', # Docstring linter + 'format-docstring', # Docstring formatter + 'docstripy', # Convert docstrings to other formats + 'interrogate', # Docstring coverage checker + 'copier', # Template management + 'mike', # MkDocs: Versioned documentation support + 'mkdocs', # Static site generator + 'mkdocs-material', # Documentation framework on top of MkDocs + 'mkdocs-autorefs', # MkDocs: Auto-references support + 'mkdocs-jupyter', # MkDocs: Jupyter notebook support + 'mkdocs-plugin-inline-svg', # MkDocs: Inline SVG support + 'mkdocs-markdownextradata-plugin', # MkDocs: Markdown extra data support, such as global variables + 'mkdocstrings-python', # MkDocs: Python docstring support + 'pyyaml', # YAML parser + 'spdx-headers', # SPDX license header validation ] [project.urls] -homepage = 'https://app.easyscience.software' -source = 'https://github.com/EasyScience/EasyApp' -tracker = 'https://github.com/EasyScience/EasyApp/issues' +Documentation = 'https://easyscience.github.io/gui-components' +'Release Notes' = 'https://github.com/easyscience/gui-components/releases' +'Source Code' = 'https://github.com/easyscience/gui-components' +'Issue Tracker' = 'https://github.com/easyscience/gui-components/issues' + +############################ +# Build system configuration +############################ + +[build-system] +build-backend = 'hatchling.build' +requires = ['hatchling', 'versioningit'] + +############################# +# Configuration for hatchling +############################# + +# 'hatch' -- Build system for Python +# https://hatch.pypa.io/ [tool.hatch.build.targets.wheel] -packages = ['src/EasyApp'] +packages = ['src/EasyApplication'] + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.version] +source = 'versioningit' # Use versioningit to manage the version + +################################ +# Configuration for versioningit +################################ + +# 'versioningit' -- Versioning from git tags +# https://versioningit.readthedocs.io/ + +# Versioningit generates versions from git tags, so we don't need to +# either specify them statically in pyproject.toml or save them in the +# source code. Do not use {distance} in the version format, as it +# forces a version bump for every commit, which triggers unnecessary +# pixi.lock update without any changes to the source code. + +[tool.versioningit.format] +distance = '{base_version}+dev{distance}' # example: 1.2.3.post4+dev3 +dirty = '{base_version}+dirty{distance}' # example: 0.5.8+dirty3 +distance-dirty = '{base_version}+devdirty{distance}' # example: 0.5.8+devdirty3 + +# Configure how versioningit detects versions from Git +# - 'match' ensures it only considers tags starting with 'v' +# - 'default-tag' is used as a fallback when no matching tag is found +[tool.versioningit.vcs] +method = 'git' +match = ['v*'] +default-tag = 'v999.0.0' + +################################ +# Configuration for interrogate +################################ + +# 'interrogate' -- Docstring coverage checker +# https://interrogate.readthedocs.io/en/latest/ + +[tool.interrogate] +fail-under = 0 # Minimum docstring coverage percentage to pass +verbose = 1 +#exclude = ['src/**/__init__.py'] + +####################################### +# Configuration for coverage/pytest-cov +####################################### + +# 'coverage' -- Code coverage measurement tool +# https://coverage.readthedocs.io/en/latest/ + +[tool.coverage.run] +branch = true # Measure branch coverage as well +source = ['src'] # Limit coverage to the source code directory + +[tool.coverage.report] +show_missing = true # Show missing lines +skip_covered = false # Skip files with 100% coverage in the report +fail_under = 0 # Minimum coverage percentage to pass + +########################## +# Configuration for pytest +########################## + +# 'pytest' -- Testing framework +# https://docs.pytest.org/en/stable/ + +[tool.pytest.ini_options] +addopts = '--import-mode=importlib' +markers = ['fast: mark test as fast (should be run on every push)'] +testpaths = ['tests'] + +######################## +# Configuration for ruff +######################## + +# 'ruff' -- Python linter and code formatter +# https://docs.astral.sh/ruff/rules/ + +[tool.ruff] +exclude = ['tmp'] +indent-width = 4 +line-length = 99 # See also `max-line-length` in [tool.ruff.lint.pycodestyle] +preview = true # Enable new rules that are not yet stable, like DOC + +# Formatting options for Ruff + +[tool.ruff.format] +docstring-code-format = true # Whether to format code snippets in docstrings +docstring-code-line-length = 72 # Line length for code snippets in docstrings +indent-style = 'space' # PEP 8 recommends using spaces over tabs +quote-style = 'single' # But double quotes in docstrings (PEP 8, PEP 257) + +# Linting rules to use with Ruff + +[tool.ruff.lint] +select = [ + # Various rules + #'C90', # https://docs.astral.sh/ruff/rules/#mccabe-c90 + #'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d + 'F', # https://docs.astral.sh/ruff/rules/#pyflakes-f + #'FLY', # https://docs.astral.sh/ruff/rules/#flynt-fly + #'FURB', # https://docs.astral.sh/ruff/rules/#refurb-furb + 'I', # https://docs.astral.sh/ruff/rules/#isort-i + #'N', # https://docs.astral.sh/ruff/rules/#pep8-naming-n + #'NPY', # https://docs.astral.sh/ruff/rules/#numpy-specific-rules-npy + #'PGH', # https://docs.astral.sh/ruff/rules/#pygrep-hooks-pgh + #'PERF', # https://docs.astral.sh/ruff/rules/#perflint-perf + #'RUF', # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf + #'TRY', # https://docs.astral.sh/ruff/rules/#tryceratops-try + #'UP', # https://docs.astral.sh/ruff/rules/#pyupgrade-up + # pycodestyle (E, W) rules + 'E', # https://docs.astral.sh/ruff/rules/#error-e + 'W', # https://docs.astral.sh/ruff/rules/#warning-w + # Pylint (PL) rules + #'PLC', # https://docs.astral.sh/ruff/rules/#convention-plc + #'PLE', # https://docs.astral.sh/ruff/rules/#error-ple + #'PLR', # https://docs.astral.sh/ruff/rules/#refactor-plr + #'PLW', # https://docs.astral.sh/ruff/rules/#warning-plw + # flake8 rules + #'A', # https://docs.astral.sh/ruff/rules/#flake8-builtins-a + #'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann + #'ARG', # https://docs.astral.sh/ruff/rules/#flake8-unused-arguments-arg + #'ASYNC', # https://docs.astral.sh/ruff/rules/#flake8-async-async + #'B', # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b + #'BLE', # https://docs.astral.sh/ruff/rules/#flake8-blind-except-ble + #'C4', # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4 + #'COM', # https://docs.astral.sh/ruff/rules/#flake8-commas-com + #'DTZ', # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz + #'EM', # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em + #'FA', # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa + #'FBT', # https://docs.astral.sh/ruff/rules/#flake8-boolean-trap-fbt + #'FIX', # https://docs.astral.sh/ruff/rules/#flake8-fixme-fix + #'G', # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g + #'ICN', # https://docs.astral.sh/ruff/rules/#flake8-import-conventions-icn + #'INP', # https://docs.astral.sh/ruff/rules/#flake8-no-pep420-inp + #'ISC', # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc + #'LOG', # https://docs.astral.sh/ruff/rules/#flake8-logging-log + #'PIE', # https://docs.astral.sh/ruff/rules/#flake8-pie-pie + #'PT', # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt + #'PTH', # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth + #'PYI', # https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi + #'RET', # https://docs.astral.sh/ruff/rules/#flake8-return-ret + #'RSE', # https://docs.astral.sh/ruff/rules/#flake8-raise-rse + 'S', # https://docs.astral.sh/ruff/rules/#flake8-bandit-s + #'SIM', # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim + #'SLF', # https://docs.astral.sh/ruff/rules/#flake8-self-slf + #'SLOT', # https://docs.astral.sh/ruff/rules/#flake8-slots-slot + #'T20', # https://docs.astral.sh/ruff/rules/#flake8-print-t20 + #'TC', # https://docs.astral.sh/ruff/rules/#flake8-type-checking-tc + #'TD', # https://docs.astral.sh/ruff/rules/#flake8-todos-td + #'TID', # https://docs.astral.sh/ruff/rules/#flake8-tidy-imports-tid +] + +# Exceptions to the linting rules + +# Ignore specific rules globally +ignore = [ + 'COM812', # https://docs.astral.sh/ruff/rules/missing-trailing-comma/ + # The following is replaced by 'D'/[tool.ruff.lint.pydocstyle] and [tool.pydoclint] + 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc + # Disable, as [tool.format_docstring] split one-line docstrings into the canonical multi-line layout + 'D200', # https://docs.astral.sh/ruff/rules/unnecessary-multiline-docstring/ +] + +# Ignore specific rules in certain files or directories +[tool.ruff.lint.per-file-ignores] +'*/__init__.py' = [ + 'F401', # re-exports are intentional in __init__.py +] +'tests/**' = [ + 'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann + 'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d + 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc + 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ + 'S101', # https://docs.astral.sh/ruff/rules/assert/ +] +'docs/**' = [ + 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ + 'T201', # https://docs.astral.sh/ruff/rules/print/ +] + +# Specific options for certain rules + +[tool.ruff.lint.flake8-tidy-imports] +# Disallow all relative imports +ban-relative-imports = 'all' + +[tool.ruff.lint.isort] +# Forces all from imports to appear on their own line +force-single-line = true + +[tool.ruff.lint.mccabe] +# Cyclomatic complexity threshold (default is 10) +max-complexity = 10 + +[tool.ruff.lint.pycodestyle] +# PEP 8 line length guidance: +# https://peps.python.org/pep-0008/#maximum-line-length +# Use 99 characters as the project-wide maximum for regular code lines. +# Use 72 characters for docstrings. +max-line-length = 99 # See also `line-length` in [tool.ruff] +max-doc-length = 72 + +[tool.ruff.lint.pydocstyle] +convention = 'numpy' + +[tool.ruff.lint.pylint] +# Ruff counts `self`/`cls` in max-args; traditional pylint does not. +# Setting 6 here matches pylint's default of 5 (excluding self). +max-args = 6 +max-positional-args = 6 + +############################# +# Configuration for pydoclint +############################# + +# 'pydoclint' -- Docstring linter, a faster alternative to +# 'darglint' or 'darglint2'. +# https://pypi.org/project/pydoclint/ + +# This is a more advanced docstring linter compared to Ruff's built-in +# docstring check rules D or DOC. For example, among many other things, +# it can check that arguments in the docstring, which are used by MkDocs +# and IDEs to render parameter documentation, remain synchronized with +# the parameter declarations in the code (in function's signature). + +[tool.pydoclint] +exclude = '\.' # Temporarily disable pydoclint until we are ready +style = 'numpy' +check-style-mismatch = true +check-arg-defaults = true +allow-init-docstring = true + +#################################### +# Configuration for format-docstring +#################################### + +# 'format-docstring' -- Code formatter for docstrings +# https://github.com/jsh9/format-docstring + +[tool.format_docstring] +exclude = '\.' # Temporarily disable format-docstring until we are ready +docstring_style = 'numpy' +line_length = 72 +fix_rst_backticks = true +verbose = 'default' diff --git a/resources/images/ea_logo.svg b/resources/images/ea_logo.svg deleted file mode 100644 index bae13662..00000000 --- a/resources/images/ea_logo.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/images/ea_logo_wfont.svg b/resources/images/ea_logo_wfont.svg deleted file mode 100644 index ccab6452..00000000 --- a/resources/images/ea_logo_wfont.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - easyapp - - - - - - - - - - - \ No newline at end of file diff --git a/resources/images/vscode_debug.jpg b/resources/images/vscode_debug.jpg deleted file mode 100644 index 4adc396d..00000000 Binary files a/resources/images/vscode_debug.jpg and /dev/null differ diff --git a/src/EasyApp/Gui/Charts/ChartTemplateHeatmap2dPlotly.html b/src/EasyApp/Gui/Charts/ChartTemplateHeatmap2dPlotly.html deleted file mode 100644 index a3ed0722..00000000 --- a/src/EasyApp/Gui/Charts/ChartTemplateHeatmap2dPlotly.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - -
- - - - - - diff --git a/src/EasyApp/Gui/Charts/ChartTemplateSimple1dPlotly.html b/src/EasyApp/Gui/Charts/ChartTemplateSimple1dPlotly.html deleted file mode 100644 index 9c1f47a1..00000000 --- a/src/EasyApp/Gui/Charts/ChartTemplateSimple1dPlotly.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - -
- - - - - - diff --git a/src/EasyApp/Gui/Components/AppBarCentralTabs.qml b/src/EasyApp/Gui/Components/AppBarCentralTabs.qml deleted file mode 100644 index 87101edd..00000000 --- a/src/EasyApp/Gui/Components/AppBarCentralTabs.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick -import QtQuick.Controls - -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements - -EaElements.TabBar { - showBottomBorder: true -} diff --git a/src/EasyApp/Gui/Html/BasicReport.html b/src/EasyApp/Gui/Html/BasicReport.html deleted file mode 100644 index d40f58cf..00000000 --- a/src/EasyApp/Gui/Html/BasicReport.html +++ /dev/null @@ -1,342 +0,0 @@ - - - - - - - - - - - - - - -
- -

Summary report

- -
-

Project

-

- Name: Slanting line
- Description: Straight line, negative slope, Siglent SDS1202X-E
- Model: Line
- Experimental data: Siglent SDS1202X-E
- Last modified: 09.02.2023 14:13
-

-
- -
-

Software

-

- Analysis: EasyExample v0.8.4-beta
- Charts: Plotly JavaScript v2.18.0
- Calculation engine: Custom
- Minimization engine: Custom
-

-
- -
-

Model

- - -
Line function: y = M•x + C
-
- -
-

Parameters

- - - - -
No. Parameter Value Units
1 Slope M 3.0000
2 y-Intercept C 1.0000
-
- -
-

Fitting

-
-
- -
- - - - - - diff --git a/src/EasyApp/Gui/Html/BlankPage.html b/src/EasyApp/Gui/Html/BlankPage.html deleted file mode 100644 index bd54434b..00000000 --- a/src/EasyApp/Gui/Html/BlankPage.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/EasyApp/Gui/Html/Plotly1dBarPlot.html b/src/EasyApp/Gui/Html/Plotly1dBarPlot.html deleted file mode 100644 index 7cae1eb0..00000000 --- a/src/EasyApp/Gui/Html/Plotly1dBarPlot.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - - diff --git a/src/EasyApp/Gui/Html/Plotly1dLine.html b/src/EasyApp/Gui/Html/Plotly1dLine.html deleted file mode 100644 index b0974ffa..00000000 --- a/src/EasyApp/Gui/Html/Plotly1dLine.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - - diff --git a/src/EasyApp/Gui/Html/Plotly1dMeasVsCalc.html b/src/EasyApp/Gui/Html/Plotly1dMeasVsCalc.html deleted file mode 100644 index 9874b1a7..00000000 --- a/src/EasyApp/Gui/Html/Plotly1dMeasVsCalc.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - - diff --git a/src/EasyApp/Gui/Html/Plotly2dHeatmap.html b/src/EasyApp/Gui/Html/Plotly2dHeatmap.html deleted file mode 100644 index e1ce435a..00000000 --- a/src/EasyApp/Gui/Html/Plotly2dHeatmap.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - - diff --git a/src/EasyApp/Gui/Html/Plotly2dPolarHeatmap.html b/src/EasyApp/Gui/Html/Plotly2dPolarHeatmap.html deleted file mode 100644 index 6ddac6d1..00000000 --- a/src/EasyApp/Gui/Html/Plotly2dPolarHeatmap.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - - diff --git a/src/EasyApp/Gui/Html/Plotly3dMesh.html b/src/EasyApp/Gui/Html/Plotly3dMesh.html deleted file mode 100644 index 8d3ceac5..00000000 --- a/src/EasyApp/Gui/Html/Plotly3dMesh.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - diff --git a/src/EasyApp/Gui/Html/Plotly3dScatter.html b/src/EasyApp/Gui/Html/Plotly3dScatter.html deleted file mode 100644 index 0e48da28..00000000 --- a/src/EasyApp/Gui/Html/Plotly3dScatter.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - diff --git a/src/EasyApp/Gui/Html/Plotly3dSurface.html b/src/EasyApp/Gui/Html/Plotly3dSurface.html deleted file mode 100644 index 18f82394..00000000 --- a/src/EasyApp/Gui/Html/Plotly3dSurface.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - -
-
-
- - - - - diff --git a/src/EasyApp/Gui/Logic/Plotting.js b/src/EasyApp/Gui/Logic/Plotting.js deleted file mode 100644 index e12f77f7..00000000 --- a/src/EasyApp/Gui/Logic/Plotting.js +++ /dev/null @@ -1,642 +0,0 @@ -///////// -// Common -///////// - -function headCommon() { - const list = [ - '', - '', - '' - ] - return list.join('\n') -} - -function chartHtml(head, chart, toolbar='') { - const list = [ - '', - '', - '', - head, - '', - '', - toolbar, - '', - '', - '' - ] - return list.join('\n') -} - -//////// -// Bokeh -//////// - -function bokehInfo() { - const version = '2.4.3' - return { - version: version, - url: `https://docs.bokeh.org/en/${version}` - } -} - -function bokehHtml(data, specs) { - const head = bokehHead(specs) - const chart = bokehChart(data, specs) - const html = chartHtml(head, chart) - return html -} - -function bokehHeadScripts() { - const baseSrc = 'https://cdn.pydata.org/bokeh/release' - const version = bokehInfo().version - const list = [ - ``, - ``, - ``, - `` - ] - return list.join('\n') -} - -function bokehHeadStyle(specs) { - const list = [ - '' - ] - return list.join('\n') -} - -function bokehHead(specs) { - const list = [ - headCommon(), - bokehHeadScripts(), - bokehHeadStyle(specs) - ] - return list.join('\n') -} - -function bokehChart(data, specs) { - if (!data.hasMeasured && !data.hasCalculated && !data.hasPlotRanges) { - return "" - } - // List of strings to be filled below - let chart = [] - - // Tooltips - chart.push(bokehAddMainTooltip(data, specs)) - chart.push(bokehAddBraggTooltip(specs)) - - // Data sources - chart.push('const main_source = new Bokeh.ColumnDataSource()') - // Charts array - chart.push('const charts = []') - - // Main chart (top) - chart.push(...bokehCreateMainChart(data, specs)) - chart.push(...bokehAddMainTools('main_chart')) - chart.push(...bokehAddHiddenXAxis('main_chart', specs)) - chart.push(...bokehAddVisibleYAxis('main_chart', specs)) - if (data.hasBackground) { - chart.push(...bokehAddBackgroundDataToMainChart(data, specs)) - } - if (data.hasMeasured) { - chart.push(...bokehAddMeasuredDataToMainChart(data, specs)) - } - if (data.hasPhase) { - chart.push(...bokehAddPhaseDataToMainChart(data, specs)) - } - if (data.hasCalculated) { - chart.push(...bokehAddCalculatedDataToMainChart(data, specs)) - } - chart.push(`charts.push([main_chart])`) - - // Bragg peaks chart (middle) - if (data.hasBragg) { - chart.push(...bokehCreateBraggChart(data, specs)) - chart.push(...bokehAddBraggTools()) - chart.push(...bokehAddHiddenXAxis('bragg_chart', specs)) - chart.push(...bokehAddHiddenYAxis('bragg_chart')) - chart.push(...bokehAddDataToBraggChart(data, specs)) - chart.push(`charts.push([bragg_chart])`) - } - - // Difference chart (bottom) - if (data.hasDifference) { - chart.push(...bokehCreateDiffChart(data, specs)) - chart.push(...bokehAddMainTools('diff_chart')) - chart.push(...bokehAddHiddenXAxis('diff_chart', specs)) - chart.push(...bokehAddVisibleYAxis('diff_chart', specs)) - chart.push(...bokehAddDataToDiffChart(data, specs)) - chart.push(...adjustDifferenceYRange()) - chart.push(`diff_chart.ygrid[0].ticker.desired_num_ticks = 3`) - chart.push(`charts.push([diff_chart])`) - } - - // xAxis chart (very bottom) - chart.push(...bokehCreateXAxisChart(data, specs)) - chart.push(...bokehAddVisibleXAxis('xaxis_chart', specs)) - chart.push(...bokehAddHiddenYAxis('xaxis_chart')) - chart.push(`charts.push([xaxis_chart])`) - - // Charts array grid layout - chart.push(`const grid_options = {toolbar_location: "above"}`) - chart.push(`const gridplot = new Bokeh.Plotting.gridplot(charts, grid_options)`) - - chart.push(...[ - 'function OnClick() {', - 'main_chart.reset.emit()', - '//console.log("AAA", document.querySelector(".bk-tool-icon-reset"))', - '//console.log("BBB", document.getElementById("bk-tool-icon-reset"))', - ' //document.getElementById("bk-tool-icon-reset").click()', - ' document.querySelector(".bk-tool-icon-reset").click()', - '}' - ]) - - // Show charts - if (typeof specs.containerId !== 'undefined') { - chart.push(`Bokeh.Plotting.show(gridplot, "#${specs.containerId}")`) - } else { - chart.push(`Bokeh.Plotting.show(gridplot)`) - } - - // Return as string - return chart.join('\n') -} - -// Bokeh charts - -function bokehCreateMainChart(data, specs) { - return [`const main_chart = new Bokeh.Plotting.figure({`, - ` tools: "reset,undo,redo",`, - - ` height: ${specs.mainChartHeight},`, - ` width: ${specs.chartWidth},`, - - ` x_range: new Bokeh.Range1d({`, - ` start: ${data.ranges.min_x},`, - ` end: ${data.ranges.max_x}`, - ` }),`, - ` y_range: new Bokeh.Range1d({`, - ` start: ${data.ranges.min_y},`, - ` end: ${data.ranges.max_y}`, - ` }),`, - - ` y_axis_label: "${specs.yMainAxisTitle}",`, - - ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, - ` background: "${specs.chartBackgroundColor}",`, - ` background_fill_color: "${specs.chartBackgroundColor}",`, - ` border_fill_color: "${specs.chartBackgroundColor}",`, - ` //border_fill_color: "red",`, - - ` min_border_right: ${1.5 * specs.fontPixelSize},`, - ` min_border_top: ${0.5 * specs.fontPixelSize},`, - ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, - `})`] -} - -function bokehCreateBraggChart(data, specs) { - const num_phases = Object.keys(data.bragg).length - const y_margin = 0.65 - const y_min = -num_phases + 1 - y_margin - const y_max = y_margin - return [`const bragg_chart = new Bokeh.Plotting.figure({`, - ` tools: "",`, - - ` height: ${specs.braggChartHeight},`, - ` width: ${specs.chartWidth},`, - - ` x_range: main_chart.x_range,`, - ` y_range: new Bokeh.Range1d({ start: ${y_min}, end: ${y_max} }),`, - - ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, - ` background: "${specs.chartBackgroundColor}",`, - ` background_fill_color: "${specs.chartBackgroundColor}",`, - ` border_fill_color: "${specs.chartBackgroundColor}",`, - ` //border_fill_color: "green",`, - - ` min_border_top: ${0.5 * specs.fontPixelSize},`, - ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, - `})`] -} - -function bokehCreateDiffChart(data, specs) { - return [`const diff_chart = new Bokeh.Plotting.figure({`, - ` tools: "reset",`, - - ` height: ${specs.differenceChartHeight},`, - ` width: ${specs.chartWidth},`, - - ` x_range: main_chart.x_range,`, - - ` y_axis_label: "${specs.yDifferenceAxisTitle}",`, - - ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, - ` background: "${specs.chartBackgroundColor}",`, - ` background_fill_color: "${specs.chartBackgroundColor}",`, - ` border_fill_color: "${specs.chartBackgroundColor}",`, - ` //border_fill_color: "blue",`, - - ` min_border_top: ${0.5 * specs.fontPixelSize},`, - ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, - `})`] -} - -function bokehCreateXAxisChart(data, specs) { - return [`const xaxis_chart = new Bokeh.Plotting.figure({`, - ` tools: "",`, - - ` height: ${specs.xAxisChartHeight},`, - ` width: ${specs.chartWidth},`, - - ` x_range: main_chart.x_range,`, - ` y_range: new Bokeh.Range1d({ start: 0, end: 1 }),`, - - ` x_axis_label: "${specs.xAxisTitle}",`, - - ` outline_line_color: null,`, - ` background: "${specs.chartBackgroundColor}",`, - ` background_fill_color: "${specs.chartBackgroundColor}",`, - ` border_fill_color: "${specs.chartBackgroundColor}",`, - ` //border_fill_color: "orange",`, - - ` min_border_top: 0,`, - ` min_border_bottom: 0`, - `})`] -} - -// Misc - -function adjustDifferenceYRange() { - return [`function differenceChartMeanY() {`, - ` let ySum = 0, yCount = 0`, - ` for (let i in main_source.data.x_diff) {`, - ` if (diff_chart.x_range.start <= main_source.data.x_diff[i] && main_source.data.x_diff[i] <= diff_chart.x_range.end) {`, - ` ySum += main_source.data.y_diff[i]`, - ` yCount += 1`, - ` }`, - ` }`, - ` if (yCount > 0) {`, - ` return ySum / yCount`, - ` }`, - ` return 0`, - `}`, - - `function differenceChartHalfRangeY() {`, - ` const mainChartRangeY = main_chart.y_range.end - main_chart.y_range.start`, - ` const mainChartAxesHeight = main_chart.height - main_chart.min_border_top - main_chart.min_border_bottom`, - ` const differenceChartAxesHeight = diff_chart.height - diff_chart.min_border_top - diff_chart.min_border_bottom`, - ` const differenceToMainChartHeightRatio = differenceChartAxesHeight / mainChartAxesHeight`, - ` const differenceChartRangeY = mainChartRangeY * differenceToMainChartHeightRatio`, - ` return 0.5 * differenceChartRangeY`, - `}`, - - `diff_chart.y_range = new Bokeh.Range1d({`, - ` start: differenceChartMeanY() - differenceChartHalfRangeY(),`, - ` end: differenceChartMeanY() + differenceChartHalfRangeY()`, - `})`, - - `main_chart.y_range.change.connect(function() {`, - ` diff_chart.y_range.start = differenceChartMeanY() - differenceChartHalfRangeY()`, - ` diff_chart.y_range.end = differenceChartMeanY() + differenceChartHalfRangeY()`, - `})`] -} - -// Bokeh tools - -function bokehAddMainTools(chart) { - return [`${chart}.add_tools(new Bokeh.HoverTool({tooltips:main_tooltip, point_policy:"snap_to_data", mode:"mouse"}))`, - `${chart}.add_tools(new Bokeh.BoxZoomTool())`, - `${chart}.toolbar.active_drag = "box_zoom"`, - `${chart}.add_tools(new Bokeh.PanTool())`] -} - -function bokehAddBraggTools() { - return [`bragg_chart.add_tools(new Bokeh.HoverTool({tooltips:bragg_tooltip, point_policy:"snap_to_data", mode:"mouse"}))`] -} - -// Bokeh axes - -function bokehAddVisibleXAxis(chart, specs) { - return [`${chart}.xaxis[0].axis_label_text_font = "PT Sans"`, - `${chart}.xaxis[0].axis_label_text_font_style = "normal"`, - `${chart}.xaxis[0].axis_label_text_font_size = "${specs.fontPixelSize}px"`, - `${chart}.xaxis[0].axis_label_text_color = "${specs.chartForegroundColor}"`, - `${chart}.xaxis[0].axis_label_standoff = ${specs.fontPixelSize - 5}`, - `${chart}.xaxis[0].axis_line_color = null`, - - `${chart}.xaxis[0].major_label_text_font = "PT Sans"`, - `${chart}.xaxis[0].major_label_text_font_size = "${specs.fontPixelSize}px"`, - `${chart}.xaxis[0].major_label_text_color = "${specs.chartForegroundColor}"`, - `${chart}.xaxis[0].major_label_standoff = 0`, - `${chart}.xaxis[0].major_tick_line_color = null`, - `${chart}.xaxis[0].major_tick_in = 0`, - `${chart}.xaxis[0].major_tick_out = 0`, - `${chart}.xaxis[0].minor_tick_line_color = null`, - `${chart}.xaxis[0].minor_tick_out = 0`, - - `${chart}.xgrid[0].grid_line_color = null`] -} - -function bokehAddHiddenXAxis(chart, specs) { - return [`${chart}.xaxis[0].axis_label_text_font_size = "0px"`, - `${chart}.xaxis[0].axis_line_color = null`, - - `${chart}.xaxis[0].major_label_text_font_size = "0px"`, - `${chart}.xaxis[0].major_tick_line_color = "${specs.chartGridLineColor}"`, - `${chart}.xaxis[0].major_tick_in = 0`, - `${chart}.xaxis[0].major_tick_out = 0`, - `${chart}.xaxis[0].minor_tick_line_color = "${specs.chartMinorGridLineColor}"`, - `${chart}.xaxis[0].minor_tick_out = 0`, - - `${chart}.xgrid[0].grid_line_color = "${specs.chartGridLineColor}"`] -} - -function bokehAddVisibleYAxis(chart, specs) { - return [`${chart}.yaxis[0].axis_label_text_font = "PT Sans"`, - `${chart}.yaxis[0].axis_label_text_font_style = "normal"`, - `${chart}.yaxis[0].axis_label_text_font_size = "${specs.fontPixelSize}px"`, - `${chart}.yaxis[0].axis_label_text_color = "${specs.chartForegroundColor}"`, - `${chart}.yaxis[0].axis_label_standoff = ${specs.fontPixelSize}`, - `${chart}.yaxis[0].axis_line_color = null`, - - `${chart}.yaxis[0].major_label_text_font = "PT Sans"`, - `${chart}.yaxis[0].major_label_text_font_size = "${specs.fontPixelSize}px"`, - `${chart}.yaxis[0].major_label_text_color = "${specs.chartForegroundColor}"`, - `${chart}.yaxis[0].major_tick_line_color = "${specs.chartGridLineColor}"`, - `${chart}.yaxis[0].major_tick_in = 0`, - `${chart}.yaxis[0].major_tick_out = 0`, - `${chart}.yaxis[0].minor_tick_line_color = "${specs.chartMinorGridLineColor}"`, - `${chart}.yaxis[0].minor_tick_out = 0`, - - `${chart}.ygrid[0].grid_line_color = "${specs.chartGridLineColor}"`] -} - -function bokehAddHiddenYAxis(chart) { - return [`${chart}.yaxis[0].axis_line_color = null`, - - `${chart}.yaxis[0].major_tick_in = 0`, - `${chart}.yaxis[0].major_tick_out = 0`, - `${chart}.yaxis[0].minor_tick_out = 0`, - `${chart}.yaxis[0].major_label_text_font_size = "0px"`, - - `${chart}.ygrid[0].grid_line_color = null`] -} - -// Bokeh data - -function bokehAddBackgroundDataToMainChart(data, specs) { - return [`main_source.data.x_bkg = [${data.background.x}]`, - `main_source.data.y_bkg = [${data.background.y}]`, - - 'const bkgLine = new Bokeh.Line({', - ' x: { field: "x_bkg" },', - ' y: { field: "y_bkg" },', - ` line_color: "${specs.backgroundLineColor}",`, - ` line_alpha: 0.5,`, - ` line_dash: [4, 2],`, - ` line_width: ${specs.backgroundLineWidth},`, - '})', - - 'main_chart.add_glyph(bkgLine, main_source)'] -} - -function bokehAddMeasuredDataToMainChart(data, specs) { - - - return [`main_source.data.x_meas = [${data.measured.x}]`, - `main_source.data.y_meas = [${data.measured.y}]`, - `main_source.data.sy_meas = [${data.measured.sy}]`, - `main_source.data.y_meas_upper = [${data.measured.y_upper}]`, - `main_source.data.y_meas_lower = [${data.measured.y_lower}]`, - - `const measLineTop = new Bokeh.Line({`, - ` x: { field: "x_meas" },`, - ` y: { field: "y_meas_upper" },`, - ` line_color: "${specs.measuredLineColor}",`, - ` line_alpha: 0.4,`, - ` line_width: ${specs.measuredLineWidth}`, - `})`, - `const measLineBottom = new Bokeh.Line({`, - ` x: { field: "x_meas" },`, - ` y: { field: "y_meas_lower" },`, - ` line_color: "${specs.measuredLineColor}",`, - ` line_width: ${specs.measuredLineWidth},`, - ` line_alpha: 0.4`, - `})`, - `const measArea = new Bokeh.VArea({`, - ` x: { field: "x_meas" },`, - ` y1: { field: "y_meas_upper" },`, - ` y2: { field: "y_meas_lower" },`, - ` fill_color: "${specs.measuredAreaColor}",`, - ` fill_alpha: 0.35`, - `})`, - - `main_chart.add_glyph(measArea, main_source)`, - `main_chart.add_glyph(measLineTop, main_source)`, - `main_chart.add_glyph(measLineBottom, main_source)`] - - -} - -function bokehAddCalculatedDataToMainChart(data, specs) { - - return [`main_source.data.x_calc = [${data.calculated.x}]`, - `main_source.data.y_calc = [${data.calculated.y}]`, - - 'const calcLine = new Bokeh.Line({', - ' x: { field: "x_calc" },', - ' y: { field: "y_calc" },', - ` line_color: "${specs.calculatedLineColor}",`, - ` line_width: ${specs.calculatedLineWidth},`, - ` line_alpha: 0.8`, - '})', - - 'main_chart.add_glyph(calcLine, main_source)'] -} - -function bokehAddPhaseDataToMainChart(data, specs) { - let out = [] - out.push('let phaseLine = new Bokeh.Line()') - for (const phase_index in data.phase) { - out.push(`main_source.data.x_phase_${phase_index} = [${data.phase[phase_index].x}]`) - out.push(`main_source.data.y_phase_${phase_index}_upper = [${data.phase[phase_index].y_upper}]`) - out.push(`main_source.data.y_phase_${phase_index}_lower = [${data.phase[phase_index].y_lower}]`) - out.push(`const phaseLine_${phase_index} = new Bokeh.Line({`) - out.push(` x: { field: "x_phase_${phase_index}" },`) - out.push(` y: { field: "y_phase_${phase_index}_upper" },`) - out.push(` line_color: "${specs.phaseLineColor[phase_index]}",`) - out.push(` line_width: ${specs.phaseLineWidth},`) - out.push(` line_alpha: 0.6,`) - out.push('})') - out.push(`const phaseArea_${phase_index} = new Bokeh.VArea({`) - out.push(` x: { field: "x_phase_${phase_index}" },`) - out.push(` y1: { field: "y_phase_${phase_index}_upper" },`) - out.push(` y2: { field: "y_phase_${phase_index}_lower" },`) - out.push(` fill_color: "${specs.phaseLineColor[phase_index]}",`) - out.push(` fill_alpha: 0.1`) - out.push('})') - out.push(`main_chart.add_glyph(phaseArea_${phase_index}, main_source)`) - out.push(`main_chart.add_glyph(phaseLine_${phase_index}, main_source)`) - - } - return out -} - -function bokehAddDataToBraggChart(data, specs) { - - - let out = [] - for (const phase_index in data.bragg) { - console.log("---", phase_index, data.bragg[phase_index].x.slice(0,200) ) - out.push(`const bragg_source_${phase_index} = new Bokeh.ColumnDataSource()`) - - out.push(`bragg_source_${phase_index}.data.x_bragg = [${data.bragg[phase_index].x}]`) - out.push(`bragg_source_${phase_index}.data.y_bragg = [${data.bragg[phase_index].y}]`) - out.push(`bragg_source_${phase_index}.data.h_bragg = [${data.bragg[phase_index].h}]`) - out.push(`bragg_source_${phase_index}.data.k_bragg = [${data.bragg[phase_index].k}]`) - out.push(`bragg_source_${phase_index}.data.l_bragg = [${data.bragg[phase_index].l}]`) - - out.push(`const braggTicks_${phase_index} = new Bokeh.Scatter({`) - out.push(` x: { field: "x_bragg" },`) - out.push(` y: { field: "y_bragg" },`) - out.push(` marker: "dash",`) - out.push(` size: ${1.5 * specs.fontPixelSize},`) - out.push(` line_color: "${specs.braggTicksColor[phase_index]}",`) - out.push(` angle: ${Math.PI / 2.}`) - out.push('})') - out.push(`bragg_chart.add_glyph(braggTicks_${phase_index}, bragg_source_${phase_index})`) - } - return out -} - -function bokehAddDataToDiffChart(data, specs) { - - - - - return [`main_source.data.x_diff = [${data.difference.x}]`, - `main_source.data.y_diff = [${data.difference.y}]`, - `main_source.data.y_diff_upper = [${data.difference.y_upper}]`, - `main_source.data.y_diff_lower = [${data.difference.y_lower}]`, - - `const diffLineTop = new Bokeh.Line({`, - ` x: { field: "x_diff" },`, - ` y: { field: "y_diff_upper" },`, - ` line_color: "${specs.differenceLineColor}",`, - ` line_alpha: 0.4,`, - ` line_width: ${specs.differenceLineWidth}`, - `})`, - `const diffLineBottom = new Bokeh.Line({`, - ` x: { field: "x_diff" },`, - ` y: { field: "y_diff_lower" },`, - ` line_color: "${specs.differenceLineColor}",`, - ` line_alpha: 0.4,`, - ` line_width: ${specs.differenceLineWidth}`, - `})`, - `const diffArea = new Bokeh.VArea({`, - ` x: { field: "x_diff" },`, - ` y1: { field: "y_diff_upper" },`, - ` y2: { field: "y_diff_lower" },`, - ` fill_color: "${specs.differenceAreaColor}",`, - ` fill_alpha: 0.35`, - `})`, - - `diff_chart.add_glyph(diffArea, main_source)`, - `diff_chart.add_glyph(diffLineTop, main_source)`, - `diff_chart.add_glyph(diffLineBottom, main_source)`] -} - -// Bokeh tooltips - -function bokehMainTooltipRow(color, label, value, sigma='') { - return [``, - ` ${label}: `, - ` ${value}`, - ` ${sigma}`, - ``] -} - -function bokehAddMainTooltip(data, specs) { - const x_meas = bokehMainTooltipRow(EaStyle.Colors.themeForegroundDisabled, 'x', '@x_meas{0.00}') - const x_calc = bokehMainTooltipRow(EaStyle.Colors.themeForegroundDisabled, 'x', '@x_calc{0.00}') - const y_meas = bokehMainTooltipRow(specs.measuredLineColor, 'meas', '@y_meas{0.0}', '± @sy_meas{0.0}') - const y_calc = bokehMainTooltipRow(specs.calculatedLineColor, 'calc', '@y_calc{0.0}') - const y_bkg = bokehMainTooltipRow(specs.backgroundLineColor, 'bkg', '@y_bkg{0.0}') - const y_diff = bokehMainTooltipRow(specs.differenceLineColor, 'diff', '@y_diff{0.0}') - let y_phases = [] - for (const phase_index in data.phase) { - if (typeof specs.phaseLineColor !== 'undefined') { - y_phases.push(bokehMainTooltipRow(specs.phaseLineColor[phase_index], `phase ${phase_index}`, `@y_phase_${phase_index}_upper{0.0}`)) - } - } - - let table = [] - table.push(...[`
`, ``, ``]) - // x - if (data.hasMeasured) { - table.push(...x_meas) - } else if (data.hasCalculated) { - table.push(...x_calc) - } - // y - if (data.hasMeasured) { - table.push(...y_meas) - } - if (data.hasCalculated) { - table.push(...y_calc) - } - for (const phase_index in data.phase) { - if (typeof y_phases[phase_index] !== 'undefined') { - table.push(...y_phases[phase_index]) - } - } - if (data.hasBackground) { - table.push(...y_bkg) - } - if (data.hasDifference) { - table.push(...y_diff) - } - table.push(...[``, `
`, `
`]) - - const tooltip = JSON.stringify(table.join('\n')) - return `const main_tooltip = (${tooltip})` -} - -function bokehBraggTooltipSpan(color, label, value) { - return `${label}: ${value}` -} - -function bokehAddBraggTooltip(specs) { - const x_bragg = bokehBraggTooltipSpan(EaStyle.Colors.themeForegroundDisabled, 'x', '@x_bragg{0.00}') - const hkl_bragg = bokehBraggTooltipSpan(specs.calculatedLineColor, 'hkl', '(@h_bragg @k_bragg @l_bragg)') - - const table = [`
`, - x_bragg, - ' ', - hkl_bragg, - `
`] - - const tooltip = JSON.stringify(table.join('\n')) - return `const bragg_tooltip = (${tooltip})` -} diff --git a/src/EasyApp/Gui/Logic/ProjectConfig.js b/src/EasyApp/Gui/Logic/ProjectConfig.js deleted file mode 100644 index 0c88b8e5..00000000 --- a/src/EasyApp/Gui/Logic/ProjectConfig.js +++ /dev/null @@ -1,29 +0,0 @@ -function projectConfig() { - return { - tool: { - poetry: { - name: "easyDiffraction", - version: "0.8.0-beta.1" - } - }, - ci: { - app: { - info: { - date: '01.01.2001', - branch_name: 'master', - commit_sha_short: 'undefined' - }, - tutorials: { - video: { - fps: 15 - } - } - }, - project: { - subdirs: { - screenshots: "" - } - } - } - } -} diff --git a/src/EasyApp/Gui/Logic/Translate.js b/src/EasyApp/Gui/Logic/Translate.js deleted file mode 100644 index 6739f42b..00000000 --- a/src/EasyApp/Gui/Logic/Translate.js +++ /dev/null @@ -1,14 +0,0 @@ -class Translator { - - // Functions - - languagesAsXml() { - return "enEnglish" - } - - defaultLanguageIndex() { - return 0 - } - - selectLanguage(index) {} -} diff --git a/src/EasyApp/Gui/Logic/Utils.js b/src/EasyApp/Gui/Logic/Utils.js deleted file mode 100644 index ecfb6e96..00000000 --- a/src/EasyApp/Gui/Logic/Utils.js +++ /dev/null @@ -1,244 +0,0 @@ -function prettyXml(xml, tab = ' ') -{ - let formatted = '' - let indent = '' - - xml.split(/>\s*\r\n' - - if (node.match( /^]*[^\/]$/ )) - indent += tab - }) - - return formatted.substring(1, formatted.length-3); -} - -function prettyJson(json, tab = ' ') -{ - return JSON.stringify(json, null, tab.length) -} - - -function osPathSep() { - if (Qt.platform.os === "windows") { - return '\\' - } - return '/' -} - -// converts a URL to a local file path -function urlToLocalFile(url) -{ - if (Qt.platform.os === "windows") - { - return url.replace('file:///', '').split('/').join('\\') - } - else if (Qt.platform.os === "osx" || Qt.platform.os === "linux" || Qt.platform.os === "unix") - { - return url.replace('file://', '') - } - else - { - return url - } -} - -function isQmlScene() -{ - const runnerPath = Qt.application.arguments[0] - if (runnerPath.includes('qmlscene')) - { - return true - } - return false -} - -// XMLHttpRequest: Using PUT on a local file is disabled by default. -// Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature. -// E.g., 'QML_XHR_ALLOW_FILE_WRITE=1 qml main.qml' -function writeFile(url, content) { - const method = "PUT" - const async = false - const request = new XMLHttpRequest() - request.onreadystatechange = () => { - if (request.readyState === XMLHttpRequest.DONE) { - if (request.status === 200) { - print(`Succeeded to write file: '${url}'`) - } else { - print(`Failed to write file: '${url}'. Status: ${request.status}`) - } - } - } - request.open(method, url, async) - request.send(content) -} - -// XMLHttpRequest: Using GET on a local file is disabled by default. -// Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature. -// E.g., 'QML_XHR_ALLOW_FILE_READ=1 qml main.qml' -function readFile(url) { - const method = "GET" - const async = false - const request = new XMLHttpRequest() - request.onreadystatechange = () => { - if (request.readyState === XMLHttpRequest.DONE) { - if (request.status === 200) { - print(`Succeeded to read file: '${url}'`) - } else { - print(`Failed to read file: '${url}'. Status: ${request.status}`) - } - } - } - request.open(method, url, async) - request.send() - return request.responseText -} - - - - -function toFixed(value, digitsCount = 4) -{ - if (typeof value === 'undefined') - { - return "" - } - else if (typeof value == 'number') - { - return value.toFixed(digitsCount) - } - else - { - return value - } -} - -function toMaxPrecision(value, digitsCount = 5) { - if (typeof value === 'number') { - return Number(value.toPrecision(digitsCount)).toString() - } else if (typeof value === 'string') { - return value - } else if (typeof value === 'undefined') { - return "" - } else { - console.error(`Value ${value} with type '${typeof value}' is not supported`) - return "" - } -} - -function toDefaultPrecision(x) { - const defaultPrecision = 3 - return Number(x.toPrecision(defaultPrecision)).toString() -} - -function toSinglePrecision(x) { - if (x === 0) { - return '' - } - return Number(x.toPrecision(1)).toString() -} - -function toErrSinglePrecision(x, dx) { - dx = Number(dx.toPrecision(1)) - return toFixedUncertainty(x, dx) -} - -function toSamePrecision(x, y) { - return toFixedUncertainty(x, y) -} - -// https://gist.github.com/davidselassie/3838522 - -function roundAway(x) { - // Rounds a number to the next integer away from 0 - // - // Args: - // x - Number to round - // Returns: - // rounded - Next integer from x away from 0 - - if (x >= 0) { - return Math.ceil(x) - } else { - return Math.floor(x) - } -} - -function roundToIndex(x, index) { - // Rounds a number to a given index around the decimal point - // - // Args: - // x - Number to round - // index - Index of the least significan digit; 0 is the decimal point - // Returns: - // rounded - Number rounded using the least signficant digit - - var power = Math.pow(10, -index) - return Math.round(x * power) / power -} - -function toFixedUncertainty(x, dx) { - // Returns the string representation of a number correctly rounded given - // an uncertainty value. - // - // Args: - // x - Number to print - // dx - Uncertainty in x - // Returns: - // x_string - String with x properly rounded given dx - - // If there is no uncertainty, return the entire number - if (dx === undefined || dx === 0) { - ////return x.toString(); - return toDefaultPrecision(x) - } - - // Find out the least significant digit using the uncertainty - var roundingIndex = roundAway(Math.log(dx) / Math.log(10)) - // Round using that number of digits. - var roundedString = roundToIndex(x, roundingIndex).toString() - - // Now we have to only show the digits that are significant - - // If we're rounding a whole number - if (roundingIndex >= 0) { - // Find out if we want more significant digits that we have - var overshot = roundingIndex - roundedString.length + 1 - if (overshot <= 0) { - return roundedString; - // If so, add more 0s on the beginning. - } else { - return Array(overshot + 1).join('0') + roundedString; - } - // If we're rounding to a decimal place - } else { - var decimalIndex = roundedString.indexOf('.'); - // If there isn't a '.', we're rounding to 0 if we got here. - if (decimalIndex < 0) { - roundedString = '0.' - decimalIndex = 1 - } - - // Find out if the least significant digit is off the end of the number - var lastIndex = decimalIndex + 1 - roundingIndex - var overshot = lastIndex - roundedString.length - if (overshot <= 0) { - return roundedString.slice(0, lastIndex) - // If so, add more 0s to show the precision we have. - } else { - return roundedString + Array(overshot + 1).join('0') - } - } -} - - -// Consider using python backend -// Either -// from uncertainties import ufloat -// or -// from decimal import Decimal -// paramStr = str(Decimal(valueStr).quantize(Decimal(errorStr))) # Sets value precision to be the same as for the standard uncertainty diff --git a/src/EasyApp/Logic/Utils/__init__.py b/src/EasyApp/Logic/Utils/__init__.py deleted file mode 100644 index eae7a7e4..00000000 --- a/src/EasyApp/Logic/Utils/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = "github.com/AndrewSazonov" diff --git a/src/EasyApp/Logic/__init__.py b/src/EasyApp/Logic/__init__.py deleted file mode 100644 index 278612ae..00000000 --- a/src/EasyApp/Logic/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__author__ = "github.com/AndrewSazonov" -__version__ = "0.0.1" diff --git a/src/EasyApp/__init__.py b/src/EasyApp/__init__.py deleted file mode 100644 index a7edaabe..00000000 --- a/src/EasyApp/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -import importlib.metadata - -# Set package version -try: - __version__ = importlib.metadata.version("EasyApp") -except ImportError: - __version__ = "development" \ No newline at end of file diff --git a/src/EasyApp/Gui/Animations/ColorReset.qml b/src/EasyApplication/Gui/Animations/ColorReset.qml similarity index 90% rename from src/EasyApp/Gui/Animations/ColorReset.qml rename to src/EasyApplication/Gui/Animations/ColorReset.qml index c31ab50e..bfeef0b7 100644 --- a/src/EasyApp/Gui/Animations/ColorReset.qml +++ b/src/EasyApplication/Gui/Animations/ColorReset.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle SequentialAnimation { property alias target: colorChangeAnimo.target diff --git a/src/EasyApp/Gui/Animations/ThemeChange.qml b/src/EasyApplication/Gui/Animations/ThemeChange.qml similarity index 75% rename from src/EasyApp/Gui/Animations/ThemeChange.qml rename to src/EasyApplication/Gui/Animations/ThemeChange.qml index b97bd3e5..a7536897 100644 --- a/src/EasyApp/Gui/Animations/ThemeChange.qml +++ b/src/EasyApplication/Gui/Animations/ThemeChange.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle PropertyAnimation { duration: EaStyle.Times.themeChange diff --git a/src/EasyApp/Gui/Animations/TranslationChange.qml b/src/EasyApplication/Gui/Animations/TranslationChange.qml similarity index 93% rename from src/EasyApp/Gui/Animations/TranslationChange.qml rename to src/EasyApplication/Gui/Animations/TranslationChange.qml index 1b88fece..d3a7ab61 100644 --- a/src/EasyApp/Gui/Animations/TranslationChange.qml +++ b/src/EasyApplication/Gui/Animations/TranslationChange.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle SequentialAnimation { diff --git a/src/EasyApp/Gui/Animations/qmldir b/src/EasyApplication/Gui/Animations/qmldir similarity index 100% rename from src/EasyApp/Gui/Animations/qmldir rename to src/EasyApplication/Gui/Animations/qmldir diff --git a/src/EasyApplication/Gui/Charts/ChartTemplateHeatmap2dPlotly.html b/src/EasyApplication/Gui/Charts/ChartTemplateHeatmap2dPlotly.html new file mode 100644 index 00000000..b0c05f70 --- /dev/null +++ b/src/EasyApplication/Gui/Charts/ChartTemplateHeatmap2dPlotly.html @@ -0,0 +1,45 @@ + + + + + + + + +
+ + + + diff --git a/src/EasyApplication/Gui/Charts/ChartTemplateSimple1dPlotly.html b/src/EasyApplication/Gui/Charts/ChartTemplateSimple1dPlotly.html new file mode 100644 index 00000000..294d7a8f --- /dev/null +++ b/src/EasyApplication/Gui/Charts/ChartTemplateSimple1dPlotly.html @@ -0,0 +1,135 @@ + + + + + + + + +
+ + + + diff --git a/src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml b/src/EasyApplication/Gui/Charts/ChartViewHeatmap2dPlotly.qml similarity index 83% rename from src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml rename to src/EasyApplication/Gui/Charts/ChartViewHeatmap2dPlotly.qml index 58104a32..89a46ff8 100644 --- a/src/EasyApp/Gui/Charts/ChartViewHeatmap2dPlotly.qml +++ b/src/EasyApplication/Gui/Charts/ChartViewHeatmap2dPlotly.qml @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: 2022 EasyTexture contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2022 Contributors to the EasyTexture project - import QtQuick 2.15 import QtQuick.Controls 2.15 import QtWebEngine 1.10 -import easyApp.Gui.Elements 1.0 as EaElements +import EasyApplication.Gui.Elements 1.0 as EaElements Rectangle { id: container diff --git a/src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml b/src/EasyApplication/Gui/Charts/ChartViewSimple1dPlotly.qml similarity index 90% rename from src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml rename to src/EasyApplication/Gui/Charts/ChartViewSimple1dPlotly.qml index 4ea22fcb..2f156693 100644 --- a/src/EasyApp/Gui/Charts/ChartViewSimple1dPlotly.qml +++ b/src/EasyApplication/Gui/Charts/ChartViewSimple1dPlotly.qml @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: 2022 EasyTexture contributors -// SPDX-License-Identifier: BSD-3-Clause -// © 2022 Contributors to the EasyTexture project - import QtQuick 2.15 import QtQuick.Controls 2.15 import QtWebEngine 1.10 -import easyApp.Gui.Elements 1.0 as EaElements +import EasyApplication.Gui.Elements 1.0 as EaElements Rectangle { id: container diff --git a/src/EasyApp/Gui/Charts/Plotly1dBarPlot.qml b/src/EasyApplication/Gui/Charts/Plotly1dBarPlot.qml similarity index 97% rename from src/EasyApp/Gui/Charts/Plotly1dBarPlot.qml rename to src/EasyApplication/Gui/Charts/Plotly1dBarPlot.qml index 78aac480..5bd6a36a 100644 --- a/src/EasyApp/Gui/Charts/Plotly1dBarPlot.qml +++ b/src/EasyApplication/Gui/Charts/Plotly1dBarPlot.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtWebEngine -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle import Gui.Globals as Globals WebEngineView { diff --git a/src/EasyApp/Gui/Charts/Plotly1dLine.qml b/src/EasyApplication/Gui/Charts/Plotly1dLine.qml similarity index 100% rename from src/EasyApp/Gui/Charts/Plotly1dLine.qml rename to src/EasyApplication/Gui/Charts/Plotly1dLine.qml diff --git a/src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml b/src/EasyApplication/Gui/Charts/Plotly1dMeasVsCalc.qml similarity index 99% rename from src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml rename to src/EasyApplication/Gui/Charts/Plotly1dMeasVsCalc.qml index 0db20fe9..dc284f42 100644 --- a/src/EasyApp/Gui/Charts/Plotly1dMeasVsCalc.qml +++ b/src/EasyApplication/Gui/Charts/Plotly1dMeasVsCalc.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtWebEngine -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle WebEngineView { diff --git a/src/EasyApp/Gui/Charts/Plotly2dHeatmap.qml b/src/EasyApplication/Gui/Charts/Plotly2dHeatmap.qml similarity index 100% rename from src/EasyApp/Gui/Charts/Plotly2dHeatmap.qml rename to src/EasyApplication/Gui/Charts/Plotly2dHeatmap.qml diff --git a/src/EasyApp/Gui/Charts/Plotly2dPolarHeatmap.qml b/src/EasyApplication/Gui/Charts/Plotly2dPolarHeatmap.qml similarity index 100% rename from src/EasyApp/Gui/Charts/Plotly2dPolarHeatmap.qml rename to src/EasyApplication/Gui/Charts/Plotly2dPolarHeatmap.qml diff --git a/src/EasyApp/Gui/Charts/Plotly3dScatter.qml b/src/EasyApplication/Gui/Charts/Plotly3dScatter.qml similarity index 100% rename from src/EasyApp/Gui/Charts/Plotly3dScatter.qml rename to src/EasyApplication/Gui/Charts/Plotly3dScatter.qml diff --git a/src/EasyApp/Gui/Charts/Plotly3dSurface.qml b/src/EasyApplication/Gui/Charts/Plotly3dSurface.qml similarity index 100% rename from src/EasyApp/Gui/Charts/Plotly3dSurface.qml rename to src/EasyApplication/Gui/Charts/Plotly3dSurface.qml diff --git a/src/EasyApp/Gui/Charts/QtCharts1dBase 2.qml b/src/EasyApplication/Gui/Charts/QtCharts1dBase 2.qml similarity index 96% rename from src/EasyApp/Gui/Charts/QtCharts1dBase 2.qml rename to src/EasyApplication/Gui/Charts/QtCharts1dBase 2.qml index a1807fe0..c4e80f6a 100644 --- a/src/EasyApp/Gui/Charts/QtCharts1dBase 2.qml +++ b/src/EasyApplication/Gui/Charts/QtCharts1dBase 2.qml @@ -2,10 +2,10 @@ import QtQuick import QtQuick.Controls import QtCharts -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Charts as EaCharts +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Charts as EaCharts Rectangle { diff --git a/src/EasyApp/Gui/Charts/QtCharts1dBase.qml b/src/EasyApplication/Gui/Charts/QtCharts1dBase.qml similarity index 97% rename from src/EasyApp/Gui/Charts/QtCharts1dBase.qml rename to src/EasyApplication/Gui/Charts/QtCharts1dBase.qml index 1379eee2..0aaff222 100644 --- a/src/EasyApp/Gui/Charts/QtCharts1dBase.qml +++ b/src/EasyApplication/Gui/Charts/QtCharts1dBase.qml @@ -2,9 +2,9 @@ import QtQuick import QtQuick.Controls import QtCharts -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Charts as EaCharts +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Charts as EaCharts ChartView { diff --git a/src/EasyApp/Gui/Charts/QtCharts1dMeasVsCalc.qml b/src/EasyApplication/Gui/Charts/QtCharts1dMeasVsCalc.qml similarity index 92% rename from src/EasyApp/Gui/Charts/QtCharts1dMeasVsCalc.qml rename to src/EasyApplication/Gui/Charts/QtCharts1dMeasVsCalc.qml index 948b7085..9c5d1c84 100644 --- a/src/EasyApp/Gui/Charts/QtCharts1dMeasVsCalc.qml +++ b/src/EasyApplication/Gui/Charts/QtCharts1dMeasVsCalc.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtCharts -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Charts as EaCharts +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Charts as EaCharts EaCharts.QtCharts1dBase { diff --git a/src/EasyApp/Gui/Charts/QtCharts1dValueAxis.qml b/src/EasyApplication/Gui/Charts/QtCharts1dValueAxis.qml similarity index 86% rename from src/EasyApp/Gui/Charts/QtCharts1dValueAxis.qml rename to src/EasyApplication/Gui/Charts/QtCharts1dValueAxis.qml index 7385f683..0aafd528 100644 --- a/src/EasyApp/Gui/Charts/QtCharts1dValueAxis.qml +++ b/src/EasyApplication/Gui/Charts/QtCharts1dValueAxis.qml @@ -1,9 +1,9 @@ import QtQuick import QtCharts -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals 1.0 as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals 1.0 as EaGlobals ValueAxis { diff --git a/src/EasyApp/Gui/Charts/qmldir b/src/EasyApplication/Gui/Charts/qmldir similarity index 100% rename from src/EasyApp/Gui/Charts/qmldir rename to src/EasyApplication/Gui/Charts/qmldir diff --git a/src/EasyApp/Gui/Components/AboutDialog.qml b/src/EasyApplication/Gui/Components/AboutDialog.qml similarity index 97% rename from src/EasyApp/Gui/Components/AboutDialog.qml rename to src/EasyApplication/Gui/Components/AboutDialog.qml index 05928536..403f172d 100644 --- a/src/EasyApp/Gui/Components/AboutDialog.qml +++ b/src/EasyApplication/Gui/Components/AboutDialog.qml @@ -4,9 +4,9 @@ import QtQuick.Controls.impl import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements EaElements.Dialog { diff --git a/src/EasyApplication/Gui/Components/AppBarCentralTabs.qml b/src/EasyApplication/Gui/Components/AppBarCentralTabs.qml new file mode 100644 index 00000000..9bfa2a0f --- /dev/null +++ b/src/EasyApplication/Gui/Components/AppBarCentralTabs.qml @@ -0,0 +1,9 @@ +import QtQuick +import QtQuick.Controls + +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements + +EaElements.TabBar { + showBottomBorder: true +} diff --git a/src/EasyApp/Gui/Components/AppBarLeftButtons.qml b/src/EasyApplication/Gui/Components/AppBarLeftButtons.qml similarity index 100% rename from src/EasyApp/Gui/Components/AppBarLeftButtons.qml rename to src/EasyApplication/Gui/Components/AppBarLeftButtons.qml diff --git a/src/EasyApp/Gui/Components/AppBarRightButtons.qml b/src/EasyApplication/Gui/Components/AppBarRightButtons.qml similarity index 100% rename from src/EasyApp/Gui/Components/AppBarRightButtons.qml rename to src/EasyApplication/Gui/Components/AppBarRightButtons.qml diff --git a/src/EasyApp/Gui/Components/ApplicationWindow.qml b/src/EasyApplication/Gui/Components/ApplicationWindow.qml similarity index 93% rename from src/EasyApp/Gui/Components/ApplicationWindow.qml rename to src/EasyApplication/Gui/Components/ApplicationWindow.qml index 4bbd05cd..fa906080 100644 --- a/src/EasyApp/Gui/Components/ApplicationWindow.qml +++ b/src/EasyApplication/Gui/Components/ApplicationWindow.qml @@ -1,11 +1,11 @@ import QtQuick import QtCore -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents EaElements.ApplicationWindow { diff --git a/src/EasyApp/Gui/Components/BasicReport.qml b/src/EasyApplication/Gui/Components/BasicReport.qml similarity index 98% rename from src/EasyApp/Gui/Components/BasicReport.qml rename to src/EasyApplication/Gui/Components/BasicReport.qml index 6a6fd9a0..676e1b93 100644 --- a/src/EasyApp/Gui/Components/BasicReport.qml +++ b/src/EasyApplication/Gui/Components/BasicReport.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtWebEngine -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle WebEngineView { diff --git a/src/EasyApp/Gui/Components/ContentArea.qml b/src/EasyApplication/Gui/Components/ContentArea.qml similarity index 100% rename from src/EasyApp/Gui/Components/ContentArea.qml rename to src/EasyApplication/Gui/Components/ContentArea.qml diff --git a/src/EasyApp/Gui/Components/ContentPage.qml b/src/EasyApplication/Gui/Components/ContentPage.qml similarity index 92% rename from src/EasyApp/Gui/Components/ContentPage.qml rename to src/EasyApplication/Gui/Components/ContentPage.qml index a0e22ded..7d265ee9 100644 --- a/src/EasyApp/Gui/Components/ContentPage.qml +++ b/src/EasyApplication/Gui/Components/ContentPage.qml @@ -1,9 +1,9 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements Item { id: page diff --git a/src/EasyApp/Gui/Components/GuideWindow.qml b/src/EasyApplication/Gui/Components/GuideWindow.qml similarity index 93% rename from src/EasyApp/Gui/Components/GuideWindow.qml rename to src/EasyApplication/Gui/Components/GuideWindow.qml index 19604553..916a6036 100644 --- a/src/EasyApp/Gui/Components/GuideWindow.qml +++ b/src/EasyApplication/Gui/Components/GuideWindow.qml @@ -3,9 +3,9 @@ import QtQuick.Controls import QtQuick.Controls.impl import QtQuick.Layouts 1.12 -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements import Gui.Globals as ExGlobals diff --git a/src/EasyApp/Gui/Components/GuideWindowContainer.qml b/src/EasyApplication/Gui/Components/GuideWindowContainer.qml similarity index 100% rename from src/EasyApp/Gui/Components/GuideWindowContainer.qml rename to src/EasyApplication/Gui/Components/GuideWindowContainer.qml diff --git a/src/EasyApp/Gui/Components/JsonListModel.qml b/src/EasyApplication/Gui/Components/JsonListModel.qml similarity index 100% rename from src/EasyApp/Gui/Components/JsonListModel.qml rename to src/EasyApplication/Gui/Components/JsonListModel.qml diff --git a/src/EasyApp/Gui/Components/MainContent.qml b/src/EasyApplication/Gui/Components/MainContent.qml similarity index 93% rename from src/EasyApp/Gui/Components/MainContent.qml rename to src/EasyApplication/Gui/Components/MainContent.qml index f45677e5..e771dce8 100644 --- a/src/EasyApp/Gui/Components/MainContent.qml +++ b/src/EasyApplication/Gui/Components/MainContent.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Elements as EaElements Item { id: mainAreaContainer diff --git a/src/EasyApp/Gui/Components/PreferencesDialog.qml b/src/EasyApplication/Gui/Components/PreferencesDialog.qml similarity index 98% rename from src/EasyApp/Gui/Components/PreferencesDialog.qml rename to src/EasyApplication/Gui/Components/PreferencesDialog.qml index cc969d76..ba9a04cd 100644 --- a/src/EasyApp/Gui/Components/PreferencesDialog.qml +++ b/src/EasyApplication/Gui/Components/PreferencesDialog.qml @@ -6,10 +6,10 @@ import QtQuick.Controls.Material.impl //import QtQuick.XmlListModel 2.15 import QtCore -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents EaElements.Dialog { diff --git a/src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml b/src/EasyApplication/Gui/Components/ProjectDescriptionDialog.qml similarity index 95% rename from src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml rename to src/EasyApplication/Gui/Components/ProjectDescriptionDialog.qml index 371154e7..57b705bb 100644 --- a/src/EasyApp/Gui/Components/ProjectDescriptionDialog.qml +++ b/src/EasyApplication/Gui/Components/ProjectDescriptionDialog.qml @@ -3,10 +3,10 @@ import QtQuick.Controls import QtQuick.Dialogs import QtCore -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Logic as EaLogic EaElements.Dialog { id: dialog diff --git a/src/EasyApp/Gui/Components/SideBar.qml b/src/EasyApplication/Gui/Components/SideBar.qml similarity index 95% rename from src/EasyApp/Gui/Components/SideBar.qml rename to src/EasyApplication/Gui/Components/SideBar.qml index b4e31031..fab6c9f7 100644 --- a/src/EasyApp/Gui/Components/SideBar.qml +++ b/src/EasyApplication/Gui/Components/SideBar.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Item { id: sideBarContainer diff --git a/src/EasyApp/Gui/Components/SideBarColumn.qml b/src/EasyApplication/Gui/Components/SideBarColumn.qml similarity index 84% rename from src/EasyApp/Gui/Components/SideBarColumn.qml rename to src/EasyApplication/Gui/Components/SideBarColumn.qml index 6ee0415c..f58486c2 100644 --- a/src/EasyApp/Gui/Components/SideBarColumn.qml +++ b/src/EasyApplication/Gui/Components/SideBarColumn.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Flickable { diff --git a/src/EasyApp/Gui/Components/TableView.qml b/src/EasyApplication/Gui/Components/TableView.qml similarity index 94% rename from src/EasyApp/Gui/Components/TableView.qml rename to src/EasyApplication/Gui/Components/TableView.qml index 72e906ef..543d3728 100644 --- a/src/EasyApp/Gui/Components/TableView.qml +++ b/src/EasyApplication/Gui/Components/TableView.qml @@ -1,11 +1,11 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Components as EaComponents +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Components as EaComponents ListView { diff --git a/src/EasyApp/Gui/Components/TableViewAdvancedLabel.qml b/src/EasyApplication/Gui/Components/TableViewAdvancedLabel.qml similarity index 90% rename from src/EasyApp/Gui/Components/TableViewAdvancedLabel.qml rename to src/EasyApplication/Gui/Components/TableViewAdvancedLabel.qml index ab602f16..7639f7f6 100644 --- a/src/EasyApp/Gui/Components/TableViewAdvancedLabel.qml +++ b/src/EasyApplication/Gui/Components/TableViewAdvancedLabel.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Button { id: control diff --git a/src/EasyApp/Gui/Components/TableViewButton.qml b/src/EasyApplication/Gui/Components/TableViewButton.qml similarity index 75% rename from src/EasyApp/Gui/Components/TableViewButton.qml rename to src/EasyApplication/Gui/Components/TableViewButton.qml index 358f3069..9f8b4185 100644 --- a/src/EasyApp/Gui/Components/TableViewButton.qml +++ b/src/EasyApplication/Gui/Components/TableViewButton.qml @@ -1,7 +1,7 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle EaElements.TabButton { property int horizontalAlignment: Text.AlignHCenter diff --git a/src/EasyApp/Gui/Components/TableViewCheckBox.qml b/src/EasyApplication/Gui/Components/TableViewCheckBox.qml similarity index 74% rename from src/EasyApp/Gui/Components/TableViewCheckBox.qml rename to src/EasyApplication/Gui/Components/TableViewCheckBox.qml index 828f85bd..803a6599 100644 --- a/src/EasyApp/Gui/Components/TableViewCheckBox.qml +++ b/src/EasyApplication/Gui/Components/TableViewCheckBox.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Elements as EaElements EaElements.CheckBox { property int horizontalAlignment: Text.AlignHCenter diff --git a/src/EasyApp/Gui/Components/TableViewComboBox.qml b/src/EasyApplication/Gui/Components/TableViewComboBox.qml similarity index 81% rename from src/EasyApp/Gui/Components/TableViewComboBox.qml rename to src/EasyApplication/Gui/Components/TableViewComboBox.qml index fa196dd8..3b0bc055 100644 --- a/src/EasyApp/Gui/Components/TableViewComboBox.qml +++ b/src/EasyApplication/Gui/Components/TableViewComboBox.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Elements as EaElements EaElements.ComboBox { property int horizontalAlignment: Text.AlignHCenter diff --git a/src/EasyApp/Gui/Components/TableViewDelegate.qml b/src/EasyApplication/Gui/Components/TableViewDelegate.qml similarity index 94% rename from src/EasyApp/Gui/Components/TableViewDelegate.qml rename to src/EasyApplication/Gui/Components/TableViewDelegate.qml index 07093035..8916937d 100644 --- a/src/EasyApp/Gui/Components/TableViewDelegate.qml +++ b/src/EasyApplication/Gui/Components/TableViewDelegate.qml @@ -1,7 +1,7 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations Rectangle { id: control diff --git a/src/EasyApp/Gui/Components/TableViewHeader.qml b/src/EasyApplication/Gui/Components/TableViewHeader.qml similarity index 86% rename from src/EasyApp/Gui/Components/TableViewHeader.qml rename to src/EasyApplication/Gui/Components/TableViewHeader.qml index caba7f03..43a63d37 100644 --- a/src/EasyApp/Gui/Components/TableViewHeader.qml +++ b/src/EasyApplication/Gui/Components/TableViewHeader.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations Rectangle { default property alias contentRowData: contentRow.data diff --git a/src/EasyApp/Gui/Components/TableViewLabel.qml b/src/EasyApplication/Gui/Components/TableViewLabel.qml similarity index 91% rename from src/EasyApp/Gui/Components/TableViewLabel.qml rename to src/EasyApplication/Gui/Components/TableViewLabel.qml index 3aeab937..bff527a2 100644 --- a/src/EasyApp/Gui/Components/TableViewLabel.qml +++ b/src/EasyApplication/Gui/Components/TableViewLabel.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements EaElements.Label { id: control diff --git a/src/EasyApp/Gui/Components/TableViewLabelControl.qml b/src/EasyApplication/Gui/Components/TableViewLabelControl.qml similarity index 90% rename from src/EasyApp/Gui/Components/TableViewLabelControl.qml rename to src/EasyApplication/Gui/Components/TableViewLabelControl.qml index 3846e417..cb47fbdf 100644 --- a/src/EasyApp/Gui/Components/TableViewLabelControl.qml +++ b/src/EasyApplication/Gui/Components/TableViewLabelControl.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Button { id: control diff --git a/src/EasyApp/Gui/Components/TableViewParameter.qml b/src/EasyApplication/Gui/Components/TableViewParameter.qml similarity index 97% rename from src/EasyApp/Gui/Components/TableViewParameter.qml rename to src/EasyApplication/Gui/Components/TableViewParameter.qml index 0b105da8..bf2b5270 100644 --- a/src/EasyApp/Gui/Components/TableViewParameter.qml +++ b/src/EasyApplication/Gui/Components/TableViewParameter.qml @@ -1,8 +1,8 @@ import QtQuick -import EasyApp.Gui.Logic as EaLogic -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Logic as EaLogic +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements EaElements.TextInput { id: control diff --git a/src/EasyApp/Gui/Components/TableViewTextInput.qml b/src/EasyApplication/Gui/Components/TableViewTextInput.qml similarity index 78% rename from src/EasyApp/Gui/Components/TableViewTextInput.qml rename to src/EasyApplication/Gui/Components/TableViewTextInput.qml index fecc3d9e..45d283ec 100644 --- a/src/EasyApp/Gui/Components/TableViewTextInput.qml +++ b/src/EasyApplication/Gui/Components/TableViewTextInput.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Elements as EaElements EaElements.TextInput { property string headerText: "" diff --git a/src/EasyApp/Gui/Components/TableViewTwoRowsAdvancedLabel.qml b/src/EasyApplication/Gui/Components/TableViewTwoRowsAdvancedLabel.qml similarity index 95% rename from src/EasyApp/Gui/Components/TableViewTwoRowsAdvancedLabel.qml rename to src/EasyApplication/Gui/Components/TableViewTwoRowsAdvancedLabel.qml index 1ba75252..0eb081dc 100644 --- a/src/EasyApp/Gui/Components/TableViewTwoRowsAdvancedLabel.qml +++ b/src/EasyApplication/Gui/Components/TableViewTwoRowsAdvancedLabel.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Button { id: control diff --git a/src/EasyApp/Gui/Components/qmldir b/src/EasyApplication/Gui/Components/qmldir similarity index 100% rename from src/EasyApp/Gui/Components/qmldir rename to src/EasyApplication/Gui/Components/qmldir diff --git a/src/EasyApp/Gui/Elements/AppBarTabButton.qml b/src/EasyApplication/Gui/Elements/AppBarTabButton.qml similarity index 94% rename from src/EasyApp/Gui/Elements/AppBarTabButton.qml rename to src/EasyApplication/Gui/Elements/AppBarTabButton.qml index 47b81027..f8a80db3 100644 --- a/src/EasyApp/Gui/Elements/AppBarTabButton.qml +++ b/src/EasyApplication/Gui/Elements/AppBarTabButton.qml @@ -1,8 +1,8 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements EaElements.TabButton { id: control diff --git a/src/EasyApp/Gui/Elements/ApplicationWindow.qml b/src/EasyApplication/Gui/Elements/ApplicationWindow.qml similarity index 94% rename from src/EasyApp/Gui/Elements/ApplicationWindow.qml rename to src/EasyApplication/Gui/Elements/ApplicationWindow.qml index f6de7891..f2d33f37 100644 --- a/src/EasyApp/Gui/Elements/ApplicationWindow.qml +++ b/src/EasyApplication/Gui/Elements/ApplicationWindow.qml @@ -2,12 +2,12 @@ import QtQuick import QtQuick.Controls import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements -import EasyApp.Logic.Maintenance as EaMaintenance +import EasyApplication.Logic.Maintenance as EaMaintenance T.ApplicationWindow { diff --git a/src/EasyApp/Gui/Elements/Button.qml b/src/EasyApplication/Gui/Elements/Button.qml similarity index 95% rename from src/EasyApp/Gui/Elements/Button.qml rename to src/EasyApplication/Gui/Elements/Button.qml index 813d1591..7c666e1c 100644 --- a/src/EasyApp/Gui/Elements/Button.qml +++ b/src/EasyApplication/Gui/Elements/Button.qml @@ -3,8 +3,8 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations T.Button { diff --git a/src/EasyApp/Gui/Elements/CheckBox.qml b/src/EasyApplication/Gui/Elements/CheckBox.qml similarity index 92% rename from src/EasyApp/Gui/Elements/CheckBox.qml rename to src/EasyApplication/Gui/Elements/CheckBox.qml index 7c9c18e1..56ca8985 100644 --- a/src/EasyApp/Gui/Elements/CheckBox.qml +++ b/src/EasyApplication/Gui/Elements/CheckBox.qml @@ -1,10 +1,10 @@ import QtQuick import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.CheckBox { id: control diff --git a/src/EasyApp/Gui/Elements/CheckIndicator.qml b/src/EasyApplication/Gui/Elements/CheckIndicator.qml similarity index 93% rename from src/EasyApp/Gui/Elements/CheckIndicator.qml rename to src/EasyApplication/Gui/Elements/CheckIndicator.qml index 6f238d6b..a7a88508 100644 --- a/src/EasyApp/Gui/Elements/CheckIndicator.qml +++ b/src/EasyApplication/Gui/Elements/CheckIndicator.qml @@ -1,9 +1,9 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements Rectangle { id: indicatorItem diff --git a/src/EasyApp/Gui/Elements/ComboBox.qml b/src/EasyApplication/Gui/Elements/ComboBox.qml similarity index 97% rename from src/EasyApp/Gui/Elements/ComboBox.qml rename to src/EasyApplication/Gui/Elements/ComboBox.qml index 30b2be16..99d76cdf 100644 --- a/src/EasyApp/Gui/Elements/ComboBox.qml +++ b/src/EasyApplication/Gui/Elements/ComboBox.qml @@ -5,10 +5,10 @@ import QtQuick.Controls.impl import QtQuick.Controls.Material.impl import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.ComboBox { id: control diff --git a/src/EasyApp/Gui/Elements/CursorDelegate.qml b/src/EasyApplication/Gui/Elements/CursorDelegate.qml similarity index 94% rename from src/EasyApp/Gui/Elements/CursorDelegate.qml rename to src/EasyApplication/Gui/Elements/CursorDelegate.qml index 86dc5ef7..a2c2fea5 100644 --- a/src/EasyApp/Gui/Elements/CursorDelegate.qml +++ b/src/EasyApplication/Gui/Elements/CursorDelegate.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Rectangle { id: cursor diff --git a/src/EasyApp/Gui/Elements/Dialog.qml b/src/EasyApplication/Gui/Elements/Dialog.qml similarity index 94% rename from src/EasyApp/Gui/Elements/Dialog.qml rename to src/EasyApplication/Gui/Elements/Dialog.qml index 9b7e7574..feb6cff1 100644 --- a/src/EasyApp/Gui/Elements/Dialog.qml +++ b/src/EasyApplication/Gui/Elements/Dialog.qml @@ -4,10 +4,10 @@ import QtQuick.Controls.impl import QtQuick.Controls.Material.impl import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Dialog { id: control diff --git a/src/EasyApp/Gui/Elements/DialogButtonBox.qml b/src/EasyApplication/Gui/Elements/DialogButtonBox.qml similarity index 89% rename from src/EasyApp/Gui/Elements/DialogButtonBox.qml rename to src/EasyApplication/Gui/Elements/DialogButtonBox.qml index 0b985c82..ac391ef3 100644 --- a/src/EasyApp/Gui/Elements/DialogButtonBox.qml +++ b/src/EasyApplication/Gui/Elements/DialogButtonBox.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.DialogButtonBox { id: control diff --git a/src/EasyApp/Gui/Elements/GroupBox.qml b/src/EasyApplication/Gui/Elements/GroupBox.qml similarity index 97% rename from src/EasyApp/Gui/Elements/GroupBox.qml rename to src/EasyApplication/Gui/Elements/GroupBox.qml index dd34b8ed..526f9298 100644 --- a/src/EasyApp/Gui/Elements/GroupBox.qml +++ b/src/EasyApplication/Gui/Elements/GroupBox.qml @@ -3,10 +3,10 @@ import QtQuick.Controls import QtQuick.Controls.Basic // Fixes EasyApp/Gui/Elements/GroupBox.qml:51:22: QML Row: The current style does not support customization of this control (property: "contentItem" item: QQuickRow(0x60000381e200, parent=0x0, geometry=0,0 0x0)). Please customize a non-native style (such as Basic, Fusion, Material, etc). For more information, see: https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#customization-reference import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements +import EasyApplication.Gui.Animations as EaAnimations T.GroupBox { diff --git a/src/EasyApp/Gui/Elements/GroupButton.qml b/src/EasyApplication/Gui/Elements/GroupButton.qml similarity index 92% rename from src/EasyApp/Gui/Elements/GroupButton.qml rename to src/EasyApplication/Gui/Elements/GroupButton.qml index ec7ba857..ae4492c8 100644 --- a/src/EasyApp/Gui/Elements/GroupButton.qml +++ b/src/EasyApplication/Gui/Elements/GroupButton.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Button { implicitWidth: (parent.width - parent.spacing) * 0.5 - 1 diff --git a/src/EasyApp/Gui/Elements/GroupColumn.qml b/src/EasyApplication/Gui/Elements/GroupColumn.qml similarity index 80% rename from src/EasyApp/Gui/Elements/GroupColumn.qml rename to src/EasyApplication/Gui/Elements/GroupColumn.qml index fba6af32..baf15b6c 100644 --- a/src/EasyApp/Gui/Elements/GroupColumn.qml +++ b/src/EasyApplication/Gui/Elements/GroupColumn.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Column { width: parent.width - EaStyle.Sizes.fontPixelSize diff --git a/src/EasyApp/Gui/Elements/GroupRow.qml b/src/EasyApplication/Gui/Elements/GroupRow.qml similarity index 74% rename from src/EasyApp/Gui/Elements/GroupRow.qml rename to src/EasyApplication/Gui/Elements/GroupRow.qml index e8710d71..7dbb1b20 100644 --- a/src/EasyApp/Gui/Elements/GroupRow.qml +++ b/src/EasyApplication/Gui/Elements/GroupRow.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Controls.Material -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Row { spacing: EaStyle.Sizes.groupBoxSpacing * 0.5 diff --git a/src/EasyApp/Gui/Elements/Label.qml b/src/EasyApplication/Gui/Elements/Label.qml similarity index 92% rename from src/EasyApp/Gui/Elements/Label.qml rename to src/EasyApplication/Gui/Elements/Label.qml index aeab7ae2..7f6a0f56 100644 --- a/src/EasyApp/Gui/Elements/Label.qml +++ b/src/EasyApplication/Gui/Elements/Label.qml @@ -1,8 +1,8 @@ import QtQuick import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations T.Label { id: control diff --git a/src/EasyApp/Gui/Elements/LinkedImage.qml b/src/EasyApplication/Gui/Elements/LinkedImage.qml similarity index 88% rename from src/EasyApp/Gui/Elements/LinkedImage.qml rename to src/EasyApplication/Gui/Elements/LinkedImage.qml index e4e40f0b..b62565d6 100644 --- a/src/EasyApp/Gui/Elements/LinkedImage.qml +++ b/src/EasyApplication/Gui/Elements/LinkedImage.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Image { id: control diff --git a/src/EasyApp/Gui/Elements/Menu.qml b/src/EasyApplication/Gui/Elements/Menu.qml similarity index 98% rename from src/EasyApp/Gui/Elements/Menu.qml rename to src/EasyApplication/Gui/Elements/Menu.qml index b481479b..ede3433c 100644 --- a/src/EasyApp/Gui/Elements/Menu.qml +++ b/src/EasyApplication/Gui/Elements/Menu.qml @@ -4,7 +4,7 @@ import QtQuick.Controls.Material import QtQuick.Controls.Material.impl import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle T.Menu { id: control diff --git a/src/EasyApp/Gui/Elements/MenuItem.qml b/src/EasyApplication/Gui/Elements/MenuItem.qml similarity index 94% rename from src/EasyApp/Gui/Elements/MenuItem.qml rename to src/EasyApplication/Gui/Elements/MenuItem.qml index b20fd2fd..344c2e0b 100644 --- a/src/EasyApp/Gui/Elements/MenuItem.qml +++ b/src/EasyApplication/Gui/Elements/MenuItem.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.MenuItem { id: control diff --git a/src/EasyApp/Gui/Elements/ParamComboBox.qml b/src/EasyApplication/Gui/Elements/ParamComboBox.qml similarity index 97% rename from src/EasyApp/Gui/Elements/ParamComboBox.qml rename to src/EasyApplication/Gui/Elements/ParamComboBox.qml index 48bdd089..4d1df5bf 100644 --- a/src/EasyApp/Gui/Elements/ParamComboBox.qml +++ b/src/EasyApplication/Gui/Elements/ParamComboBox.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements EaElements.ComboBox { diff --git a/src/EasyApp/Gui/Elements/ParamTextField.qml b/src/EasyApplication/Gui/Elements/ParamTextField.qml similarity index 97% rename from src/EasyApp/Gui/Elements/ParamTextField.qml rename to src/EasyApplication/Gui/Elements/ParamTextField.qml index e84e4936..d794a3d7 100644 --- a/src/EasyApp/Gui/Elements/ParamTextField.qml +++ b/src/EasyApplication/Gui/Elements/ParamTextField.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Logic as EaLogic -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Logic as EaLogic +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements EaElements.TextField { diff --git a/src/EasyApp/Gui/Elements/Parameter.qml b/src/EasyApplication/Gui/Elements/Parameter.qml similarity index 85% rename from src/EasyApp/Gui/Elements/Parameter.qml rename to src/EasyApplication/Gui/Elements/Parameter.qml index 271b425c..86fd6346 100644 --- a/src/EasyApp/Gui/Elements/Parameter.qml +++ b/src/EasyApplication/Gui/Elements/Parameter.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements EaElements.TextField { diff --git a/src/EasyApp/Gui/Elements/RadioButton.qml b/src/EasyApplication/Gui/Elements/RadioButton.qml similarity index 95% rename from src/EasyApp/Gui/Elements/RadioButton.qml rename to src/EasyApplication/Gui/Elements/RadioButton.qml index 6d265d7a..32be0357 100644 --- a/src/EasyApp/Gui/Elements/RadioButton.qml +++ b/src/EasyApplication/Gui/Elements/RadioButton.qml @@ -2,10 +2,10 @@ import QtQuick import QtQuick.Controls import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.RadioButton { id: control diff --git a/src/EasyApp/Gui/Elements/RadioIndicator.qml b/src/EasyApplication/Gui/Elements/RadioIndicator.qml similarity index 86% rename from src/EasyApp/Gui/Elements/RadioIndicator.qml rename to src/EasyApplication/Gui/Elements/RadioIndicator.qml index 68c4ad57..bd9bc9e9 100644 --- a/src/EasyApp/Gui/Elements/RadioIndicator.qml +++ b/src/EasyApplication/Gui/Elements/RadioIndicator.qml @@ -1,6 +1,6 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle Rectangle { id: indicator diff --git a/src/EasyApp/Gui/Elements/RemoteController.qml b/src/EasyApplication/Gui/Elements/RemoteController.qml similarity index 99% rename from src/EasyApp/Gui/Elements/RemoteController.qml rename to src/EasyApplication/Gui/Elements/RemoteController.qml index 53a83940..b131617a 100644 --- a/src/EasyApp/Gui/Elements/RemoteController.qml +++ b/src/EasyApplication/Gui/Elements/RemoteController.qml @@ -3,9 +3,9 @@ import QtQuick.Controls import QtMultimedia import QtTest -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Elements as EaElements Item { id: rc diff --git a/src/EasyApp/Gui/Elements/RemotePointer.qml b/src/EasyApplication/Gui/Elements/RemotePointer.qml similarity index 100% rename from src/EasyApp/Gui/Elements/RemotePointer.qml rename to src/EasyApplication/Gui/Elements/RemotePointer.qml diff --git a/src/EasyApp/Gui/Elements/RunningLabel.qml b/src/EasyApplication/Gui/Elements/RunningLabel.qml similarity index 90% rename from src/EasyApp/Gui/Elements/RunningLabel.qml rename to src/EasyApplication/Gui/Elements/RunningLabel.qml index 8ec9182f..e7c798fe 100644 --- a/src/EasyApp/Gui/Elements/RunningLabel.qml +++ b/src/EasyApplication/Gui/Elements/RunningLabel.qml @@ -1,7 +1,7 @@ import QtQuick -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Item { id: control diff --git a/src/EasyApp/Gui/Elements/ScrollBar.qml b/src/EasyApplication/Gui/Elements/ScrollBar.qml similarity index 98% rename from src/EasyApp/Gui/Elements/ScrollBar.qml rename to src/EasyApplication/Gui/Elements/ScrollBar.qml index 9aa4eb54..cd7f2a6e 100644 --- a/src/EasyApp/Gui/Elements/ScrollBar.qml +++ b/src/EasyApplication/Gui/Elements/ScrollBar.qml @@ -2,7 +2,7 @@ import QtQuick import QtQuick.Templates as T import QtQuick.Controls.Material -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle T.ScrollBar { id: control diff --git a/src/EasyApp/Gui/Elements/ScrollIndicator.qml b/src/EasyApplication/Gui/Elements/ScrollIndicator.qml similarity index 96% rename from src/EasyApp/Gui/Elements/ScrollIndicator.qml rename to src/EasyApplication/Gui/Elements/ScrollIndicator.qml index 0f10c22c..81e2f98c 100644 --- a/src/EasyApp/Gui/Elements/ScrollIndicator.qml +++ b/src/EasyApplication/Gui/Elements/ScrollIndicator.qml @@ -1,7 +1,7 @@ import QtQuick import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle +import EasyApplication.Gui.Style as EaStyle T.ScrollIndicator { id: control diff --git a/src/EasyApp/Gui/Elements/SideBarButton.qml b/src/EasyApplication/Gui/Elements/SideBarButton.qml similarity index 95% rename from src/EasyApp/Gui/Elements/SideBarButton.qml rename to src/EasyApplication/Gui/Elements/SideBarButton.qml index 204a5e2a..5faf38e6 100644 --- a/src/EasyApp/Gui/Elements/SideBarButton.qml +++ b/src/EasyApplication/Gui/Elements/SideBarButton.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Button { id: control diff --git a/src/EasyApp/Gui/Elements/Slider.qml b/src/EasyApplication/Gui/Elements/Slider.qml similarity index 92% rename from src/EasyApp/Gui/Elements/Slider.qml rename to src/EasyApplication/Gui/Elements/Slider.qml index 955f1893..e95f9e90 100644 --- a/src/EasyApp/Gui/Elements/Slider.qml +++ b/src/EasyApplication/Gui/Elements/Slider.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -import EasyApp.Gui.Logic as EaLogic -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Logic as EaLogic +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Slider { id: control diff --git a/src/EasyApp/Gui/Elements/SliderHandle.qml b/src/EasyApplication/Gui/Elements/SliderHandle.qml similarity index 92% rename from src/EasyApp/Gui/Elements/SliderHandle.qml rename to src/EasyApplication/Gui/Elements/SliderHandle.qml index e84057fc..88ed8d0f 100644 --- a/src/EasyApp/Gui/Elements/SliderHandle.qml +++ b/src/EasyApplication/Gui/Elements/SliderHandle.qml @@ -2,8 +2,8 @@ import QtQuick import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations Item { id: root diff --git a/src/EasyApp/Gui/Elements/SpinBox.qml b/src/EasyApplication/Gui/Elements/SpinBox.qml similarity index 96% rename from src/EasyApp/Gui/Elements/SpinBox.qml rename to src/EasyApplication/Gui/Elements/SpinBox.qml index 44324aed..b7c2faa9 100644 --- a/src/EasyApp/Gui/Elements/SpinBox.qml +++ b/src/EasyApplication/Gui/Elements/SpinBox.qml @@ -1,9 +1,9 @@ import QtQuick import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.SpinBox { diff --git a/src/EasyApp/Gui/Elements/SplashScreen.qml b/src/EasyApplication/Gui/Elements/SplashScreen.qml similarity index 97% rename from src/EasyApp/Gui/Elements/SplashScreen.qml rename to src/EasyApplication/Gui/Elements/SplashScreen.qml index cce6871b..b42b7930 100644 --- a/src/EasyApp/Gui/Elements/SplashScreen.qml +++ b/src/EasyApplication/Gui/Elements/SplashScreen.qml @@ -3,8 +3,8 @@ import QtQuick.Controls import QtQuick.Window -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Elements as EaElements Window { diff --git a/src/EasyApp/Gui/Elements/StatusBar.qml b/src/EasyApplication/Gui/Elements/StatusBar.qml similarity index 86% rename from src/EasyApp/Gui/Elements/StatusBar.qml rename to src/EasyApplication/Gui/Elements/StatusBar.qml index c50d6acd..11ac8a06 100644 --- a/src/EasyApp/Gui/Elements/StatusBar.qml +++ b/src/EasyApplication/Gui/Elements/StatusBar.qml @@ -1,9 +1,9 @@ import QtQuick import QtQuick.Controls -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements Rectangle { id: statusBar diff --git a/src/EasyApp/Gui/Elements/StatusBarItem.qml b/src/EasyApplication/Gui/Elements/StatusBarItem.qml similarity index 94% rename from src/EasyApp/Gui/Elements/StatusBarItem.qml rename to src/EasyApplication/Gui/Elements/StatusBarItem.qml index 2fadc841..fec4624e 100644 --- a/src/EasyApp/Gui/Elements/StatusBarItem.qml +++ b/src/EasyApplication/Gui/Elements/StatusBarItem.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.Button { id: control diff --git a/src/EasyApp/Gui/Elements/TabBar.qml b/src/EasyApplication/Gui/Elements/TabBar.qml similarity index 95% rename from src/EasyApp/Gui/Elements/TabBar.qml rename to src/EasyApplication/Gui/Elements/TabBar.qml index c11428a7..d92ec211 100644 --- a/src/EasyApp/Gui/Elements/TabBar.qml +++ b/src/EasyApplication/Gui/Elements/TabBar.qml @@ -3,8 +3,8 @@ import QtQuick.Templates as T import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations T.TabBar { id: control diff --git a/src/EasyApp/Gui/Elements/TabButton.qml b/src/EasyApplication/Gui/Elements/TabButton.qml similarity index 95% rename from src/EasyApp/Gui/Elements/TabButton.qml rename to src/EasyApplication/Gui/Elements/TabButton.qml index 69f1c285..851643a9 100644 --- a/src/EasyApp/Gui/Elements/TabButton.qml +++ b/src/EasyApplication/Gui/Elements/TabButton.qml @@ -5,10 +5,10 @@ import QtQuick.Controls.impl import QtQuick.Controls.Material import QtQuick.Controls.Material.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.TabButton { id: control diff --git a/src/EasyApp/Gui/Elements/TextArea.qml b/src/EasyApplication/Gui/Elements/TextArea.qml similarity index 94% rename from src/EasyApp/Gui/Elements/TextArea.qml rename to src/EasyApplication/Gui/Elements/TextArea.qml index 4dd4c570..12d36a86 100644 --- a/src/EasyApp/Gui/Elements/TextArea.qml +++ b/src/EasyApplication/Gui/Elements/TextArea.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.TextArea { diff --git a/src/EasyApp/Gui/Elements/TextField.qml b/src/EasyApplication/Gui/Elements/TextField.qml similarity index 96% rename from src/EasyApp/Gui/Elements/TextField.qml rename to src/EasyApplication/Gui/Elements/TextField.qml index ddebe6e1..16af3c05 100644 --- a/src/EasyApp/Gui/Elements/TextField.qml +++ b/src/EasyApplication/Gui/Elements/TextField.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.TextField { id: control diff --git a/src/EasyApp/Gui/Elements/TextInput.qml b/src/EasyApplication/Gui/Elements/TextInput.qml similarity index 95% rename from src/EasyApp/Gui/Elements/TextInput.qml rename to src/EasyApplication/Gui/Elements/TextInput.qml index 54a91ebf..fc960d15 100644 --- a/src/EasyApp/Gui/Elements/TextInput.qml +++ b/src/EasyApplication/Gui/Elements/TextInput.qml @@ -3,9 +3,9 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.TextField { diff --git a/src/EasyApp/Gui/Elements/ToolButton.qml b/src/EasyApplication/Gui/Elements/ToolButton.qml similarity index 93% rename from src/EasyApp/Gui/Elements/ToolButton.qml rename to src/EasyApplication/Gui/Elements/ToolButton.qml index 9c6ab8ca..0832ced7 100644 --- a/src/EasyApp/Gui/Elements/ToolButton.qml +++ b/src/EasyApplication/Gui/Elements/ToolButton.qml @@ -3,10 +3,10 @@ import QtQuick.Templates as T import QtQuick.Controls import QtQuick.Controls.impl -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.ToolButton { id: control diff --git a/src/EasyApp/Gui/Elements/ToolTip.qml b/src/EasyApplication/Gui/Elements/ToolTip.qml similarity index 95% rename from src/EasyApp/Gui/Elements/ToolTip.qml rename to src/EasyApplication/Gui/Elements/ToolTip.qml index c0eabaca..ec4a29b0 100644 --- a/src/EasyApp/Gui/Elements/ToolTip.qml +++ b/src/EasyApplication/Gui/Elements/ToolTip.qml @@ -3,10 +3,10 @@ import QtQuick.Effects import QtQuick.Controls.Material.impl import QtQuick.Templates as T -import EasyApp.Gui.Style as EaStyle -import EasyApp.Gui.Globals as EaGlobals -import EasyApp.Gui.Animations as EaAnimations -import EasyApp.Gui.Elements as EaElements +import EasyApplication.Gui.Style as EaStyle +import EasyApplication.Gui.Globals as EaGlobals +import EasyApplication.Gui.Animations as EaAnimations +import EasyApplication.Gui.Elements as EaElements T.ToolTip { diff --git a/src/EasyApp/Gui/Elements/ToolTipShadow.qml b/src/EasyApplication/Gui/Elements/ToolTipShadow.qml similarity index 100% rename from src/EasyApp/Gui/Elements/ToolTipShadow.qml rename to src/EasyApplication/Gui/Elements/ToolTipShadow.qml diff --git a/src/EasyApp/Gui/Elements/qmldir b/src/EasyApplication/Gui/Elements/qmldir similarity index 100% rename from src/EasyApp/Gui/Elements/qmldir rename to src/EasyApplication/Gui/Elements/qmldir diff --git a/src/EasyApp/Gui/Globals/Vars.qml b/src/EasyApplication/Gui/Globals/Vars.qml similarity index 95% rename from src/EasyApp/Gui/Globals/Vars.qml rename to src/EasyApplication/Gui/Globals/Vars.qml index b541e8b3..1acdf7e6 100644 --- a/src/EasyApp/Gui/Globals/Vars.qml +++ b/src/EasyApplication/Gui/Globals/Vars.qml @@ -3,7 +3,7 @@ pragma Singleton import QtQuick import QtCore -import EasyApp.Gui.Logic as EaLogic +import EasyApplication.Gui.Logic as EaLogic QtObject { diff --git a/src/EasyApp/Gui/Globals/qmldir b/src/EasyApplication/Gui/Globals/qmldir similarity index 100% rename from src/EasyApp/Gui/Globals/qmldir rename to src/EasyApplication/Gui/Globals/qmldir diff --git a/src/EasyApplication/Gui/Html/BasicReport.html b/src/EasyApplication/Gui/Html/BasicReport.html new file mode 100644 index 00000000..e55b83d8 --- /dev/null +++ b/src/EasyApplication/Gui/Html/BasicReport.html @@ -0,0 +1,421 @@ + + + + + + + + + + + +
+

Summary report

+ +
+

Project

+

+ Name: Slanting line
+ Description: Straight line, negative slope, Siglent + SDS1202X-E
+ Model: Line
+ Experimental data: Siglent SDS1202X-E
+ Last modified: 09.02.2023 14:13
+

+
+ +
+

Software

+

+ Analysis: EasyExample v0.8.4-beta
+ Charts: + Plotly JavaScript v2.18.0
+ Calculation engine: Custom
+ Minimization engine: Custom
+

+
+ +
+

Model

+ + + + +
Line function: y = M•x + C
+
+ +
+

Parameters

+ + + + + + + + + + + + + + + + + + + +
No.ParameterValueUnits
1Slope M3.0000
2y-Intercept C1.0000
+
+ +
+

Fitting

+
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/BlankPage.html b/src/EasyApplication/Gui/Html/BlankPage.html new file mode 100644 index 00000000..4b3b4339 --- /dev/null +++ b/src/EasyApplication/Gui/Html/BlankPage.html @@ -0,0 +1,2 @@ + + diff --git a/src/EasyApp/Gui/Html/PTSans-Bold.ttf b/src/EasyApplication/Gui/Html/PTSans-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Html/PTSans-Bold.ttf rename to src/EasyApplication/Gui/Html/PTSans-Bold.ttf diff --git a/src/EasyApp/Gui/Html/PTSans-Regular.ttf b/src/EasyApplication/Gui/Html/PTSans-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Html/PTSans-Regular.ttf rename to src/EasyApplication/Gui/Html/PTSans-Regular.ttf diff --git a/src/EasyApplication/Gui/Html/Plotly1dBarPlot.html b/src/EasyApplication/Gui/Html/Plotly1dBarPlot.html new file mode 100644 index 00000000..d2e31eed --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly1dBarPlot.html @@ -0,0 +1,139 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly1dLine.html b/src/EasyApplication/Gui/Html/Plotly1dLine.html new file mode 100644 index 00000000..9c8afda3 --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly1dLine.html @@ -0,0 +1,151 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly1dMeasVsCalc.html b/src/EasyApplication/Gui/Html/Plotly1dMeasVsCalc.html new file mode 100644 index 00000000..a75f8d27 --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly1dMeasVsCalc.html @@ -0,0 +1,356 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly2dHeatmap.html b/src/EasyApplication/Gui/Html/Plotly2dHeatmap.html new file mode 100644 index 00000000..a683db0c --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly2dHeatmap.html @@ -0,0 +1,156 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly2dPolarHeatmap.html b/src/EasyApplication/Gui/Html/Plotly2dPolarHeatmap.html new file mode 100644 index 00000000..01bef54c --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly2dPolarHeatmap.html @@ -0,0 +1,148 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly3dMesh.html b/src/EasyApplication/Gui/Html/Plotly3dMesh.html new file mode 100644 index 00000000..585ddb03 --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly3dMesh.html @@ -0,0 +1,130 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly3dScatter.html b/src/EasyApplication/Gui/Html/Plotly3dScatter.html new file mode 100644 index 00000000..8e6d69c3 --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly3dScatter.html @@ -0,0 +1,249 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApplication/Gui/Html/Plotly3dSurface.html b/src/EasyApplication/Gui/Html/Plotly3dSurface.html new file mode 100644 index 00000000..9bb844e2 --- /dev/null +++ b/src/EasyApplication/Gui/Html/Plotly3dSurface.html @@ -0,0 +1,170 @@ + + + + + + + + + + + +
+
+
+ + + + diff --git a/src/EasyApp/Gui/Html/plotly-2.18.0.min.js b/src/EasyApplication/Gui/Html/plotly-2.18.0.min.js similarity index 100% rename from src/EasyApp/Gui/Html/plotly-2.18.0.min.js rename to src/EasyApplication/Gui/Html/plotly-2.18.0.min.js diff --git a/src/EasyApplication/Gui/Logic/Plotting.js b/src/EasyApplication/Gui/Logic/Plotting.js new file mode 100644 index 00000000..f20ab7b8 --- /dev/null +++ b/src/EasyApplication/Gui/Logic/Plotting.js @@ -0,0 +1,723 @@ +///////// +// Common +///////// + +function headCommon() { + const list = [ + '', + '', + '', + ] + return list.join('\n') +} + +function chartHtml(head, chart, toolbar = '') { + const list = [ + '', + '', + '', + head, + '', + '', + toolbar, + '', + '', + '', + ] + return list.join('\n') +} + +//////// +// Bokeh +//////// + +function bokehInfo() { + const version = '2.4.3' + return { + version: version, + url: `https://docs.bokeh.org/en/${version}`, + } +} + +function bokehHtml(data, specs) { + const head = bokehHead(specs) + const chart = bokehChart(data, specs) + const html = chartHtml(head, chart) + return html +} + +function bokehHeadScripts() { + const baseSrc = 'https://cdn.pydata.org/bokeh/release' + const version = bokehInfo().version + const list = [ + ``, + ``, + ``, + ``, + ] + return list.join('\n') +} + +function bokehHeadStyle(specs) { + const list = [ + '', + ] + return list.join('\n') +} + +function bokehHead(specs) { + const list = [headCommon(), bokehHeadScripts(), bokehHeadStyle(specs)] + return list.join('\n') +} + +function bokehChart(data, specs) { + if (!data.hasMeasured && !data.hasCalculated && !data.hasPlotRanges) { + return '' + } + // List of strings to be filled below + let chart = [] + + // Tooltips + chart.push(bokehAddMainTooltip(data, specs)) + chart.push(bokehAddBraggTooltip(specs)) + + // Data sources + chart.push('const main_source = new Bokeh.ColumnDataSource()') + // Charts array + chart.push('const charts = []') + + // Main chart (top) + chart.push(...bokehCreateMainChart(data, specs)) + chart.push(...bokehAddMainTools('main_chart')) + chart.push(...bokehAddHiddenXAxis('main_chart', specs)) + chart.push(...bokehAddVisibleYAxis('main_chart', specs)) + if (data.hasBackground) { + chart.push(...bokehAddBackgroundDataToMainChart(data, specs)) + } + if (data.hasMeasured) { + chart.push(...bokehAddMeasuredDataToMainChart(data, specs)) + } + if (data.hasPhase) { + chart.push(...bokehAddPhaseDataToMainChart(data, specs)) + } + if (data.hasCalculated) { + chart.push(...bokehAddCalculatedDataToMainChart(data, specs)) + } + chart.push(`charts.push([main_chart])`) + + // Bragg peaks chart (middle) + if (data.hasBragg) { + chart.push(...bokehCreateBraggChart(data, specs)) + chart.push(...bokehAddBraggTools()) + chart.push(...bokehAddHiddenXAxis('bragg_chart', specs)) + chart.push(...bokehAddHiddenYAxis('bragg_chart')) + chart.push(...bokehAddDataToBraggChart(data, specs)) + chart.push(`charts.push([bragg_chart])`) + } + + // Difference chart (bottom) + if (data.hasDifference) { + chart.push(...bokehCreateDiffChart(data, specs)) + chart.push(...bokehAddMainTools('diff_chart')) + chart.push(...bokehAddHiddenXAxis('diff_chart', specs)) + chart.push(...bokehAddVisibleYAxis('diff_chart', specs)) + chart.push(...bokehAddDataToDiffChart(data, specs)) + chart.push(...adjustDifferenceYRange()) + chart.push(`diff_chart.ygrid[0].ticker.desired_num_ticks = 3`) + chart.push(`charts.push([diff_chart])`) + } + + // xAxis chart (very bottom) + chart.push(...bokehCreateXAxisChart(data, specs)) + chart.push(...bokehAddVisibleXAxis('xaxis_chart', specs)) + chart.push(...bokehAddHiddenYAxis('xaxis_chart')) + chart.push(`charts.push([xaxis_chart])`) + + // Charts array grid layout + chart.push(`const grid_options = {toolbar_location: "above"}`) + chart.push( + `const gridplot = new Bokeh.Plotting.gridplot(charts, grid_options)`, + ) + + chart.push( + ...[ + 'function OnClick() {', + 'main_chart.reset.emit()', + '//console.log("AAA", document.querySelector(".bk-tool-icon-reset"))', + '//console.log("BBB", document.getElementById("bk-tool-icon-reset"))', + ' //document.getElementById("bk-tool-icon-reset").click()', + ' document.querySelector(".bk-tool-icon-reset").click()', + '}', + ], + ) + + // Show charts + if (typeof specs.containerId !== 'undefined') { + chart.push(`Bokeh.Plotting.show(gridplot, "#${specs.containerId}")`) + } else { + chart.push(`Bokeh.Plotting.show(gridplot)`) + } + + // Return as string + return chart.join('\n') +} + +// Bokeh charts + +function bokehCreateMainChart(data, specs) { + return [ + `const main_chart = new Bokeh.Plotting.figure({`, + ` tools: "reset,undo,redo",`, + + ` height: ${specs.mainChartHeight},`, + ` width: ${specs.chartWidth},`, + + ` x_range: new Bokeh.Range1d({`, + ` start: ${data.ranges.min_x},`, + ` end: ${data.ranges.max_x}`, + ` }),`, + ` y_range: new Bokeh.Range1d({`, + ` start: ${data.ranges.min_y},`, + ` end: ${data.ranges.max_y}`, + ` }),`, + + ` y_axis_label: "${specs.yMainAxisTitle}",`, + + ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, + ` background: "${specs.chartBackgroundColor}",`, + ` background_fill_color: "${specs.chartBackgroundColor}",`, + ` border_fill_color: "${specs.chartBackgroundColor}",`, + ` //border_fill_color: "red",`, + + ` min_border_right: ${1.5 * specs.fontPixelSize},`, + ` min_border_top: ${0.5 * specs.fontPixelSize},`, + ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, + `})`, + ] +} + +function bokehCreateBraggChart(data, specs) { + const num_phases = Object.keys(data.bragg).length + const y_margin = 0.65 + const y_min = -num_phases + 1 - y_margin + const y_max = y_margin + return [ + `const bragg_chart = new Bokeh.Plotting.figure({`, + ` tools: "",`, + + ` height: ${specs.braggChartHeight},`, + ` width: ${specs.chartWidth},`, + + ` x_range: main_chart.x_range,`, + ` y_range: new Bokeh.Range1d({ start: ${y_min}, end: ${y_max} }),`, + + ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, + ` background: "${specs.chartBackgroundColor}",`, + ` background_fill_color: "${specs.chartBackgroundColor}",`, + ` border_fill_color: "${specs.chartBackgroundColor}",`, + ` //border_fill_color: "green",`, + + ` min_border_top: ${0.5 * specs.fontPixelSize},`, + ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, + `})`, + ] +} + +function bokehCreateDiffChart(data, specs) { + return [ + `const diff_chart = new Bokeh.Plotting.figure({`, + ` tools: "reset",`, + + ` height: ${specs.differenceChartHeight},`, + ` width: ${specs.chartWidth},`, + + ` x_range: main_chart.x_range,`, + + ` y_axis_label: "${specs.yDifferenceAxisTitle}",`, + + ` outline_line_color: "${EaStyle.Colors.chartAxis}",`, + ` background: "${specs.chartBackgroundColor}",`, + ` background_fill_color: "${specs.chartBackgroundColor}",`, + ` border_fill_color: "${specs.chartBackgroundColor}",`, + ` //border_fill_color: "blue",`, + + ` min_border_top: ${0.5 * specs.fontPixelSize},`, + ` min_border_bottom: ${0.5 * specs.fontPixelSize}`, + `})`, + ] +} + +function bokehCreateXAxisChart(data, specs) { + return [ + `const xaxis_chart = new Bokeh.Plotting.figure({`, + ` tools: "",`, + + ` height: ${specs.xAxisChartHeight},`, + ` width: ${specs.chartWidth},`, + + ` x_range: main_chart.x_range,`, + ` y_range: new Bokeh.Range1d({ start: 0, end: 1 }),`, + + ` x_axis_label: "${specs.xAxisTitle}",`, + + ` outline_line_color: null,`, + ` background: "${specs.chartBackgroundColor}",`, + ` background_fill_color: "${specs.chartBackgroundColor}",`, + ` border_fill_color: "${specs.chartBackgroundColor}",`, + ` //border_fill_color: "orange",`, + + ` min_border_top: 0,`, + ` min_border_bottom: 0`, + `})`, + ] +} + +// Misc + +function adjustDifferenceYRange() { + return [ + `function differenceChartMeanY() {`, + ` let ySum = 0, yCount = 0`, + ` for (let i in main_source.data.x_diff) {`, + ` if (diff_chart.x_range.start <= main_source.data.x_diff[i] && main_source.data.x_diff[i] <= diff_chart.x_range.end) {`, + ` ySum += main_source.data.y_diff[i]`, + ` yCount += 1`, + ` }`, + ` }`, + ` if (yCount > 0) {`, + ` return ySum / yCount`, + ` }`, + ` return 0`, + `}`, + + `function differenceChartHalfRangeY() {`, + ` const mainChartRangeY = main_chart.y_range.end - main_chart.y_range.start`, + ` const mainChartAxesHeight = main_chart.height - main_chart.min_border_top - main_chart.min_border_bottom`, + ` const differenceChartAxesHeight = diff_chart.height - diff_chart.min_border_top - diff_chart.min_border_bottom`, + ` const differenceToMainChartHeightRatio = differenceChartAxesHeight / mainChartAxesHeight`, + ` const differenceChartRangeY = mainChartRangeY * differenceToMainChartHeightRatio`, + ` return 0.5 * differenceChartRangeY`, + `}`, + + `diff_chart.y_range = new Bokeh.Range1d({`, + ` start: differenceChartMeanY() - differenceChartHalfRangeY(),`, + ` end: differenceChartMeanY() + differenceChartHalfRangeY()`, + `})`, + + `main_chart.y_range.change.connect(function() {`, + ` diff_chart.y_range.start = differenceChartMeanY() - differenceChartHalfRangeY()`, + ` diff_chart.y_range.end = differenceChartMeanY() + differenceChartHalfRangeY()`, + `})`, + ] +} + +// Bokeh tools + +function bokehAddMainTools(chart) { + return [ + `${chart}.add_tools(new Bokeh.HoverTool({tooltips:main_tooltip, point_policy:"snap_to_data", mode:"mouse"}))`, + `${chart}.add_tools(new Bokeh.BoxZoomTool())`, + `${chart}.toolbar.active_drag = "box_zoom"`, + `${chart}.add_tools(new Bokeh.PanTool())`, + ] +} + +function bokehAddBraggTools() { + return [ + `bragg_chart.add_tools(new Bokeh.HoverTool({tooltips:bragg_tooltip, point_policy:"snap_to_data", mode:"mouse"}))`, + ] +} + +// Bokeh axes + +function bokehAddVisibleXAxis(chart, specs) { + return [ + `${chart}.xaxis[0].axis_label_text_font = "PT Sans"`, + `${chart}.xaxis[0].axis_label_text_font_style = "normal"`, + `${chart}.xaxis[0].axis_label_text_font_size = "${specs.fontPixelSize}px"`, + `${chart}.xaxis[0].axis_label_text_color = "${specs.chartForegroundColor}"`, + `${chart}.xaxis[0].axis_label_standoff = ${specs.fontPixelSize - 5}`, + `${chart}.xaxis[0].axis_line_color = null`, + + `${chart}.xaxis[0].major_label_text_font = "PT Sans"`, + `${chart}.xaxis[0].major_label_text_font_size = "${specs.fontPixelSize}px"`, + `${chart}.xaxis[0].major_label_text_color = "${specs.chartForegroundColor}"`, + `${chart}.xaxis[0].major_label_standoff = 0`, + `${chart}.xaxis[0].major_tick_line_color = null`, + `${chart}.xaxis[0].major_tick_in = 0`, + `${chart}.xaxis[0].major_tick_out = 0`, + `${chart}.xaxis[0].minor_tick_line_color = null`, + `${chart}.xaxis[0].minor_tick_out = 0`, + + `${chart}.xgrid[0].grid_line_color = null`, + ] +} + +function bokehAddHiddenXAxis(chart, specs) { + return [ + `${chart}.xaxis[0].axis_label_text_font_size = "0px"`, + `${chart}.xaxis[0].axis_line_color = null`, + + `${chart}.xaxis[0].major_label_text_font_size = "0px"`, + `${chart}.xaxis[0].major_tick_line_color = "${specs.chartGridLineColor}"`, + `${chart}.xaxis[0].major_tick_in = 0`, + `${chart}.xaxis[0].major_tick_out = 0`, + `${chart}.xaxis[0].minor_tick_line_color = "${specs.chartMinorGridLineColor}"`, + `${chart}.xaxis[0].minor_tick_out = 0`, + + `${chart}.xgrid[0].grid_line_color = "${specs.chartGridLineColor}"`, + ] +} + +function bokehAddVisibleYAxis(chart, specs) { + return [ + `${chart}.yaxis[0].axis_label_text_font = "PT Sans"`, + `${chart}.yaxis[0].axis_label_text_font_style = "normal"`, + `${chart}.yaxis[0].axis_label_text_font_size = "${specs.fontPixelSize}px"`, + `${chart}.yaxis[0].axis_label_text_color = "${specs.chartForegroundColor}"`, + `${chart}.yaxis[0].axis_label_standoff = ${specs.fontPixelSize}`, + `${chart}.yaxis[0].axis_line_color = null`, + + `${chart}.yaxis[0].major_label_text_font = "PT Sans"`, + `${chart}.yaxis[0].major_label_text_font_size = "${specs.fontPixelSize}px"`, + `${chart}.yaxis[0].major_label_text_color = "${specs.chartForegroundColor}"`, + `${chart}.yaxis[0].major_tick_line_color = "${specs.chartGridLineColor}"`, + `${chart}.yaxis[0].major_tick_in = 0`, + `${chart}.yaxis[0].major_tick_out = 0`, + `${chart}.yaxis[0].minor_tick_line_color = "${specs.chartMinorGridLineColor}"`, + `${chart}.yaxis[0].minor_tick_out = 0`, + + `${chart}.ygrid[0].grid_line_color = "${specs.chartGridLineColor}"`, + ] +} + +function bokehAddHiddenYAxis(chart) { + return [ + `${chart}.yaxis[0].axis_line_color = null`, + + `${chart}.yaxis[0].major_tick_in = 0`, + `${chart}.yaxis[0].major_tick_out = 0`, + `${chart}.yaxis[0].minor_tick_out = 0`, + `${chart}.yaxis[0].major_label_text_font_size = "0px"`, + + `${chart}.ygrid[0].grid_line_color = null`, + ] +} + +// Bokeh data + +function bokehAddBackgroundDataToMainChart(data, specs) { + return [ + `main_source.data.x_bkg = [${data.background.x}]`, + `main_source.data.y_bkg = [${data.background.y}]`, + + 'const bkgLine = new Bokeh.Line({', + ' x: { field: "x_bkg" },', + ' y: { field: "y_bkg" },', + ` line_color: "${specs.backgroundLineColor}",`, + ` line_alpha: 0.5,`, + ` line_dash: [4, 2],`, + ` line_width: ${specs.backgroundLineWidth},`, + '})', + + 'main_chart.add_glyph(bkgLine, main_source)', + ] +} + +function bokehAddMeasuredDataToMainChart(data, specs) { + return [ + `main_source.data.x_meas = [${data.measured.x}]`, + `main_source.data.y_meas = [${data.measured.y}]`, + `main_source.data.sy_meas = [${data.measured.sy}]`, + `main_source.data.y_meas_upper = [${data.measured.y_upper}]`, + `main_source.data.y_meas_lower = [${data.measured.y_lower}]`, + + `const measLineTop = new Bokeh.Line({`, + ` x: { field: "x_meas" },`, + ` y: { field: "y_meas_upper" },`, + ` line_color: "${specs.measuredLineColor}",`, + ` line_alpha: 0.4,`, + ` line_width: ${specs.measuredLineWidth}`, + `})`, + `const measLineBottom = new Bokeh.Line({`, + ` x: { field: "x_meas" },`, + ` y: { field: "y_meas_lower" },`, + ` line_color: "${specs.measuredLineColor}",`, + ` line_width: ${specs.measuredLineWidth},`, + ` line_alpha: 0.4`, + `})`, + `const measArea = new Bokeh.VArea({`, + ` x: { field: "x_meas" },`, + ` y1: { field: "y_meas_upper" },`, + ` y2: { field: "y_meas_lower" },`, + ` fill_color: "${specs.measuredAreaColor}",`, + ` fill_alpha: 0.35`, + `})`, + + `main_chart.add_glyph(measArea, main_source)`, + `main_chart.add_glyph(measLineTop, main_source)`, + `main_chart.add_glyph(measLineBottom, main_source)`, + ] +} + +function bokehAddCalculatedDataToMainChart(data, specs) { + return [ + `main_source.data.x_calc = [${data.calculated.x}]`, + `main_source.data.y_calc = [${data.calculated.y}]`, + + 'const calcLine = new Bokeh.Line({', + ' x: { field: "x_calc" },', + ' y: { field: "y_calc" },', + ` line_color: "${specs.calculatedLineColor}",`, + ` line_width: ${specs.calculatedLineWidth},`, + ` line_alpha: 0.8`, + '})', + + 'main_chart.add_glyph(calcLine, main_source)', + ] +} + +function bokehAddPhaseDataToMainChart(data, specs) { + let out = [] + out.push('let phaseLine = new Bokeh.Line()') + for (const phase_index in data.phase) { + out.push( + `main_source.data.x_phase_${phase_index} = [${data.phase[phase_index].x}]`, + ) + out.push( + `main_source.data.y_phase_${phase_index}_upper = [${data.phase[phase_index].y_upper}]`, + ) + out.push( + `main_source.data.y_phase_${phase_index}_lower = [${data.phase[phase_index].y_lower}]`, + ) + out.push(`const phaseLine_${phase_index} = new Bokeh.Line({`) + out.push(` x: { field: "x_phase_${phase_index}" },`) + out.push(` y: { field: "y_phase_${phase_index}_upper" },`) + out.push(` line_color: "${specs.phaseLineColor[phase_index]}",`) + out.push(` line_width: ${specs.phaseLineWidth},`) + out.push(` line_alpha: 0.6,`) + out.push('})') + out.push(`const phaseArea_${phase_index} = new Bokeh.VArea({`) + out.push(` x: { field: "x_phase_${phase_index}" },`) + out.push(` y1: { field: "y_phase_${phase_index}_upper" },`) + out.push(` y2: { field: "y_phase_${phase_index}_lower" },`) + out.push(` fill_color: "${specs.phaseLineColor[phase_index]}",`) + out.push(` fill_alpha: 0.1`) + out.push('})') + out.push(`main_chart.add_glyph(phaseArea_${phase_index}, main_source)`) + out.push(`main_chart.add_glyph(phaseLine_${phase_index}, main_source)`) + } + return out +} + +function bokehAddDataToBraggChart(data, specs) { + let out = [] + for (const phase_index in data.bragg) { + console.log('---', phase_index, data.bragg[phase_index].x.slice(0, 200)) + out.push( + `const bragg_source_${phase_index} = new Bokeh.ColumnDataSource()`, + ) + + out.push( + `bragg_source_${phase_index}.data.x_bragg = [${data.bragg[phase_index].x}]`, + ) + out.push( + `bragg_source_${phase_index}.data.y_bragg = [${data.bragg[phase_index].y}]`, + ) + out.push( + `bragg_source_${phase_index}.data.h_bragg = [${data.bragg[phase_index].h}]`, + ) + out.push( + `bragg_source_${phase_index}.data.k_bragg = [${data.bragg[phase_index].k}]`, + ) + out.push( + `bragg_source_${phase_index}.data.l_bragg = [${data.bragg[phase_index].l}]`, + ) + + out.push(`const braggTicks_${phase_index} = new Bokeh.Scatter({`) + out.push(` x: { field: "x_bragg" },`) + out.push(` y: { field: "y_bragg" },`) + out.push(` marker: "dash",`) + out.push(` size: ${1.5 * specs.fontPixelSize},`) + out.push(` line_color: "${specs.braggTicksColor[phase_index]}",`) + out.push(` angle: ${Math.PI / 2}`) + out.push('})') + out.push( + `bragg_chart.add_glyph(braggTicks_${phase_index}, bragg_source_${phase_index})`, + ) + } + return out +} + +function bokehAddDataToDiffChart(data, specs) { + return [ + `main_source.data.x_diff = [${data.difference.x}]`, + `main_source.data.y_diff = [${data.difference.y}]`, + `main_source.data.y_diff_upper = [${data.difference.y_upper}]`, + `main_source.data.y_diff_lower = [${data.difference.y_lower}]`, + + `const diffLineTop = new Bokeh.Line({`, + ` x: { field: "x_diff" },`, + ` y: { field: "y_diff_upper" },`, + ` line_color: "${specs.differenceLineColor}",`, + ` line_alpha: 0.4,`, + ` line_width: ${specs.differenceLineWidth}`, + `})`, + `const diffLineBottom = new Bokeh.Line({`, + ` x: { field: "x_diff" },`, + ` y: { field: "y_diff_lower" },`, + ` line_color: "${specs.differenceLineColor}",`, + ` line_alpha: 0.4,`, + ` line_width: ${specs.differenceLineWidth}`, + `})`, + `const diffArea = new Bokeh.VArea({`, + ` x: { field: "x_diff" },`, + ` y1: { field: "y_diff_upper" },`, + ` y2: { field: "y_diff_lower" },`, + ` fill_color: "${specs.differenceAreaColor}",`, + ` fill_alpha: 0.35`, + `})`, + + `diff_chart.add_glyph(diffArea, main_source)`, + `diff_chart.add_glyph(diffLineTop, main_source)`, + `diff_chart.add_glyph(diffLineBottom, main_source)`, + ] +} + +// Bokeh tooltips + +function bokehMainTooltipRow(color, label, value, sigma = '') { + return [ + ``, + ` ${label}: `, + ` ${value}`, + ` ${sigma}`, + ``, + ] +} + +function bokehAddMainTooltip(data, specs) { + const x_meas = bokehMainTooltipRow( + EaStyle.Colors.themeForegroundDisabled, + 'x', + '@x_meas{0.00}', + ) + const x_calc = bokehMainTooltipRow( + EaStyle.Colors.themeForegroundDisabled, + 'x', + '@x_calc{0.00}', + ) + const y_meas = bokehMainTooltipRow( + specs.measuredLineColor, + 'meas', + '@y_meas{0.0}', + '± @sy_meas{0.0}', + ) + const y_calc = bokehMainTooltipRow( + specs.calculatedLineColor, + 'calc', + '@y_calc{0.0}', + ) + const y_bkg = bokehMainTooltipRow( + specs.backgroundLineColor, + 'bkg', + '@y_bkg{0.0}', + ) + const y_diff = bokehMainTooltipRow( + specs.differenceLineColor, + 'diff', + '@y_diff{0.0}', + ) + let y_phases = [] + for (const phase_index in data.phase) { + if (typeof specs.phaseLineColor !== 'undefined') { + y_phases.push( + bokehMainTooltipRow( + specs.phaseLineColor[phase_index], + `phase ${phase_index}`, + `@y_phase_${phase_index}_upper{0.0}`, + ), + ) + } + } + + let table = [] + table.push(...[`
`, ``, ``]) + // x + if (data.hasMeasured) { + table.push(...x_meas) + } else if (data.hasCalculated) { + table.push(...x_calc) + } + // y + if (data.hasMeasured) { + table.push(...y_meas) + } + if (data.hasCalculated) { + table.push(...y_calc) + } + for (const phase_index in data.phase) { + if (typeof y_phases[phase_index] !== 'undefined') { + table.push(...y_phases[phase_index]) + } + } + if (data.hasBackground) { + table.push(...y_bkg) + } + if (data.hasDifference) { + table.push(...y_diff) + } + table.push(...[``, `
`, `
`]) + + const tooltip = JSON.stringify(table.join('\n')) + return `const main_tooltip = (${tooltip})` +} + +function bokehBraggTooltipSpan(color, label, value) { + return `${label}: ${value}` +} + +function bokehAddBraggTooltip(specs) { + const x_bragg = bokehBraggTooltipSpan( + EaStyle.Colors.themeForegroundDisabled, + 'x', + '@x_bragg{0.00}', + ) + const hkl_bragg = bokehBraggTooltipSpan( + specs.calculatedLineColor, + 'hkl', + '(@h_bragg @k_bragg @l_bragg)', + ) + + const table = [ + `
`, + x_bragg, + ' ', + hkl_bragg, + `
`, + ] + + const tooltip = JSON.stringify(table.join('\n')) + return `const bragg_tooltip = (${tooltip})` +} diff --git a/src/EasyApplication/Gui/Logic/ProjectConfig.js b/src/EasyApplication/Gui/Logic/ProjectConfig.js new file mode 100644 index 00000000..41e01d8f --- /dev/null +++ b/src/EasyApplication/Gui/Logic/ProjectConfig.js @@ -0,0 +1,29 @@ +function projectConfig() { + return { + tool: { + poetry: { + name: 'easyDiffraction', + version: '0.8.0-beta.1', + }, + }, + ci: { + app: { + info: { + date: '01.01.2001', + branch_name: 'master', + commit_sha_short: 'undefined', + }, + tutorials: { + video: { + fps: 15, + }, + }, + }, + project: { + subdirs: { + screenshots: '', + }, + }, + }, + } +} diff --git a/src/EasyApplication/Gui/Logic/Translate.js b/src/EasyApplication/Gui/Logic/Translate.js new file mode 100644 index 00000000..1620c1ab --- /dev/null +++ b/src/EasyApplication/Gui/Logic/Translate.js @@ -0,0 +1,13 @@ +class Translator { + // Functions + + languagesAsXml() { + return 'enEnglish' + } + + defaultLanguageIndex() { + return 0 + } + + selectLanguage(index) {} +} diff --git a/src/EasyApplication/Gui/Logic/Utils.js b/src/EasyApplication/Gui/Logic/Utils.js new file mode 100644 index 00000000..e80310a3 --- /dev/null +++ b/src/EasyApplication/Gui/Logic/Utils.js @@ -0,0 +1,226 @@ +function prettyXml(xml, tab = ' ') { + let formatted = '' + let indent = '' + + xml.split(/>\s*\r\n' + + if (node.match(/^]*[^\/]$/)) indent += tab + }) + + return formatted.substring(1, formatted.length - 3) +} + +function prettyJson(json, tab = ' ') { + return JSON.stringify(json, null, tab.length) +} + +function osPathSep() { + if (Qt.platform.os === 'windows') { + return '\\' + } + return '/' +} + +// converts a URL to a local file path +function urlToLocalFile(url) { + if (Qt.platform.os === 'windows') { + return url.replace('file:///', '').split('/').join('\\') + } else if ( + Qt.platform.os === 'osx' || + Qt.platform.os === 'linux' || + Qt.platform.os === 'unix' + ) { + return url.replace('file://', '') + } else { + return url + } +} + +function isQmlScene() { + const runnerPath = Qt.application.arguments[0] + if (runnerPath.includes('qmlscene')) { + return true + } + return false +} + +// XMLHttpRequest: Using PUT on a local file is disabled by default. +// Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature. +// E.g., 'QML_XHR_ALLOW_FILE_WRITE=1 qml main.qml' +function writeFile(url, content) { + const method = 'PUT' + const async = false + const request = new XMLHttpRequest() + request.onreadystatechange = () => { + if (request.readyState === XMLHttpRequest.DONE) { + if (request.status === 200) { + print(`Succeeded to write file: '${url}'`) + } else { + print(`Failed to write file: '${url}'. Status: ${request.status}`) + } + } + } + request.open(method, url, async) + request.send(content) +} + +// XMLHttpRequest: Using GET on a local file is disabled by default. +// Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature. +// E.g., 'QML_XHR_ALLOW_FILE_READ=1 qml main.qml' +function readFile(url) { + const method = 'GET' + const async = false + const request = new XMLHttpRequest() + request.onreadystatechange = () => { + if (request.readyState === XMLHttpRequest.DONE) { + if (request.status === 200) { + print(`Succeeded to read file: '${url}'`) + } else { + print(`Failed to read file: '${url}'. Status: ${request.status}`) + } + } + } + request.open(method, url, async) + request.send() + return request.responseText +} + +function toFixed(value, digitsCount = 4) { + if (typeof value === 'undefined') { + return '' + } else if (typeof value == 'number') { + return value.toFixed(digitsCount) + } else { + return value + } +} + +function toMaxPrecision(value, digitsCount = 5) { + if (typeof value === 'number') { + return Number(value.toPrecision(digitsCount)).toString() + } else if (typeof value === 'string') { + return value + } else if (typeof value === 'undefined') { + return '' + } else { + console.error( + `Value ${value} with type '${typeof value}' is not supported`, + ) + return '' + } +} + +function toDefaultPrecision(x) { + const defaultPrecision = 3 + return Number(x.toPrecision(defaultPrecision)).toString() +} + +function toSinglePrecision(x) { + if (x === 0) { + return '' + } + return Number(x.toPrecision(1)).toString() +} + +function toErrSinglePrecision(x, dx) { + dx = Number(dx.toPrecision(1)) + return toFixedUncertainty(x, dx) +} + +function toSamePrecision(x, y) { + return toFixedUncertainty(x, y) +} + +// https://gist.github.com/davidselassie/3838522 + +function roundAway(x) { + // Rounds a number to the next integer away from 0 + // + // Args: + // x - Number to round + // Returns: + // rounded - Next integer from x away from 0 + + if (x >= 0) { + return Math.ceil(x) + } else { + return Math.floor(x) + } +} + +function roundToIndex(x, index) { + // Rounds a number to a given index around the decimal point + // + // Args: + // x - Number to round + // index - Index of the least significan digit; 0 is the decimal point + // Returns: + // rounded - Number rounded using the least signficant digit + + var power = Math.pow(10, -index) + return Math.round(x * power) / power +} + +function toFixedUncertainty(x, dx) { + // Returns the string representation of a number correctly rounded given + // an uncertainty value. + // + // Args: + // x - Number to print + // dx - Uncertainty in x + // Returns: + // x_string - String with x properly rounded given dx + + // If there is no uncertainty, return the entire number + if (dx === undefined || dx === 0) { + ////return x.toString(); + return toDefaultPrecision(x) + } + + // Find out the least significant digit using the uncertainty + var roundingIndex = roundAway(Math.log(dx) / Math.log(10)) + // Round using that number of digits. + var roundedString = roundToIndex(x, roundingIndex).toString() + + // Now we have to only show the digits that are significant + + // If we're rounding a whole number + if (roundingIndex >= 0) { + // Find out if we want more significant digits that we have + var overshot = roundingIndex - roundedString.length + 1 + if (overshot <= 0) { + return roundedString + // If so, add more 0s on the beginning. + } else { + return Array(overshot + 1).join('0') + roundedString + } + // If we're rounding to a decimal place + } else { + var decimalIndex = roundedString.indexOf('.') + // If there isn't a '.', we're rounding to 0 if we got here. + if (decimalIndex < 0) { + roundedString = '0.' + decimalIndex = 1 + } + + // Find out if the least significant digit is off the end of the number + var lastIndex = decimalIndex + 1 - roundingIndex + var overshot = lastIndex - roundedString.length + if (overshot <= 0) { + return roundedString.slice(0, lastIndex) + // If so, add more 0s to show the precision we have. + } else { + return roundedString + Array(overshot + 1).join('0') + } + } +} + +// Consider using python backend +// Either +// from uncertainties import ufloat +// or +// from decimal import Decimal +// paramStr = str(Decimal(valueStr).quantize(Decimal(errorStr))) # Sets value precision to be the same as for the standard uncertainty diff --git a/src/EasyApp/Gui/Logic/qmldir b/src/EasyApplication/Gui/Logic/qmldir similarity index 100% rename from src/EasyApp/Gui/Logic/qmldir rename to src/EasyApplication/Gui/Logic/qmldir diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Black.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Black.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Black.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Black.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Bold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Bold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Bold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraLight.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraLight.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraLight.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-ExtraLight.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Light.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Light.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Light.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Light.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Medium.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Medium.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Medium.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Medium.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-SemiBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-SemiBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-SemiBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-SemiBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Thin.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Thin.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Thin.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/EncodeSans-Thin.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans/download.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans/download.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Black.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Black.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Black.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Black.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Bold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Bold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Bold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraLight.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraLight.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraLight.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-ExtraLight.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Light.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Light.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Light.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Light.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Medium.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Medium.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Medium.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Medium.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-SemiBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-SemiBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-SemiBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-SemiBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Thin.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Thin.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Thin.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/EncodeSansCondensed-Thin.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/download.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Condensed/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Condensed/download.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Black.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Black.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Black.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Black.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Bold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Bold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Bold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraLight.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraLight.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraLight.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-ExtraLight.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Light.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Light.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Light.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Light.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Medium.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Medium.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Medium.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Medium.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-SemiBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-SemiBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-SemiBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-SemiBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Thin.ttf b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Thin.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Thin.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/EncodeSansExpanded-Thin.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/download.txt b/src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Encode_Sans_Expanded/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/Encode_Sans_Expanded/download.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 5 Free-Solid-900.otf b/src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 5 Free-Solid-900.otf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 5 Free-Solid-900.otf rename to src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 5 Free-Solid-900.otf diff --git a/src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 6 Free-Solid-900.otf b/src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 6 Free-Solid-900.otf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 6 Free-Solid-900.otf rename to src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 6 Free-Solid-900.otf diff --git a/src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 7 Free-Solid-900.otf b/src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 7 Free-Solid-900.otf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/FontAwesome/Font Awesome 7 Free-Solid-900.otf rename to src/EasyApplication/Gui/Resources/Fonts/FontAwesome/Font Awesome 7 Free-Solid-900.otf diff --git a/src/EasyApp/Gui/Resources/Fonts/FontAwesome/LICENSE.txt b/src/EasyApplication/Gui/Resources/Fonts/FontAwesome/LICENSE.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/FontAwesome/LICENSE.txt rename to src/EasyApplication/Gui/Resources/Fonts/FontAwesome/LICENSE.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Black.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Black.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Black.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Black.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-BlackItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-BlackItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-BlackItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-BlackItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Bold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Bold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Bold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-BoldItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-BoldItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-BoldItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-BoldItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraBoldItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraBoldItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraBoldItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraBoldItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraLight.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraLight.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraLight.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraLight.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraLightItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraLightItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-ExtraLightItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-ExtraLightItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Italic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Italic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Italic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Italic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Light.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Light.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Light.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Light.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-LightItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-LightItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-LightItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-LightItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-SemiBold.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-SemiBold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-SemiBold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-SemiBold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-SemiBoldItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-SemiBoldItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/Nunito-SemiBoldItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/Nunito-SemiBoldItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/Nunito/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/Nunito/download.txt b/src/EasyApplication/Gui/Resources/Fonts/Nunito/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/Nunito/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/Nunito/download.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Mono/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/PT_Mono/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Mono/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/PT_Mono/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Mono/PTMono-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/PT_Mono/PTMono-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Mono/PTMono-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/PT_Mono/PTMono-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Mono/download.txt b/src/EasyApplication/Gui/Resources/Fonts/PT_Mono/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Mono/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/PT_Mono/download.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/OFL.txt b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/OFL.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/OFL.txt rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/OFL.txt diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Bold.ttf b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Bold.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Bold.ttf rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Bold.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-BoldItalic.ttf b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-BoldItalic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-BoldItalic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-BoldItalic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Italic.ttf b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Italic.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Italic.ttf rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Italic.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Regular.ttf b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Regular.ttf similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/PTSans-Regular.ttf rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/PTSans-Regular.ttf diff --git a/src/EasyApp/Gui/Resources/Fonts/PT_Sans/download.txt b/src/EasyApplication/Gui/Resources/Fonts/PT_Sans/download.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Fonts/PT_Sans/download.txt rename to src/EasyApplication/Gui/Resources/Fonts/PT_Sans/download.txt diff --git a/src/EasyApp/Gui/Resources/Icons/description.txt b/src/EasyApplication/Gui/Resources/Icons/description.txt similarity index 100% rename from src/EasyApp/Gui/Resources/Icons/description.txt rename to src/EasyApplication/Gui/Resources/Icons/description.txt diff --git a/src/EasyApp/Gui/Style/Colors.qml b/src/EasyApplication/Gui/Style/Colors.qml similarity index 97% rename from src/EasyApp/Gui/Style/Colors.qml rename to src/EasyApplication/Gui/Style/Colors.qml index 6fcb5843..294ce144 100644 --- a/src/EasyApp/Gui/Style/Colors.qml +++ b/src/EasyApplication/Gui/Style/Colors.qml @@ -4,7 +4,7 @@ import QtQuick import QtQuick.Controls.Material import QtCore -import EasyApp.Gui.Globals as EaGlobals +import EasyApplication.Gui.Globals as EaGlobals QtObject { diff --git a/src/EasyApp/Gui/Style/Fonts.qml b/src/EasyApplication/Gui/Style/Fonts.qml similarity index 100% rename from src/EasyApp/Gui/Style/Fonts.qml rename to src/EasyApplication/Gui/Style/Fonts.qml diff --git a/src/EasyApp/Gui/Style/Sizes.qml b/src/EasyApplication/Gui/Style/Sizes.qml similarity index 100% rename from src/EasyApp/Gui/Style/Sizes.qml rename to src/EasyApplication/Gui/Style/Sizes.qml diff --git a/src/EasyApp/Gui/Style/Times.qml b/src/EasyApplication/Gui/Style/Times.qml similarity index 100% rename from src/EasyApp/Gui/Style/Times.qml rename to src/EasyApplication/Gui/Style/Times.qml diff --git a/src/EasyApp/Gui/Style/qmldir b/src/EasyApplication/Gui/Style/qmldir similarity index 100% rename from src/EasyApp/Gui/Style/qmldir rename to src/EasyApplication/Gui/Style/qmldir diff --git a/src/EasyApp/Logic/Logging.py b/src/EasyApplication/Logic/Logging.py similarity index 78% rename from src/EasyApp/Logic/Logging.py rename to src/EasyApplication/Logic/Logging.py index 7b0b28b2..3b3527e5 100644 --- a/src/EasyApp/Logic/Logging.py +++ b/src/EasyApplication/Logic/Logging.py @@ -1,29 +1,30 @@ -# SPDX-FileCopyrightText: 2024 EasyApp contributors +# SPDX-FileCopyrightText: 2026 EasyScience contributors # SPDX-License-Identifier: BSD-3-Clause -# © 2024 Contributors to the EasyApp project - -# https://docs.python.org/3/library/logging.html -# https://docs.python.org/3/howto/logging-cookbook.html -# https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output -# https://stackoverflow.com/questions/42936810/python-logging-module-set-formatter-dynamically -# https://doc.qt.io/qt-6/qtquick-debugging.html -# https://raymii.org/s/articles/Disable_logging_in_QT_and_QML.html +import inspect +import logging import os +import pathlib import sys import time -import pathlib -import inspect -import logging - -from PySide6.QtCore import QObject, Signal, Property, QtMsgType, QUrl, QSettings +from PySide6.QtCore import Property +from PySide6.QtCore import QObject +from PySide6.QtCore import QSettings +from PySide6.QtCore import QtMsgType +from PySide6.QtCore import QUrl +from PySide6.QtCore import Signal LOGGER_LEVELS = { 'disabled': 40, - 'error': 30, # logging.CRITICAL, logging.ERROR, QtMsgType.QtSystemMsg, QtMsgType.QtCriticalMsg, QtMsgType.QtFatalMsg - 'info': 20, # logging.INFO, logging.WARNING, QtMsgType.QtInfoMsg, QtMsgType.QtWarningMsg - 'debug': 10 # logging.NOTSET, logging.DEBUG, QtMsgType.QtDebugMsg + # logging.CRITICAL, logging.ERROR, QtMsgType.QtSystemMsg, + # QtMsgType.QtCriticalMsg, QtMsgType.QtFatalMsg + 'error': 30, + # logging.INFO, logging.WARNING, QtMsgType.QtInfoMsg, + # QtMsgType.QtWarningMsg + 'info': 20, + # logging.NOTSET, logging.DEBUG, QtMsgType.QtDebugMsg + 'debug': 10, } COUNT_WIDTH = 5 @@ -32,15 +33,14 @@ FUNC_NAME_WIDTH = 34 MAIN_MSG_WIDTH = 150 -class Logger: +class Logger: def __init__(self): self._count = 0 self._level = self._getLevelFromSettings() self._getLevelFromSettings() self._startTime = time.time() - #self._consoleFormat = logging.Formatter('{asctime}.{msecs:03.0f} {message}', datefmt='%H:%M:%S', style='{') self._consoleFormat = logging.Formatter('{message}', datefmt='%H:%M:%S', style='{') self._consoleHandler = logging.StreamHandler() self._consoleHandler.setFormatter(self._consoleFormat) @@ -98,7 +98,7 @@ def _getLevelFromSettings(self): settingsIniFileName = 'settings.ini' settingsIniFilePath = str(homeDirPath.joinpath(f'.{appName}', settingsIniFileName)) settings = QSettings(settingsIniFilePath, QSettings.IniFormat) - level = settings.value("Preferences.Develop/loggingLevel", 'debug') + level = settings.value('Preferences.Develop/loggingLevel', 'debug') level = level.lower() return level @@ -150,9 +150,13 @@ def _formattedConsoleMsg(self, msg, level, category, funcName, filePath, lineNo) relativePath = os.path.relpath(filePath, start) fileUrl = f'file:///{relativePath}' sourceUrl = f'{fileUrl}:{lineNo}' - except: + except: # noqa pass - txt = f'{self._count:>{COUNT_WIDTH}d} {self._timing()} {category:>{CATEGORY_WIDTH}} {level:<{LEVEL_WIDTH}} {msg:<{MAIN_MSG_WIDTH}.{MAIN_MSG_WIDTH}} {funcName:<{FUNC_NAME_WIDTH}.{FUNC_NAME_WIDTH}} {sourceUrl}' + txt = ( + f'{self._count:>{COUNT_WIDTH}d} {self._timing()} {category:>{CATEGORY_WIDTH}} ' + f'{level:<{LEVEL_WIDTH}} {msg:<{MAIN_MSG_WIDTH}.{MAIN_MSG_WIDTH}} ' + f'{funcName:<{FUNC_NAME_WIDTH}.{FUNC_NAME_WIDTH}} {sourceUrl}' + ) txt = self._colorize(txt, level, category) return txt @@ -164,12 +168,12 @@ def qtMsgTypeToCustomLevel(msgType): QtMsgType.QtWarningMsg: 'info', QtMsgType.QtCriticalMsg: 'error', QtMsgType.QtSystemMsg: 'error', - QtMsgType.QtFatalMsg: 'error' + QtMsgType.QtFatalMsg: 'error', }[msgType] @staticmethod def rest(s, n): - splitted = [' '*28*bool(i) + s[i: i + n] for i in range(0, len(s), n)] + splitted = [' ' * 28 * bool(i) + s[i : i + n] for i in range(0, len(s), n)] joined = '\n'.join(splitted[1:]) return joined diff --git a/src/EasyApp/Logic/Maintenance.py b/src/EasyApplication/Logic/Maintenance.py similarity index 69% rename from src/EasyApp/Logic/Maintenance.py rename to src/EasyApplication/Logic/Maintenance.py index 76aca379..567b2e9a 100644 --- a/src/EasyApp/Logic/Maintenance.py +++ b/src/EasyApplication/Logic/Maintenance.py @@ -1,17 +1,22 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + import os import pathlib import re -import urllib.request import sys - -from PySide6.QtCore import QObject, QProcess, Property, Signal, Slot -from PySide6.QtWidgets import QApplication +import urllib.request from EasyApp.Logic.Logging import console +from PySide6.QtCore import Property +from PySide6.QtCore import QObject +from PySide6.QtCore import QProcess +from PySide6.QtCore import Signal +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QApplication class Updater(QObject): - # SIGNALS updateFound = Signal() @@ -31,10 +36,10 @@ def __init__(self, parent=None): # private members self._silent_check = True - self._error_message = "" - self._web_version = "" - self._web_date = "" - self._release_notes = "" + self._error_message = '' + self._web_version = '' + self._web_date = '' + self._release_notes = '' self._process = self._createUpdaterProcess() # connections @@ -46,12 +51,12 @@ def __init__(self, parent=None): @Slot() def checkUpdate(self): - console.debug("Updater checkUpdate called") + console.debug('Updater checkUpdate called') if self._process.state() == QProcess.Running: return - self._process.setArguments(["--checkupdates", "--verbose"]) + self._process.setArguments(['--checkupdates', '--verbose']) self._process.start() @Slot() @@ -59,13 +64,13 @@ def installUpdate(self): """ Start the external maintenance tool as detached process """ - console.debug("Updater installUpdate called") + console.debug('Updater installUpdate called') if self._process.state() == QProcess.Running: return program = os.path.join(self._process.workingDirectory(), self._process.program()) - arguments = ["--updater", "--verbose"] + arguments = ['--updater', '--verbose'] updater_started = QProcess.startDetached(program, arguments) @@ -111,16 +116,19 @@ def _createUpdaterProcess(self): return process def _onStarted(self): - console.debug("Updater process started") - self._web_version = "" - self._web_date = "" - self._error_message = "" + console.debug('Updater process started') + self._web_version = '' + self._web_date = '' + self._error_message = '' self.webVersionChanged.emit() self.webDateChanged.emit() self.errorMessageChanged.emit() def _onFinished(self, exit_code: int, exit_status: QProcess.ExitStatus): - console.debug(f"Updater process finished with exit code: '{exit_code}' and exit status: '{exit_status}'") + console.debug( + f'Updater process finished with exit code: ' + f"'{exit_code}' and exit status: '{exit_status}'" + ) # Get updater process output and error, if any std_out = self._process.readAllStandardOutput().data().decode('utf-8') @@ -128,21 +136,24 @@ def _onFinished(self, exit_code: int, exit_status: QProcess.ExitStatus): # Debug printing if std_out: - console.debug(f"Updater standard output:\n{std_out}") + console.debug(f'Updater standard output:\n{std_out}') if std_err: - console.debug(f"Updater standard error:\n{std_err}") + console.debug(f'Updater standard error:\n{std_err}') # Something went wrong if exit_code != 0 or exit_status != QProcess.ExitStatus.NormalExit: - console.debug("Updater process failed") - self._error_message = f"Updater process finished with\n* exit code: {exit_code} \n* exit status: {exit_status}" + console.debug('Updater process failed') + self._error_message = ( + f'Updater process finished with\n* exit code: ' + f'{exit_code} \n* exit status: {exit_status}' + ) self.errorMessageChanged.emit() if not self.silentCheck: self.updateFailed.emit() return # Process finished succesfully - console.debug("Updater process succeeded; checking for updates...") + console.debug('Updater process succeeded; checking for updates...') # Check if a new version of any of the app component is found pattern = r'' @@ -150,13 +161,13 @@ def _onFinished(self, exit_code: int, exit_status: QProcess.ExitStatus): # No new versions are found if not matches: - console.debug("Updater did not find any updates") + console.debug('Updater did not find any updates') if not self.silentCheck: self.updateNotFound.emit() return # New version is found - console.debug(f"Updater found component(s) with new version(s): {matches}") + console.debug(f'Updater found component(s) with new version(s): {matches}') self._web_version = matches[0] # TODO: Update this if multiple components are available self._web_date = self._getWebDate() self._release_notes = self._getReleaseNotes() @@ -179,27 +190,28 @@ def _getAppChangelog(self): try: return pathlib.Path(path).read_text() except Exception as exception: - console.debug(f"Failed to read local file {path} with exception {exception}") - return "" + console.debug(f'Failed to read local file {path} with exception {exception}') + return '' def _getWebChangelog(self): url = Updater.webChangelogUrl() try: - with urllib.request.urlopen(url) as f: + with urllib.request.urlopen(url) as f: # noqa return f.read().decode('utf-8') except Exception as exception: - console.debug(f"Failed to read web file {url} with exception {exception}") - return "" + console.debug(f'Failed to read web file {url} with exception {exception}') + return '' def _getReleaseNotes(self): app_changelog = self._getAppChangelog() web_changelog = self._getWebChangelog() # remove overlapping part - release_notes = web_changelog.replace(app_changelog, "") - # TODO: Temporary solution to change default headers size and and empty lines (QML Text.MarkdownText) - release_notes = re.sub(r'\n### ', "\n____\n#### ", release_notes) - release_notes = re.sub(r'\n# ', "\n____\n____\n### ", release_notes) - release_notes = re.sub(r'^# ', "### ", release_notes) + release_notes = web_changelog.replace(app_changelog, '') + # TODO: Temporary solution to change default headers size and + # empty lines (QML Text.MarkdownText) + release_notes = re.sub(r'\n### ', '\n____\n#### ', release_notes) + release_notes = re.sub(r'\n# ', '\n____\n____\n### ', release_notes) + release_notes = re.sub(r'^# ', '### ', release_notes) return release_notes def _getWebDate(self): @@ -214,30 +226,30 @@ def _getWebDate(self): @staticmethod def exeRelativePath(): if sys.platform.startswith('win'): - return "..\\MaintenanceTool.exe" + return '..\\MaintenanceTool.exe' elif sys.platform.startswith('darwin'): - return "../../../MaintenanceTool.app/Contents/MacOS/MaintenanceTool" + return '../../../MaintenanceTool.app/Contents/MacOS/MaintenanceTool' else: - return "../MaintenanceTool" + return '../MaintenanceTool' @staticmethod def appChangelogPath(): if sys.platform.startswith('win'): - relative_path = "..\\CHANGELOG.md" + relative_path = '..\\CHANGELOG.md' elif sys.platform.startswith('darwin'): - relative_path = "../../../CHANGELOG.md" + relative_path = '../../../CHANGELOG.md' else: - relative_path = "../CHANGELOG.md" + relative_path = '../CHANGELOG.md' path = os.path.join(QApplication.applicationDirPath(), relative_path) return path @staticmethod def webChangelogUrl(): if sys.platform.startswith('win'): - os_dir = "Windows" + os_dir = 'Windows' elif sys.platform.startswith('darwin'): - os_dir = "macOS" + os_dir = 'macOS' else: - os_dir = "Linux" + os_dir = 'Linux' url = f'https://download.easydiffraction.org/onlineRepository/{os_dir}/CHANGELOG.md' return url diff --git a/src/EasyApp/Logic/Maintenance/Updater.qml b/src/EasyApplication/Logic/Maintenance/Updater.qml similarity index 100% rename from src/EasyApp/Logic/Maintenance/Updater.qml rename to src/EasyApplication/Logic/Maintenance/Updater.qml diff --git a/src/EasyApp/Logic/Maintenance/qmldir b/src/EasyApplication/Logic/Maintenance/qmldir similarity index 100% rename from src/EasyApp/Logic/Maintenance/qmldir rename to src/EasyApplication/Logic/Maintenance/qmldir diff --git a/src/EasyApp/Logic/Translate.py b/src/EasyApplication/Logic/Translate.py similarity index 83% rename from src/EasyApp/Logic/Translate.py rename to src/EasyApplication/Logic/Translate.py index 21a0da69..717b0a43 100644 --- a/src/EasyApp/Logic/Translate.py +++ b/src/EasyApplication/Logic/Translate.py @@ -1,11 +1,18 @@ -__author__ = "github.com/AndrewSazonov" -__version__ = "0.0.1" +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + import os -from PySide6.QtCore import QObject, QTranslator, QLocale, Property, Slot -#from PySide6.QtWidgets import QApplication -#from PySide6.QtQml import QQmlApplicationEngine +from PySide6.QtCore import Property +from PySide6.QtCore import QLocale +from PySide6.QtCore import QObject +from PySide6.QtCore import QTranslator +from PySide6.QtCore import Slot + +# from PySide6.QtWidgets import QApplication +# from PySide6.QtQml import QQmlApplicationEngine + class Translator(QObject): def __init__(self, app, engine, translations_path, languages): diff --git a/src/EasyApp/Logic/Utils/Utils.py b/src/EasyApplication/Logic/Utils/Utils.py similarity index 67% rename from src/EasyApp/Logic/Utils/Utils.py rename to src/EasyApplication/Logic/Utils/Utils.py index 698e76ec..a32c959f 100644 --- a/src/EasyApp/Logic/Utils/Utils.py +++ b/src/EasyApplication/Logic/Utils/Utils.py @@ -1,19 +1,22 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + import os import sys from urllib.parse import urlparse - # Utils + def generalize_path(fpath: str) -> str: """ - Generalize the filepath to be platform-specific, so all file operations - can be performed. + Generalize the filepath to be platform-specific, so all file + operations can be performed. :param URI fpath: URI to the file :return URI filename: platform specific URI """ filename = urlparse(fpath).path - if not sys.platform.startswith("win"): + if not sys.platform.startswith('win'): return filename if filename[0] == '/': filename = filename[1:].replace('/', os.path.sep) diff --git a/src/EasyApplication/Logic/Utils/__init__.py b/src/EasyApplication/Logic/Utils/__init__.py new file mode 100644 index 00000000..4e798e20 --- /dev/null +++ b/src/EasyApplication/Logic/Utils/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause diff --git a/src/EasyApplication/Logic/__init__.py b/src/EasyApplication/Logic/__init__.py new file mode 100644 index 00000000..4e798e20 --- /dev/null +++ b/src/EasyApplication/Logic/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause diff --git a/src/EasyApplication/__init__.py b/src/EasyApplication/__init__.py new file mode 100644 index 00000000..4e798e20 --- /dev/null +++ b/src/EasyApplication/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/functional/test_dummy.py b/tests/functional/test_dummy.py new file mode 100644 index 00000000..6927fe89 --- /dev/null +++ b/tests/functional/test_dummy.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + + +def test_dummy(): + calculated = 2 + 2 + expected = 4 + assert calculated == expected diff --git a/tests/integration/fitting/test_dummy.py b/tests/integration/fitting/test_dummy.py new file mode 100644 index 00000000..2256189c --- /dev/null +++ b/tests/integration/fitting/test_dummy.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +import pytest + + +@pytest.mark.fast +def test_dummy_fast(): + calculated = 2 + 2 + expected = 4 + assert calculated == expected + + +def test_dummy_slow(): + calculated = sum(i * j for i in range(10000) for j in range(10000)) + expected = 2499500025000000 + assert calculated == expected diff --git a/tests/integration/scipp-analysis/test_dummy.py b/tests/integration/scipp-analysis/test_dummy.py new file mode 100644 index 00000000..2256189c --- /dev/null +++ b/tests/integration/scipp-analysis/test_dummy.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + +import pytest + + +@pytest.mark.fast +def test_dummy_fast(): + calculated = 2 + 2 + expected = 4 + assert calculated == expected + + +def test_dummy_slow(): + calculated = sum(i * j for i in range(10000) for j in range(10000)) + expected = 2499500025000000 + assert calculated == expected diff --git a/tests/unit/test_dummy.py b/tests/unit/test_dummy.py new file mode 100644 index 00000000..6927fe89 --- /dev/null +++ b/tests/unit/test_dummy.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause + + +def test_dummy(): + calculated = 2 + 2 + expected = 4 + assert calculated == expected diff --git a/tools/license_headers.py b/tools/license_headers.py new file mode 100644 index 00000000..f276ca1b --- /dev/null +++ b/tools/license_headers.py @@ -0,0 +1,321 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +"""Add, remove, or check SPDX headers in Python files.""" + +from __future__ import annotations + +import argparse +import fnmatch +import tomllib +from datetime import datetime +from pathlib import Path +from typing import Any +from typing import Optional +from typing import Union + +from git import Repo +from spdx_headers.core import find_repository_root +from spdx_headers.core import get_copyright_info +from spdx_headers.core import has_spdx_header +from spdx_headers.data import load_license_data +from spdx_headers.operations import add_header_to_single_file +from spdx_headers.operations import remove_header_from_single_file + +LICENSE_DATABASE = load_license_data() + + +def load_pyproject(repo_path: Union[str, Path]) -> dict[str, Any]: + """ + Load and return parsed ``pyproject.toml`` data for the repository. + """ + repo_root = find_repository_root(repo_path) + pyproject_path = repo_root / 'pyproject.toml' + + with pyproject_path.open('rb') as file_handle: + return tomllib.load(file_handle) + + +def get_pyproject_value(pyproject_data: dict[str, Any], dotted_key: str) -> Any: + """Return a nested ``pyproject.toml`` value from a dotted key.""" + value: Any = pyproject_data + for part in dotted_key.split('.'): + if not isinstance(value, dict) or part not in value: + raise KeyError(dotted_key) + value = value[part] + return value + + +def normalize_pattern(pattern: str) -> str: + """Normalize an exclude pattern to a POSIX-style relative path.""" + normalized = Path(pattern).as_posix() + if normalized.startswith('./'): + normalized = normalized[2:] + return normalized.rstrip('/') + + +def get_exclude_patterns( + repo_path: Union[str, Path], + exclude_values: list[str], + exclude_from_pyproject_toml: Optional[str], +) -> list[str]: + """ + Return normalized exclude patterns from CLI and ``pyproject.toml``. + """ + pyproject_data = load_pyproject(repo_path) + patterns: list[str] = [] + + if exclude_from_pyproject_toml: + value = get_pyproject_value(pyproject_data, exclude_from_pyproject_toml) + if not isinstance(value, list) or not all(isinstance(item, str) for item in value): + raise ValueError( + f'{exclude_from_pyproject_toml} in pyproject.toml must be a list of strings.', + ) + patterns.extend(value) + + for item in exclude_values: + try: + value = get_pyproject_value(pyproject_data, item) + except KeyError: + patterns.append(item) + continue + + if not isinstance(value, list) or not all(isinstance(entry, str) for entry in value): + raise ValueError(f'{item} in pyproject.toml must be a list of strings.') + patterns.extend(value) + + normalized_patterns: list[str] = [] + seen: set[str] = set() + for pattern in patterns: + normalized = normalize_pattern(pattern) + if normalized and normalized not in seen: + normalized_patterns.append(normalized) + seen.add(normalized) + + return normalized_patterns + + +def get_file_creation_year(file_path: Union[str, Path]) -> str: + """Return the year the file was first added to Git history. + + If the year cannot be determined, fall back to the current year. + """ + file_path = Path(file_path) + + repo = Repo(file_path, search_parent_directories=True) + root = Path(repo.working_tree_dir).resolve() + rel_path = file_path.resolve().relative_to(root) + + rel_path_git = rel_path.as_posix() + + log_output = repo.git.log( + '--follow', + '--diff-filter=A', + '--reverse', + '--format=%ad', + '--date=format:%Y', + '--', + rel_path_git, + ).strip() + + year = log_output.splitlines()[0].strip() if log_output else '' + + return year or str(datetime.now().year) + + +def get_org_url(repo_path: Union[str, Path]) -> str: + """ + Return the organization URL derived from the repository source URL. + """ + pyproject_data = load_pyproject(repo_path) + repo_url = pyproject_data['project']['urls']['Source Code'] + return repo_url.rsplit('/', 1)[0] + + +def get_project_license(repo_path: Union[str, Path]) -> str: + """Return the project license value from ``pyproject.toml``.""" + pyproject_data = load_pyproject(repo_path) + return pyproject_data['project']['license'] + + +def get_copyright_holder(repo_path: Union[str, Path]) -> str: + """Return the repository copyright holder name.""" + _, name, _ = get_copyright_info(repo_path) + return name + + +def add_spdx_header( + target_file: Union[str, Path], + *, + license_key: str, + copyright_holder: str, + org_url: str, +) -> None: + """Add SPDX headers to one file.""" + year = get_file_creation_year(target_file) + + add_header_to_single_file( + filepath=target_file, + license_key=license_key, + license_data=LICENSE_DATABASE, + year=year, + name=copyright_holder, + email=org_url, + ) + + +def is_excluded(relative_path: str, exclude_patterns: list[str]) -> bool: + """Return whether a relative path should be excluded.""" + for pattern in exclude_patterns: + if fnmatch.fnmatch(relative_path, pattern): + return True + if relative_path == pattern: + return True + if relative_path.startswith(f'{pattern}/'): + return True + return False + + +def iter_python_files( + paths: list[str], + *, + repo_root: Path, + exclude_patterns: list[str], + parser: argparse.ArgumentParser, +) -> list[Path]: + """Collect Python files under the given paths after exclusions.""" + files: list[Path] = [] + seen: set[Path] = set() + + for base_dir in paths: + base_path = Path(base_dir) + if not base_path.exists(): + parser.error(f'Path does not exist: {base_dir}') + + if base_path.is_file(): + candidates = [base_path] if base_path.suffix == '.py' else [] + else: + candidates = sorted(base_path.rglob('*.py')) + + for py_file in candidates: + resolved = py_file.resolve() + try: + relative_path = resolved.relative_to(repo_root).as_posix() + except ValueError: + relative_path = py_file.as_posix() + + if is_excluded(relative_path, exclude_patterns): + continue + + if resolved not in seen: + files.append(py_file) + seen.add(resolved) + + return files + + +def run_add( + files: list[Path], + *, + license_key: str, + copyright_holder: str, + org_url: str, +) -> int: + """Add SPDX headers to all selected files.""" + for py_file in files: + add_spdx_header( + py_file, + license_key=license_key, + copyright_holder=copyright_holder, + org_url=org_url, + ) + return 0 + + +def run_remove(files: list[Path]) -> int: + """Remove SPDX headers from all selected files.""" + for py_file in files: + remove_header_from_single_file(py_file) + return 0 + + +def run_check(files: list[Path]) -> int: + """Check SPDX headers in all selected files.""" + missing_files = [py_file for py_file in files if not has_spdx_header(py_file)] + + if not missing_files: + print('✓ All Python files have valid SPDX headers.') + return 0 + + print('✗ The following files are missing SPDX headers:') + for py_file in missing_files: + print(f' - {py_file.as_posix()}') + print(f'\nFound {len(missing_files)} files without SPDX headers.') + return 1 + + +def build_parser() -> argparse.ArgumentParser: + """Build the CLI argument parser.""" + parser = argparse.ArgumentParser( + description='Add, remove, or check SPDX headers in Python files.', + ) + subparsers = parser.add_subparsers(dest='command', required=True) + + for command_name in ('check', 'remove', 'add'): + command_parser = subparsers.add_parser(command_name) + command_parser.add_argument( + 'paths', + nargs='+', + help='Relative paths to scan (e.g. src tests)', + ) + command_parser.add_argument( + '--exclude', + nargs='*', + default=[], + help='Exclude paths, glob patterns, or pyproject dotted keys.', + ) + command_parser.add_argument( + '--exclude-from-pyproject-toml', + help='Read exclude patterns from a dotted key in pyproject.toml.', + ) + + return parser + + +def main(argv: Optional[list[str]] = None) -> int: + """Run the SPDX header CLI.""" + parser = build_parser() + args = parser.parse_args(argv) + + repo_path = Path('.').resolve() + repo_root = find_repository_root(repo_path).resolve() + exclude_patterns = get_exclude_patterns( + repo_path, + args.exclude, + args.exclude_from_pyproject_toml, + ) + files = iter_python_files( + args.paths, + repo_root=repo_root, + exclude_patterns=exclude_patterns, + parser=parser, + ) + + if args.command == 'check': + return run_check(files) + + if args.command == 'remove': + return run_remove(files) + + license_key = get_project_license(repo_path) + copyright_holder = get_copyright_holder(repo_path) + org_url = get_org_url(repo_path) + return run_add( + files, + license_key=license_key, + copyright_holder=copyright_holder, + org_url=org_url, + ) + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/tools/test_scripts.py b/tools/test_scripts.py new file mode 100644 index 00000000..e24b28e2 --- /dev/null +++ b/tools/test_scripts.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +"""Test runner for tutorial scripts in the 'tutorials' directory. + +This test discovers and executes all Python scripts located under the +'tutorials' directory to ensure they run without errors. + +Important: each script must be executed in a fresh Python process. +Running many tutorials in-process (e.g. via runpy) leaks global state +between scripts (notably cached calculator dictionaries keyed only by +model/experiment names), which can cause false failures. +""" + +import os +import subprocess # noqa: S404 +import sys +from pathlib import Path + +import pytest + +_repo_root = Path(__file__).resolve().parents[1] +_src_root = _repo_root / 'src' + +# Discover tutorial scripts, excluding temporary checkpoint files +TUTORIALS = [ + p for p in Path('docs/docs/tutorials').rglob('*.py') if '.ipynb_checkpoints' not in p.parts +] + + +@pytest.mark.parametrize('script_path', TUTORIALS) +def test_script_runs(script_path: Path): + """Execute a tutorial script and fail if it raises an exception. + + Each script is run in the context of __main__ to mimic standalone + execution. + """ + env = os.environ.copy() + if _src_root.exists(): + existing = env.get('PYTHONPATH', '') + env['PYTHONPATH'] = ( + str(_src_root) if not existing else str(_src_root) + os.pathsep + existing + ) + + # This is a test harness executing repo-local tutorial scripts. + # We intentionally use subprocess isolation to prevent cross-test + # global state leaks (e.g. calculator caches) that can cause false + # failures when running tutorials in a shared interpreter. + result = subprocess.run( # noqa: S603 + [sys.executable, str(script_path)], + cwd=str(_repo_root), + env=env, + capture_output=True, + text=True, + ) + if result.returncode != 0: + details = (result.stdout or '') + (result.stderr or '') + pytest.fail(f'{script_path}\n{details.strip()}') diff --git a/tools/update_docs_assets.py b/tools/update_docs_assets.py new file mode 100644 index 00000000..f4fe7f36 --- /dev/null +++ b/tools/update_docs_assets.py @@ -0,0 +1,91 @@ +""" +Update documentation assets from the assets-branding repository. + +This script fetches branding assets (logos, icons, images) from the +easyscience/assets-branding GitHub repository and copies them to the +appropriate locations in the documentation directory. +""" + +import shutil +from pathlib import Path + +import pooch + +# Configuration: Define what to fetch and where to copy +GITHUB_REPO = 'easyscience/assets-branding' +GITHUB_BRANCH = 'master' +BASE_URL = f'https://raw.githubusercontent.com/{GITHUB_REPO}/refs/heads/{GITHUB_BRANCH}' +PROJECT_NAME = 'easyapplication' + +# Mapping of source files to destination paths +# Format: "source_path_in_repo": "destination_path_in_project" +ASSETS_MAP = { + # Logos + f'{PROJECT_NAME}/logos/dark.svg': 'docs/docs/assets/images/logo_dark.svg', + f'{PROJECT_NAME}/logos/light.svg': 'docs/docs/assets/images/logo_light.svg', + # Favicon + f'{PROJECT_NAME}/icons/color.png': 'docs/docs/assets/images/favicon.png', + # Icon overrides + f'{PROJECT_NAME}/icons/bw.svg': f'docs/overrides/.icons/{PROJECT_NAME}.svg', + 'easyscience-org/icons/eso-icon_bw.svg': 'docs/overrides/.icons/easyscience.svg', +} + + +def fetch_and_copy_asset( + source_path: str, + dest_path: str, + cache_dir: Path, +) -> None: + """ + Fetch an asset from GitHub and copy it to the destination. + + Args: + source_path: Path to the file in the GitHub repository + dest_path: Destination path in the project + cache_dir: Directory to cache downloaded files + """ + url = f'{BASE_URL}/{source_path}' + + # Create a unique cache filename based on source path + cache_filename = source_path.replace('/', '_') + + # Download file using pooch + file_path = pooch.retrieve( + url=url, + known_hash=None, # Skip hash verification + path=cache_dir, + fname=cache_filename, + ) + + # Create destination directory if it doesn't exist + dest = Path(dest_path) + dest.parent.mkdir(parents=True, exist_ok=True) + + # Copy the file to destination + shutil.copy2(file_path, dest) + print(f'Copied {file_path} -> {dest_path}') + + +def main(): + """Main function to update all documentation assets.""" + print('📥 Updating documentation assets...') + print(f' Repository: {GITHUB_REPO}') + print(f' Branch: {GITHUB_BRANCH}\n') + + # Use a temporary cache directory + cache_dir = Path.home() / '.cache' / GITHUB_REPO + cache_dir.mkdir(parents=True, exist_ok=True) + + # Fetch and copy each asset + for source_path, dest_path in ASSETS_MAP.items(): + try: + fetch_and_copy_asset(source_path, dest_path, cache_dir) + print() + except Exception as e: + print(f'❌ Failed to fetch {source_path}: {e}') + + print('\n✅ Documentation assets updated successfully!') + + +if __name__ == '__main__': + main() diff --git a/tools/update_github_labels.py b/tools/update_github_labels.py new file mode 100644 index 00000000..84de575e --- /dev/null +++ b/tools/update_github_labels.py @@ -0,0 +1,341 @@ +# SPDX-FileCopyrightText: 2026 EasyScience contributors +# SPDX-License-Identifier: BSD-3-Clause +"""Set/update GitHub labels for current or specified easyscience +repository. + +Requires: + - gh CLI installed + - gh auth login completed + +Usage: + python update_github_labels.py + python update_github_labels.py --dry-run + python update_github_labels.py --repo easyscience/my-repo + python update_github_labels.py --repo easyscience/my-repo --dry-run +""" + +from __future__ import annotations + +import argparse +import json +import shlex +import subprocess # noqa: S404 +import sys +from dataclasses import dataclass + +EASYSCIENCE_ORG = 'easyscience' + + +# Data structures + + +@dataclass(frozen=True) +class Label: + """A GitHub label with name, color, and description.""" + + name: str + color: str + description: str = '' + + +@dataclass(frozen=True) +class LabelRename: + """Mapping from old label name to new label name.""" + + old: str + new: str + + +class Colors: + """Hex color codes for label groups.""" + + SCOPE = 'd73a4a' + MAINTAINER = '0e8a16' + PRIORITY = 'fbca04' + BOT = '5319e7' + + +LABEL_RENAMES = [ + # Default GitHub labels to rename (if they exist) + LabelRename('bug', '[scope] bug'), + LabelRename('documentation', '[scope] documentation'), + LabelRename('duplicate', '[maintainer] duplicate'), + LabelRename('enhancement', '[scope] enhancement'), + LabelRename('good first issue', '[maintainer] good first issue'), + LabelRename('help wanted', '[maintainer] help wanted'), + LabelRename('invalid', '[maintainer] invalid'), + LabelRename('question', '[maintainer] question'), + LabelRename('wontfix', '[maintainer] wontfix'), + # Custom label renames (if they exist) + LabelRename('[bot] pull request', '[bot] release'), +] + +LABELS = [ + # Scope labels + Label( + '[scope] bug', + Colors.SCOPE, + 'Bug report or fix (major.minor.PATCH)', + ), + Label( + '[scope] documentation', + Colors.SCOPE, + 'Documentation only changes (major.minor.patch.POST)', + ), + Label( + '[scope] enhancement', + Colors.SCOPE, + 'Adds/improves features (major.MINOR.patch)', + ), + Label( + '[scope] maintenance', + Colors.SCOPE, + 'Code/tooling cleanup, no feature or bugfix (major.minor.PATCH)', + ), + Label( + '[scope] significant', + Colors.SCOPE, + 'Breaking or major changes (MAJOR.minor.patch)', + ), + Label( + '[scope] ⚠️ label needed', + Colors.SCOPE, + 'Automatically added to issues and PRs without a [scope] label', + ), + # Maintainer labels + Label( + '[maintainer] duplicate', + Colors.MAINTAINER, + 'Already reported or submitted', + ), + Label( + '[maintainer] good first issue', + Colors.MAINTAINER, + 'Good entry-level issue for newcomers', + ), + Label( + '[maintainer] help wanted', + Colors.MAINTAINER, + 'Needs additional help to resolve or implement', + ), + Label( + '[maintainer] invalid', + Colors.MAINTAINER, + 'Invalid, incorrect or outdated', + ), + Label( + '[maintainer] question', + Colors.MAINTAINER, + 'Needs clarification, discussion, or more information', + ), + Label( + '[maintainer] wontfix', + Colors.MAINTAINER, + 'Will not be fixed or continued', + ), + # Priority labels + Label( + '[priority] lowest', + Colors.PRIORITY, + 'Very low urgency', + ), + Label( + '[priority] low', + Colors.PRIORITY, + 'Low importance', + ), + Label( + '[priority] medium', + Colors.PRIORITY, + 'Normal/default priority', + ), + Label( + '[priority] high', + Colors.PRIORITY, + 'Should be prioritized soon', + ), + Label( + '[priority] highest', + Colors.PRIORITY, + 'Urgent. Needs attention ASAP', + ), + Label( + '[priority] ⚠️ label needed', + Colors.PRIORITY, + 'Automatically added to issues without a [priority] label', + ), + # Bot label + Label( + '[bot] release', + Colors.BOT, + 'Automated release PR. Excluded from changelog/versioning', + ), + Label( + '[bot] backmerge', + Colors.BOT, + 'Automated backmerge master → develop failed due to conflicts', + ), +] + + +# Helpers + + +@dataclass(frozen=True) +class CmdResult: + """Result of a shell command execution.""" + + returncode: int + stdout: str + stderr: str + + +def run_cmd( + args: list[str], + *, + dry_run: bool, + check: bool = True, +) -> CmdResult: + """Run a command (or print it in dry-run mode).""" + cmd_str = ' '.join(shlex.quote(a) for a in args) + + if dry_run: + print(f' [dry-run] {cmd_str}') + return CmdResult(0, '', '') + + proc = subprocess.run( + args=args, + text=True, + capture_output=True, + ) + result = CmdResult( + proc.returncode, + proc.stdout.strip(), + proc.stderr.strip(), + ) + + if check and proc.returncode != 0: + raise RuntimeError(f'Command failed ({proc.returncode}): {cmd_str}\n{result.stderr}') + + return result + + +def get_current_repo() -> str: + """Get the current repository name in 'owner/repo' format.""" + result = subprocess.run( + args=[ + 'gh', + 'repo', + 'view', + '--json', + 'nameWithOwner', + ], + text=True, + capture_output=True, + check=True, + ) + data = json.loads(result.stdout) + name_with_owner = data.get('nameWithOwner', '') + + if '/' not in name_with_owner: + raise RuntimeError('Could not determine current repository name') + + return name_with_owner + + +def rename_label( + repo: str, + rename: LabelRename, + *, + dry_run: bool, +) -> None: + """Rename a label, silently skipping if it doesn't exist.""" + result = run_cmd( + args=[ + 'gh', + 'label', + 'edit', + rename.old, + '--name', + rename.new, + '--repo', + repo, + ], + dry_run=dry_run, + check=False, + ) + + if dry_run or result.returncode == 0: + print(f' Rename: {rename.old!r} → {rename.new!r}') + else: + print(f' Skip (not found): {rename.old!r}') + + +def upsert_label( + repo: str, + label: Label, + *, + dry_run: bool, +) -> None: + """Create or update a label.""" + run_cmd( + [ + 'gh', + 'label', + 'create', + label.name, + '--color', + label.color, + '--description', + label.description, + '--force', + '--repo', + repo, + ], + dry_run=dry_run, + ) + print(f' Upsert: {label.name!r}') + + +# Main + + +def main() -> int: + """Entry point: parse arguments and sync labels.""" + parser = argparse.ArgumentParser(description='Sync GitHub labels for easyscience repos') + parser.add_argument( + '--repo', + help='Target repository (owner/name)', + ) + parser.add_argument( + '--dry-run', + action='store_true', + help='Print actions without applying changes', + ) + args = parser.parse_args() + + repo = args.repo or get_current_repo() + org = repo.split('/')[0] + + if org.lower() != EASYSCIENCE_ORG: + print(f"Error: repository '{repo}' is not under '{EASYSCIENCE_ORG}'", file=sys.stderr) + return 2 + + print(f'Repository: {repo}') + if args.dry_run: + print('Mode: DRY-RUN (no changes will be made)\n') + + print('\nRenaming default labels...') + for rename in LABEL_RENAMES: + rename_label(repo, rename, dry_run=args.dry_run) + + print('\nUpserting labels...') + for label in LABELS: + upsert_label(repo, label, dry_run=args.dry_run) + + print('\nDone.') + return 0 + + +if __name__ == '__main__': + raise SystemExit(main())