Skip to content

Commit

Permalink
Upgrade pydantic and python-on-whales
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejbrown committed Oct 13, 2023
1 parent 9ca6ab9 commit d3a742e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10.7
3.11.4
55 changes: 28 additions & 27 deletions buildrunner/validation/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import Dict, List, Optional, Set, Union

# pylint: disable=no-name-in-module
from pydantic import BaseModel, Field, validator, ValidationError
from pydantic import BaseModel, Field, field_validator, ValidationError

from buildrunner.validation.errors import Errors, get_validation_errors
from buildrunner.validation.step import Step, StepPushCommitDict
Expand All @@ -28,31 +28,32 @@ class GithubModel(BaseModel, extra='forbid'):

class SSHKey(BaseModel, extra='forbid'):
""" SSH key model """
file: Optional[str]
key: Optional[str]
password: Optional[str]
prompt_password: Optional[bool] = Field(alias='prompt-password')
aliases: Optional[List[str]]

version: Optional[float]
steps: Optional[Dict[str, Step]]

github: Optional[Dict[str, GithubModel]]
file: Optional[str] = None
key: Optional[str] = None
password: Optional[str] = None
prompt_password: Optional[bool] = Field(alias='prompt-password', default=None)
aliases: Optional[List[str]] = None

version: Optional[float] = None
steps: Optional[Dict[str, Step]] = None
# steps: Optional[Dict[str, str]] = None
# steps: Optional[str] = None

github: Optional[Dict[str, GithubModel]] = None
# Global config attributes
env: Optional[Dict[str, str]]
build_servers: Optional[Dict[str, Union[str, List[str]]]] = Field(alias='build-servers')
env: Optional[Dict[str, str]] = None
build_servers: Optional[Dict[str, Union[str, List[str]]]] = Field(alias='build-servers', default=None)
# Intentionally has loose restrictions on ssh-keys since documentation isn't clear
ssh_keys: Optional[Union[SSHKey, List[SSHKey]]] = Field(alias='ssh-keys')
local_files: Optional[Dict[str, str]] = Field(alias='local-files')
caches_root: Optional[str] = Field(alias='caches-root')
docker_registry: Optional[str] = Field(alias='docker-registry')
temp_dir: Optional[str] = Field(alias='temp-dir')
disable_multi_platform: Optional[bool] = Field(alias='disable-multi-platform')

# Note this is pydantic version 1.10 syntax
@validator('steps')
ssh_keys: Optional[Union[SSHKey, List[SSHKey]]] = Field(alias='ssh-keys', default=None)
local_files: Optional[Dict[str, str]] = Field(alias='local-files', default=None)
caches_root: Optional[str] = Field(alias='caches-root', default=None)
docker_registry: Optional[str] = Field(alias='docker-registry', default=None)
temp_dir: Optional[str] = Field(alias='temp-dir', default=None)
disable_multi_platform: Optional[bool] = Field(alias='disable-multi-platform', default=None)

