From 1fe554a3b7a3b237db165927a01653f643ec23d3 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:33:59 -0800 Subject: [PATCH 01/17] Update Project --- .github/FUNDING.yml | 1 + .github/disabled/publish.yaml | 37 ----- .github/workflows/build.yaml | 71 +++++++--- .github/workflows/docs.yaml | 83 ++++++----- .github/workflows/lint.yaml | 168 ++++++++++++++++++++++ .github/workflows/pages.yaml | 47 +++++++ .github/workflows/preview.yaml | 43 ++++++ .github/workflows/release.yaml | 168 ++++++++++++++++++++++ .gitignore | 16 ++- .prettierignore | 16 +++ .prettierrc.json | 20 +++ LICENSE | 21 +++ README.md | 88 ++++++++++-- build.ps1 | 48 +++++++ docs/syntax-highlighting.css | 246 +++++++++++++++++++++++++++++++++ docs/theme.css | 20 +++ pyproject.toml | 104 ++++++++++++++ requirements.txt | 1 - setup.cfg | 6 - setup.py | 34 ----- src/vultr/__init__.py | 4 + src/vultr/version.py | 13 ++ vultr.py => src/vultr/vultr.py | 103 +++++++------- 23 files changed, 1157 insertions(+), 201 deletions(-) create mode 100644 .github/FUNDING.yml delete mode 100644 .github/disabled/publish.yaml create mode 100644 .github/workflows/lint.yaml create mode 100644 .github/workflows/pages.yaml create mode 100644 .github/workflows/preview.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 LICENSE create mode 100644 build.ps1 create mode 100644 docs/syntax-highlighting.css create mode 100644 docs/theme.css create mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py create mode 100644 src/vultr/__init__.py create mode 100644 src/vultr/version.py rename vultr.py => src/vultr/vultr.py (59%) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..f72beb8 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: cssnr diff --git a/.github/disabled/publish.yaml b/.github/disabled/publish.yaml deleted file mode 100644 index 0eba812..0000000 --- a/.github/disabled/publish.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: "GitHub Pages" - -on: - release: - types: [published] -# workflow_dispatch: -# environment: -# type: choice -# description: Choose Environment -# options: -# - testpypi -# - pypi - push: - -env: - ENVIRONMENT: "testpypi" - REPOSITORY: "https://test.pypi.org/legacy/" - -jobs: - publish: - name: "Publish" - runs-on: ubuntu-latest - timeout-minutes: 5 - if: github.event_name == 'release' && !github.event.release.prerelease - - permissions: - id-token: write - - environment: - name: ${{ env.ENVIRONMENT }} - url: https://pypi.org/project/vultr-python/ - - steps: - - name: "PyPi Publish" - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: ${{ env.REPOSITORY }} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e61c27d..7e712b0 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,11 +1,16 @@ -name: "Build" +name: "Build Package" on: - workflow_dispatch: - release: - types: [published] - pull_request: - branches: ["master"] + workflow_call: + inputs: + name: + description: "Artifact Name" + type: string + required: true + path: + description: "Build Path" + type: string + default: dist jobs: build: @@ -15,21 +20,55 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@v5 - - name: "Setup Python" - uses: actions/setup-python@v4 + - name: "Debug event.json" + continue-on-error: true + run: cat "${GITHUB_EVENT_PATH}" + + - name: "Debug CTX github" + continue-on-error: true + env: + GITHUB_CTX: ${{ toJSON(github) }} + run: echo "$GITHUB_CTX" + + #- name: "Debug Environment" + # continue-on-error: true + # run: env + + - name: "Setup Python 3.13" + uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.13" + cache: "pip" - - name: "Build" + - name: "Install" run: | python -m pip install -U pip - python -m pip install -U build + python -m pip install --group dev + + - name: "Build" + run: | python -m build - - name: "Upload Artifact" - uses: actions/upload-artifact@v3 + - name: "List Artifacts" + env: + path: ${{ inputs.path }} + run: | + ls -lAh ${path}/* + results="$(ls -lAh ${path}/* | awk '{print $9" - "$5}')" + markdown='Artifacts:\n```text\n'"${results}"'\n```' + echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY + + - name: "Upload to Actions" + uses: actions/upload-artifact@v5 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + + - name: "Send Failure Notification" + if: ${{ failure() }} + uses: sarisia/actions-status-discord@v1 with: - name: vultr-python - path: dist/ + webhook: ${{ secrets.DISCORD_WEBHOOK }} + description: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 13916ff..63ec273 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -1,12 +1,16 @@ -name: "GitHub Pages" +name: "Build Docs" on: - push: - branches: ["master"] - workflow_dispatch: - repository_dispatch: - types: - - webhook + workflow_call: + inputs: + name: + description: "Artifact Name" + type: string + default: github-pages + path: + description: "Build Path" + type: string + default: site jobs: build: @@ -16,51 +20,54 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@v5 - - name: "Setup Python" - uses: actions/setup-python@v4 + - name: "Setup Python 3.13" + uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.13" + cache: "pip" - name: "Build Docs" run: | python -m pip install -U pip python -m pip install -U pdoc - python -m pip install -Ur requirements.txt - python -m pdoc -o _site vultr.py + python -m pip install --group dev + python -m pdoc -o "${{ inputs.path }}" -t docs src/vultr/vultr.py - name: "Update Permissions" run: | - chmod -c -R +rX "_site/" | while read line; do - echo "::warning title=Invalid file permissions automatically fixed::$line" + chmod -c -R +rX "${{ inputs.path }}" | while read line; do + echo "::notice::Fixed invalid file permissions: ${line}" done + - name: "List Artifacts" + env: + path: ${{ inputs.path }} + run: | + ls -lAh ${path}/* + results="$(ls -lAh ${path}/* | awk '{print $9" - "$5}')" + markdown='Artifacts:\n```text\n'"${results}"'\n```' + echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY + - name: "Upload Pages Artifact" - uses: actions/upload-pages-artifact@v2 + if: ${{ inputs.name == 'github-pages' }} + uses: actions/upload-pages-artifact@v4 with: - path: _site/ - - deploy: - name: "Deploy" - runs-on: ubuntu-latest - timeout-minutes: 5 - needs: build + path: ${{ inputs.path }} - permissions: - pages: write - id-token: write - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - - steps: - - name: "Configure Pages" - uses: actions/configure-pages@v3 + - name: "Upload Artifact" + if: ${{ inputs.name != 'github-pages' }} + uses: actions/upload-artifact@v5 + with: + name: ${{ inputs.name }} + path: ${{ inputs.path }} + if-no-files-found: "error" + include-hidden-files: true - - name: "Deploy Pages" - id: deployment - uses: actions/deploy-pages@v2 + - name: "Send Failure Notification" + if: ${{ failure() }} + uses: sarisia/actions-status-discord@v1 with: - artifact_name: github-pages + webhook: ${{ secrets.DISCORD_WEBHOOK }} + description: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..fa59d14 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,168 @@ +name: "Lint" + +on: + workflow_dispatch: + push: + branches: [master] + paths-ignore: + - ".gitignore" + - ".prettierignore" + - "MANIFEST.in" + - "pyproject.toml" + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: "Lint" + runs-on: ubuntu-latest + timeout-minutes: 5 + + permissions: + contents: read + + steps: + - name: "Checkout" + uses: actions/checkout@v5 + + - name: "Debug event.json" + continue-on-error: true + run: cat "${GITHUB_EVENT_PATH}" + + - name: "Debug CTX github" + continue-on-error: true + env: + GITHUB_CTX: ${{ toJSON(github) }} + run: echo "$GITHUB_CTX" + + - name: "Debug Environment" + continue-on-error: true + run: env + + #- name: "Check Changed Files" + # id: changed + # uses: tj-actions/changed-files@v47 + # with: + # files: | + # src/** + # tests/** + # pyproject.toml + + - name: "Setup Python 3.13" + uses: actions/setup-python@v6 + with: + python-version: "3.13" + cache: "pip" + + - name: "Install" + id: install + run: | + python -m pip install -U pip + python -m pip install --group dev + python -m pip install -e . + python -m pip list + + - name: "Debug" + if: ${{ !github.event.act }} + continue-on-error: true + run: | + python -V + which python + echo "::group::pip list" + python -m pip list + echo "::endgroup::" + + - name: "astral-sh/ruff" + if: ${{ !cancelled() }} + uses: astral-sh/ruff-action@v3 + with: + version: latest + + - name: "astral-sh/ty" + if: ${{ !cancelled() }} + run: | + ty check --python "$(which python)" -v + + - name: "psf/black" + if: ${{ !cancelled() }} + uses: psf/black@stable + + - name: "isort" + if: ${{ !cancelled() }} + uses: isort/isort-action@v1 + + - name: "mypy" + if: ${{ !cancelled() }} + run: | + mypy src + + - name: "bandit" + if: ${{ !cancelled() }} + run: | + bandit -c pyproject.toml -r src + + - name: "prettier" + if: ${{ !cancelled() }} + run: | + echo "::group::Install" + npm install prettier + echo "::endgroup::" + npx prettier --check . + + - name: "yamllint" + if: ${{ !cancelled() }} + env: + CONFIG: "{extends: relaxed, ignore: [node_modules/], rules: {line-length: {max: 119}}}" + run: | + echo "::group::List Files" + yamllint -d '${{ env.CONFIG }}' --list-files . + echo "::endgroup::" + yamllint -d '${{ env.CONFIG }}' . + + - name: "actionlint" + if: ${{ !cancelled() }} + run: | + echo "::group::Download" + loc=$(curl -sI https://github.com/rhysd/actionlint/releases/latest | grep -i '^location:') + echo "loc: ${loc}" + tag=$(echo "${loc}" | sed -E 's|.*/tag/v?(.*)|\1|' | tr -d '\t\r\n') + echo "tag: ${tag}" + url="https://github.com/rhysd/actionlint/releases/latest/download/actionlint_${tag}_linux_amd64.tar.gz" + echo "url: ${url}" + curl -sL "${url}" | tar xz -C "${RUNNER_TEMP}" actionlint + file "${RUNNER_TEMP}/actionlint" + "${RUNNER_TEMP}/actionlint" --version + echo "::endgroup::" + "${RUNNER_TEMP}/actionlint" -color -verbose -shellcheck= -pyflakes= + + #- name: "pytest" + # if: ${{ !cancelled() }} + # id: coverage + # run: | + # coverage run -m pytest + # coverage xml + # coverage report -m + + #- name: "codecov" + # if: ${{ !cancelled() && steps.coverage.outcome == 'success' }} + # uses: codecov/codecov-action@v5 + # with: + # token: ${{ secrets.CODECOV_TOKEN }} + + #- name: "hadolint" + # if: ${{ !cancelled() }} + # uses: hadolint/hadolint-action@v3.3.0 + # with: + # dockerfile: Dockerfile + + #- name: "Vale" + # if: ${{ !cancelled() }} + # uses: errata-ai/vale-action@v2.1.1 + + #- name: "SonarQube" + # uses: SonarSource/sonarqube-scan-action@v4 + # env: + # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml new file mode 100644 index 0000000..d204eed --- /dev/null +++ b/.github/workflows/pages.yaml @@ -0,0 +1,47 @@ +name: "GitHub Pages" + +on: + workflow_dispatch: + push: + branches: [master] + paths: + - ".github/workflows/pages.yaml" + - "docs/**" + - "src/**" + +jobs: + build: + name: "Build" + if: ${{ !contains(github.event.head_commit.message, '#nopreview') }} + uses: ./.github/workflows/docs.yaml + permissions: + contents: read + secrets: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + + deploy: + name: "Deploy" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: build + + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: "Deploy Pages" + id: deployment + uses: actions/deploy-pages@v4 + + - name: "Send Notification" + if: ${{ !cancelled() }} + continue-on-error: true + uses: sarisia/actions-status-discord@v1 + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + description: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml new file mode 100644 index 0000000..15dab80 --- /dev/null +++ b/.github/workflows/preview.yaml @@ -0,0 +1,43 @@ +name: "Preview" + +on: + workflow_dispatch: + push: + branches-ignore: [master] + paths: + - ".github/workflows/preview.yaml" + - "docs/**" + - "src/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: "Build" + if: ${{ !contains(github.event.head_commit.message, '#nopreview') }} + uses: ./.github/workflows/docs.yaml + permissions: + contents: read + with: + name: artifact + secrets: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + + deploy: + name: "Deploy" + uses: cssnr/workflows/.github/workflows/deploy-static.yaml@master + needs: build + permissions: + contents: read + with: + name: "preview" + url: "https://dev-static.cssnr.com/" + robots: true + secrets: + host: ${{ secrets.DEV_DEPLOY_HOST }} + port: ${{ secrets.DEV_DEPLOY_PORT }} + user: ${{ secrets.DEV_DEPLOY_USER }} + pass: ${{ secrets.DEV_DEPLOY_PASS }} + webhook: ${{ secrets.DISCORD_WEBHOOK }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..c575493 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,168 @@ +name: "Release" + +on: + release: + types: [published] + +env: + url: "https://${{ github.event.release.prerelease && 'test.' || '' }}pypi.org/p/vultr-python" + repository-url: "https://${{ github.event.release.prerelease && 'test' || 'upload' }}.pypi.org/legacy/" + +jobs: + build: + name: "Build" + uses: ./.github/workflows/build.yaml + secrets: inherit + with: + name: "release" + + publish: + name: "Publish" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: [build] + + permissions: + contents: write + id-token: write + + environment: + name: ${{ github.event.release.prerelease && 'test' || 'pypi' }} + url: ${{ env.url }} + + steps: + - name: "Debug event.json" + continue-on-error: true + run: cat "${GITHUB_EVENT_PATH}" + + - name: "Debug CTX github" + continue-on-error: true + env: + GITHUB_CTX: ${{ toJSON(github) }} + run: echo "$GITHUB_CTX" + + #- name: "Debug Environment" + # continue-on-error: true + # run: env + + - name: "Debug" + run: | + echo "github.ref_name: ${{ github.ref_name }}" + echo "name: ${{ github.event.release.prerelease && 'test' || 'pypi' }}" + echo "env.url: ${{ env.url }}" + echo "env.repository-url: ${{ env.repository-url }}" + + - name: "Download Artifact" + uses: actions/download-artifact@v6 + with: + name: "release" + path: "dist" + + - name: "Verify Artifacts" + env: + path: "dist" + tag: ${{ github.ref_name }} + run: | + ls -lAh ${path}/* + results="$(ls -lAh ${path}/* | awk '{print $9" - "$5}')" + markdown='Artifacts:\n```text\n'"${results}"'\n```' + echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY + ls ${path} | grep -- "-${tag}-" > /dev/null + + - name: "Publish to PyPI" + id: publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + verbose: true + repository-url: ${{ env.repository-url }} + #attestations: false + + - name: "Summary" + if: ${{ always() }} + env: + tag: ${{ github.ref_name }} + url: ${{ env.url }} + repository-url: ${{ env.repository-url }} + run: | + if [ "${{ steps.publish.outcome }}" == "success" ];then + markdown="🎉 Published Version: \`${tag}\`\n\n[${url}](${url})\n\n" + else + markdown="⛔ Error Publishing Version: \`${tag}\`\n\n" + fi + markdown+="Repository URL: \`${repository-url}\`" + echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY + + - name: "Send Notification" + if: ${{ !cancelled() }} + uses: sarisia/actions-status-discord@v1 + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + description: | + ${{ env.url }} + ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} + + release: + name: "Release" + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: [publish] + + steps: + - name: "Debug" + continue-on-error: true + run: | + echo "github.ref_name: ${{ github.ref_name }}" + echo "github.event.release.prerelease: ${{ github.event.release.prerelease }}" + + - name: "Debug event.json" + continue-on-error: true + run: cat "${GITHUB_EVENT_PATH}" + + - name: "Debug CTX github" + continue-on-error: true + env: + GITHUB_CTX: ${{ toJSON(github) }} + run: echo "$GITHUB_CTX" + + #- name: "Debug Environment" + # continue-on-error: true + # run: env + + #- name: "Update Latest Tag" + # if: ${{ !github.event.release.prerelease }} + # uses: cssnr/update-version-tags-action@latest + # continue-on-error: true + # with: + # major: false + # minor: false + # tags: latest + # #tag: ${{ github.ref_name }} + + - name: "Download Artifact" + uses: actions/download-artifact@v6 + with: + name: "release" + path: "dist" + + - name: "List Artifacts" + run: | + ls -lAh dist + ls dist | grep -- "-${{ github.ref_name }}-" > /dev/null + + - name: "Upload Release" + uses: cssnr/upload-release-action@latest + with: + globs: dist/* + + - name: "Update Release Notes Action" + continue-on-error: true + uses: smashedr/update-release-notes-action@master + with: + location: tail + + - name: "Send Failure Notification" + if: ${{ failure() }} + uses: sarisia/actions-status-discord@v1 + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + description: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} diff --git a/.gitignore b/.gitignore index 19197fa..5702a98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,19 @@ +# Generic .idea/ *.iml .vscode/ -dist/ -_site/ +.venv/ venv/ -**/__pycache__/ +__pycache__/ *.egg-info/ +build/ +dist/ +*.log +*.pyc .coverage +coverage.xml +# Zensical +site/ +.cache/ +# App +_site/ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5b4267c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,16 @@ +# IDE +.idea/ +.vscode/ + +# Build +dist/ +node_modules/ + +# Tools +.ruff_cache/ +.mypy_cache/ +.pytest_cache/ + +# Files +package-lock.json +*.html diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..4541eb0 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,20 @@ +{ + "trailingComma": "es5", + "semi": false, + "singleQuote": true, + "printWidth": 90, + "overrides": [ + { + "files": ["**/*.html", "**/*.yaml", "**/*.yml"], + "options": { + "singleQuote": false + } + }, + { + "files": ["**/*.js", "**/*.mjs", "**/*.css", "**/*.scss"], + "options": { + "tabWidth": 4 + } + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ffe8abf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 CSSNR + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2901fc9..d4756fc 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,56 @@ -[![Discord](https://img.shields.io/discord/899171661457293343?color=7289da&label=discord&logo=discord&logoColor=white&style=flat)](https://discord.gg/wXy6m2X8wY) +[![PyPI Version](https://img.shields.io/pypi/v/vultr-python?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) +[![GitHub Release Version](https://img.shields.io/github/v/release/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/releases) +[![TOML Python Version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fcssnr%2Fvultr-python%2Frefs%2Fheads%2Fmaster%2Fpyproject.toml&query=%24.project.requires-python&logo=python&logoColor=white&label=python)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) +[![PyPI Downloads](https://img.shields.io/pypi/dm/vultr-python?logo=pypi&logoColor=white)](https://pypistats.org/packages/vultr-python) +[![Pepy Total Downloads](https://img.shields.io/pepy/dt/vultr-python?logo=pypi&logoColor=white&label=total)](https://clickpy.clickhouse.com/dashboard/vultr-python) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9b356c4327df41e395c81de1c717ce11)](https://app.codacy.com/gh/cssnr/vultr-python/dashboard) -[![PyPI](https://img.shields.io/pypi/v/vultr-python)](https://pypi.org/project/vultr-python/) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cssnr_vultr-python&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python) +[![Workflow Lint](https://img.shields.io/github/actions/workflow/status/cssnr/vultr-python/lint.yaml?logo=cachet&label=lint)](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml) +[![Workflow Release](https://img.shields.io/github/actions/workflow/status/cssnr/vultr-python/release.yaml?logo=cachet&label=release)](https://github.com/cssnr/vultr-python/actions/workflows/release.yaml) +[![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/pypi?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) +[![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/github-pages?logo=materialformkdocs&logoColor=white&label=github-pages)](https://cssnr.github.io/vultr-python) +[![GitHub Last Commit](https://img.shields.io/github/last-commit/cssnr/vultr-python?logo=github&label=updated)](https://github.com/cssnr/vultr-python/graphs/commit-activity) +[![GitHub Repo Size](https://img.shields.io/github/repo-size/cssnr/vultr-python?logo=bookstack&logoColor=white&label=repo%20size)](https://github.com/cssnr/vultr-python) +[![GitHub Top Language](https://img.shields.io/github/languages/top/cssnr/vultr-python?logo=htmx&logoColor=white)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) +[![GitHub Contributors](https://img.shields.io/github/contributors-anon/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/graphs/contributors) +[![GitHub Discussions](https://img.shields.io/github/discussions/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/discussions) +[![GitHub Forks](https://img.shields.io/github/forks/cssnr/vultr-python?style=flat&logo=github)](https://github.com/cssnr/vultr-python/forks) +[![GitHub Repo Stars](https://img.shields.io/github/stars/cssnr/vultr-python?style=flat&logo=github)](https://github.com/cssnr/vultr-python/stargazers) +[![GitHub Org Stars](https://img.shields.io/github/stars/cssnr?style=flat&logo=github&label=org%20stars)](https://cssnr.github.io/) +[![Discord](https://img.shields.io/discord/899171661457293343?logo=discord&logoColor=white&label=discord&color=7289da)](https://discord.gg/wXy6m2X8wY) +[![Ko-fi](https://img.shields.io/badge/Ko--fi-72a5f2?logo=kofi&label=support)](https://ko-fi.com/cssnr) [![](https://repository-images.githubusercontent.com/441314848/513fb2f4-39cb-4bbc-8d47-a2cde9ccbd65)](https://www.vultr.com/?ref=6905748) + # Vultr Python +- [Install](#Install) +- [Usage](#Usage) +- [Support](#Support) +- [Contributing](#Contributing) + Python 3 wrapper for the Vultr API v2. -* Vultr: [https://www.vultr.com](https://www.vultr.com/?ref=6905748) -* Vultr API: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) -* Vultr Python Docs: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) +- Vultr: [https://www.vultr.com](https://www.vultr.com/?ref=6905748) +- Vultr API: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) +- Vultr Python Docs: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) -This is currently a WIP and not complete, but has some useful functions. -Feel free to request additional functions and more on [Discord](https://discord.gg/wXy6m2X8wY). +> [!TIP] +> This project is not complete, but has many useful functions. +> Please submit a [Feature Request](https://github.com/cssnr/vultr-python/discussions/categories/feature-requests) or report any [Issues](https://github.com/cssnr/vultr-python/issues). ## Install -From PyPi using pip: +From PyPi: https://pypi.org/project/vultr-python + ```text python -m pip install vultr-python ``` -From Source using setuptools: +From Source: + ```text git clone https://github.com/cssnr/vultr-python.git -cd vultr-python -python setup.py install +python -m pip install vultr-python ``` ## Usage @@ -32,31 +58,40 @@ python setup.py install You will need to create an api key and whitelist your IP address. Most functions do not work without an API Key. -* [https://my.vultr.com/settings/#settingsapi](https://my.vultr.com/settings/#settingsapi) +- [https://my.vultr.com/settings/#settingsapi](https://my.vultr.com/settings/#settingsapi) Initialize the class with your API Key or with the `VULTR_API_KEY` environment variable. + ```python from vultr import Vultr vultr = Vultr('VULTR_API_KEY') ``` + List plans and get available regions for that plan + ```python plans = vultr.list_plans() plan = plans[0] # 0 seems to be the basic 5 dollar plan regions = vultr.list_regions() available = vultr.filter_regions(regions, plan['locations']) ``` + Get the OS list and filter by name + ```python os_list = vultr.list_os() ubuntu_lts = vultr.filter_os(os_list, 'Ubuntu 20.04 x64') ``` + Create a new ssh key from key string + ```python sshkey = vultr.create_key('key-name', 'ssh-rsa AAAA...') ``` + Create a new instance + ```python hostname = 'my-new-host' data = { @@ -70,8 +105,31 @@ data = { instance = vultr.create_instance(**data) ``` -View all functions at the Doc site: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) +View all functions on the documentation site: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) + +View the Vultr API documentation at: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) + +# Support + +For general help or to request a feature, see: + +- Q&A Discussion: https://github.com/cssnr/vultr-python/discussions/categories/q-a +- Request a Feature: https://github.com/cssnr/vultr-python/discussions/categories/feature-requests +- Chat with us on Discord: https://discord.gg/wXy6m2X8wY + +If you are experiencing an issue/bug or getting unexpected results, you can: + +- Report an Issue: https://github.com/cssnr/vultr-python/issues +- Provide General Feedback: [https://cssnr.github.io/feedback/](https://cssnr.github.io/feedback/?app=vultr-python) +- Chat with us on Discord: https://discord.gg/wXy6m2X8wY + +# Contributing + +If you would like to submit a PR, please review the [CONTRIBUTING.md](#contributing-ov-file). + +Please consider making a donation to support the development of this project +and [additional](https://cssnr.com/) open source projects. -View the full API documentation at Vultr: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) +[![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/cssnr) -If you have more questions, concerns, or comments? Join our [Discord](https://discord.gg/wXy6m2X8wY) for more information... +For a full list of current projects visit: [https://cssnr.github.io/](https://cssnr.github.io/) diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..5db65bf --- /dev/null +++ b/build.ps1 @@ -0,0 +1,48 @@ +param ( + [switch]$c, + [switch]$i, + [switch]$u +) + +$ErrorActionPreference = "Stop" + +write-output "Clean: $c" +write-output "Install: $i" +write-output "Uninstall: $u" + +if ($u) { + Write-Host -ForegroundColor Red "Uninstalling..." + python -m pip uninstall -y vultr-python +} + +$egg_dir = ".\src\*.egg-info" +if (Test-Path $egg_dir) { + Write-Host -ForegroundColor Cyan "Removing: $egg_dir" + Remove-Item -Force -Recurse $egg_dir +} +$cache_dir = ".\src\*\__pycache__" +if (Test-Path $cache_dir) { + Write-Host -ForegroundColor Cyan "Removing: $cache_dir" + Remove-Item -Force -Recurse $cache_dir +} +if (Test-Path ".\dist") { + Write-Host -ForegroundColor Cyan "Removing: .\dist" + Remove-Item -Force -Recurse ".\dist" +} +if (Test-Path ".\build") { + Write-Host -ForegroundColor Cyan "Removing: .\build" + Remove-Item -Force -Recurse ".\build" +} +if ($c) { + Write-Host -ForegroundColor Yellow "Clean Only. Not Building or Installing!" + exit +} + +python -m build + +if ($args[0] -eq "i") { + Write-Host -ForegroundColor Green "Installing..." + python -m pip install .\dist\vultr_python-0.0.1-py3-none-any.whl +} + +Write-Output "Success." diff --git a/docs/syntax-highlighting.css b/docs/syntax-highlighting.css new file mode 100644 index 0000000..e5ec354 --- /dev/null +++ b/docs/syntax-highlighting.css @@ -0,0 +1,246 @@ +/* monokai color scheme, see pdoc/template/README.md */ +pre { + line-height: 125%; +} +span.linenos { + color: inherit; + background-color: transparent; + padding-left: 5px; + padding-right: 20px; +} +.pdoc-code .hll { + background-color: #49483e; +} +.pdoc-code { + background: #272822; + color: #f8f8f2; +} +.pdoc-code .c { + color: #75715e; +} /* Comment */ +.pdoc-code .err { + color: #960050; + background-color: #1e0010; +} /* Error */ +.pdoc-code .esc { + color: #f8f8f2; +} /* Escape */ +.pdoc-code .g { + color: #f8f8f2; +} /* Generic */ +.pdoc-code .k { + color: #66d9ef; +} /* Keyword */ +.pdoc-code .l { + color: #ae81ff; +} /* Literal */ +.pdoc-code .n { + color: #f8f8f2; +} /* Name */ +.pdoc-code .o { + color: #f92672; +} /* Operator */ +.pdoc-code .x { + color: #f8f8f2; +} /* Other */ +.pdoc-code .p { + color: #f8f8f2; +} /* Punctuation */ +.pdoc-code .ch { + color: #75715e; +} /* Comment.Hashbang */ +.pdoc-code .cm { + color: #75715e; +} /* Comment.Multiline */ +.pdoc-code .cp { + color: #75715e; +} /* Comment.Preproc */ +.pdoc-code .cpf { + color: #75715e; +} /* Comment.PreprocFile */ +.pdoc-code .c1 { + color: #75715e; +} /* Comment.Single */ +.pdoc-code .cs { + color: #75715e; +} /* Comment.Special */ +.pdoc-code .gd { + color: #f92672; +} /* Generic.Deleted */ +.pdoc-code .ge { + color: #f8f8f2; + font-style: italic; +} /* Generic.Emph */ +.pdoc-code .gr { + color: #f8f8f2; +} /* Generic.Error */ +.pdoc-code .gh { + color: #f8f8f2; +} /* Generic.Heading */ +.pdoc-code .gi { + color: #a6e22e; +} /* Generic.Inserted */ +.pdoc-code .go { + color: #66d9ef; +} /* Generic.Output */ +.pdoc-code .gp { + color: #f92672; + font-weight: bold; +} /* Generic.Prompt */ +.pdoc-code .gs { + color: #f8f8f2; + font-weight: bold; +} /* Generic.Strong */ +.pdoc-code .gu { + color: #75715e; +} /* Generic.Subheading */ +.pdoc-code .gt { + color: #f8f8f2; +} /* Generic.Traceback */ +.pdoc-code .kc { + color: #66d9ef; +} /* Keyword.Constant */ +.pdoc-code .kd { + color: #66d9ef; +} /* Keyword.Declaration */ +.pdoc-code .kn { + color: #f92672; +} /* Keyword.Namespace */ +.pdoc-code .kp { + color: #66d9ef; +} /* Keyword.Pseudo */ +.pdoc-code .kr { + color: #66d9ef; +} /* Keyword.Reserved */ +.pdoc-code .kt { + color: #66d9ef; +} /* Keyword.Type */ +.pdoc-code .ld { + color: #e6db74; +} /* Literal.Date */ +.pdoc-code .m { + color: #ae81ff; +} /* Literal.Number */ +.pdoc-code .s { + color: #e6db74; +} /* Literal.String */ +.pdoc-code .na { + color: #a6e22e; +} /* Name.Attribute */ +.pdoc-code .nb { + color: #f8f8f2; +} /* Name.Builtin */ +.pdoc-code .nc { + color: #a6e22e; +} /* Name.Class */ +.pdoc-code .no { + color: #66d9ef; +} /* Name.Constant */ +.pdoc-code .nd { + color: #a6e22e; +} /* Name.Decorator */ +.pdoc-code .ni { + color: #f8f8f2; +} /* Name.Entity */ +.pdoc-code .ne { + color: #a6e22e; +} /* Name.Exception */ +.pdoc-code .nf { + color: #a6e22e; +} /* Name.Function */ +.pdoc-code .nl { + color: #f8f8f2; +} /* Name.Label */ +.pdoc-code .nn { + color: #f8f8f2; +} /* Name.Namespace */ +.pdoc-code .nx { + color: #a6e22e; +} /* Name.Other */ +.pdoc-code .py { + color: #f8f8f2; +} /* Name.Property */ +.pdoc-code .nt { + color: #f92672; +} /* Name.Tag */ +.pdoc-code .nv { + color: #f8f8f2; +} /* Name.Variable */ +.pdoc-code .ow { + color: #f92672; +} /* Operator.Word */ +.pdoc-code .w { + color: #f8f8f2; +} /* Text.Whitespace */ +.pdoc-code .mb { + color: #ae81ff; +} /* Literal.Number.Bin */ +.pdoc-code .mf { + color: #ae81ff; +} /* Literal.Number.Float */ +.pdoc-code .mh { + color: #ae81ff; +} /* Literal.Number.Hex */ +.pdoc-code .mi { + color: #ae81ff; +} /* Literal.Number.Integer */ +.pdoc-code .mo { + color: #ae81ff; +} /* Literal.Number.Oct */ +.pdoc-code .sa { + color: #e6db74; +} /* Literal.String.Affix */ +.pdoc-code .sb { + color: #e6db74; +} /* Literal.String.Backtick */ +.pdoc-code .sc { + color: #e6db74; +} /* Literal.String.Char */ +.pdoc-code .dl { + color: #e6db74; +} /* Literal.String.Delimiter */ +.pdoc-code .sd { + color: #e6db74; +} /* Literal.String.Doc */ +.pdoc-code .s2 { + color: #e6db74; +} /* Literal.String.Double */ +.pdoc-code .se { + color: #ae81ff; +} /* Literal.String.Escape */ +.pdoc-code .sh { + color: #e6db74; +} /* Literal.String.Heredoc */ +.pdoc-code .si { + color: #e6db74; +} /* Literal.String.Interpol */ +.pdoc-code .sx { + color: #e6db74; +} /* Literal.String.Other */ +.pdoc-code .sr { + color: #e6db74; +} /* Literal.String.Regex */ +.pdoc-code .s1 { + color: #e6db74; +} /* Literal.String.Single */ +.pdoc-code .ss { + color: #e6db74; +} /* Literal.String.Symbol */ +.pdoc-code .bp { + color: #f8f8f2; +} /* Name.Builtin.Pseudo */ +.pdoc-code .fm { + color: #a6e22e; +} /* Name.Function.Magic */ +.pdoc-code .vc { + color: #f8f8f2; +} /* Name.Variable.Class */ +.pdoc-code .vg { + color: #f8f8f2; +} /* Name.Variable.Global */ +.pdoc-code .vi { + color: #f8f8f2; +} /* Name.Variable.Instance */ +.pdoc-code .vm { + color: #f8f8f2; +} /* Name.Variable.Magic */ diff --git a/docs/theme.css b/docs/theme.css new file mode 100644 index 0000000..60b447a --- /dev/null +++ b/docs/theme.css @@ -0,0 +1,20 @@ +:root { + --pdoc-background: #212529; +} + +.pdoc { + --text: #f7f7f7; + --muted: #9d9d9d; + --link: #58a6ff; + --link-hover: #3989ff; + --code: #333; + --active: #555; + + --accent: #343434; + --accent2: #555; + + --nav-hover: rgba(0, 0, 0, 0.1); + --name: #77c1ff; + --def: #0cdd0c; + --annotation: #00c037; +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..052de90 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,104 @@ +# Project +[project] +name = "vultr-python" +description = "Python 3 wrapper for the Vultr API v2.0" +authors = [{ name="Shane" }] +readme = "README.md" +dynamic = ["version"] +requires-python = ">=3.6" +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.06", + "Programming Language :: Python :: 3.07", + "Programming Language :: Python :: 3.08", + "Programming Language :: Python :: 3.09", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Operating System :: OS Independent", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Natural Language :: English", +] +license = { text = "MIT" } +#license = { file = "LICENSE" } + +dependencies = ["requests"] + +[dependency-groups] +dev = [ + "bandit", + "black", + "build", + "coverage", + "isort", + "mypy", + "requests", + "ruff", + "setuptools", + "ty", + "types-requests", +] + +[project.urls] +Homepage = "https://cssnr.com/" +Documentation = "https://cssnr.github.io/vultr-python" +Source = "https://github.com/cssnr/vultr-python" +Issues = "https://github.com/cssnr/vultr-python/issues" +Funding = "https://ko-fi.com/cssnr" + +# Setup Tools +#[tool.setuptools.package-data] +#vultr = ["py.typed"] +[tool.setuptools.dynamic] +version = { attr = "vultr.version.__version__" } + +# Build System +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +# Bandit +# https://bandit.readthedocs.io/en/latest/config.html +[tool.bandit] +exclude_dirs = ["venv"] +skips = ["B105", "B107"] + +# Black +# https://black.readthedocs.io/en/stable/usage_and_configuration/ +[tool.black] +line-length = 119 +extend-exclude = '(\.github)' + +# Coverage +# https://coverage.readthedocs.io/en/latest/ +[tool.coverage.run] +omit = ["*.egg-info/*", ".github/*"] +source = ["src"] + +# Isort +# https://pycqa.github.io/isort/docs/configuration/options.html +[tool.isort] +profile = "black" +lines_after_imports = 2 +src_paths = ["src", "test"] +skip = ["venv", ".github"] + +# Mypy +# https://mypy.readthedocs.io/en/stable/config_file.html +[tool.mypy] +#ignore_missing_imports = true +exclude = ["venv"] + +# Ruff +# https://docs.astral.sh/ruff/configuration/ +[tool.ruff] +line-length = 119 +target-version = "py313" +extend-exclude = [".github"] + +[tool.ruff.lint] +select = ["E4", "E7", "E9", "F", "B", "Q"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f229360..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8fbaec7..0000000 --- a/setup.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[flake8] -exclude = venv,*migrations* -max-line-length = 119 - -[coverage:run] -omit = *venv*,*migrations* diff --git a/setup.py b/setup.py deleted file mode 100644 index 2d26b5b..0000000 --- a/setup.py +++ /dev/null @@ -1,34 +0,0 @@ -import os -from setuptools import setup - - -with open(os.path.join(os.path.dirname(__file__), 'README.md'), 'r') as f: - long_description = f.read() - -setup( - name='vultr-python', - version='0.1.5', - description='Python 3 wrapper for the Vultr API v2.0', - long_description=long_description, - long_description_content_type="text/markdown", - url='https://github.com/cssnr/vultr-python', - author='Shane', - author_email='shane@sapps.me', - py_modules=['vultr'], - install_requires=['requests'], - python_requires='>=3.5', - include_package_data=True, - zip_safe=False, - platforms='any', - project_urls={ - 'Documentation': 'https://cssnr.github.io/vultr-python', - 'Source': 'https://github.com/cssnr/vultr-python', - }, - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3 :: Only', - ], -) diff --git a/src/vultr/__init__.py b/src/vultr/__init__.py new file mode 100644 index 0000000..706f507 --- /dev/null +++ b/src/vultr/__init__.py @@ -0,0 +1,4 @@ +from .vultr import Vultr + + +__all__ = ["Vultr"] diff --git a/src/vultr/version.py b/src/vultr/version.py new file mode 100644 index 0000000..1edcd39 --- /dev/null +++ b/src/vultr/version.py @@ -0,0 +1,13 @@ +import os +import re + + +def get_version() -> str: + version = os.environ.get("GITHUB_REF_NAME", "0.0.1") + pattern = r"^\d+\.\d+\.\d+(?:[abc]\d*)?$" + match = re.match(pattern, version) + return version if match else "0.0.1" + + +__version__ = get_version() + diff --git a/vultr.py b/src/vultr/vultr.py similarity index 59% rename from vultr.py rename to src/vultr/vultr.py index 108a745..96f0b50 100644 --- a/vultr.py +++ b/src/vultr/vultr.py @@ -1,146 +1,147 @@ import os -import requests from typing import Optional, Union +import requests + class Vultr(object): - url = 'https://api.vultr.com/v2' + url = "https://api.vultr.com/v2" def __init__(self, api_key: Optional[str] = None): """ :param str api_key: Vultr API Key or VULTR_API_KEY environment variable """ - self.api_key = api_key or os.getenv('VULTR_API_KEY') + self.api_key = api_key or os.getenv("VULTR_API_KEY") self.s = requests.session() if self.api_key: - self.s.headers.update({'Authorization': f'Bearer {self.api_key}'}) + self.s.headers.update({"Authorization": f"Bearer {self.api_key}"}) def list_os(self): - url = f'{self.url}/os' - return self._get(url)['os'] + url = f"{self.url}/os" + return self._get(url)["os"] def list_plans(self): - url = f'{self.url}/plans' - return self._get(url)['plans'] + url = f"{self.url}/plans" + return self._get(url)["plans"] def list_regions(self): - url = f'{self.url}/regions' - return self._get(url)['regions'] + url = f"{self.url}/regions" + return self._get(url)["regions"] def list_instances(self): - url = f'{self.url}/instances' - return self._get(url)['instances'] + url = f"{self.url}/instances" + return self._get(url)["instances"] def get_instance(self, instance: Union[str, dict]): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}' - return self._get(url)['instance'] + url = f"{self.url}/instances/{instance_id}" + return self._get(url)["instance"] def create_instance(self, region: str, plan: str, **kwargs): - data = {'region': region, 'plan': plan} + data = {"region": region, "plan": plan} data.update(kwargs) - url = f'{self.url}/instances' - return self._post(url, data)['instance'] + url = f"{self.url}/instances" + return self._post(url, data)["instance"] def update_instance(self, instance: Union[str, dict], **kwargs): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}' - return self._patch(url, kwargs)['instance'] + url = f"{self.url}/instances/{instance_id}" + return self._patch(url, kwargs)["instance"] def delete_instance(self, instance: Union[str, dict]): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}' + url = f"{self.url}/instances/{instance_id}" return self._delete(url) def list_keys(self): - url = f'{self.url}/ssh-keys' - return self._get(url)['ssh_keys'] + url = f"{self.url}/ssh-keys" + return self._get(url)["ssh_keys"] def get_key(self, key: Union[str, dict]): key_id = self._get_obj_key(key) - url = f'{self.url}/ssh-keys/{key_id}' - return self._get(url)['ssh_key'] + url = f"{self.url}/ssh-keys/{key_id}" + return self._get(url)["ssh_key"] def create_key(self, name: str, key: str, **kwargs): - data = {'name': name, 'ssh_key': key} + data = {"name": name, "ssh_key": key} data.update(kwargs) - url = f'{self.url}/ssh-keys' - return self._post(url, data)['ssh_key'] + url = f"{self.url}/ssh-keys" + return self._post(url, data)["ssh_key"] def update_key(self, key: Union[str, dict], **kwargs): key_id = self._get_obj_key(key) - url = f'{self.url}/ssh-keys/{key_id}' - return self._patch(url, kwargs)['ssh_key'] + url = f"{self.url}/ssh-keys/{key_id}" + return self._patch(url, kwargs)["ssh_key"] def delete_key(self, key: Union[str, dict]): key_id = self._get_obj_key(key) - url = f'{self.url}/ssh-keys/{key_id}' + url = f"{self.url}/ssh-keys/{key_id}" return self._delete(url) def list_scripts(self): - url = f'{self.url}/startup-scripts' - return self._get(url)['startup_scripts'] + url = f"{self.url}/startup-scripts" + return self._get(url)["startup_scripts"] def get_script(self, script: Union[str, dict]): script_id = self._get_obj_key(script) - url = f'{self.url}/startup-scripts/{script_id}' - return self._get(url)['startup_script'] + url = f"{self.url}/startup-scripts/{script_id}" + return self._get(url)["startup_script"] def create_script(self, name: str, script: str, **kwargs): - data = {'name': name, 'script': script} + data = {"name": name, "script": script} data.update(kwargs) - url = f'{self.url}/startup-scripts' - return self._post(url, data)['startup_script'] + url = f"{self.url}/startup-scripts" + return self._post(url, data)["startup_script"] def update_script(self, script: Union[str, dict], **kwargs): script_id = self._get_obj_key(script) - url = f'{self.url}/startup-scripts/{script_id}' - return self._patch(url, kwargs)['startup_script'] + url = f"{self.url}/startup-scripts/{script_id}" + return self._patch(url, kwargs)["startup_script"] def delete_script(self, script: Union[str, dict]): script_id = self._get_obj_key(script) - url = f'{self.url}/startup-scripts/{script_id}' + url = f"{self.url}/startup-scripts/{script_id}" return self._delete(url) def list_ipv4(self, instance: Union[str, dict]): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}/ipv4' - return self._get(url)['ipv4s'] + url = f"{self.url}/instances/{instance_id}/ipv4" + return self._get(url)["ipv4s"] def create_ipv4(self, instance: Union[str, dict], **kwargs): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}/ipv4' - return self._post(url, kwargs)['ipv4'] + url = f"{self.url}/instances/{instance_id}/ipv4" + return self._post(url, kwargs)["ipv4"] def delete_ipv4(self, instance: Union[str, dict]): instance_id = self._get_obj_key(instance) - url = f'{self.url}/instances/{instance_id}/ipv4' + url = f"{self.url}/instances/{instance_id}/ipv4" return self._delete(url) @staticmethod def filter_keys(keys: list, name: str) -> dict: try: - return next(d for d in keys if d['name'].lower() == name.lower()) + return next(d for d in keys if d["name"].lower() == name.lower()) except StopIteration: return {} @staticmethod def filter_os(os_list: list, name: str) -> dict: try: - return next(d for d in os_list if d['name'].lower() == name.lower()) + return next(d for d in os_list if d["name"].lower() == name.lower()) except StopIteration: return {} @staticmethod def filter_scripts(scripts: list, name: str) -> dict: try: - return next(d for d in scripts if d['name'].lower() == name.lower()) + return next(d for d in scripts if d["name"].lower() == name.lower()) except StopIteration: return {} @staticmethod def filter_regions(regions: list, locations: list) -> list: - return [d for d in regions if d['id'] in locations] + return [d for d in regions if d["id"] in locations] def _get(self, url): r = self.s.get(url, timeout=10) @@ -167,7 +168,7 @@ def _delete(self, url): return None @staticmethod - def _get_obj_key(obj, key='id'): + def _get_obj_key(obj, key="id"): if isinstance(obj, str): return obj elif isinstance(obj, int): @@ -176,4 +177,4 @@ def _get_obj_key(obj, key='id'): if key in obj: return obj[key] else: - raise ValueError(f'Unable to parse object: {key}') + raise ValueError(f"Unable to parse object: {key}") From d9c5c509203a8951cf70adf352689816fff3f241 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:38:46 -0800 Subject: [PATCH 02/17] Update Project --- .github/workflows/preview.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml index 15dab80..a791da5 100644 --- a/.github/workflows/preview.yaml +++ b/.github/workflows/preview.yaml @@ -18,12 +18,11 @@ jobs: name: "Build" if: ${{ !contains(github.event.head_commit.message, '#nopreview') }} uses: ./.github/workflows/docs.yaml + secrets: inherit permissions: contents: read with: name: artifact - secrets: - webhook: ${{ secrets.DISCORD_WEBHOOK }} deploy: name: "Deploy" From a5b835b2d935cad3f740d72ba61e003c701b6418 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:49:13 -0800 Subject: [PATCH 03/17] Update build.yaml --- .github/workflows/build.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7e712b0..92a7c85 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -55,8 +55,13 @@ jobs: env: path: ${{ inputs.path }} run: | - ls -lAh ${path}/* - results="$(ls -lAh ${path}/* | awk '{print $9" - "$5}')" + echo "::group::ls" + ls -lAhR "${path}" + echo "::endgroup::" + echo "::group::tree" + tree "${path}" + echo "::endgroup::" + results="$(tree "${path}")" markdown='Artifacts:\n```text\n'"${results}"'\n```' echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY From fe70bf527f3ff27e1419626b58fee70fadd1b83f Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:58:29 -0800 Subject: [PATCH 04/17] Update WFs --- .github/workflows/pages.yaml | 1 + .github/workflows/preview.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index d204eed..e2d346e 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -5,6 +5,7 @@ on: push: branches: [master] paths: + - ".github/workflows/docs.yaml" - ".github/workflows/pages.yaml" - "docs/**" - "src/**" diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml index a791da5..465f3f1 100644 --- a/.github/workflows/preview.yaml +++ b/.github/workflows/preview.yaml @@ -5,6 +5,7 @@ on: push: branches-ignore: [master] paths: + - ".github/workflows/docs.yaml" - ".github/workflows/preview.yaml" - "docs/**" - "src/**" From aaf84f186ae12420d38830cbca101f60a8a39eef Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sat, 22 Nov 2025 22:00:37 -0800 Subject: [PATCH 05/17] Update WFs --- .github/workflows/docs.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 63ec273..3d70022 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -45,8 +45,13 @@ jobs: env: path: ${{ inputs.path }} run: | - ls -lAh ${path}/* - results="$(ls -lAh ${path}/* | awk '{print $9" - "$5}')" + echo "::group::ls" + ls -lAhR "${path}" + echo "::endgroup::" + echo "::group::tree" + tree "${path}" + echo "::endgroup::" + results="$(tree "${path}")" markdown='Artifacts:\n```text\n'"${results}"'\n```' echo -e "${markdown}" >> $GITHUB_STEP_SUMMARY From 516648ffa0aa50c6d489a35f0988ffcc000805cb Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 00:19:40 -0800 Subject: [PATCH 06/17] Update Docs --- .github/workflows/docs.yaml | 26 +++++++++++++++++++++++--- .github/workflows/lint.yaml | 1 - README.md | 4 +++- docs/module.html.jinja2 | 2 ++ src/vultr/__init__.py | 6 ++++++ 5 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 docs/module.html.jinja2 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 3d70022..0e081e7 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -12,6 +12,10 @@ on: type: string default: site +env: + logo: "https://raw.githubusercontent.com/smashedr/repo-images/refs/heads/master/vultr-python/logo128.png" + link: ${{ github.event.repository.html_url }} + jobs: build: name: "Build" @@ -22,6 +26,18 @@ jobs: - name: "Checkout" uses: actions/checkout@v5 + - name: "Debug CTX github" + continue-on-error: true + env: + GITHUB_CTX: ${{ toJSON(github) }} + run: echo "$GITHUB_CTX" + + - name: "Debug" + continue-on-error: true + run: | + echo "logo: ${{ env.logo }}" + echo "link: ${{ env.link }}" + - name: "Setup Python 3.13" uses: actions/setup-python@v6 with: @@ -33,12 +49,16 @@ jobs: python -m pip install -U pip python -m pip install -U pdoc python -m pip install --group dev - python -m pdoc -o "${{ inputs.path }}" -t docs src/vultr/vultr.py + python -m pdoc -t docs -o "${{ inputs.path }}" \ + --favicon "${{ env.logo }}" \ + --logo "${{ env.logo }}" \ + --logo-link "${{ env.link }}" \ + vultr - name: "Update Permissions" run: | - chmod -c -R +rX "${{ inputs.path }}" | while read line; do - echo "::notice::Fixed invalid file permissions: ${line}" + chmod -c -R +rX "${{ inputs.path }}" | while read name; do + echo "::notice::Fixed invalid file permissions: ${name}" done - name: "List Artifacts" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index fa59d14..7dfc8cd 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -66,7 +66,6 @@ jobs: python -m pip list - name: "Debug" - if: ${{ !github.event.act }} continue-on-error: true run: | python -V diff --git a/README.md b/README.md index d4756fc..8331e2a 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,12 @@ [![GitHub Org Stars](https://img.shields.io/github/stars/cssnr?style=flat&logo=github&label=org%20stars)](https://cssnr.github.io/) [![Discord](https://img.shields.io/discord/899171661457293343?logo=discord&logoColor=white&label=discord&color=7289da)](https://discord.gg/wXy6m2X8wY) [![Ko-fi](https://img.shields.io/badge/Ko--fi-72a5f2?logo=kofi&label=support)](https://ko-fi.com/cssnr) -[![](https://repository-images.githubusercontent.com/441314848/513fb2f4-39cb-4bbc-8d47-a2cde9ccbd65)](https://www.vultr.com/?ref=6905748) # Vultr Python + +Vultr Python + - [Install](#Install) - [Usage](#Usage) - [Support](#Support) diff --git a/docs/module.html.jinja2 b/docs/module.html.jinja2 new file mode 100644 index 0000000..229f2a8 --- /dev/null +++ b/docs/module.html.jinja2 @@ -0,0 +1,2 @@ +{% extends "default/module.html.jinja2" %} +{% block title %}Vultr Python{% endblock %} diff --git a/src/vultr/__init__.py b/src/vultr/__init__.py index 706f507..ef9c667 100644 --- a/src/vultr/__init__.py +++ b/src/vultr/__init__.py @@ -1,3 +1,9 @@ +""" +.. include:: ../../README.md + :start-line: 41 + :end-line: 109 +""" + from .vultr import Vultr From b84e16e51812bf90e8100478ac67e3b67137dfb2 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 00:21:33 -0800 Subject: [PATCH 07/17] Update Docs --- .github/workflows/docs.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 0e081e7..664856a 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -48,7 +48,8 @@ jobs: run: | python -m pip install -U pip python -m pip install -U pdoc - python -m pip install --group dev + #python -m pip install --group dev + python -m pip install . python -m pdoc -t docs -o "${{ inputs.path }}" \ --favicon "${{ env.logo }}" \ --logo "${{ env.logo }}" \ From 1987bdb6a69c5bd6cd67f836d0ae3cbfb4729262 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 00:25:01 -0800 Subject: [PATCH 08/17] Update Docs --- .github/workflows/docs.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 664856a..21272c5 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -48,8 +48,7 @@ jobs: run: | python -m pip install -U pip python -m pip install -U pdoc - #python -m pip install --group dev - python -m pip install . + python -m pip install -e . python -m pdoc -t docs -o "${{ inputs.path }}" \ --favicon "${{ env.logo }}" \ --logo "${{ env.logo }}" \ From 9d6049ba7d502d3e79e73a25997ac81596b857ac Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 01:19:40 -0800 Subject: [PATCH 09/17] Update Docs --- docs/index.md | 88 +++++++++++++++++++++++++++++++++++++++++++ src/vultr/__init__.py | 4 +- 2 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 docs/index.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..1bf3e22 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,88 @@ +[![PyPI Version](https://img.shields.io/pypi/v/vultr-python?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) +[![PyPI Downloads](https://img.shields.io/pypi/dm/vultr-python?logo=pypi&logoColor=white)](https://pypistats.org/packages/vultr-python) +[![Pepy Total Downloads](https://img.shields.io/pepy/dt/vultr-python?logo=pypi&logoColor=white&label=total)](https://clickpy.clickhouse.com/dashboard/vultr-python) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9b356c4327df41e395c81de1c717ce11)](https://app.codacy.com/gh/cssnr/vultr-python/dashboard) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cssnr_vultr-python&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python) +[![GitHub Contributors](https://img.shields.io/github/contributors-anon/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/graphs/contributors) +[![GitHub Discussions](https://img.shields.io/github/discussions/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/discussions) +[![GitHub Forks](https://img.shields.io/github/forks/cssnr/vultr-python?style=flat&logo=github)](https://github.com/cssnr/vultr-python/forks) +[![GitHub Repo Stars](https://img.shields.io/github/stars/cssnr/vultr-python?style=flat&logo=github)](https://github.com/cssnr/vultr-python/stargazers) +[![GitHub Org Stars](https://img.shields.io/github/stars/cssnr?style=flat&logo=github&label=org%20stars)](https://cssnr.github.io/) +[![Discord](https://img.shields.io/discord/899171661457293343?logo=discord&logoColor=white&label=discord&color=7289da)](https://discord.gg/wXy6m2X8wY) +[![Ko-fi](https://img.shields.io/badge/Ko--fi-72a5f2?logo=kofi&label=support)](https://ko-fi.com/cssnr) + +Python 3 wrapper for the [Vultr API v2](https://www.vultr.com/api/?ref=6905748). + +[Jump to the API Documentation](#Vultr) + +## Install + +From PyPi: https://pypi.org/project/vultr-python + +```text +python -m pip install vultr-python +``` + +From Source: + +```text +git clone https://github.com/cssnr/vultr-python.git +python -m pip install vultr-python +``` + +## Usage + +You will need to create an api key and whitelist your IP address. + +- [https://my.vultr.com/settings/#settingsapi](https://my.vultr.com/settings/#settingsapi) + +Initialize the class with your API Key or with the `VULTR_API_KEY` environment variable. + +```python +from vultr import Vultr + +vultr = Vultr('VULTR_API_KEY') +``` + +List plans and get available regions for that plan + +```python +plans = vultr.list_plans() +plan = plans[0] # 0 seems to be the basic 5 dollar plan +regions = vultr.list_regions() +available = vultr.filter_regions(regions, plan['locations']) +``` + +Get the OS list and filter by name + +```python +os_list = vultr.list_os() +ubuntu_lts = vultr.filter_os(os_list, 'Ubuntu 20.04 x64') +``` + +Create a new ssh key from key string + +```python +sshkey = vultr.create_key('key-name', 'ssh-rsa AAAA...') +``` + +Create a new instance + +```python +hostname = 'my-new-host' +data = { + 'region': available[0]['id'], + 'plan': plan['id'], + 'os_id': ubuntu_lts['id'], + 'sshkey_id': [sshkey['id']], + 'hostname': hostname, + 'label': hostname, +} +instance = vultr.create_instance(**data) +``` + +  + +Vultr API Reference: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) + +--- diff --git a/src/vultr/__init__.py b/src/vultr/__init__.py index ef9c667..6cc4cfb 100644 --- a/src/vultr/__init__.py +++ b/src/vultr/__init__.py @@ -1,7 +1,5 @@ """ -.. include:: ../../README.md - :start-line: 41 - :end-line: 109 +.. include:: ../../docs/index.md """ from .vultr import Vultr From e6a3c099ee00c3eb649e47cd8185988509dede85 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 01:28:27 -0800 Subject: [PATCH 10/17] Lint --- .github/workflows/pages.yaml | 4 +--- src/vultr/version.py | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index e2d346e..be6a19f 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -13,12 +13,10 @@ on: jobs: build: name: "Build" - if: ${{ !contains(github.event.head_commit.message, '#nopreview') }} uses: ./.github/workflows/docs.yaml + secrets: inherit permissions: contents: read - secrets: - webhook: ${{ secrets.DISCORD_WEBHOOK }} deploy: name: "Deploy" diff --git a/src/vultr/version.py b/src/vultr/version.py index 1edcd39..bf9d384 100644 --- a/src/vultr/version.py +++ b/src/vultr/version.py @@ -10,4 +10,3 @@ def get_version() -> str: __version__ = get_version() - From c9f9e8a3041e270f5fdd513d9f2e221e771164f8 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 01:36:23 -0800 Subject: [PATCH 11/17] Cleanup --- README.md | 15 ++++++++------- build.ps1 | 48 ------------------------------------------------ docs/index.md | 2 +- 3 files changed, 9 insertions(+), 56 deletions(-) delete mode 100644 build.ps1 diff --git a/README.md b/README.md index 8331e2a..dcaf995 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,12 @@ Python 3 wrapper for the Vultr API v2. > [!TIP] > This project is not complete, but has many useful functions. -> Please submit a [Feature Request](https://github.com/cssnr/vultr-python/discussions/categories/feature-requests) or report any [Issues](https://github.com/cssnr/vultr-python/issues). +> Please submit a [Feature Request](https://github.com/cssnr/vultr-python/discussions/categories/feature-requests) +> or report any [Issues](https://github.com/cssnr/vultr-python/issues). ## Install -From PyPi: https://pypi.org/project/vultr-python +From PyPi: ```text python -m pip install vultr-python @@ -115,15 +116,15 @@ View the Vultr API documentation at: [https://www.vultr.com/api](https://www.vul For general help or to request a feature, see: -- Q&A Discussion: https://github.com/cssnr/vultr-python/discussions/categories/q-a -- Request a Feature: https://github.com/cssnr/vultr-python/discussions/categories/feature-requests -- Chat with us on Discord: https://discord.gg/wXy6m2X8wY +- Q&A Discussion: +- Request a Feature: +- Chat with us on Discord: If you are experiencing an issue/bug or getting unexpected results, you can: -- Report an Issue: https://github.com/cssnr/vultr-python/issues +- Report an Issue: - Provide General Feedback: [https://cssnr.github.io/feedback/](https://cssnr.github.io/feedback/?app=vultr-python) -- Chat with us on Discord: https://discord.gg/wXy6m2X8wY +- Chat with us on Discord: # Contributing diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index 5db65bf..0000000 --- a/build.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -param ( - [switch]$c, - [switch]$i, - [switch]$u -) - -$ErrorActionPreference = "Stop" - -write-output "Clean: $c" -write-output "Install: $i" -write-output "Uninstall: $u" - -if ($u) { - Write-Host -ForegroundColor Red "Uninstalling..." - python -m pip uninstall -y vultr-python -} - -$egg_dir = ".\src\*.egg-info" -if (Test-Path $egg_dir) { - Write-Host -ForegroundColor Cyan "Removing: $egg_dir" - Remove-Item -Force -Recurse $egg_dir -} -$cache_dir = ".\src\*\__pycache__" -if (Test-Path $cache_dir) { - Write-Host -ForegroundColor Cyan "Removing: $cache_dir" - Remove-Item -Force -Recurse $cache_dir -} -if (Test-Path ".\dist") { - Write-Host -ForegroundColor Cyan "Removing: .\dist" - Remove-Item -Force -Recurse ".\dist" -} -if (Test-Path ".\build") { - Write-Host -ForegroundColor Cyan "Removing: .\build" - Remove-Item -Force -Recurse ".\build" -} -if ($c) { - Write-Host -ForegroundColor Yellow "Clean Only. Not Building or Installing!" - exit -} - -python -m build - -if ($args[0] -eq "i") { - Write-Host -ForegroundColor Green "Installing..." - python -m pip install .\dist\vultr_python-0.0.1-py3-none-any.whl -} - -Write-Output "Success." diff --git a/docs/index.md b/docs/index.md index 1bf3e22..f88478e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,7 +17,7 @@ Python 3 wrapper for the [Vultr API v2](https://www.vultr.com/api/?ref=6905748). ## Install -From PyPi: https://pypi.org/project/vultr-python +From PyPi: ```text python -m pip install vultr-python From 5b5a4ca61c9ed461414d8341cbb29d280d556941 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 01:40:43 -0800 Subject: [PATCH 12/17] Cleanup --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index dcaf995..7f0c869 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ [![PyPI Version](https://img.shields.io/pypi/v/vultr-python?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) -[![GitHub Release Version](https://img.shields.io/github/v/release/cssnr/vultr-python?logo=github)](https://github.com/cssnr/vultr-python/releases) [![TOML Python Version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fcssnr%2Fvultr-python%2Frefs%2Fheads%2Fmaster%2Fpyproject.toml&query=%24.project.requires-python&logo=python&logoColor=white&label=python)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) [![PyPI Downloads](https://img.shields.io/pypi/dm/vultr-python?logo=pypi&logoColor=white)](https://pypistats.org/packages/vultr-python) [![Pepy Total Downloads](https://img.shields.io/pepy/dt/vultr-python?logo=pypi&logoColor=white&label=total)](https://clickpy.clickhouse.com/dashboard/vultr-python) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9b356c4327df41e395c81de1c717ce11)](https://app.codacy.com/gh/cssnr/vultr-python/dashboard) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cssnr_vultr-python&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python) [![Workflow Lint](https://img.shields.io/github/actions/workflow/status/cssnr/vultr-python/lint.yaml?logo=cachet&label=lint)](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml) -[![Workflow Release](https://img.shields.io/github/actions/workflow/status/cssnr/vultr-python/release.yaml?logo=cachet&label=release)](https://github.com/cssnr/vultr-python/actions/workflows/release.yaml) [![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/pypi?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) [![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/github-pages?logo=materialformkdocs&logoColor=white&label=github-pages)](https://cssnr.github.io/vultr-python) [![GitHub Last Commit](https://img.shields.io/github/last-commit/cssnr/vultr-python?logo=github&label=updated)](https://github.com/cssnr/vultr-python/graphs/commit-activity) From 9cdb88068808917b6462fac93fec9f0dcfa5b7c4 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:00:19 -0800 Subject: [PATCH 13/17] Add Badge Links --- README.md | 15 +++++++++------ docs/index.md | 8 ++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7f0c869..a51dfc3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9b356c4327df41e395c81de1c717ce11)](https://app.codacy.com/gh/cssnr/vultr-python/dashboard) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cssnr_vultr-python&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python) [![Workflow Lint](https://img.shields.io/github/actions/workflow/status/cssnr/vultr-python/lint.yaml?logo=cachet&label=lint)](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml) -[![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/pypi?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/vultr-python/) [![GitHub Deployments](https://img.shields.io/github/deployments/cssnr/vultr-python/github-pages?logo=materialformkdocs&logoColor=white&label=github-pages)](https://cssnr.github.io/vultr-python) [![GitHub Last Commit](https://img.shields.io/github/last-commit/cssnr/vultr-python?logo=github&label=updated)](https://github.com/cssnr/vultr-python/graphs/commit-activity) [![GitHub Repo Size](https://img.shields.io/github/repo-size/cssnr/vultr-python?logo=bookstack&logoColor=white&label=repo%20size)](https://github.com/cssnr/vultr-python) @@ -30,15 +29,19 @@ Python 3 wrapper for the Vultr API v2. -- Vultr: [https://www.vultr.com](https://www.vultr.com/?ref=6905748) -- Vultr API: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) -- Vultr Python Docs: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) +[![PyPi](https://img.shields.io/badge/pypi-006dad?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/vultr-python) +[![Docs](https://img.shields.io/badge/docs-198754?style=for-the-badge&logo=mdbook)](https://cssnr.github.io/vultr-python) +[![Vultr](https://img.shields.io/badge/vultr-007bfc?style=for-the-badge&logo=vultr)](https://www.vultr.com/api/?ref=6905748) + +Vultr API Reference: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) > [!TIP] > This project is not complete, but has many useful functions. > Please submit a [Feature Request](https://github.com/cssnr/vultr-python/discussions/categories/feature-requests) > or report any [Issues](https://github.com/cssnr/vultr-python/issues). +For more details visit [vultr.com](https://www.vultr.com/?ref=6905748) or checkout the [Vultr Pricing](https://www.vultr.com/pricing/). + ## Install From PyPi: @@ -106,9 +109,9 @@ data = { instance = vultr.create_instance(**data) ``` -View all functions on the documentation site: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) +Full Documentation: [https://cssnr.github.io/vultr-python](https://cssnr.github.io/vultr-python) -View the Vultr API documentation at: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) +Vultr API Reference: [https://www.vultr.com/api](https://www.vultr.com/api/?ref=6905748) # Support diff --git a/docs/index.md b/docs/index.md index f88478e..196e055 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,7 +13,11 @@ Python 3 wrapper for the [Vultr API v2](https://www.vultr.com/api/?ref=6905748). -[Jump to the API Documentation](#Vultr) +[![GitHub](https://img.shields.io/badge/github-232925?style=for-the-badge&logo=github)](https://github.com/cssnr/vultr-python) +[![PyPi](https://img.shields.io/badge/pypi-006dad?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/vultr-python) +[![Docs](https://img.shields.io/badge/vultr-007bfc?style=for-the-badge&logo=vultr)](https://www.vultr.com/api/?ref=6905748) + +[⬇️ Jump to the API Documentation](#Vultr) ## Install @@ -32,7 +36,7 @@ python -m pip install vultr-python ## Usage -You will need to create an api key and whitelist your IP address. +You will need to create an api key and whitelist your IP address. Most functions do not work without an API Key. - [https://my.vultr.com/settings/#settingsapi](https://my.vultr.com/settings/#settingsapi) From 42b4b3fd0c7f69d4551c01267963f9102bbc6187 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:26:44 -0800 Subject: [PATCH 14/17] Update Badges --- README.md | 1 + docs/index.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a51dfc3..ef847a9 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Python 3 wrapper for the Vultr API v2. +[![GitHub](https://img.shields.io/badge/github-232925?style=for-the-badge&logo=github)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) [![PyPi](https://img.shields.io/badge/pypi-006dad?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/vultr-python) [![Docs](https://img.shields.io/badge/docs-198754?style=for-the-badge&logo=mdbook)](https://cssnr.github.io/vultr-python) [![Vultr](https://img.shields.io/badge/vultr-007bfc?style=for-the-badge&logo=vultr)](https://www.vultr.com/api/?ref=6905748) diff --git a/docs/index.md b/docs/index.md index 196e055..f982dec 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,9 +13,10 @@ Python 3 wrapper for the [Vultr API v2](https://www.vultr.com/api/?ref=6905748). -[![GitHub](https://img.shields.io/badge/github-232925?style=for-the-badge&logo=github)](https://github.com/cssnr/vultr-python) +[![GitHub](https://img.shields.io/badge/github-232925?style=for-the-badge&logo=github)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) [![PyPi](https://img.shields.io/badge/pypi-006dad?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/vultr-python) -[![Docs](https://img.shields.io/badge/vultr-007bfc?style=for-the-badge&logo=vultr)](https://www.vultr.com/api/?ref=6905748) +[![Docs](https://img.shields.io/badge/docs-198754?style=for-the-badge&logo=mdbook)](#Vultr) +[![Vultr](https://img.shields.io/badge/vultr-007bfc?style=for-the-badge&logo=vultr)](https://www.vultr.com/api/?ref=6905748) [⬇️ Jump to the API Documentation](#Vultr) From 30150440449526908dec42fe21d95f16e959db6b Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:42:14 -0800 Subject: [PATCH 15/17] Codacy is Retarded --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5702a98..08b9fdc 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,3 @@ coverage.xml site/ .cache/ # App -_site/ From ab44373b2802904960af90e24abb0fa18339a2cc Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:49:41 -0800 Subject: [PATCH 16/17] Updates --- README.md | 2 +- docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ef847a9..198deaf 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Vultr API Reference: [https://www.vultr.com/api](https://www.vultr.com/api/?ref= > Please submit a [Feature Request](https://github.com/cssnr/vultr-python/discussions/categories/feature-requests) > or report any [Issues](https://github.com/cssnr/vultr-python/issues). -For more details visit [vultr.com](https://www.vultr.com/?ref=6905748) or checkout the [Vultr Pricing](https://www.vultr.com/pricing/). +For more details visit [www.vultr.com](https://www.vultr.com/?ref=6905748). ## Install diff --git a/docs/index.md b/docs/index.md index f982dec..c27277d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ [![Discord](https://img.shields.io/discord/899171661457293343?logo=discord&logoColor=white&label=discord&color=7289da)](https://discord.gg/wXy6m2X8wY) [![Ko-fi](https://img.shields.io/badge/Ko--fi-72a5f2?logo=kofi&label=support)](https://ko-fi.com/cssnr) -Python 3 wrapper for the [Vultr API v2](https://www.vultr.com/api/?ref=6905748). +Python 3 wrapper for the [Vultr](https://www.vultr.com/?ref=6905748) API v2. [![GitHub](https://img.shields.io/badge/github-232925?style=for-the-badge&logo=github)](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme) [![PyPi](https://img.shields.io/badge/pypi-006dad?style=for-the-badge&logo=pypi&logoColor=white)](https://pypi.org/project/vultr-python) From 066bb5d5e671d483a53491b2aac4a6ca4a0c632b Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Sun, 23 Nov 2025 14:30:57 -0800 Subject: [PATCH 17/17] Add .gitattributes --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..217ed8e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +docs/syntax-highlighting.css linguist-generated +docs/theme.css linguist-generated