Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Run pytest tests
on:
push:

jobs:
lint_python:
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up uv
uses: astral-sh/setup-uv@eb1897b8dc4b5d5bfe39a428a8f2304605e0983c # v7.0.0

- name: Run pytest
run: uv run pytest
2 changes: 1 addition & 1 deletion pyhelm3/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -1042,4 +1042,4 @@ def client_version(self) -> semver.VersionInfo:
shell_formatted_command, capture_output=True, check=True, shell=True
)
version_str = proc.stdout.decode().removeprefix("v")
return semver.parse_version_info(version_str)
return semver.Version.parse(version_str)
22 changes: 5 additions & 17 deletions pyhelm3/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@
import typing as t

import yaml
from pydantic import AnyUrl as PydanticAnyUrl
from pydantic import (
AnyUrl,
BaseModel,
DirectoryPath,
Field,
FilePath,
HttpUrl,
PrivateAttr,
TypeAdapter,
UrlConstraints,
constr,
field_validator,
)
from pydantic import HttpUrl as PydanticHttpUrl
from pydantic.functional_validators import AfterValidator
from typing_extensions import Annotated

from .command import Command, SafeLoader
Expand Down Expand Up @@ -68,16 +66,6 @@ def validate_str_as(validate_type):
return lambda v: str(adapter.validate_python(v))


class PydanticDataUrl(PydanticAnyUrl):
_constraints = UrlConstraints(allowed_schemes=["data"])


#: Annotated string types for URLs
AnyUrl = t.Annotated[str, AfterValidator(validate_str_as(PydanticAnyUrl))]
HttpUrl = t.Annotated[str, AfterValidator(validate_str_as(PydanticHttpUrl))]
DataUrl = t.Annotated[str, AfterValidator(validate_str_as(PydanticDataUrl))]


class ChartDependency(BaseModel):
"""
Model for a chart dependency.
Expand Down Expand Up @@ -159,14 +147,14 @@ class ChartMetadata(BaseModel):
maintainers: t.List[ChartMaintainer] = Field(
default_factory=list, description="List of maintainers for the chart."
)
icon: t.Optional[HttpUrl | DataUrl] = Field(
icon: t.Optional[AnyUrl] = Field(
None, description="URL to an SVG or PNG image to be used as an icon."
)
app_version: t.Optional[NonEmptyString] = Field(
None,
alias="appVersion",
description=(
"The version of the app that this chart deploys. " "SemVer is not required."
"The version of the app that this chart deploys. SemVer is not required."
),
)
deprecated: bool = Field(False, description="Whether this chart is deprecated.")
Expand Down Expand Up @@ -214,7 +202,7 @@ async def _run_command(self, command_method):
"""
method = getattr(self._command, command_method)
# We only need the kwargs if the ref is not a direct reference
if isinstance(self.ref, (pathlib.Path, HttpUrl)):
if isinstance(self.ref, (HttpUrl, pathlib.Path)):
return await method(self.ref)
else:
return await method(self.ref, repo=self.repo, version=self.metadata.version)
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ license = "Apache-2.0"
requires-python = ">=3.10"
dependencies = [
"pyyaml >= 6.0.2,<7",
"pydantic >= 2.10.6,<3",
"semver >= 2.9.1,<3"
"pydantic >= 2.10.6",
"semver >= 3.0.0"
]

[dependency-groups]
dev = [
"black >= 26.5.1,<26.6",
"hatch-vcs>=0.5.0",
"pytest>=8.3.5,<9",
"pytest-asyncio>=0.25.3,<0.26",
"pytest-asyncio>=0.25.3",
"ruff>=0.15.22,<0.16",
]

Expand Down
7 changes: 7 additions & 0 deletions tests/test-chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v2
name: test-chart
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"
icon: data://notreal
29 changes: 29 additions & 0 deletions tests/test_chart.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import pathlib

import pytest
from pydantic import AnyUrl, HttpUrl

from pyhelm3 import Client

Expand All @@ -11,3 +14,29 @@ async def test_oci_chart():
)

assert chart.metadata.name == "etcd"


@pytest.mark.asyncio
async def test_http_chart():
helm_client = Client()
chart = await helm_client.get_chart(
chart_ref="https://github.com/prometheus-community/helm-charts/releases/download/kube-prometheus-stack-87.20.0/kube-prometheus-stack-87.20.0.tgz",
)

# Check the chart is loaded correctly and metadata parsed
assert chart.metadata.name == "kube-prometheus-stack"
readme = await chart.readme()
assert isinstance(readme, str)
assert isinstance(chart.ref, HttpUrl)


@pytest.mark.asyncio
async def test_local_chart():
helm_client = Client()
chart = await helm_client.get_chart(
chart_ref=pathlib.Path.cwd() / "tests/test-chart",
)
# Check the chart is loaded correctly and icon url parsed
assert chart.metadata.name == "test-chart"
assert isinstance(chart.metadata.icon, AnyUrl)
assert str(chart.metadata.icon) == "data://notreal"
47 changes: 29 additions & 18 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.