@field_validator('steps')
@classmethod
def validate_steps(cls, values) -> None:
def validate_steps(cls, vals) -> None:
"""
Validate the config file
Expand Down Expand Up @@ -115,7 +116,7 @@ def validate_multi_platform_build(mp_push_tags: Set[str]):
ValueError | pydantic.ValidationError: If the config file is invalid
"""
# Iterate through each step
for step_name, step in values.items():
for step_name, step in vals.items():
if step.is_multi_platform():
if step.build.platform is not None:
raise ValueError(f'Cannot specify both platform ({step.build.platform}) and '
Expand All @@ -128,23 +129,23 @@ def validate_multi_platform_build(mp_push_tags: Set[str]):
validate_push(step.push, mp_push_tags, step_name)

has_multi_platform_build = False
for step in values.values():
for step in vals.values():
has_multi_platform_build = has_multi_platform_build or step.is_multi_platform()

if has_multi_platform_build:
mp_push_tags = set()
validate_multi_platform_build(mp_push_tags)

# Validate that all tags are unique across all multi-platform step
for step_name, step in values.items():
for step_name, step in vals.items():
# Check that there are no single platform tags that match multi-platform tags
if not step.is_multi_platform():
if step.push is not None:
validate_push(push=step.push,
mp_push_tags=mp_push_tags,
step_name=step_name,
update_mp_push_tags=False)
return values
return vals


def validate_config(**kwargs) -> Errors:
Expand Down
108 changes: 54 additions & 54 deletions buildrunner/validation/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,97 +22,97 @@ class StepPypiPush(BaseModel, extra='forbid'):
class Artifact(BaseModel):
""" Artifact model """
# Intentionally loose restrictions
format: Optional[str]
type: Optional[Any]
compression: Optional[str]
push: Optional[bool]
format: Optional[str] = None
type: Optional[Any] = None
compression: Optional[str] = None
push: Optional[bool] = None


class StepBuild(BaseModel, extra='forbid'):
""" Build model within a step """
path: Optional[str]
dockerfile: Optional[str]
pull: Optional[bool]
platform: Optional[str]
platforms: Optional[List[str]]
inject: Optional[Dict[str, Optional[str]]]
no_cache: Optional[bool] = Field(alias='no-cache')
buildargs: Optional[Dict[str, Any]]
path: Optional[str] = None
dockerfile: Optional[str] = None
pull: Optional[bool] = None
platform: Optional[str] = None
platforms: Optional[List[str]] = None
inject: Optional[Dict[str, Optional[str]]] = None
no_cache: Optional[bool] = Field(alias='no-cache', default=None)
buildargs: Optional[Dict[str, Any]] = None


class RunAndServicesBase(BaseModel):
"""
Base model for Run and Service
which has several common fields
"""
image: Optional[str]
cmd: Optional[str]
image: Optional[str] = None
cmd: Optional[str] = None
# Intentionally loose restrictions
provisioners: Optional[Dict[str, str]]
shell: Optional[str]
cwd: Optional[str]
user: Optional[str]
hostname: Optional[str]
dns: Optional[List[str]]
dns_search: Optional[str]
extra_hosts: Optional[Dict[str, str]]
env: Optional[Dict[str, Optional[str]]]
files: Optional[Dict[str, str]]
volumes_from: Optional[List[str]]
ports: Optional[Dict[int, Optional[Union[int, None]]]]
pull: Optional[bool]
systemd: Optional[bool]
containers: Optional[List[str]]
caches: Optional[Dict[str, Union[str, List[str]]]]
provisioners: Optional[Dict[str, str]] = None
shell: Optional[str] = None
cwd: Optional[str] = None
user: Optional[str] = None
hostname: Optional[str] = None
dns: Optional[List[str]] = None
dns_search: Optional[str] = None
extra_hosts: Optional[Dict[str, str]] = None
env: Optional[Dict[str, Optional[str]]] = None
files: Optional[Dict[str, str]] = None
volumes_from: Optional[List[str]] = None
ports: Optional[Dict[int, Optional[Union[int, None]]]] = None
pull: Optional[bool] = None
systemd: Optional[bool] = None
containers: Optional[List[str]] = None
caches: Optional[Dict[str, Union[str, List[str]]]] = None


class Service(RunAndServicesBase, extra='forbid'):
""" Service model """
build: Optional[Union[StepBuild, str]]
wait_for: Optional[List[Any]]
inject_ssh_agent: Optional[bool] = Field(alias='inject-ssh-agent')
build: Optional[Union[StepBuild, str]] = None
wait_for: Optional[List[Any]] = None
inject_ssh_agent: Optional[bool] = Field(alias='inject-ssh-agent', default=None)
# Not sure if this is valid, but it is in a test file
# Didn't use StepRun because of the potential to have a infinitely nested model
run: Optional[Any]
run: Optional[Any] = None


class StepRun(RunAndServicesBase, extra='forbid'):
""" Run model within a step """
xfail: Optional[bool]
services: Optional[Dict[str, Service]]
cmds: Optional[List[str]]
ssh_keys: Optional[List[str]] = Field(alias='ssh-keys')
artifacts: Optional[Dict[str, Optional[Artifact]]]
platform: Optional[str]
cap_add: Optional[Union[str, List[str]]]
privileged: Optional[bool]
post_build: Optional[Union[str, Dict[str, Any]]] = Field(alias='post-build')
no_cache: Optional[bool] = Field(alias='no-cache')
xfail: Optional[bool] = None
services: Optional[Dict[str, Service]] = None
cmds: Optional[List[str]] = None
ssh_keys: Optional[List[str]] = Field(alias='ssh-keys', default=None)
artifacts: Optional[Dict[str, Union[Artifact, None]]] = None
platform: Optional[str] = None
cap_add: Optional[Union[str, List[str]]] = None
privileged: Optional[bool] = None
post_build: Optional[Union[str, Dict[str, Any]]] = Field(alias='post-build', default=None)
no_cache: Optional[bool] = Field(alias='no-cache', default=None)


class StepRemote(BaseModel, extra='forbid'):
""" Remote model within a step """
# Not sure if host is optional or required
host: Optional[str]
host: Optional[str] = None
cmd: str
artifacts: Optional[Dict[str, Union[Artifact, None]]]
artifacts: Optional[Dict[str, Union[Artifact, None]]] = None


class StepPushCommitDict(BaseModel, extra='forbid'):
""" Push model within a step """
repository: str
tags: Optional[List[str]]
tags: Optional[List[str]] = None


class Step(BaseModel, extra='forbid'):
""" Step model """
build: Optional[Union[StepBuild, str]]
push: Optional[Union[StepPushCommitDict, List[Union[str, StepPushCommitDict]], str]]
commit: Optional[Union[StepPushCommitDict, List[Union[str, StepPushCommitDict]], str]]
remote: Optional[StepRemote]
run: Optional[StepRun]
depends: Optional[List[str]]
pypi_push: Optional[Union[StepPypiPush, str]] = Field(alias='pypi-push')
build: Optional[Union[StepBuild, str]] = None
push: Optional[Union[StepPushCommitDict, List[Union[str, StepPushCommitDict]], str]] = None
commit: Optional[Union[StepPushCommitDict, List[Union[str, StepPushCommitDict]], str]] = None
remote: Optional[StepRemote] = None
run: Optional[StepRun] = None
depends: Optional[List[str]] = None
pypi_push: Optional[Union[StepPypiPush, str]] = Field(alias='pypi-push', default=None)

def is_multi_platform(self):
"""
Expand Down
4 changes: 2 additions & 2 deletions requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ twine>=3.2.0
vcsinfo>=2.1.105
graphlib-backport>=1.0.3
timeout-decorator>=0.5.0
python-on-whales>=0.61.0
python-on-whales>=0.64.3
# python-on-whales requires pydantic 1.10.11 08/2023
pydantic>=1.10.11
pydantic>=2.4.2
retry2>=0.9.5
9 changes: 7 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#
# pip-compile requirements.in
#
annotated-types==0.6.0
# via pydantic
bcrypt==4.0.1
# via
# -r requirements.in
Expand Down Expand Up @@ -73,17 +75,19 @@ pkginfo==1.9.6
# via twine
pycparser==2.21
# via cffi
pydantic==1.10.11
pydantic==2.4.2
# via
# -r requirements.in
# python-on-whales
pydantic-core==2.10.1
# via pydantic
pygments==2.15.1
# via
# readme-renderer
# rich
pynacl==1.5.0
# via paramiko
python-on-whales==0.62.0
python-on-whales==0.65.0
# via -r requirements.in
pyyaml==6.0
# via -r requirements.in
Expand Down Expand Up @@ -119,6 +123,7 @@ typer==0.9.0
typing-extensions==4.7.1
# via
# pydantic
# pydantic-core
# python-on-whales
# typer
urllib3==2.0.3
Expand Down

0 comments on commit d3a742e

Please sign in to comment.