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 @@
-[](https://discord.gg/wXy6m2X8wY)
+[](https://pypi.org/project/vultr-python/)
+[](https://github.com/cssnr/vultr-python/releases)
+[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
+[](https://pypistats.org/packages/vultr-python)
+[](https://clickpy.clickhouse.com/dashboard/vultr-python)
[](https://app.codacy.com/gh/cssnr/vultr-python/dashboard)
-[](https://pypi.org/project/vultr-python/)
+[](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python)
+[](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml)
+[](https://github.com/cssnr/vultr-python/actions/workflows/release.yaml)
+[](https://pypi.org/project/vultr-python/)
+[](https://cssnr.github.io/vultr-python)
+[](https://github.com/cssnr/vultr-python/graphs/commit-activity)
+[](https://github.com/cssnr/vultr-python)
+[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
+[](https://github.com/cssnr/vultr-python/graphs/contributors)
+[](https://github.com/cssnr/vultr-python/discussions)
+[](https://github.com/cssnr/vultr-python/forks)
+[](https://github.com/cssnr/vultr-python/stargazers)
+[](https://cssnr.github.io/)
+[](https://discord.gg/wXy6m2X8wY)
+[](https://ko-fi.com/cssnr)
[](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)
+[](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 @@
[](https://cssnr.github.io/)
[](https://discord.gg/wXy6m2X8wY)
[](https://ko-fi.com/cssnr)
-[](https://www.vultr.com/?ref=6905748)
# 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 @@
+[](https://pypi.org/project/vultr-python/)
+[](https://pypistats.org/packages/vultr-python)
+[](https://clickpy.clickhouse.com/dashboard/vultr-python)
+[](https://app.codacy.com/gh/cssnr/vultr-python/dashboard)
+[](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python)
+[](https://github.com/cssnr/vultr-python/graphs/contributors)
+[](https://github.com/cssnr/vultr-python/discussions)
+[](https://github.com/cssnr/vultr-python/forks)
+[](https://github.com/cssnr/vultr-python/stargazers)
+[](https://cssnr.github.io/)
+[](https://discord.gg/wXy6m2X8wY)
+[](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 @@
[](https://pypi.org/project/vultr-python/)
-[](https://github.com/cssnr/vultr-python/releases)
[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
[](https://pypistats.org/packages/vultr-python)
[](https://clickpy.clickhouse.com/dashboard/vultr-python)
[](https://app.codacy.com/gh/cssnr/vultr-python/dashboard)
[](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python)
[](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml)
-[](https://github.com/cssnr/vultr-python/actions/workflows/release.yaml)
[](https://pypi.org/project/vultr-python/)
[](https://cssnr.github.io/vultr-python)
[](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 @@
[](https://app.codacy.com/gh/cssnr/vultr-python/dashboard)
[](https://sonarcloud.io/summary/new_code?id=cssnr_vultr-python)
[](https://github.com/cssnr/vultr-python/actions/workflows/lint.yaml)
-[](https://pypi.org/project/vultr-python/)
[](https://cssnr.github.io/vultr-python)
[](https://github.com/cssnr/vultr-python/graphs/commit-activity)
[](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)
+[](https://pypi.org/project/vultr-python)
+[](https://cssnr.github.io/vultr-python)
+[](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)
+[](https://github.com/cssnr/vultr-python)
+[](https://pypi.org/project/vultr-python)
+[](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.
+[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
[](https://pypi.org/project/vultr-python)
[](https://cssnr.github.io/vultr-python)
[](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).
-[](https://github.com/cssnr/vultr-python)
+[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
[](https://pypi.org/project/vultr-python)
-[](https://www.vultr.com/api/?ref=6905748)
+[](#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 @@
[](https://discord.gg/wXy6m2X8wY)
[](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.
[](https://github.com/cssnr/vultr-python?tab=readme-ov-file#readme)
[](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