diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 94248a4..e1e67ba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,7 +30,7 @@ on:
- main
env:
- VERSION_NUMBER: 'v1.5.2'
+ VERSION_NUMBER: 'v1.6.0'
DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli'
AWS_REGION: 'us-west-2'
@@ -147,7 +147,7 @@ jobs:
working-directory: packages
run: |
cloudsmith push deb \
- digitalghost-dev/poke-cli/debian/trixie \
+ digitalghost-dev/poke-cli/debian/bookworm \
poke-cli_${{ env.VERSION_NUMBER }}_linux_${{ matrix.arch }}.deb
upload-rpm-packages:
@@ -226,27 +226,11 @@ jobs:
fi
echo "✅ All packages uploaded successfully! ✅"
- lint-cli-dockerfile:
+ build-docs-docker-image:
runs-on: ubuntu-22.04
needs: [ gosec ]
if: needs.gosec.result == 'success'
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Lint Dockerfile
- uses: 'hadolint/hadolint-action@v3.1.0'
- with:
- dockerfile: Dockerfile
- failure-threshold: 'error'
-
-
- build-docs-docker-image:
- runs-on: ubuntu-22.04
- needs: [ lint-cli-dockerfile ]
- if: needs.lint-cli-dockerfile.result == 'success'
-
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -310,11 +294,26 @@ jobs:
docker tag docs:latest ${{ secrets.AWS_DOCS_ECR_NAME }}:latest
docker push ${{ secrets.AWS_DOCS_ECR_NAME }}:latest
- build-cli-docker-image:
+ lint-cli-dockerfile:
runs-on: ubuntu-22.04
- needs: [gosec]
+ needs: [ gosec ]
if: needs.gosec.result == 'success'
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Lint Dockerfile
+ uses: 'hadolint/hadolint-action@v3.1.0'
+ with:
+ dockerfile: Dockerfile
+ failure-threshold: 'error'
+
+ build-cli-docker-image:
+ runs-on: ubuntu-22.04
+ needs: [ lint-cli-dockerfile ]
+ if: needs.lint-cli-dockerfile.result == 'success'
+
steps:
- name: Checkout
uses: actions/checkout@v4
diff --git a/.gitignore b/.gitignore
index 4dbb8c5..f922e54 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,25 +35,26 @@ card_data/.venv
__pycache__/
# Terraform
-### Ignore CLI configuration files
.terraformrc
terraform.rc
-
**/*.tfvars
**/*.tfvars.json
-
-### Terraform state files
**/*.tfstate
**/*.tfstate.*
-
-### Terraform crash log files
crash.log
crash.*.log
-### .terraform
+# dbt
+card_data/logs/
+dbt_packages/
+logs/
+
+target/
+dbt_packages/
card_data/infrastructure/supabase/access-token
/card_data/infrastructure/supabase/access-token
**/.terraform/
card_data/.tmp*/**
+
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 9496198..46cfe4d 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -14,7 +14,7 @@ builds:
- windows
- darwin
ldflags:
- - -s -w -X main.version=v1.5.2
+ - -s -w -X main.version=v1.6.0
archives:
- formats: [ 'zip' ]
diff --git a/Dockerfile b/Dockerfile
index f54c710..9ea0df2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,7 +8,7 @@ RUN go mod download
COPY . .
-RUN go build -ldflags "-X main.version=v1.5.2" -o poke-cli .
+RUN go build -ldflags "-X main.version=v1.6.0" -o poke-cli .
# build 2
FROM --platform=$BUILDPLATFORM alpine:3.22
diff --git a/README.md b/README.md
index 3b065f9..0ea351b 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Pokémon CLI
-
+
@@ -24,7 +24,7 @@ View future plans in the [Roadmap](#roadmap) section.
---
## Demo
-
+
---
## Installation
@@ -64,11 +64,14 @@ View future plans in the [Roadmap](#roadmap) section.
This package repository is generously hosted by Cloudsmith.
Cloudsmith is a fully cloud-based service that lets you easily create, store, and share packages in any format, anywhere.
-| Package Type | Distributions | Repository Setup | Installation Command |
-|--------------|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
-| `apk` | Alpine | `sudo apk add --no-cache bash && curl -1sLf 'https://dl.cloudsmith.io/basic/digitalghost-dev/poke-cli/setup.alpine.sh' \| sudo -E bash` | `sudo apk add poke-cli=1.5.2 --update-cache` |
-| `deb` | Ubuntu, Debian | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.deb.sh' \| sudo -E bash` | `sudo apt-get install poke-cli=1.5.2` |
-| `rpm` | Fedora, CentOS, Red Hat, openSUSE | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.rpm.sh' \| sudo -E bash` | `sudo yum install poke-cli-1.5.2-1` |
+1. Run the **Repository Setup** script first for the correct Linux distribution.
+2. Run the corresponding **Installation Command** afterward.
+
+| Package Type | Distributions | Repository Setup | Installation Command |
+|:------------:|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
+| `apk` | Alpine | `sudo apk add --no-cache bash && curl -1sLf 'https://dl.cloudsmith.io/basic/digitalghost-dev/poke-cli/setup.alpine.sh' \| sudo -E bash` | `sudo apk add poke-cli --update-cache` |
+| `deb` | Ubuntu, Debian | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.deb.sh' \| sudo -E bash` | `sudo apt-get install poke-cli` |
+| `rpm` | Fedora, CentOS, Red Hat, openSUSE | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.rpm.sh' \| sudo -E bash` | `sudo yum install poke-cli` |
### Docker Image
@@ -83,11 +86,11 @@ Cloudsmith is a fully cloud-based service that lets you easily create, store, an
3. Choose how to interact with the container:
* Run a single command and exit:
```bash
- docker run --rm -it digitalghostdev/poke-cli:v1.5.2
[subcommand] flag]
+ docker run --rm -it digitalghostdev/poke-cli:v1.6.0 [subcommand] flag]
```
* Enter the container and use its shell:
```bash
- docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.5.2 -c "cd /app && exec sh"
+ docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.6.0 -c "cd /app && exec sh"
# placed into the /app directory, run the program with './poke-cli'
# example: ./poke-cli ability swift-swim
```
@@ -181,7 +184,7 @@ Below is a list of the planned/completed commands and flags:
- [x] `natures`: get data about natures.
- [x] `pokemon`: get data about a Pokémon.
- [x] `-a | --abilities`: display the Pokémon's abilities.
- - [ ] `-d | --defense`: display the Pokémon's type defences.
+ - [x] `-d | --defense`: display the Pokémon's type defences.
- [x] `-i | --image`: display a pixel image of the Pokémon.
- [x] `-s | --stats`: display the Pokémon's base stats.
- [x] `-m | --moves`: display learnable moves.
diff --git a/card_data/pyproject.toml b/card_data/pyproject.toml
index f0d43d0..77f5fa5 100644
--- a/card_data/pyproject.toml
+++ b/card_data/pyproject.toml
@@ -10,6 +10,8 @@ dependencies = [
"dagster-dg-cli>=1.11.3",
"dagster-postgres>=0.27.3",
"dagster-webserver>=1.11.3",
+ "dbt-core>=1.10.8",
+ "dbt-postgres>=1.9.0",
"pandas>=2.3.1",
"polars>=1.31.0",
"psycopg2-binary>=2.9.10",
diff --git a/card_data/uv.lock b/card_data/uv.lock
index d7d9130..2979706 100644
--- a/card_data/uv.lock
+++ b/card_data/uv.lock
@@ -2,6 +2,24 @@ version = 1
revision = 2
requires-python = ">=3.12"
+[[package]]
+name = "agate"
+version = "1.9.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "isodate" },
+ { name = "leather" },
+ { name = "parsedatetime" },
+ { name = "python-slugify" },
+ { name = "pytimeparse" },
+ { name = "tzdata", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/29/77/6f5df1c68bf056f5fdefc60ccc616303c6211e71cd6033c830c12735f605/agate-1.9.1.tar.gz", hash = "sha256:bc60880c2ee59636a2a80cd8603d63f995be64526abf3cbba12f00767bcd5b3d", size = 202303, upload-time = "2023-12-21T20:05:24.316Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/53/89b197cb472a3175d73384761a3413fd58e6b65a794c1102d148b8de87bd/agate-1.9.1-py2.py3-none-any.whl", hash = "sha256:1cf329510b3dde07c4ad1740b7587c9c679abc3dcd92bb1107eabc10c2e03c50", size = 95085, upload-time = "2023-12-21T20:05:21.954Z" },
+]
+
[[package]]
name = "alembic"
version = "1.16.4"
@@ -69,6 +87,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/76/2d/f6ffed80e0299b14c5b945d208ba892f2a13270dff7d88f439890b4fd315/aws_secretsmanager_caching-1.1.3-py3-none-any.whl", hash = "sha256:5dd8588520335ca5cc7f5ae5948e5e85f2f5b58c1341bda0db4acf6399806f78", size = 18427, upload-time = "2024-06-20T21:14:41.638Z" },
]
+[[package]]
+name = "babel"
+version = "2.17.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" },
+]
+
[[package]]
name = "backoff"
version = "2.2.1"
@@ -102,6 +129,8 @@ dependencies = [
{ name = "dagster-dg-cli" },
{ name = "dagster-postgres" },
{ name = "dagster-webserver" },
+ { name = "dbt-core" },
+ { name = "dbt-postgres" },
{ name = "pandas" },
{ name = "polars" },
{ name = "psycopg2-binary" },
@@ -127,6 +156,8 @@ requires-dist = [
{ name = "dagster-dg-cli", specifier = ">=1.11.3" },
{ name = "dagster-postgres", specifier = ">=0.27.3" },
{ name = "dagster-webserver", specifier = ">=1.11.3" },
+ { name = "dbt-core", specifier = ">=1.10.8" },
+ { name = "dbt-postgres", specifier = ">=1.9.0" },
{ name = "pandas", specifier = ">=2.3.1" },
{ name = "polars", specifier = ">=1.31.0" },
{ name = "psycopg2-binary", specifier = ">=2.9.10" },
@@ -302,6 +333,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/79/b3/28ac139109d9005ad3f6b6f8976ffede6706a6478e21c889ce36c840918e/cryptography-45.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97", size = 3390016, upload-time = "2025-07-02T13:05:50.811Z" },
]
+[[package]]
+name = "daff"
+version = "1.4.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e1/d0/c0a1374db3afad0f9dfe6c795e5df102af03d49ad5e6e8502fb09eb88110/daff-1.4.2.tar.gz", hash = "sha256:47f0391eda7e2b5011f7ccac006b9178accb465bcb94a2c9f284257fff5d2686", size = 148251, upload-time = "2025-05-04T19:24:11.521Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/29/fe/d54a874e8d7b88bc03c459f63a993305db50039b734fab751a0466dabfc1/daff-1.4.2-py3-none-any.whl", hash = "sha256:88981a21d065e4378b5c4bd40b975dbfdea9b7ff540071f3bb5e20cc8b3590b5", size = 144922, upload-time = "2025-05-04T19:24:09.999Z" },
+]
+
[[package]]
name = "dagster"
version = "1.11.3"
@@ -475,6 +515,164 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/49/e6/e4cca605a6bb5eb9802062e03efdf26206d13ad36d7bade569f44503f88d/dagster_webserver-1.11.3-py3-none-any.whl", hash = "sha256:38589e97e8076076990d757c528dd5d7e22ac9e4be28ead450020908e8085ddd", size = 12712291, upload-time = "2025-07-24T20:06:21.801Z" },
]
+[[package]]
+name = "dbt-adapters"
+version = "1.16.3"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "agate" },
+ { name = "dbt-common" },
+ { name = "dbt-protos" },
+ { name = "mashumaro", extra = ["msgpack"] },
+ { name = "protobuf" },
+ { name = "pytz" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/1d/08/b9a0f15b6311742317bab7c03c955dc3eae58c3d7092c17581e3e5ea1186/dbt_adapters-1.16.3.tar.gz", hash = "sha256:d49d3e57befaba36edf009e6fe001d95dd0c902e5aa6678df0812dcd905259ff", size = 130177, upload-time = "2025-07-21T23:04:17.544Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c0/54/36267e4067d91bbafed68cc2c524cee8532021c880e7df53c396ea0385d8/dbt_adapters-1.16.3-py3-none-any.whl", hash = "sha256:234af35140ce42753d093ff056d4cd40a7d2d80c062ed9030891494dff9a18b7", size = 167004, upload-time = "2025-07-21T23:04:16.079Z" },
+]
+
+[[package]]
+name = "dbt-common"
+version = "1.27.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "agate" },
+ { name = "colorama" },
+ { name = "dbt-protos" },
+ { name = "deepdiff" },
+ { name = "isodate" },
+ { name = "jinja2" },
+ { name = "jsonschema" },
+ { name = "mashumaro", extra = ["msgpack"] },
+ { name = "pathspec" },
+ { name = "protobuf" },
+ { name = "python-dateutil" },
+ { name = "requests" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c0/b9/0d0e0463a8a5e0bec09a095e68dcdd641e8f9888dc3c1642547f1f829c47/dbt_common-1.27.1.tar.gz", hash = "sha256:1cc5b0579768a03800d90ecd9b5646c9648c970b8f278d85e1760c836007a4db", size = 83971, upload-time = "2025-07-21T20:46:43.534Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/e7/b504d0814a99c0f33ea5d5735692025469dee01468ac1930c963f215635f/dbt_common-1.27.1-py3-none-any.whl", hash = "sha256:9753e8f79d2d648c7716dd9e07dbbdd518ca3c3d101b6d2ee6e423ea9b6a20b5", size = 86084, upload-time = "2025-07-21T20:46:41.917Z" },
+]
+
+[[package]]
+name = "dbt-core"
+version = "1.10.8"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "agate" },
+ { name = "click" },
+ { name = "daff" },
+ { name = "dbt-adapters" },
+ { name = "dbt-common" },
+ { name = "dbt-extractor" },
+ { name = "dbt-protos" },
+ { name = "dbt-semantic-interfaces" },
+ { name = "jinja2" },
+ { name = "jsonschema" },
+ { name = "mashumaro", extra = ["msgpack"] },
+ { name = "networkx" },
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "protobuf" },
+ { name = "pydantic" },
+ { name = "pytz" },
+ { name = "pyyaml" },
+ { name = "requests" },
+ { name = "snowplow-tracker" },
+ { name = "sqlparse" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/36/87/eb0f9913be5fb2651ce0b4307185a5b2a0d903efb02c9fdc80802a0b1b18/dbt_core-1.10.8.tar.gz", hash = "sha256:eb00b7169ea078aa609548258ceebaa5801605a87de33ce14fd6cbc823c9734c", size = 897380, upload-time = "2025-08-12T13:13:51.169Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4b/17/fdc3adfd4af08dfec7f75d7fc5e8c661549f88391fa9a271429433ea3533/dbt_core-1.10.8-py3-none-any.whl", hash = "sha256:117029971a32b78abc598548f63375990a9a5fcec7471aca14182dc2da7e5002", size = 983451, upload-time = "2025-08-12T13:13:49.32Z" },
+]
+
+[[package]]
+name = "dbt-extractor"
+version = "0.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/06/1f7b5d277af4bd7c3ab5065f79407c46a73950f0879fac69e51067c87649/dbt_extractor-0.6.0.tar.gz", hash = "sha256:d6cf08ec793b8bc2bd6e260ef818230ae68a4f71436fa489f08d7db1a52e2ffe", size = 270461, upload-time = "2025-04-07T16:46:30.532Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9f/dd/ec8f9e48e7dd5a52a69cca7907681d1779cf1cc8b02f2aa2acb6a2bf8bb4/dbt_extractor-0.6.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4b6b1e70dde78cb904ca7a8958c2c803e77779b6ce108f4ea7ac479f5700db89", size = 790206, upload-time = "2025-04-07T16:46:05.352Z" },
+ { url = "https://files.pythonhosted.org/packages/03/5f/233f326336aa21fbd9e7268f239a8464af145abd398a360d894c3286699d/dbt_extractor-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dcf14ed245de8df269815ff4c4f555fa72d2621f4fff37c023b8c99d0e421b4f", size = 404381, upload-time = "2025-04-07T16:46:07.471Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/2a/e14c13b9a437780c5712525ce537915b531bba45481fc7102deb4492ff83/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af451633390ac19669d3bde6c79822e657d32f5d903b3388bb00d56333fd52d5", size = 435109, upload-time = "2025-04-07T16:46:09.443Z" },
+ { url = "https://files.pythonhosted.org/packages/58/2e/1ef1cd2b36973bea0a6823a7b7cd1b3db29b61ddebb015ceaea88b9e9347/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05bcfab7ebd70296ceb31742e8333ba66a2c939de44e61a7088bebafa939aaf6", size = 434550, upload-time = "2025-04-07T16:46:10.916Z" },
+ { url = "https://files.pythonhosted.org/packages/40/5a/468a2855181aaee5402efbf9ef757d074cd306eec22bbcd267cdd0edbe94/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71b3f8897138cc6698d313b9a3d0450fd021937ff5463269ee18ed415541781b", size = 470137, upload-time = "2025-04-07T16:46:12.36Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/18/611dceb2fa7ea668471f290f34fec55fa3283e3ee9d0475d964e6ffaff97/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:868af715a6328d7317ce6e4db238f850f660fef13fb36b7ab4cf9163ed5f54ff", size = 524331, upload-time = "2025-04-07T16:46:14.177Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/ad/9dd410d4d95e336ae6b10c53c939bf1ff8e9991e1adb5ea4aefc4a87c445/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c1fd2b083a75e80b13e9874dc9699bfdfddf3baa9b6a8dea48de06d51a082733", size = 517959, upload-time = "2025-04-07T16:46:15.68Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/4f/6994cdfb51c5652fad0c8f9cf5b3ec1816cb10e99ed145eb27e6a9bcc16b/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:311f0d3a4994751c541a4fa303d205727ba90e90c85286c03d3d9284e2bf0bd4", size = 494850, upload-time = "2025-04-07T16:46:17.265Z" },
+ { url = "https://files.pythonhosted.org/packages/df/5e/fad01e18d68ffd09c0f39cdedeed8fcaaea74a8b46d1a944472b5f95b72b/dbt_extractor-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aecfa43f7e6f139e76d47e4e1d7b189655ae19a8cf697686230bacb89a94ae74", size = 442739, upload-time = "2025-04-07T16:46:19.002Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/82/49068ee2b9f38aa34d0f3196bb7b71d11af86630d5ed5cb6626108c97cd6/dbt_extractor-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a5cb810edc60c0486f78cc29739ebda70c81b10a1686861e78addc9f91fcd7de", size = 618014, upload-time = "2025-04-07T16:46:21.571Z" },
+ { url = "https://files.pythonhosted.org/packages/18/c6/cdaf1ac8959d571b5cb3587b8afef9e5fe60b99fe59aca94560808501d8b/dbt_extractor-0.6.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:080fd1edf123926ed97929c65a75874d0fea687ccd5d3ebbc9e81b339f099604", size = 697290, upload-time = "2025-04-07T16:46:23.089Z" },
+ { url = "https://files.pythonhosted.org/packages/94/6d/46bdb9a809c66784fcc19b853311568cfd3041c075f0a578cb7116686841/dbt_extractor-0.6.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1b9ed7b15df983a735f87773f6765db8458680c02fcebbf89df4e238503c0e08", size = 644443, upload-time = "2025-04-07T16:46:24.463Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/02/b111856273e414ac80ef58d2103c9b7c6a5b29b1ec248999d3d5873ada00/dbt_extractor-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:caeaba8d8c813f8e32d586c12615c0c7d6b99bee4f1be845312e80ef731de164", size = 613017, upload-time = "2025-04-07T16:46:25.913Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/de/d1492ab6beaf0a18aee17c7a9562592ac2981e962b4058262f5eb6dabfc5/dbt_extractor-0.6.0-cp39-abi3-win32.whl", hash = "sha256:369dcc3499f160256756585783f1308868076d5a65d0a051348d22da8b90e67d", size = 252721, upload-time = "2025-04-07T16:46:27.295Z" },
+ { url = "https://files.pythonhosted.org/packages/60/36/f5b1c4159fa911607f3a49fcbc535e4783870fd887bc0a1b3ad42587cb73/dbt_extractor-0.6.0-cp39-abi3-win_amd64.whl", hash = "sha256:a79a570fdcb672505ac2bdc12360a2a7aec622ef604d8c607225854ff862518c", size = 277146, upload-time = "2025-04-07T16:46:28.991Z" },
+]
+
+[[package]]
+name = "dbt-postgres"
+version = "1.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "agate" },
+ { name = "dbt-adapters" },
+ { name = "dbt-common" },
+ { name = "dbt-core" },
+ { name = "psycopg2-binary" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/09/24/03eae698e7f0bffb579a120758fcf95cdf7a58caccec79254195b4a1cb4c/dbt_postgres-1.9.0.tar.gz", hash = "sha256:b0574e9e1e66d8a5cd627b1d464ec0278eef7342f0b5babe4f987eee9d02a143", size = 23555, upload-time = "2024-12-09T18:46:56.564Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/30/bb/8e48678036e5f89b49f72c98e41fa41ebe853c219e658cad3797afbc50b9/dbt_postgres-1.9.0-py3-none-any.whl", hash = "sha256:c85d1adb419251ac989e5f720fdbb964aa6c280da7739dc8c48d44e6f45d354a", size = 35182, upload-time = "2024-12-09T18:46:54.414Z" },
+]
+
+[[package]]
+name = "dbt-protos"
+version = "1.0.348"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "protobuf" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a0/73/94a28249678aab925824497284f6bbb5f8e740613c10be6bf66042701aa7/dbt_protos-1.0.348.tar.gz", hash = "sha256:d8834c685c323b1533c1c7fdb5db5636cffab2f1a58515caba54b3dc13a3578b", size = 76628, upload-time = "2025-07-21T20:27:10.353Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c1/d1/90bd370d92db997c635412661e0d0088b64d481f1365088842bb4823ccc0/dbt_protos-1.0.348-py3-none-any.whl", hash = "sha256:5d89171b64058170b39a80fc69abbd344170ac637c5dee90e7b3cbd7b1a43fe4", size = 94035, upload-time = "2025-07-21T20:27:09.015Z" },
+]
+
+[[package]]
+name = "dbt-semantic-interfaces"
+version = "0.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "importlib-metadata" },
+ { name = "jinja2" },
+ { name = "jsonschema" },
+ { name = "more-itertools" },
+ { name = "pydantic" },
+ { name = "python-dateutil" },
+ { name = "pyyaml" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b0/91/c702d8fb143541fda10f5eb7a7a89f34bda38ee043ecb3e3653363d0c5a0/dbt_semantic_interfaces-0.9.0.tar.gz", hash = "sha256:5c921257dce8bb51c9ffb5479f2bdd959e16ebfb98ee833de6daa70788c47271", size = 93865, upload-time = "2025-07-09T20:06:30.454Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b3/82/41708b2b69d5fead88dea5ca0d863d6291da83ca6f1bd19246842d397e2b/dbt_semantic_interfaces-0.9.0-py3-none-any.whl", hash = "sha256:1b54c06ba89190a47a7f0563360930a0cce869e55b484ca09d261ade0e319155", size = 147008, upload-time = "2025-07-09T20:06:32.466Z" },
+]
+
+[[package]]
+name = "deepdiff"
+version = "7.0.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "ordered-set" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/70/10/6f4b0bd0627d542f63a24f38e29d77095dc63d5f45bc1a7b4a6ca8750fa9/deepdiff-7.0.1.tar.gz", hash = "sha256:260c16f052d4badbf60351b4f77e8390bee03a0b516246f6839bc813fb429ddf", size = 421718, upload-time = "2024-04-08T22:59:24.578Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/e6/d27d37dc55dbf40cdbd665aa52844b065ac760c9a02a02265f97ea7a4256/deepdiff-7.0.1-py3-none-any.whl", hash = "sha256:447760081918216aa4fd4ca78a4b6a848b81307b2ea94c810255334b759e1dc3", size = 80825, upload-time = "2024-04-08T22:59:21.885Z" },
+]
+
[[package]]
name = "docstring-parser"
version = "0.17.0"
@@ -737,6 +935,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/eb/427ed2b20a38a4ee29f24dbe4ae2dafab198674fe9a85e3d6adf9e5f5f41/inflect-7.5.0-py3-none-any.whl", hash = "sha256:2aea70e5e70c35d8350b8097396ec155ffd68def678c7ff97f51aa69c1d92344", size = 35197, upload-time = "2024-12-28T17:11:15.931Z" },
]
+[[package]]
+name = "isodate"
+version = "0.6.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "six" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/7a/c0a56c7d56c7fa723988f122fa1f1ccf8c5c4ccc48efad0d214b49e5b1af/isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9", size = 28443, upload-time = "2021-12-13T20:28:31.525Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b6/85/7882d311924cbcfc70b1890780763e36ff0b140c7e51c110fc59a532f087/isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", size = 41722, upload-time = "2021-12-13T20:28:29.073Z" },
+]
+
[[package]]
name = "jinja2"
version = "3.1.6"
@@ -785,6 +995,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" },
]
+[[package]]
+name = "leather"
+version = "0.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ed/6e/48a05e2f7f62a616d675cfee182643f2dd8023bf7429aa326f4bebd629c8/leather-0.4.0.tar.gz", hash = "sha256:f964bec2086f3153a6c16e707f20cb718f811f57af116075f4c0f4805c608b95", size = 43877, upload-time = "2024-02-23T22:03:36.657Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a1/30/9ec597c962c5249ebd5c580386e4b5f2884cd943af42634291ee3b406415/leather-0.4.0-py2.py3-none-any.whl", hash = "sha256:18290bc93749ae39039af5e31e871fcfad74d26c4c3ea28ea4f681f4571b3a2b", size = 30256, upload-time = "2024-02-23T22:03:34.75Z" },
+]
+
[[package]]
name = "mako"
version = "1.3.10"
@@ -856,6 +1075,23 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
]
+[[package]]
+name = "mashumaro"
+version = "3.14"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/eb/47/0a450b281bef2d7e97ec02c8e1168d821e283f58e02e6c403b2bb4d73c1c/mashumaro-3.14.tar.gz", hash = "sha256:5ef6f2b963892cbe9a4ceb3441dfbea37f8c3412523f25d42e9b3a7186555f1d", size = 166160, upload-time = "2024-10-23T21:48:40.164Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1b/35/8d63733a2c12149d0c7663c29bf626bdbeea5f0ff963afe58a42b4810981/mashumaro-3.14-py3-none-any.whl", hash = "sha256:c12a649599a8f7b1a0b35d18f12e678423c3066189f7bc7bd8dd431c5c8132c3", size = 92183, upload-time = "2024-10-23T21:48:38.334Z" },
+]
+
+[package.optional-dependencies]
+msgpack = [
+ { name = "msgpack" },
+]
+
[[package]]
name = "mdurl"
version = "0.1.2"
@@ -874,6 +1110,34 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" },
]
+[[package]]
+name = "msgpack"
+version = "1.1.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/45/b1/ea4f68038a18c77c9467400d166d74c4ffa536f34761f7983a104357e614/msgpack-1.1.1.tar.gz", hash = "sha256:77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd", size = 173555, upload-time = "2025-06-13T06:52:51.324Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e3/26/389b9c593eda2b8551b2e7126ad3a06af6f9b44274eb3a4f054d48ff7e47/msgpack-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae497b11f4c21558d95de9f64fff7053544f4d1a17731c866143ed6bb4591238", size = 82359, upload-time = "2025-06-13T06:52:03.909Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/65/7d1de38c8a22cf8b1551469159d4b6cf49be2126adc2482de50976084d78/msgpack-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:33be9ab121df9b6b461ff91baac6f2731f83d9b27ed948c5b9d1978ae28bf157", size = 79172, upload-time = "2025-06-13T06:52:05.246Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/bd/cacf208b64d9577a62c74b677e1ada005caa9b69a05a599889d6fc2ab20a/msgpack-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f64ae8fe7ffba251fecb8408540c34ee9df1c26674c50c4544d72dbf792e5ce", size = 425013, upload-time = "2025-06-13T06:52:06.341Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/ec/fd869e2567cc9c01278a736cfd1697941ba0d4b81a43e0aa2e8d71dab208/msgpack-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a494554874691720ba5891c9b0b39474ba43ffb1aaf32a5dac874effb1619e1a", size = 426905, upload-time = "2025-06-13T06:52:07.501Z" },
+ { url = "https://files.pythonhosted.org/packages/55/2a/35860f33229075bce803a5593d046d8b489d7ba2fc85701e714fc1aaf898/msgpack-1.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb643284ab0ed26f6957d969fe0dd8bb17beb567beb8998140b5e38a90974f6c", size = 407336, upload-time = "2025-06-13T06:52:09.047Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/16/69ed8f3ada150bf92745fb4921bd621fd2cdf5a42e25eb50bcc57a5328f0/msgpack-1.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d275a9e3c81b1093c060c3837e580c37f47c51eca031f7b5fb76f7b8470f5f9b", size = 409485, upload-time = "2025-06-13T06:52:10.382Z" },
+ { url = "https://files.pythonhosted.org/packages/c6/b6/0c398039e4c6d0b2e37c61d7e0e9d13439f91f780686deb8ee64ecf1ae71/msgpack-1.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fd6b577e4541676e0cc9ddc1709d25014d3ad9a66caa19962c4f5de30fc09ef", size = 412182, upload-time = "2025-06-13T06:52:11.644Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/d0/0cf4a6ecb9bc960d624c93effaeaae75cbf00b3bc4a54f35c8507273cda1/msgpack-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb29aaa613c0a1c40d1af111abf025f1732cab333f96f285d6a93b934738a68a", size = 419883, upload-time = "2025-06-13T06:52:12.806Z" },
+ { url = "https://files.pythonhosted.org/packages/62/83/9697c211720fa71a2dfb632cad6196a8af3abea56eece220fde4674dc44b/msgpack-1.1.1-cp312-cp312-win32.whl", hash = "sha256:870b9a626280c86cff9c576ec0d9cbcc54a1e5ebda9cd26dab12baf41fee218c", size = 65406, upload-time = "2025-06-13T06:52:14.271Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/23/0abb886e80eab08f5e8c485d6f13924028602829f63b8f5fa25a06636628/msgpack-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:5692095123007180dca3e788bb4c399cc26626da51629a31d40207cb262e67f4", size = 72558, upload-time = "2025-06-13T06:52:15.252Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/38/561f01cf3577430b59b340b51329803d3a5bf6a45864a55f4ef308ac11e3/msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0", size = 81677, upload-time = "2025-06-13T06:52:16.64Z" },
+ { url = "https://files.pythonhosted.org/packages/09/48/54a89579ea36b6ae0ee001cba8c61f776451fad3c9306cd80f5b5c55be87/msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9", size = 78603, upload-time = "2025-06-13T06:52:17.843Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/60/daba2699b308e95ae792cdc2ef092a38eb5ee422f9d2fbd4101526d8a210/msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8", size = 420504, upload-time = "2025-06-13T06:52:18.982Z" },
+ { url = "https://files.pythonhosted.org/packages/20/22/2ebae7ae43cd8f2debc35c631172ddf14e2a87ffcc04cf43ff9df9fff0d3/msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a", size = 423749, upload-time = "2025-06-13T06:52:20.211Z" },
+ { url = "https://files.pythonhosted.org/packages/40/1b/54c08dd5452427e1179a40b4b607e37e2664bca1c790c60c442c8e972e47/msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac", size = 404458, upload-time = "2025-06-13T06:52:21.429Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/60/6bb17e9ffb080616a51f09928fdd5cac1353c9becc6c4a8abd4e57269a16/msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b", size = 405976, upload-time = "2025-06-13T06:52:22.995Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/97/88983e266572e8707c1f4b99c8fd04f9eb97b43f2db40e3172d87d8642db/msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7", size = 408607, upload-time = "2025-06-13T06:52:24.152Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/66/36c78af2efaffcc15a5a61ae0df53a1d025f2680122e2a9eb8442fed3ae4/msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5", size = 424172, upload-time = "2025-06-13T06:52:25.704Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/87/a75eb622b555708fe0427fab96056d39d4c9892b0c784b3a721088c7ee37/msgpack-1.1.1-cp313-cp313-win32.whl", hash = "sha256:500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323", size = 65347, upload-time = "2025-06-13T06:52:26.846Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/91/7dc28d5e2a11a5ad804cf2b7f7a5fcb1eb5a4966d66a5d2b41aee6376543/msgpack-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69", size = 72341, upload-time = "2025-06-13T06:52:27.835Z" },
+]
+
[[package]]
name = "multidict"
version = "6.6.3"
@@ -937,6 +1201,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" },
]
+[[package]]
+name = "networkx"
+version = "3.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6c/4f/ccdb8ad3a38e583f214547fd2f7ff1fc160c43a75af88e6aec213404b96a/networkx-3.5.tar.gz", hash = "sha256:d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037", size = 2471065, upload-time = "2025-05-29T11:35:07.804Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec", size = 2034406, upload-time = "2025-05-29T11:35:04.961Z" },
+]
+
[[package]]
name = "numpy"
version = "2.3.1"
@@ -1060,6 +1333,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/05/75/7d591371c6c39c73de5ce5da5a2cc7b72d1d1cd3f8f4638f553c01c37b11/opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78", size = 201627, upload-time = "2025-07-29T15:12:04.174Z" },
]
+[[package]]
+name = "ordered-set"
+version = "4.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4c/ca/bfac8bc689799bcca4157e0e0ced07e70ce125193fc2e166d2e685b7e2fe/ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8", size = 12826, upload-time = "2022-01-26T14:38:56.6Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/33/55/af02708f230eb77084a299d7b08175cff006dea4f2721074b92cdb0296c0/ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562", size = 7634, upload-time = "2022-01-26T14:38:48.677Z" },
+]
+
[[package]]
name = "packaging"
version = "25.0"
@@ -1103,6 +1385,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d5/f9/07086f5b0f2a19872554abeea7658200824f5835c58a106fa8f2ae96a46c/pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", size = 13189044, upload-time = "2025-07-07T19:19:39.999Z" },
]
+[[package]]
+name = "parsedatetime"
+version = "2.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a8/20/cb587f6672dbe585d101f590c3871d16e7aec5a576a1694997a3777312ac/parsedatetime-2.6.tar.gz", hash = "sha256:4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455", size = 60114, upload-time = "2020-05-31T23:50:57.443Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/a4/3dd804926a42537bf69fb3ebb9fd72a50ba84f807d95df5ae016606c976c/parsedatetime-2.6-py3-none-any.whl", hash = "sha256:cb96edd7016872f58479e35879294258c71437195760746faffedb692aef000b", size = 42548, upload-time = "2020-05-31T23:50:56.315Z" },
+]
+
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
+]
+
[[package]]
name = "polars"
version = "1.31.0"
@@ -1395,6 +1695,27 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
]
+[[package]]
+name = "python-slugify"
+version = "8.0.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "text-unidecode" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921, upload-time = "2024-02-08T18:32:45.488Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" },
+]
+
+[[package]]
+name = "pytimeparse"
+version = "1.1.8"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/37/5d/231f5f33c81e09682708fb323f9e4041408d8223e2f0fb9742843328778f/pytimeparse-1.1.8.tar.gz", hash = "sha256:e86136477be924d7e670646a98561957e8ca7308d44841e21f5ddea757556a0a", size = 9403, upload-time = "2018-05-18T17:40:42.76Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1b/b4/afd75551a3b910abd1d922dbd45e49e5deeb4d47dc50209ce489ba9844dd/pytimeparse-1.1.8-py2.py3-none-any.whl", hash = "sha256:04b7be6cc8bd9f5647a6325444926c3ac34ee6bc7e69da4367ba282f076036bd", size = 9969, upload-time = "2018-05-18T17:40:41.28Z" },
+]
+
[[package]]
name = "pytz"
version = "2025.2"
@@ -1662,6 +1983,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
]
+[[package]]
+name = "snowplow-tracker"
+version = "1.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "requests" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ff/77/1ab6e5bafb9c80d8128f065a355377a04ac5b3c38eb719d920a9909d346e/snowplow_tracker-1.1.0.tar.gz", hash = "sha256:95d8fdc8bd542fd12a0b9a076852239cbaf0599eda8721deaf5f93f7138fe755", size = 34135, upload-time = "2025-02-21T10:58:48.112Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/10/1c76269cbf2d6e127f4415044d9ddb0295858230678bbf4bfba905593c82/snowplow_tracker-1.1.0-py3-none-any.whl", hash = "sha256:24ea32ddac9cca547421bf9ab162f5f33c00711c6ef118ad5f78093cee962224", size = 44128, upload-time = "2025-02-21T10:58:45.818Z" },
+]
+
[[package]]
name = "soda-core"
version = "3.5.5"
@@ -1783,6 +2117,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2b/ad/9e826b1bd69dc3faa5abb7b6459528e16831c0e73b353479a467ed5ee995/termcolor_whl-1.1.2-py2.py3-none-any.whl", hash = "sha256:3e7eda7348bb90ddea2d7a2171df65ed4a37adf62574fbd5459198410fdba881", size = 4824, upload-time = "2021-12-04T19:20:30.35Z" },
]
+[[package]]
+name = "text-unidecode"
+version = "1.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" },
+]
+
[[package]]
name = "tomli"
version = "2.2.1"
diff --git a/cmd/pokemon/pokemon.go b/cmd/pokemon/pokemon.go
index a13414b..0dece62 100644
--- a/cmd/pokemon/pokemon.go
+++ b/cmd/pokemon/pokemon.go
@@ -4,6 +4,11 @@ import (
"bytes"
"flag"
"fmt"
+ "io"
+ "math"
+ "os"
+ "strings"
+
"github.com/charmbracelet/lipgloss"
"github.com/digitalghost-dev/poke-cli/cmd/utils"
"github.com/digitalghost-dev/poke-cli/connections"
@@ -11,10 +16,6 @@ import (
"github.com/digitalghost-dev/poke-cli/styling"
"golang.org/x/text/cases"
"golang.org/x/text/language"
- "io"
- "math"
- "os"
- "strings"
)
// PokemonCommand processes the Pokémon command
@@ -43,7 +44,7 @@ func PokemonCommand() (string, error) {
output.WriteString(helpMessage)
}
- pokeFlags, abilitiesFlag, shortAbilitiesFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := flags.SetupPokemonFlagSet()
+ pokeFlags, abilitiesFlag, shortAbilitiesFlag, defenseFlag, shortDefenseFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := flags.SetupPokemonFlagSet()
args := os.Args
@@ -148,6 +149,13 @@ func PokemonCommand() (string, error) {
}
}
+ if *defenseFlag || *shortDefenseFlag {
+ if err := flags.DefenseFlag(&output, endpoint, pokemonName); err != nil {
+ output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err))
+ return "", fmt.Errorf("error parsing flags: %w", err)
+ }
+ }
+
if *moveFlag || *shortMoveFlag {
if err := flags.MovesFlag(&output, endpoint, pokemonName); err != nil {
output.WriteString(fmt.Sprintf("error parsing flags: %v\n", err))
diff --git a/cmd/pokemon/pokemon_test.go b/cmd/pokemon/pokemon_test.go
index 157a17f..b507e8a 100644
--- a/cmd/pokemon/pokemon_test.go
+++ b/cmd/pokemon/pokemon_test.go
@@ -1,11 +1,12 @@
package pokemon
import (
+ "os"
+ "testing"
+
"github.com/digitalghost-dev/poke-cli/cmd/utils"
"github.com/digitalghost-dev/poke-cli/styling"
"github.com/stretchr/testify/assert"
- "os"
- "testing"
)
func TestPokemonCommand(t *testing.T) {
@@ -43,6 +44,16 @@ func TestPokemonCommand(t *testing.T) {
args: []string{"pokemon", "metagross", "--abilities"},
expectedOutput: utils.LoadGolden(t, "pokemon_abilities.golden"),
},
+ {
+ name: "Pokemon defense flag",
+ args: []string{"pokemon", "dragapult", "--defense"},
+ expectedOutput: utils.LoadGolden(t, "pokemon_defense.golden"),
+ },
+ {
+ name: "Pokemon defense flag with ability immunity",
+ args: []string{"pokemon", "gastrodon", "--defense"},
+ expectedOutput: utils.LoadGolden(t, "pokemon_defense_ability_immunities.golden"),
+ },
{
name: "Pokemon image flag",
args: []string{"pokemon", "skeledirge", "--image=md"},
diff --git a/demo.gif b/demo.gif
index b144a9e..705d36c 100644
Binary files a/demo.gif and b/demo.gif differ
diff --git a/demo.tape b/demo.tape
index 966b6b8..1b3b277 100644
--- a/demo.tape
+++ b/demo.tape
@@ -63,7 +63,7 @@ Set Shell "bash"
Set FontSize 32
Set Width 2300
Set Height 1300
-Set TypingSpeed 100ms
+Set TypingSpeed 50ms
Set Theme "tokyonight-storm"
Type "poke-cli pokemon charizard --abilities --stats"
@@ -78,13 +78,25 @@ Type clear
Enter
+Type "poke-cli pokemon gastrodon --defense"
+
+Sleep 2s
+
+Enter
+
+Sleep 3s
+
+Type clear
+
+Enter
+
Type "poke-cli pokemon tyranitar --image=sm"
Sleep 2s
Enter
-Sleep 4s
+Sleep 3s
Type clear
@@ -102,7 +114,7 @@ Down@500ms 4
Enter
-Sleep 6s
+Sleep 5s
Type clear
@@ -112,7 +124,7 @@ Type "poke-cli natures"
Enter
-Sleep 4s
+Sleep 3s
Type clear
@@ -122,7 +134,7 @@ Type "poke-cli ability solar-power --pokemon"
Enter
-Sleep 4s
+Sleep 3s
Type clear
@@ -160,7 +172,7 @@ Enter
Sleep 2s
-Down@500ms 2
+Down@350ms 2
Sleep 2s
@@ -168,9 +180,9 @@ Enter
Sleep 1s
-Type@1s "char"
+Type@500ms "char"
-Sleep 2s
+Sleep 1s
Enter
@@ -190,37 +202,37 @@ Sleep 2s
Enter
-Sleep 5s
+Sleep 2.5s
Enter
-Sleep 1.5s
+Sleep 1s
Type "zapdos"
Enter
-Sleep 1.5s
+Sleep 1s
Type "50"
Enter
-Sleep 1.5s
+Sleep 1s
Type "252"
Enter
-Sleep 1.5s
+Sleep 1s
Type "31"
Enter
-Sleep 1.5s
+Sleep 1s
-Down@500ms 1
+Down@350ms 1
Type "x"
@@ -228,19 +240,19 @@ Sleep 2s
Enter
-Down@500ms 3
+Down@350ms 3
-Up@750ms 3
+Up@350ms 3
Enter
-Sleep 1.5s
+Sleep 1s
-Down@500ms 1
+Down@350ms 1
Enter
-Sleep 1.5s
+Sleep 1s
Type "1"
@@ -248,5 +260,5 @@ Sleep 2s
Enter
-Sleep 6s
+Sleep 5s
diff --git a/docs/Infrastructure_Guide/dagster.md b/docs/Infrastructure_Guide/dagster.md
new file mode 100644
index 0000000..a8ea17a
--- /dev/null
+++ b/docs/Infrastructure_Guide/dagster.md
@@ -0,0 +1,21 @@
+---
+weight: 5
+---
+
+# 5. Dagster
+
+!!! question "What is Dagster?"
+
+ Dagster is an open-source data orchestration tool that helps you build, run, and monitor your data pipelines.
+ It’s designed to make working with data workflows more reliable and maintainable, giving you clear visibility
+ into each step and making it easier to catch issues before they cause problems.
+
+ View more [about Dagster](https://dagster.io/platform-overview)
+
+## Installation
+Dagster and its components can be installed with `uv`: `
+
+```bash
+uv add dagster dagster-webserver dagster-dg-cli dagster-postgres>=0.27.3
+```
+
diff --git a/docs/Infrastructure_Guide/terraform.md b/docs/Infrastructure_Guide/terraform.md
new file mode 100644
index 0000000..372c515
--- /dev/null
+++ b/docs/Infrastructure_Guide/terraform.md
@@ -0,0 +1,42 @@
+---
+weight: 3
+---
+
+# 3. Terraform
+
+!!! question "What is Terraform?"
+
+ Terraform is an open-source Infrastructure as Code (IaC) tool for automating cloud infrastructure using code.
+ You define what you want (servers, networks, etc.) in config files, and Terraform builds and manages it across cloud providers.
+
+ Instead of manually setting up servers, networks, or other resources, you write code to describe the desired state of your infrastructure,
+ and Terraform takes care of creating and maintaining it.
+
+## Overview
+
+Terraform is used in this project to build/destroy the following resources:
+
+- AWS
+ - RDS
+ - S3
+ - VPC
+- Supabase
+
+---
+
+## Terraformer
+
+After manually creating the resources in the [AWS](aws.md) section, [terraformer](https://github.com/GoogleCloudPlatform/terraformer) can now be used to create the `terraform` files.
+Terraformer acts as a "reverse Terraform" tool where it can read from created resources on AWS.
+Although the output can sometimes be a bit verbose, it's an easy way to capture everything to create reproducible builds.
+
+### Install
+* [Install Guide](https://github.com/GoogleCloudPlatform/terraformer?tab=readme-ov-file#installation)
+
+Install Terraformer:
+
+```bash
+brew install terraformer
+```
+
+
diff --git a/docs/assets/pokemon_defense.gif b/docs/assets/pokemon_defense.gif
new file mode 100644
index 0000000..1b09447
Binary files /dev/null and b/docs/assets/pokemon_defense.gif differ
diff --git a/docs/commands.md b/docs/commands.md
index 9f4bd4b..d52e3bf 100644
--- a/docs/commands.md
+++ b/docs/commands.md
@@ -79,12 +79,13 @@ Output:
**Available Flags**
-* `--help | -h`
-* `--abilities | -a`
-* `--image=xx | -i=xx`
-* `--moves | -m`
-* `--stats | -s`
-* `--types | -t`
+* `-h | --help`
+* `-a | --abilities`
+* `-d | --defense`
+* `-i=xx | --image=xx`
+* `-m | --moves`
+* `-s | --stats`
+* `-t | --types`
!!! warning
@@ -101,7 +102,16 @@ Output:

Example:
-```shell
+```console
+$ poke-cli pokemon gastrodon --defense
+```
+
+Output:
+
+
+
+Example:
+```console
# choose between three sizes: 'sm', 'md', 'lg'
$ poke-cli pokemon tyranitar --image=sm
```
diff --git a/docs/index.md b/docs/index.md
index 228b3ec..e56ea26 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -14,4 +14,4 @@ View the [guides](Infrastructure_Guide/index.md) section for more details.
## Demo
Here is a quick demo of the CLI/TUI tool in action.
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/installation.md b/docs/installation.md
index 7c5a732..6f917b4 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -1,39 +1,49 @@
# Installation Methods
There are a variety of ways to install the tool and support for different operating systems.
-### Binary
-
-1. Head to the [releases](https://github.com/digitalghost-dev/poke-cli/releases) page of the project.
-2. Choose a version to download. The latest is best.
-3. Choose an operating system and click on the matching zipped folder to start the download.
-4. Extract the folder. The tool is ready to use.
-5. Either change directories into the extracted folder or move the binary to a chosen directory.
-6. Run the tool!
-
-??? info "View Image of Settings Screen"
- For macOS, you may have to allow the executable to run as it is not signed.
- Head to System Settings > Privacy & Security > scroll down and allow executable to run.
+* [Homebrew](#homebrew)
+* [Winget](#winget)
+* [Linux Packages](#linux-packages)
+* [Docker Image](#docker-image)
+* [Binary](#binary)
+* [Source](#source)
- 
+### Homebrew
+1. Install the Cask:
+ ```console
+ brew install --cask digitalghost-dev/tap/poke-cli
+ ````
+2. Verify install:
+ ```console
+ poke-cli -v
+ ```
-Example usage
- ```bash
- # Windows
- .\poke-cli.exe pokemon charizard --types --abilities
-
- # Unix
- .\poke-cli ability airlock --pokemon
- ```
+### Winget
+1. Install the package:
+ ```powershell
+ winget install poke-cli
+ ```
----
+2. Verify install:
+ ```console
+ poke-cli -v
+ ```
### Linux Packages
[](https://cloudsmith.com)
-_Coming Soon..._
+This package repository is generously hosted by Cloudsmith.
+Cloudsmith is a fully cloud-based service that lets you easily create, store, and share packages in any format, anywhere.
+
+1. Run the **Repository Setup** script first for the correct Linux distribution.
+2. Run the corresponding **Installation Command** afterwards.
----
+| Package Type | Distributions | Repository Setup | Installation Command |
+|:------------:|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
+| `apk` | Alpine | `sudo apk add --no-cache bash && curl -1sLf 'https://dl.cloudsmith.io/basic/digitalghost-dev/poke-cli/setup.alpine.sh' \| sudo -E bash` | `sudo apk add poke-cli=1.6.0 --update-cache` |
+| `deb` | Ubuntu, Debian | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.deb.sh' \| sudo -E bash` | `sudo apt-get install poke-cli=1.6.0` |
+| `rpm` | Fedora, CentOS, Red Hat, openSUSE | `curl -1sLf 'https://dl.cloudsmith.io/public/digitalghost-dev/poke-cli/setup.rpm.sh' \| sudo -E bash` | `sudo yum install poke-cli-1.6.0-1` |
### Docker Image
@@ -47,47 +57,50 @@ _Coming Soon..._
* Necessary.
3. Choose how to interact with the container:
* Run a single command and exit:
- ```bash
- docker run --rm -it digitalghostdev/poke-cli:v1.5.2 [subcommand] flag]
+ ```console
+ docker run --rm -it digitalghostdev/poke-cli:v1.6.0 [subcommand] flag]
```
* Enter the container and use its shell:
- ```bash
- docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.5.2 -c "cd /app && exec sh"
+ ```console
+ docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.6.0 -c "cd /app && exec sh"
# placed into the /app directory, run the program with './poke-cli'
# example: ./poke-cli ability swift-swim
```
-
----
-### Homebrew
-1. Install the Cask:
- ```bash
- brew install --cask digitalghost-dev/tap/poke-cli
- ````
-2. Verify install:
- ```bash
- poke-cli -v
- ```
-
----
+### Binary
-### Winget
-1. Install the package:
- ```powershell
- winget install poke-cli
- ```
+1. Head to the [releases](https://github.com/digitalghost-dev/poke-cli/releases) page of the project.
+2. Choose a version to download. The latest is best.
+3. Choose an operating system and click on the matching zipped folder to start the download.
+4. Extract the folder. The tool is ready to use.
+5. Either change directories into the extracted folder or move the binary to a chosen directory.
+6. Run the tool!
-2. Verify install:
- ```bash
- poke-cli -v
- ```
+> [!IMPORTANT]
+> For macOS, you may have to allow the executable to run as it is not signed. Head to System Settings > Privacy & Security > scroll down and allow executable to run.
+
+
+
+View Image of Settings
+
+
+
+
+
+
+#### Example usage
+ ```console
+ # Windows
+ .\poke-cli.exe pokemon charizard --types --abilities
----
+ # Unix
+ .\poke-cli ability airlock --pokemon
+ ```
### Source
1. Run the following command:
- ```bash
+ ```console
go install github.com/digitalghost-dev/poke-cli@latest
```
-2. The tool is ready to use!
+2. The tool should be ready to use if `$PATH` is set up.
diff --git a/flags/pokemonflagset.go b/flags/pokemonflagset.go
index aefa92e..51c93dc 100644
--- a/flags/pokemonflagset.go
+++ b/flags/pokemonflagset.go
@@ -5,13 +5,6 @@ package flags
import (
"flag"
"fmt"
- "github.com/charmbracelet/lipgloss"
- "github.com/charmbracelet/lipgloss/table"
- "github.com/digitalghost-dev/poke-cli/connections"
- "github.com/digitalghost-dev/poke-cli/styling"
- "github.com/disintegration/imaging"
- "golang.org/x/text/cases"
- "golang.org/x/text/language"
"image"
"io"
"log"
@@ -21,6 +14,15 @@ import (
"strconv"
"strings"
"sync"
+
+ "github.com/charmbracelet/lipgloss"
+ "github.com/charmbracelet/lipgloss/table"
+ "github.com/digitalghost-dev/poke-cli/connections"
+ "github.com/digitalghost-dev/poke-cli/structs"
+ "github.com/digitalghost-dev/poke-cli/styling"
+ "github.com/disintegration/imaging"
+ "golang.org/x/text/cases"
+ "golang.org/x/text/language"
)
func header(header string) string {
@@ -38,12 +40,15 @@ func header(header string) string {
return output.String()
}
-func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *string, *string, *bool, *bool, *bool, *bool, *bool, *bool) {
+func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *bool, *bool, *string, *string, *bool, *bool, *bool, *bool, *bool, *bool) {
pokeFlags := flag.NewFlagSet("pokeFlags", flag.ExitOnError)
abilitiesFlag := pokeFlags.Bool("abilities", false, "Print the Pokémon's abilities")
shortAbilitiesFlag := pokeFlags.Bool("a", false, "Print the Pokémon's abilities")
+ defenseFlag := pokeFlags.Bool("defense", false, "Print the Pokémon's type defenses")
+ shortDefenseFlag := pokeFlags.Bool("d", false, "Print the Pokémon's type defenses")
+
imageFlag := pokeFlags.String("image", "", "Print the Pokémon's default sprite")
shortImageFlag := pokeFlags.String("i", "", "Print the Pokémon's default sprite")
@@ -62,6 +67,7 @@ func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *string, *string, *bool
helpMessage := styling.HelpBorder.Render("poke-cli pokemon [flags]\n\n",
styling.StyleBold.Render("FLAGS:"),
fmt.Sprintf("\n\t%-30s %s", "-a, --abilities", "Prints the Pokémon's abilities."),
+ fmt.Sprintf("\n\t%-30s %s", "-d, --defense", "Prints the Pokémon's type defenses."),
fmt.Sprintf("\n\t%-30s %s", "-i=xx, --image=xx", "Prints out the Pokémon's default sprite."),
fmt.Sprintf("\n\t%5s%-15s", "", hintMessage),
fmt.Sprintf("\n\t%-30s %s", "-m, --moves", "Prints the Pokemon's learnable moves."),
@@ -72,7 +78,7 @@ func SetupPokemonFlagSet() (*flag.FlagSet, *bool, *bool, *string, *string, *bool
fmt.Println(helpMessage)
}
- return pokeFlags, abilitiesFlag, shortAbilitiesFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag
+ return pokeFlags, abilitiesFlag, shortAbilitiesFlag, defenseFlag, shortDefenseFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag
}
func AbilitiesFlag(w io.Writer, endpoint string, pokemonName string) error {
@@ -128,6 +134,191 @@ func AbilitiesFlag(w io.Writer, endpoint string, pokemonName string) error {
return nil
}
+func DefenseFlag(w io.Writer, endpoint string, pokemonName string) error {
+ baseURL := "https://pokeapi.co/api/v2/"
+ pokemonStruct, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
+
+ // Print the header from header func
+ _, err := fmt.Fprintln(w, header("Type Defenses"))
+ if err != nil {
+ return err
+ }
+
+ allTypes := []string{"normal", "fire", "water", "electric", "grass", "ice",
+ "fighting", "poison", "ground", "flying", "psychic",
+ "bug", "rock", "ghost", "dragon", "dark", "steel", "fairy"}
+
+ typeData := make(map[string]structs.TypesJSONStruct)
+ for _, pokeType := range pokemonStruct.Types {
+ typeStruct, _, _ := connections.TypesApiCall("type", pokeType.Type.Name, baseURL)
+ typeData[pokeType.Type.Name] = typeStruct
+ }
+
+ calculateTypeEffectiveness := func(attackingType string) float64 {
+ totalEffectiveness := 1.0
+
+ for _, pokeType := range pokemonStruct.Types {
+ typeStruct := typeData[pokeType.Type.Name]
+ effectiveness := 1.0
+
+ // Check for double damage (weakness)
+ for _, dmgType := range typeStruct.DamageRelations.DoubleDamageFrom {
+ if dmgType.Name == attackingType {
+ effectiveness = 2.0
+ break
+ }
+ }
+
+ // Check for half damage (resistance)
+ for _, dmgType := range typeStruct.DamageRelations.HalfDamageFrom {
+ if dmgType.Name == attackingType {
+ effectiveness = 0.5
+ break
+ }
+ }
+
+ // Check for no damage (immunity)
+ for _, dmgType := range typeStruct.DamageRelations.NoDamageFrom {
+ if dmgType.Name == attackingType {
+ effectiveness = 0.0
+ break
+ }
+ }
+
+ totalEffectiveness *= effectiveness
+ }
+
+ return totalEffectiveness
+ }
+
+ // Check for abilities that grant immunities or resistances
+ checkAbilityEffects := func() {
+ abilityImmunities := map[string][]string{
+ "flash-fire": {"fire"},
+ "water-absorb": {"water"},
+ "storm-drain": {"water"},
+ "volt-absorb": {"electric"},
+ "motor-drive": {"electric"},
+ "lightning-rod": {"electric"},
+ "sap-sipper": {"grass"},
+ "dry-skin": {"water"},
+ "levitate": {"ground"},
+ "earth-eater": {"ground"},
+ }
+
+ abilityResistances := map[string][]string{
+ "thick-fat": {"fire", "ice"},
+ "heatproof": {"fire"},
+ }
+
+ for _, ability := range pokemonStruct.Abilities {
+ abilityName := ability.Ability.Name
+ formattedAbilityName := cases.Title(language.English).String(strings.ReplaceAll(abilityName, "-", " "))
+
+ if types, exists := abilityImmunities[abilityName]; exists {
+ typeList := strings.Join(types, " and ")
+ _, err := fmt.Fprintf(w, "%s, with the %s ability, grants it immunity to %s type moves.\n",
+ cases.Title(language.English).String(pokemonName), formattedAbilityName, typeList)
+ if err != nil {
+ return
+ }
+ }
+
+ if types, exists := abilityResistances[abilityName]; exists {
+ typeList := strings.Join(types, " and ")
+ _, err := fmt.Fprintf(w, "%s, with the %s ability, grants it resistance to %s type moves.\n",
+ cases.Title(language.English).String(pokemonName), formattedAbilityName, typeList)
+ if err != nil {
+ return
+ }
+ }
+ }
+ }
+
+ // Calculate effectiveness for all types
+ typeEffectiveness := make(map[string]float64)
+ for _, attackingType := range allTypes {
+ typeEffectiveness[attackingType] = calculateTypeEffectiveness(attackingType)
+ }
+
+ var (
+ immune []string
+ quarterDamage []string
+ halfDamage []string
+ normal []string
+ doubleDamage []string
+ quadrupleDamage []string
+ )
+
+ for typeName, eff := range typeEffectiveness {
+ capitalizedType := cases.Title(language.English).String(typeName)
+ switch eff {
+ case 0.0:
+ immune = append(immune, capitalizedType)
+ case 0.25:
+ quarterDamage = append(quarterDamage, capitalizedType)
+ case 0.5:
+ halfDamage = append(halfDamage, capitalizedType)
+ case 1.0:
+ normal = append(normal, capitalizedType)
+ case 2.0:
+ doubleDamage = append(doubleDamage, capitalizedType)
+ case 4.0:
+ quadrupleDamage = append(quadrupleDamage, capitalizedType)
+ }
+ }
+
+ sort.Strings(immune)
+ sort.Strings(quarterDamage)
+ sort.Strings(halfDamage)
+ sort.Strings(normal)
+ sort.Strings(doubleDamage)
+ sort.Strings(quadrupleDamage)
+
+ if len(immune) > 0 {
+ _, err := fmt.Fprintf(w, "Immune: %s\n", strings.Join(immune, ", "))
+ if err != nil {
+ return err
+ }
+ }
+ if len(quarterDamage) > 0 {
+ _, err := fmt.Fprintf(w, "0.25× Damage: %s\n", strings.Join(quarterDamage, ", "))
+ if err != nil {
+ return err
+ }
+ }
+ if len(halfDamage) > 0 {
+ _, err := fmt.Fprintf(w, "0.5× Damage: %s\n", strings.Join(halfDamage, ", "))
+ if err != nil {
+ return err
+ }
+ }
+ if len(doubleDamage) > 0 {
+ _, err := fmt.Fprintf(w, "2.0× Damage: %s\n", strings.Join(doubleDamage, ", "))
+ if err != nil {
+ return err
+ }
+ }
+ if len(quadrupleDamage) > 0 {
+ _, err := fmt.Fprintf(w, "4.0× Damage: %s\n", strings.Join(quadrupleDamage, ", "))
+ if err != nil {
+ return err
+ }
+ }
+
+ // Add a newline before ability effects if there are any type effectiveness results
+ if len(immune) > 0 || len(quarterDamage) > 0 || len(halfDamage) > 0 || len(doubleDamage) > 0 || len(quadrupleDamage) > 0 {
+ _, err := fmt.Fprintln(w)
+ if err != nil {
+ return err
+ }
+ }
+
+ checkAbilityEffects()
+
+ return nil
+}
+
func ImageFlag(w io.Writer, endpoint string, pokemonName string, size string) error {
baseURL := "https://pokeapi.co/api/v2/"
pokemonStruct, _, _ := connections.PokemonApiCall(endpoint, pokemonName, baseURL)
diff --git a/flags/pokemonflagset_test.go b/flags/pokemonflagset_test.go
index 12a4a5c..df46234 100644
--- a/flags/pokemonflagset_test.go
+++ b/flags/pokemonflagset_test.go
@@ -2,24 +2,22 @@ package flags
import (
"bytes"
- "github.com/digitalghost-dev/poke-cli/styling"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
"os"
"reflect"
"strings"
"testing"
+
+ "github.com/digitalghost-dev/poke-cli/styling"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestSetupPokemonFlagSet(t *testing.T) {
- // Call the function to get the flag set and flags
- pokeFlags, abilitiesFlag, shortAbilitiesFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := SetupPokemonFlagSet()
+ pokeFlags, abilitiesFlag, shortAbilitiesFlag, defenseFlag, shortDefenseFlag, imageFlag, shortImageFlag, moveFlag, shortMoveFlag, statsFlag, shortStatsFlag, typesFlag, shortTypesFlag := SetupPokemonFlagSet()
- // Check flag set properties
assert.NotNil(t, pokeFlags, "Flag set should not be nil")
assert.Equal(t, "pokeFlags", pokeFlags.Name(), "Flag set name should be 'pokeFlags'")
- // Define test cases for flag assertions
flagTests := []struct {
flag interface{}
expected interface{}
@@ -27,6 +25,8 @@ func TestSetupPokemonFlagSet(t *testing.T) {
}{
{abilitiesFlag, false, "Abilities flag should be 'abilities'"},
{shortAbilitiesFlag, false, "Short abilities flag should be 'a'"},
+ {defenseFlag, false, "Defense flag should be 'defense'"},
+ {shortDefenseFlag, false, "Short Defense flag should be 'd'"},
{imageFlag, "", "Image flag default value should be 'md'"},
{shortImageFlag, "", "Short image flag default value should be 'md'"},
{moveFlag, false, "Move flag default value should be 'moves'"},
@@ -37,7 +37,6 @@ func TestSetupPokemonFlagSet(t *testing.T) {
{shortStatsFlag, false, "Short stats flag should be 's'"},
}
- // Run assertions for all flags
for _, tt := range flagTests {
assert.NotNil(t, tt.flag, tt.name)
assert.Equal(t, tt.expected, reflect.ValueOf(tt.flag).Elem().Interface(), tt.name)
@@ -45,16 +44,13 @@ func TestSetupPokemonFlagSet(t *testing.T) {
}
func TestAbilitiesFlag(t *testing.T) {
- // Capture standard output
var output bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
- // Call the function with a known Pokémon (e.g., bulbasaur)
err := AbilitiesFlag(&output, "pokemon", "bulbasaur")
- // Close and restore stdout
if closeErr := w.Close(); closeErr != nil {
t.Fatalf("Failed to close pipe writer: %v", closeErr)
}
@@ -67,30 +63,25 @@ func TestAbilitiesFlag(t *testing.T) {
require.NoError(t, err)
- // Define the expected output based on the API response
expectedOutput := `─────────
Abilities
Ability 1: Overgrow
Hidden Ability: Chlorophyll
`
- // Assert the actual output matches the expected output
actualOutput := styling.StripANSI(output.String())
assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the abilities flag")
}
-func TestMovesFlag(t *testing.T) {
- // Capture standard output
+func TestDefenseFlag(t *testing.T) {
var output bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
- // Call the MovesFlag function with a valid Pokémon
- err := MovesFlag(&output, "pokemon", "bulbasaur")
+ err := DefenseFlag(&output, "pokemon", "bulbasaur")
- // Close and restore stdout
if closeErr := w.Close(); closeErr != nil {
t.Fatalf("Failed to close pipe writer: %v", closeErr)
}
@@ -101,45 +92,38 @@ func TestMovesFlag(t *testing.T) {
t.Fatalf("Failed to read from pipe: %v", readErr)
}
- // Assert no errors occurred
- require.NoError(t, err, "MovesFlag should not return an error for a valid Pokémon")
+ require.NoError(t, err, "DefenseFlag should not return an error for a valid Pokémon")
- // Get the actual output and strip ANSI codes
actualOutput := styling.StripANSI(output.String())
- // Check for expected header
- assert.Contains(t, actualOutput, "Learnable Moves", "Output should contain the header 'Learnable Moves'")
+ assert.Contains(t, actualOutput, "Type Defenses", "Output should contain the header 'Type Defenses'")
- // Check for table headers
- assert.Contains(t, actualOutput, "Name", "Output should contain the 'Name' column header")
- assert.Contains(t, actualOutput, "Level", "Output should contain the 'Level' column header")
- assert.Contains(t, actualOutput, "Type", "Output should contain the 'Type' column header")
- assert.Contains(t, actualOutput, "Accuracy", "Output should contain the 'Accuracy' column header")
- assert.Contains(t, actualOutput, "Power", "Output should contain the 'Power' column header")
+ assert.Contains(t, actualOutput, "0.25× Damage", "Should include quarter damage category")
+ assert.Contains(t, actualOutput, "0.5× Damage", "Should include half damage category")
+ assert.Contains(t, actualOutput, "2.0× Damage", "Should include double damage category")
- // Since the actual moves might change with API updates, we'll just check that the output is not empty
- assert.NotEmpty(t, actualOutput, "Output should not be empty")
+ for _, typ := range []string{"Grass"} {
+ assert.Contains(t, actualOutput, typ, "Quarter damage should list %s", typ)
+ }
+ for _, typ := range []string{"Water", "Electric", "Fighting", "Fairy"} {
+ assert.Contains(t, actualOutput, typ, "Half damage should list %s", typ)
+ }
+ for _, typ := range []string{"Fire", "Ice", "Flying", "Psychic"} {
+ assert.Contains(t, actualOutput, typ, "Double damage should list %s", typ)
+ }
- // Check that the output contains some common moves for Bulbasaur
- // Note: These are common moves, but if they change in the API, this test might need updating
- assert.True(t,
- strings.Contains(actualOutput, "Tackle") ||
- strings.Contains(actualOutput, "Vine Whip") ||
- strings.Contains(actualOutput, "Growl"),
- "Output should contain at least one of Bulbasaur's common moves")
+ assert.NotContains(t, actualOutput, "Immune:", "Bulbasaur should not have immunities")
+ assert.NotContains(t, actualOutput, "4.0×", "Bulbasaur should not have 4x weaknesses")
}
func TestImageFlag(t *testing.T) {
- // Capture standard output
var output bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
- // Call the function with a known Pokémon (e.g., bulbasaur)
err := ImageFlag(&output, "pokemon", "bulbasaur", "sm")
- // Close and restore stdout
if closeErr := w.Close(); closeErr != nil {
t.Fatalf("Failed to close pipe writer: %v", closeErr)
}
@@ -152,11 +136,8 @@ func TestImageFlag(t *testing.T) {
require.NoError(t, err)
- // Validate that the output contains some expected patterns
actualOutput := styling.StripANSI(output.String())
- // Since the output is an ASCII image, we can't hardcode the expected output,
- // but we can check that it contains some general expected structure
if !strings.Contains(actualOutput, "▀") {
t.Errorf("Output does not contain the expected ASCII art characters.")
}
@@ -167,10 +148,8 @@ func TestImageFlag(t *testing.T) {
}
func TestImageFlagOptions(t *testing.T) {
- // Define valid options as a slice
validOptions := []string{"lg", "md", "sm"}
- // Test valid options
for _, option := range validOptions {
t.Run("ValidOption_"+option, func(t *testing.T) {
var buf bytes.Buffer
@@ -179,10 +158,8 @@ func TestImageFlagOptions(t *testing.T) {
})
}
- // Define invalid options as a slice
invalidOptions := []string{"s", "med", "large"}
- // Test invalid options
for _, option := range invalidOptions {
t.Run("InvalidOption_"+option, func(t *testing.T) {
var buf bytes.Buffer
@@ -192,17 +169,53 @@ func TestImageFlagOptions(t *testing.T) {
}
}
+func TestMovesFlag(t *testing.T) {
+ var output bytes.Buffer
+ stdout := os.Stdout
+ r, w, _ := os.Pipe()
+ os.Stdout = w
+
+ err := MovesFlag(&output, "pokemon", "bulbasaur")
+
+ if closeErr := w.Close(); closeErr != nil {
+ t.Fatalf("Failed to close pipe writer: %v", closeErr)
+ }
+ os.Stdout = stdout
+
+ _, readErr := output.ReadFrom(r)
+ if readErr != nil {
+ t.Fatalf("Failed to read from pipe: %v", readErr)
+ }
+
+ require.NoError(t, err, "MovesFlag should not return an error for a valid Pokémon")
+
+ actualOutput := styling.StripANSI(output.String())
+
+ assert.Contains(t, actualOutput, "Learnable Moves", "Output should contain the header 'Learnable Moves'")
+
+ assert.Contains(t, actualOutput, "Name", "Output should contain the 'Name' column header")
+ assert.Contains(t, actualOutput, "Level", "Output should contain the 'Level' column header")
+ assert.Contains(t, actualOutput, "Type", "Output should contain the 'Type' column header")
+ assert.Contains(t, actualOutput, "Accuracy", "Output should contain the 'Accuracy' column header")
+ assert.Contains(t, actualOutput, "Power", "Output should contain the 'Power' column header")
+
+ assert.NotEmpty(t, actualOutput, "Output should not be empty")
+
+ assert.True(t,
+ strings.Contains(actualOutput, "Tackle") ||
+ strings.Contains(actualOutput, "Vine Whip") ||
+ strings.Contains(actualOutput, "Growl"),
+ "Output should contain at least one of Bulbasaur's common moves")
+}
+
func TestStatsFlag(t *testing.T) {
- // Capture standard output
var output bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
- // Call the StatsFlag function with a valid Pokémon
err := StatsFlag(&output, "pokemon", "bulbasaur")
- // Close and restore stdout
if closeErr := w.Close(); closeErr != nil {
t.Fatalf("Failed to close pipe writer: %v", closeErr)
}
@@ -215,7 +228,6 @@ func TestStatsFlag(t *testing.T) {
require.NoError(t, err, "StatsFlag should not return an error for a valid Pokémon")
- // Define expected output components
expectedOutput := `──────────
Base Stats
HP ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 45
@@ -227,23 +239,19 @@ Speed ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇
Total 318
`
- // Assert output contains the expected header and typing information
actualOutput := styling.StripANSI(output.String())
assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the stats flag")
}
func TestTypesFlag(t *testing.T) {
- // Capture standard output
var output bytes.Buffer
stdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
- // Call the TypesFlag function with a valid Pokémon
err := TypesFlag(&output, "pokemon", "bulbasaur")
- // Close and restore stdout
if closeErr := w.Close(); closeErr != nil {
t.Fatalf("Failed to close pipe writer: %v", closeErr)
}
@@ -254,10 +262,8 @@ func TestTypesFlag(t *testing.T) {
t.Fatalf("Failed to read from pipe: %v", readErr)
}
- // Assert no errors occurred
require.NoError(t, err, "TypesFlag should not return an error for a valid Pokémon")
- // Define expected output components
expectedOutput := `──────
Typing
Type 1: Grass
@@ -271,8 +277,6 @@ Type 2: Poison
│You no longer need this flag. │
╰─────────────────────────────────────╯
`
-
- // Assert output contains the expected header and typing information
actualOutput := styling.StripANSI(output.String())
assert.Equal(t, expectedOutput, actualOutput, "Output should contain data for the types flag")
diff --git a/nfpm.yaml b/nfpm.yaml
index 153ab25..76d0671 100644
--- a/nfpm.yaml
+++ b/nfpm.yaml
@@ -1,13 +1,12 @@
name: "poke-cli"
arch: "arm64"
platform: "linux"
-version: "v1.5.2"
+version: "v1.6.0"
section: "default"
version_schema: semver
maintainer: "Christian S"
description: |
- A hybrid CLI/TUI tool written in Go for
- viewing Pokémon data from the terminal!
+ A hybrid CLI/TUI tool written in Go for viewing Pokémon data from the terminal!
homepage: "https://docs.poke-cli.com/"
license: "MIT"
diff --git a/testdata/main_latest_flag.golden b/testdata/main_latest_flag.golden
index 3139e8b..b4cf72d 100644
--- a/testdata/main_latest_flag.golden
+++ b/testdata/main_latest_flag.golden
@@ -1,6 +1,6 @@
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ Latest available version: ┃
-┃ • v1.5.1 ┃
+┃ • v1.5.2 ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
diff --git a/testdata/pokemon_defense.golden b/testdata/pokemon_defense.golden
new file mode 100644
index 0000000..ecbdc92
--- /dev/null
+++ b/testdata/pokemon_defense.golden
@@ -0,0 +1,13 @@
+Your selected Pokémon: Dragapult
+
+ Dragon Ghost
+
+• National Pokédex #: 887
+• Weight: 50.0kg (110.2 lbs)
+• Height: 3.0m (9′10″)
+─────────────
+Type Defenses
+Immune: Fighting, Normal
+0.5× Damage: Bug, Electric, Fire, Grass, Poison, Water
+2.0× Damage: Dark, Dragon, Fairy, Ghost, Ice
+
diff --git a/testdata/pokemon_defense_ability_immunities.golden b/testdata/pokemon_defense_ability_immunities.golden
new file mode 100644
index 0000000..2cf19a0
--- /dev/null
+++ b/testdata/pokemon_defense_ability_immunities.golden
@@ -0,0 +1,14 @@
+Your selected Pokémon: Gastrodon
+
+ Water Ground
+
+• National Pokédex #: 423
+• Weight: 29.9kg (65.9 lbs)
+• Height: 0.9m (2′11″)
+─────────────
+Type Defenses
+Immune: Electric
+0.5× Damage: Fire, Poison, Rock, Steel
+4.0× Damage: Grass
+
+Gastrodon, with the Storm Drain ability, grants it immunity to water type moves.