-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ZnTrack v0.5.0 * add CLI from #301 * poetry update * add cli test
- Loading branch information
Showing
7 changed files
with
273 additions
and
79 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import os | ||
import pathlib | ||
|
||
import pytest | ||
from typer.testing import CliRunner | ||
|
||
from zntrack import Node, NodeConfig, nodify, zn | ||
from zntrack.cli import app | ||
|
||
|
||
@pytest.fixture() | ||
def runner() -> CliRunner: | ||
return CliRunner() | ||
|
||
|
||
def test_version(runner): | ||
result = runner.invoke(app, ["--version"]) | ||
assert "ZnTrack " in result.stdout # ZnTrack v.x.y | ||
|
||
|
||
def test_init(tmp_path, runner): | ||
os.chdir(tmp_path) | ||
result = runner.invoke(app, ["init"]) | ||
assert "Creating new project" in result.stdout | ||
|
||
assert pathlib.Path("src").is_dir() | ||
assert (pathlib.Path("src") / "__init__.py").is_file() | ||
assert pathlib.Path(".git").is_dir() | ||
assert pathlib.Path(".dvc").is_dir() | ||
assert pathlib.Path("main.py").is_file() | ||
assert pathlib.Path("README.md").is_file() | ||
|
||
|
||
def test_init_gitignore(tmp_path, runner): | ||
os.chdir(tmp_path) | ||
_ = runner.invoke(app, ["init", "--gitignore"]) | ||
|
||
assert pathlib.Path("src").is_dir() | ||
assert (pathlib.Path("src") / "__init__.py").is_file() | ||
assert pathlib.Path(".git").is_dir() | ||
assert pathlib.Path(".dvc").is_dir() | ||
assert pathlib.Path(".gitignore").is_file() | ||
assert pathlib.Path("main.py").is_file() | ||
assert pathlib.Path("README.md").is_file() | ||
|
||
|
||
@pytest.mark.parametrize("force", (True, False)) | ||
def test_init_force(tmp_path, runner, force): | ||
os.chdir(tmp_path) | ||
pathlib.Path("file.txt").touch() | ||
|
||
if force: | ||
_ = runner.invoke(app, ["init", "--force"]) | ||
assert pathlib.Path("src").is_dir() | ||
assert (pathlib.Path("src") / "__init__.py").is_file() | ||
assert pathlib.Path(".git").is_dir() | ||
assert pathlib.Path(".dvc").is_dir() | ||
assert pathlib.Path("main.py").is_file() | ||
assert pathlib.Path("README.md").is_file() | ||
else: | ||
_ = runner.invoke(app, ["init"]) | ||
assert not pathlib.Path("src").exists() | ||
assert not pathlib.Path(".git").exists() | ||
assert not pathlib.Path(".dvc").exists() | ||
assert not pathlib.Path("main.py").exists() | ||
assert not pathlib.Path("README.md").exists() | ||
|
||
|
||
class InputsToOutputs(Node): | ||
inputs = zn.params() | ||
outputs = zn.outs() | ||
|
||
def run(self): | ||
self.outputs = self.inputs | ||
|
||
|
||
@nodify(outs="test.txt", params={"text": "Lorem Ipsum"}) | ||
def example_func(cfg: NodeConfig) -> NodeConfig: | ||
out_file = pathlib.Path(cfg.outs) | ||
out_file.write_text(cfg.params.text) | ||
return cfg | ||
|
||
|
||
def test_run(proj_path, runner): | ||
node = InputsToOutputs(inputs=15) | ||
node.write_graph() | ||
result = runner.invoke(app, ["run", "test_cli.InputsToOutputs"]) | ||
assert result.exit_code == 0 | ||
|
||
node = InputsToOutputs.load() | ||
assert node.outputs == 15 | ||
|
||
|
||
def test_run_nodify(proj_path, runner): | ||
example_func() | ||
result = runner.invoke(app, ["run", "test_cli.example_func"]) | ||
assert result.exit_code == 0 | ||
assert pathlib.Path("test.txt").read_text() == "Lorem Ipsum" | ||
|
||
|
||
def test_run_w_name(proj_path, runner): | ||
node = InputsToOutputs(inputs=15, name="TestNode") | ||
node.write_graph() | ||
result = runner.invoke(app, ["run", "test_cli.InputsToOutputs", "--name", "TestNode"]) | ||
assert result.exit_code == 0 | ||
|
||
node = InputsToOutputs["TestNode"] | ||
assert node.outputs == 15 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ | |
|
||
def test_version(): | ||
"""Test 'ZnTrack' version.""" | ||
assert __version__ == "0.4.5" | ||
assert __version__ == "0.5.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"""CLI Helpers.""" | ||
import dataclasses | ||
import pathlib | ||
import subprocess | ||
import urllib.request | ||
|
||
import typer | ||
|
||
|
||
@dataclasses.dataclass | ||
class Initializer: | ||
"""Initialize a new ZnTrack Project.""" | ||
|
||
name: str | ||
gitignore: bool | ||
force: bool | ||
src: pathlib.Path = pathlib.Path("src") | ||
|
||
_gitignore_url: str = ( | ||
"https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore" | ||
) | ||
|
||
def run(self): | ||
"""Run the initializer.""" | ||
self.check_empty() | ||
typer.echo(f"Creating new project: {self.name}") | ||
self.make_src() | ||
self.make_repo() | ||
self.write_main_file() | ||
self.write_readme() | ||
if self.gitignore: | ||
self.write_gitignore() | ||
|
||
def check_empty(self): | ||
"""Check if the project directory is empty. | ||
Raises | ||
------ | ||
typer.Exit: if the directory is not empty and force is false | ||
""" | ||
is_empty = not any(pathlib.Path(".").iterdir()) | ||
if not is_empty and not self.force: | ||
typer.echo( | ||
"The current working directory is not empty. If you want to initialize a" | ||
" project anyway use 'zntrack init --force'." | ||
) | ||
raise typer.Exit() | ||
|
||
def make_src(self): | ||
"""Create a src directory that contains the Node configurations.""" | ||
self.src.mkdir() | ||
init_file = self.src / "__init__.py" | ||
init_file.write_text(r'"""ZnTrack Node module."""') | ||
|
||
def write_gitignore(self): | ||
"""Create a gitignore file based on the Python gitignore template.""" | ||
gitignore = pathlib.Path(".gitignore") | ||
with urllib.request.urlopen(self._gitignore_url) as url: | ||
gitignore.write_text(url.read().decode("utf-8")) | ||
|
||
def write_main_file(self): | ||
"""Create a 'main.py' file.""" | ||
pathlib.Path("main.py").touch() | ||
|
||
def write_readme(self): | ||
"""Create a README.md file.""" | ||
pathlib.Path("README.md").write_text(f"# Welcome to {self.name} \n") | ||
|
||
def make_repo(self): | ||
"""Initialize the repository.""" | ||
subprocess.check_call(["git", "init"]) | ||
subprocess.check_call(["dvc", "init"]) |
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.8
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.10
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.9
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.8
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.9
8399902
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Report for Python 3.10