diff --git a/poetry.lock b/poetry.lock index 283e80b..2885bbf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -984,6 +984,27 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "typer" +version = "0.9.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, + {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + [[package]] name = "typing-extensions" version = "4.8.0" @@ -1029,4 +1050,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "738ec68fb794caaa73108443aa5653fda2bb4bce3953b50dc3a09db492a46e56" +content-hash = "322c547268317f46591599a02d8b8486c03b3d92b8b0a0f37adf556feb2a578f" diff --git a/pyproject.toml b/pyproject.toml index 83460cf..d266f14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ pandas = "^2.1.4" pyarrow = "^14.0.1" scipy = "^1.11.4" jinja2 = "^3.1.2" +typer = "^0.9.0" [tool.poetry.group.dev.dependencies] rich = "^13.6.0" @@ -28,6 +29,9 @@ enable = true vcs = "git" style = "semver" +[tool.poetry.scripts] +deemian = "deemian.deemian:app" + [build-system] requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"] build-backend = "poetry_dynamic_versioning.backend" diff --git a/src/deemian/deemian.py b/src/deemian/deemian.py index e69de29..0195437 100644 --- a/src/deemian/deemian.py +++ b/src/deemian/deemian.py @@ -0,0 +1,32 @@ +import typer +from rich.console import Console + +from deemian.engine.builder import DeemianData +from deemian.engine.processor import parser, InstructionTransformer +from deemian.engine.director import director + + +console = Console() +app = typer.Typer() + + +@app.command(short_help="run deemian script") +def run(script_name: str): + console.print(f"[bold magenta]Running {script_name}[/bold magenta]") + with open(script_name) as f: + text = f.read() + + command_tree = parser(text) + transformer = InstructionTransformer() + command_tree = transformer.transform(command_tree) + + deemian_data = DeemianData() + director(command_tree, deemian_data) + + +# one command one callback, just a temporary helper command +# delete this when there are multiple commands +# https://typer.tiangolo.com/tutorial/commands/one-or-multiple/ +@app.callback() +def callback(): + pass diff --git a/src/deemian/writer/templates/01_detailed_conf_first.txt b/src/deemian/writer/templates/01_detailed_conf_first.txt index 0c7f63f..e0469f1 100644 --- a/src/deemian/writer/templates/01_detailed_conf_first.txt +++ b/src/deemian/writer/templates/01_detailed_conf_first.txt @@ -4,6 +4,9 @@ interaction for "{{ pair_name }}": {%- set subject_1, subject_2 = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set confs = df.conformation.unique() -%} {%- set groupbyconf = df.groupby('conformation') -%} @@ -52,4 +55,5 @@ conf {{ "{}".format(conf).rjust(10) }} {% endfor -%} {% endif %} {% endfor %} +{% endif %} {% endfor %} diff --git a/src/deemian/writer/templates/02_detailed_type_first.txt b/src/deemian/writer/templates/02_detailed_type_first.txt index 835a1d7..26ccbd5 100644 --- a/src/deemian/writer/templates/02_detailed_type_first.txt +++ b/src/deemian/writer/templates/02_detailed_type_first.txt @@ -4,6 +4,9 @@ interaction for "{{ pair_name }}": {%- set subject_1, subject_2 = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set unique_interaction = df.interaction_type.unique() %} {%- set groupbytype = df.groupby('interaction_type') %} @@ -55,4 +58,5 @@ interaction for "{{ pair_name }}": {% endfor -%} {% endfor -%} {%- endif %} +{% endif %} {% endfor %} diff --git a/src/deemian/writer/templates/03_clustered_conf_first.txt b/src/deemian/writer/templates/03_clustered_conf_first.txt index cc17008..81f6c25 100644 --- a/src/deemian/writer/templates/03_clustered_conf_first.txt +++ b/src/deemian/writer/templates/03_clustered_conf_first.txt @@ -4,6 +4,9 @@ interaction for "{{ pair_name }}": {%- set subject_1, subject_2 = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set confs = df.conformation.unique() -%} {%- set groupbyconf = df.groupby('conformation') -%} @@ -54,4 +57,5 @@ conf {{ "{}".format(conf).rjust(10) }} {% endfor -%} {%- endif %} {% endfor %} +{% endif %} {% endfor %} diff --git a/src/deemian/writer/templates/04_clustered_type_first.txt b/src/deemian/writer/templates/04_clustered_type_first.txt index 8be88d8..359f72c 100644 --- a/src/deemian/writer/templates/04_clustered_type_first.txt +++ b/src/deemian/writer/templates/04_clustered_type_first.txt @@ -4,7 +4,9 @@ interaction for "{{ pair_name }}": {%- set subject_1, subject_2 = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} - +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set unique_interaction = df.interaction_type.unique() %} {%- set groupbytype = df.groupby('interaction_type') %} {%- if 'electrostatic_cation' in unique_interaction %} @@ -59,4 +61,5 @@ interaction for "{{ pair_name }}": {% endfor -%} {% endfor %} {%- endif %} +{% endif %} {% endfor %} diff --git a/src/deemian/writer/templates/05_summarized_conf_first.txt b/src/deemian/writer/templates/05_summarized_conf_first.txt index fba5523..e546b4f 100644 --- a/src/deemian/writer/templates/05_summarized_conf_first.txt +++ b/src/deemian/writer/templates/05_summarized_conf_first.txt @@ -4,6 +4,9 @@ interaction for "{{ pair_name }}": {%- set subjects = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set confs = df.conformation.unique() -%} {%- set groupbyconf = df.groupby('conformation') -%} @@ -63,4 +66,5 @@ conf {{ "{}".format(conf).rjust(10) }} {% endfor -%} {%- endif %} {% endfor %} +{% endif %} {% endfor %} diff --git a/src/deemian/writer/templates/06_summarized_type_first.txt b/src/deemian/writer/templates/06_summarized_type_first.txt index 80a6074..3a37686 100644 --- a/src/deemian/writer/templates/06_summarized_type_first.txt +++ b/src/deemian/writer/templates/06_summarized_type_first.txt @@ -4,7 +4,9 @@ interaction for "{{ pair_name }}": {%- set subjects = interacting_subjects[pair_name] -%} {%- set df = interaction_data.dataframe -%} - +{%- if len(df) == 0 %} + No interaction detected +{%- else -%} {%- set unique_interaction = df.interaction_type.unique() %} {%- set groupbytype = df.groupby('interaction_type') %} {%- if 'electrostatic_cation' in unique_interaction %} @@ -69,4 +71,5 @@ interaction for "{{ pair_name }}": {% endfor -%} {% endfor -%} {%- endif %} +{% endif %} {% endfor %} diff --git a/tests/test_deemian.py b/tests/test_deemian.py index a86713a..e2cafbf 100644 --- a/tests/test_deemian.py +++ b/tests/test_deemian.py @@ -1 +1,14 @@ -# from deemian import deemian +from unittest.mock import patch + +from typer.testing import CliRunner + +from deemian.deemian import app + + +runner = CliRunner() + + +def test_app(): + with patch("deemian.deemian.director"): + result = runner.invoke(app, ["run", "tests/data/n1-oseltamivir-5nzn.txt"]) + assert result.exit_code == 0