From 5749d7a1aef77b0cb6d75d1384276b419c3c08b0 Mon Sep 17 00:00:00 2001 From: Neal Kruis Date: Fri, 27 Dec 2024 14:53:22 -0700 Subject: [PATCH 1/3] Use doit for task automation. --- .github/workflows/test.yaml | 15 +----- dodo.py | 40 ++++++++++++++++ poetry.lock | 93 ++++++++++++++++++++++++++++++++----- pyproject.toml | 3 +- 4 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 dodo.py diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ae2e9fe..8bf95af 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -26,17 +26,6 @@ jobs: uses: bigladder/github-actions/setup-python-poetry@main with: python-version: ${{ matrix.python-version }} - - name: Lint with Pylint + - name: Run tasks run: | - poetry run pylint ${{env.REPOSITORY_NAME}} - poetry run pylint test/*.py - continue-on-error: true - - name: Static type checking - run: | - poetry run mypy ${{env.REPOSITORY_NAME}} - poetry run mypy test/*.py - continue-on-error: true - - name: Test - run: poetry run pytest - - name: List units - run: poetry run koozie -l + poetry run doit -v 2 diff --git a/dodo.py b/dodo.py new file mode 100644 index 0000000..b104ab3 --- /dev/null +++ b/dodo.py @@ -0,0 +1,40 @@ +import pytest + +DOIT_CONFIG = {"continue": True} + +project_name = "koozie" + + +def task_check_code(): + """Run linter(s)""" + checkers = ["pylint", "mypy", "black --check"] + source_checking_paths = [project_name, "test/*.py"] + + for checker in checkers: + for path in source_checking_paths: + yield { + "name": f"{checker} {path}", + "actions": [f"{checker} {path}"], + "verbosity": 1, # print only errors + } + + +def run_pytest(): + """Run pytest""" + return not bool(pytest.main(["-v", "-s", "test"])) + + +def task_test(): + """Performs tests""" + return { + "actions": [(run_pytest, [])], + "verbosity": 2, # print everything + } + + +def task_run_cli(): + """Run the CLI""" + return { + "actions": ["koozie -l"], + "verbosity": 1, # print only errors + } diff --git a/poetry.lock b/poetry.lock index 77b6ce2..8acd32f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "astroid" -version = "3.3.6" +version = "3.3.8" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.9.0" files = [ - {file = "astroid-3.3.6-py3-none-any.whl", hash = "sha256:db676dc4f3ae6bfe31cda227dc60e03438378d7a896aec57422c95634e8d722f"}, - {file = "astroid-3.3.6.tar.gz", hash = "sha256:6aaea045f938c735ead292204afdb977a36e989522b7833ef6fea94de743f442"}, + {file = "astroid-3.3.8-py3-none-any.whl", hash = "sha256:187ccc0c248bfbba564826c26f070494f7bc964fd286b6d9fff4420e55de828c"}, + {file = "astroid-3.3.8.tar.gz", hash = "sha256:a88c7994f914a4ea8572fac479459f4955eeccc877be3f2d959a33273b0cf40b"}, ] [package.dependencies] @@ -62,18 +62,29 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "click" -version = "8.1.7" +version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "cloudpickle" +version = "3.1.0" +description = "Pickler class to extend the standard pickle.Pickler functionality" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cloudpickle-3.1.0-py3-none-any.whl", hash = "sha256:fe11acda67f61aaaec473e3afe030feb131d78a43461b718185363384f1ba12e"}, + {file = "cloudpickle-3.1.0.tar.gz", hash = "sha256:81a929b6e3c7335c863c771d673d105f02efdb89dfaba0c90495d1c64796601b"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -100,6 +111,24 @@ files = [ graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] +[[package]] +name = "doit" +version = "0.36.0" +description = "doit - Automation Tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "doit-0.36.0-py3-none-any.whl", hash = "sha256:ebc285f6666871b5300091c26eafdff3de968a6bd60ea35dd1e3fc6f2e32479a"}, + {file = "doit-0.36.0.tar.gz", hash = "sha256:71d07ccc9514cb22fe59d98999577665eaab57e16f644d04336ae0b4bae234bc"}, +] + +[package.dependencies] +cloudpickle = "*" +importlib-metadata = ">=4.4" + +[package.extras] +toml = ["tomli"] + [[package]] name = "exceptiongroup" version = "1.2.2" @@ -148,6 +177,29 @@ typing-extensions = "*" [package.extras] test = ["pytest", "pytest-cov", "pytest-mpl", "pytest-subtests"] +[[package]] +name = "importlib-metadata" +version = "8.5.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, +] + +[package.dependencies] +zipp = ">=3.20" + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -332,17 +384,17 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pylint" -version = "3.3.2" +version = "3.3.3" description = "python code static checker" optional = false python-versions = ">=3.9.0" files = [ - {file = "pylint-3.3.2-py3-none-any.whl", hash = "sha256:77f068c287d49b8683cd7c6e624243c74f92890f767f106ffa1ddf3c0a54cb7a"}, - {file = "pylint-3.3.2.tar.gz", hash = "sha256:9ec054ec992cd05ad30a6df1676229739a73f8feeabf3912c995d17601052b01"}, + {file = "pylint-3.3.3-py3-none-any.whl", hash = "sha256:26e271a2bc8bce0fc23833805a9076dd9b4d5194e2a02164942cb3cdc37b4183"}, + {file = "pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a"}, ] [package.dependencies] -astroid = ">=3.3.5,<=3.4.0-dev0" +astroid = ">=3.3.8,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -444,7 +496,26 @@ files = [ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] +[[package]] +name = "zipp" +version = "3.21.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "bc8714af7378db482ed83c136c61aeb82322d5a8a807a66887fdce7a1c3baf24" +content-hash = "abcd1d97fac332edce5bdf66b1badf0b24346f3781eb1253d614f8f5934d8517" diff --git a/pyproject.toml b/pyproject.toml index 16f1d6b..6415339 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,8 +13,9 @@ python = "^3.10" pint = "^0.24" click = "^8.1.3" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] pytest = "^7.1.3" +doit = "*" pylint = "*" black = "*" mypy = "*" From f196e66e79de8a8016a877470e1bfc57af9b44c4 Mon Sep 17 00:00:00 2001 From: Neal Kruis Date: Fri, 27 Dec 2024 14:58:41 -0700 Subject: [PATCH 2/3] Add unit formatting. --- koozie/__init__.py | 3 ++- koozie/__main__.py | 3 ++- koozie/cli.py | 5 ++--- koozie/koozie.py | 5 +++++ test/test_koozie.py | 17 ++++++++++++++++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/koozie/__init__.py b/koozie/__init__.py index 710830c..54b6bfb 100644 --- a/koozie/__init__.py +++ b/koozie/__init__.py @@ -1,2 +1,3 @@ """koozie public interface""" -from .koozie import fr_u, to_u, convert, get_dimensionality + +from .koozie import fr_u, to_u, convert, get_dimensionality, format_units diff --git a/koozie/__main__.py b/koozie/__main__.py index 7ea3096..b3434e9 100644 --- a/koozie/__main__.py +++ b/koozie/__main__.py @@ -1,5 +1,6 @@ """Main calling point for the command line interface""" + from koozie.cli import koozie_cli if __name__ == "__main__": - koozie_cli() # pylint: disable=no-value-for-parameter + koozie_cli() # pylint: disable=no-value-for-parameter diff --git a/koozie/cli.py b/koozie/cli.py index 6f8953a..e813fb0 100644 --- a/koozie/cli.py +++ b/koozie/cli.py @@ -1,4 +1,5 @@ """koozie command line interface""" + import sys import click import koozie @@ -32,9 +33,7 @@ def list_callback(context: click.Context, _: click.Parameter, value: str) -> Non context.exit() -@click.command( - context_settings={"help_option_names": ["-h", "--help"], "ignore_unknown_options": True} -) +@click.command(context_settings={"help_option_names": ["-h", "--help"], "ignore_unknown_options": True}) @click.version_option(None, "-v", "--version") @click.option( "-l", diff --git a/koozie/koozie.py b/koozie/koozie.py index 25303c8..eb78bb1 100644 --- a/koozie/koozie.py +++ b/koozie/koozie.py @@ -79,6 +79,11 @@ def get_dimensionality(units: str) -> pint.util.UnitsContainer: return unit_registry.Unit(units).dimensionality +def format_units(units: str) -> str: + """Format units for display.""" + return f"{unit_registry.Unit(units):~P}" + + def get_unit_list() -> OrderedDict: """Get list of valid units.""" unit_list: dict = {} diff --git a/test/test_koozie.py b/test/test_koozie.py index 070c9f1..b59bf4c 100644 --- a/test/test_koozie.py +++ b/test/test_koozie.py @@ -4,7 +4,7 @@ from pytest import approx from click.testing import CliRunner -from koozie import fr_u, to_u, convert, get_dimensionality +from koozie import fr_u, to_u, convert, get_dimensionality, format_units from koozie.cli import koozie_cli @@ -28,6 +28,21 @@ def test_dimensionality(): assert get_dimensionality("F") != get_dimensionality("C") assert get_dimensionality("%") == get_dimensionality("") assert get_dimensionality("h") == get_dimensionality("s") + assert get_dimensionality("ton_ref") == get_dimensionality("W") + + +def test_unit_formatting(): + """Test unit formatting""" + assert format_units("degF") == "°F" + assert format_units("m**3/s") == "m³/s" + assert format_units("m**1.5/s") == "m¹⋅⁵/s" + assert format_units("m**2*K/W") == "K·m²/W" + assert format_units("degree") == "deg" + assert format_units("cm**3") == "cm³" + assert format_units("inch_H2O_39F") == "inch_H2O_39F" + assert format_units("cfm") == "cfm" + # assert format_units("thermal_resistance_SI") == "m²·K/W" + # assert format_units("ton_ref") == "ton_ref" def test_iterable(): From 8b07ca2eca18af8e917008d59f3f8da3aa2724c0 Mon Sep 17 00:00:00 2001 From: Neal Kruis Date: Mon, 30 Dec 2024 11:52:34 -0700 Subject: [PATCH 3/3] Apply workarounds for weird Windows issues. --- .github/workflows/test.yaml | 4 ++-- dodo.py | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8bf95af..80cd521 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -26,6 +26,6 @@ jobs: uses: bigladder/github-actions/setup-python-poetry@main with: python-version: ${{ matrix.python-version }} - - name: Run tasks + - name: Run tasks # doit -v 1 for now because of issue with Windows output stream character maps run: | - poetry run doit -v 2 + poetry run doit -v 1 diff --git a/dodo.py b/dodo.py index b104ab3..77adb8b 100644 --- a/dodo.py +++ b/dodo.py @@ -8,13 +8,17 @@ def task_check_code(): """Run linter(s)""" checkers = ["pylint", "mypy", "black --check"] - source_checking_paths = [project_name, "test/*.py"] + source_checking_paths = [project_name, "test"] for checker in checkers: for path in source_checking_paths: + command = f"{checker} {path}" + if checker == "pylint": + # Get around weird issue on Windows + command += "/*.py" yield { "name": f"{checker} {path}", - "actions": [f"{checker} {path}"], + "actions": [command], "verbosity": 1, # print only errors }