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 @@ pokemon-logo

Pokémon CLI

version-label - docker-image-size + docker-image-size ci-status-badge
@@ -24,7 +24,7 @@ View future plans in the [Roadmap](#roadmap) section. --- ## Demo -![demo](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo-v1.5.1.gif) +![demo](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo-v1.6.0.gif) --- ## 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: ![pokemon_abilities_moves](assets/pokemon_abilities_moves.gif) Example: -```shell +```console +$ poke-cli pokemon gastrodon --defense +``` + +Output: + +![pokemon_defense](assets/pokemon_defense.gif) + +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. -![demo_gif](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo-v1.5.1.gif) \ No newline at end of file +![demo_gif](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo-v1.6.0.gif) \ 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) - ![settings](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/macos_privacy_settings.png) +### 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 [![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith&style=flat-square)](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 + +![settings](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/macos_privacy_settings.png) + +
+ + +#### 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.