Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port dapp-runner to pydantic #100

Merged
merged 12 commits into from
Mar 23, 2023
Merged

Port dapp-runner to pydantic #100

merged 12 commits into from
Mar 23, 2023

Conversation

shadeofblue
Copy link
Contributor

  • remove the goth dependency from dapp-runner itself
  • remove the tailor-made BaseDescriptor
  • port DappDescriptor and its containing classes to pydantic
  • port ConfigDescriptor and its containing classes to pydantic

@shadeofblue shadeofblue self-assigned this Mar 9, 2023
@shadeofblue shadeofblue force-pushed the blue/pydantic branch 2 times, most recently from 372bd38 to b7e1752 Compare March 10, 2023 06:23
Comment on lines 62 to 63
p = v.split(":")
return {"remote_port": p.pop(), "local_port": p.pop() if p else None}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using p.pop() in this way requires way more attention, that it should... I would use more simple approach.

Suggested change
p = v.split(":")
return {"remote_port": p.pop(), "local_port": p.pop() if p else None}
p = v.split(":")
return {
"remote_port": p[0],
"local_port": p[1] if 2 <= len(p) else None,
}

Also, regex should enforce pattern of %d[:%d].

dapp_runner/descriptor/dapp.py Show resolved Hide resolved
pyproject.toml Outdated
Comment on lines 84 to 87
_tests_integration_env = "python -m venv .envs/goth"
_tests_integration_requirements = ".envs/goth/bin/pip install --extra-index-url https://test.pypi.org/simple/ goth==0.14.1 pytest pytest-asyncio pexpect"
_tests_integration_assets = ".envs/goth/bin/python -m goth create-assets tests/goth_tests/assets"
tests_integration_init = ["_tests_integration_env", "_tests_integration_requirements", "_tests_integration_assets"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent with other tasks.

Suggested change
_tests_integration_env = "python -m venv .envs/goth"
_tests_integration_requirements = ".envs/goth/bin/pip install --extra-index-url https://test.pypi.org/simple/ goth==0.14.1 pytest pytest-asyncio pexpect"
_tests_integration_assets = ".envs/goth/bin/python -m goth create-assets tests/goth_tests/assets"
tests_integration_init = ["_tests_integration_env", "_tests_integration_requirements", "_tests_integration_assets"]
tests_integration_init = ["_tests_integration_env", "_tests_integration_requirements", "_tests_integration_assets"]
_tests_integration_env = "python -m venv .envs/goth"
_tests_integration_requirements = ".envs/goth/bin/pip install --extra-index-url https://test.pypi.org/simple/ goth==0.14.1 pytest pytest-asyncio pexpect"
_tests_integration_assets = ".envs/goth/bin/python -m goth create-assets tests/goth_tests/assets"

As diff looks terrible, the intention is to have parent task first, then children tasks.

extra = "forbid"

@validator("ports", pre=True, each_item=True)
def __ports_preprocess(cls, v):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name is not consistent with __field_name__action.

class SocketProxyDescriptor(ProxyDescriptor):
"""TCP socket proxy descriptor."""


@dataclass
class CommandDescriptor:
def parse_command_descriptor(value: Union[str, List, Dict]):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving to classmethod of CommandDescriptor.

@dataclass
class NetworkDescriptor(BaseDescriptor["NetworkDescriptor"]):
@validator("init", pre=True)
def __init_commands(cls, v):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name is not consistent with __field_name__action.

class NetworkDescriptor(BaseDescriptor["NetworkDescriptor"]):
@validator("init", pre=True)
def __init_commands(cls, v):
if len(v) > 0 and isinstance(v[0], str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(v) > 0 and isinstance(v[0], str):
if len(v) and isinstance(v[0], str):

Comment on lines +199 to +203
self.__validate_nodes()
self.__implicit_proxy_init()
self.__implicit_vpn()
self.__implicit_manifest_support()
self._resolve_dependencies()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this works, it could escape few behaviors as pydantic's author mentioned. This looks like not so complicated logic that could be implemented in pydantic's per-field validators. Also, back in my pydantic-like DTOs I've moved default values from parent models down to it's children. In result, I got simpler parent models. Consider similar approach for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned on a call, these checks are not per-field and cannot be moved to the children

@shadeofblue shadeofblue linked an issue Mar 13, 2023 that may be closed by this pull request
@shadeofblue shadeofblue marked this pull request as ready for review March 22, 2023 12:20
Comment on lines 63 to 67
m = re.match("^((\\d+)\\:)?(\\d+)$", v)
if not m:
raise ValueError("Expected format: `remote_port` or `remote_port:local_port`.")

return {"remote_port": m.group(3), "local_port": m.group(2) if m.group(2) else None}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this regex can be improved.

Suggested change
m = re.match("^((\\d+)\\:)?(\\d+)$", v)
if not m:
raise ValueError("Expected format: `remote_port` or `remote_port:local_port`.")
return {"remote_port": m.group(3), "local_port": m.group(2) if m.group(2) else None}
m = re.match(r"^(?P<remote_port>\d+)(?::(?P<local_port>\d+))?$", v)
if not m:
raise ValueError("Expected format: `remote_port` or `remote_port:local_port`.")
return m.groupdict(}

@shadeofblue shadeofblue merged commit e0181d2 into main Mar 23, 2023
@shadeofblue shadeofblue deleted the blue/pydantic branch March 23, 2023 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

port dapp-runner to pydantic
2 participants