From 77258f7e53c495f248a15114aa338d602d20d281 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sat, 13 Apr 2024 08:43:05 -0700 Subject: [PATCH] python/roman-numerals: 1st iteration - py3.12 --- python/README.md | 1 + python/roman-numerals/.coverage | 1 + python/roman-numerals/.coverage.xml | 53 ++ python/roman-numerals/.coveragerc | 2 + python/roman-numerals/.pylintrc | 1 + python/roman-numerals/README.md | 7 +- python/roman-numerals/pytest.ini | 5 + python/roman-numerals/roman_numerals.py | 34 +- python/roman-numerals/roman_numerals.py,cover | 33 ++ python/roman-numerals/run-tests-python.txt | 513 ++++++++++++++++++ .../src/roman_numerals/__init__.py | 0 .../src/roman_numerals/roman_numerals.py | 1 + python/roman-numerals/test/__init__.py | 0 python/roman-numerals/test/__init__.py,cover | 0 .../test/roman_numerals_test.py | 1 + 15 files changed, 649 insertions(+), 3 deletions(-) create mode 100644 python/roman-numerals/.coverage create mode 100644 python/roman-numerals/.coverage.xml create mode 100644 python/roman-numerals/.coveragerc create mode 120000 python/roman-numerals/.pylintrc create mode 100644 python/roman-numerals/pytest.ini create mode 100644 python/roman-numerals/roman_numerals.py,cover create mode 100644 python/roman-numerals/run-tests-python.txt create mode 100644 python/roman-numerals/src/roman_numerals/__init__.py create mode 120000 python/roman-numerals/src/roman_numerals/roman_numerals.py create mode 100644 python/roman-numerals/test/__init__.py create mode 100644 python/roman-numerals/test/__init__.py,cover create mode 120000 python/roman-numerals/test/roman_numerals_test.py diff --git a/python/README.md b/python/README.md index d714801b..653a6d7f 100644 --- a/python/README.md +++ b/python/README.md @@ -41,3 +41,4 @@ - [plane-tickets](./plane-tickets/README.md) - [raindrops](./raindrops/README.md) - [reverse-string](./reverse-string/README.md) +- [roman-numerals](./roman-numerals/README.md) diff --git a/python/roman-numerals/.coverage b/python/roman-numerals/.coverage new file mode 100644 index 00000000..37ef0b9b --- /dev/null +++ b/python/roman-numerals/.coverage @@ -0,0 +1 @@ +!coverage.py: This is a private format, don't read it directly!{"arcs":{"/home/vpayno/git_vpayno/exercism-workspace/python/roman-numerals/test/__init__.py":[[0,0],[0,-1]],"/home/vpayno/git_vpayno/exercism-workspace/python/roman-numerals/roman_numerals.py":[[0,1],[1,3],[3,5],[5,6],[6,7],[7,10],[10,-1],[10,11],[11,13],[13,14],[14,15],[15,16],[16,17],[17,18],[18,19],[19,20],[20,21],[21,22],[22,23],[23,24],[24,25],[25,26],[26,28],[28,29],[29,30],[30,31],[31,29],[29,28],[28,33],[33,-10]]}} \ No newline at end of file diff --git a/python/roman-numerals/.coverage.xml b/python/roman-numerals/.coverage.xml new file mode 100644 index 00000000..7db84222 --- /dev/null +++ b/python/roman-numerals/.coverage.xml @@ -0,0 +1,53 @@ + + + + + + /home/vpayno/git_vpayno/exercism-workspace/python/roman-numerals + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/roman-numerals/.coveragerc b/python/roman-numerals/.coveragerc new file mode 100644 index 00000000..883531db --- /dev/null +++ b/python/roman-numerals/.coveragerc @@ -0,0 +1,2 @@ +[run] +omit = __init__.py, *_test.py diff --git a/python/roman-numerals/.pylintrc b/python/roman-numerals/.pylintrc new file mode 120000 index 00000000..30b33b52 --- /dev/null +++ b/python/roman-numerals/.pylintrc @@ -0,0 +1 @@ +../.pylintrc \ No newline at end of file diff --git a/python/roman-numerals/README.md b/python/roman-numerals/README.md index 56dffd2d..7146f360 100644 --- a/python/roman-numerals/README.md +++ b/python/roman-numerals/README.md @@ -96,4 +96,9 @@ Make sure to check out our Deep Dive video at the end to explore the different a ### Based on -The Roman Numeral Kata - https://codingdojo.org/kata/RomanNumerals/ \ No newline at end of file +The Roman Numeral Kata - https://codingdojo.org/kata/RomanNumerals/ + +### My Solution + +- [my solution](./roman_numerals.py) +- [run-tests](./run-tests-python.txt) diff --git a/python/roman-numerals/pytest.ini b/python/roman-numerals/pytest.ini new file mode 100644 index 00000000..8dc12a49 --- /dev/null +++ b/python/roman-numerals/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +pythonpath = . +addopts = --doctest-modules +markers = + task: exercise task/step diff --git a/python/roman-numerals/roman_numerals.py b/python/roman-numerals/roman_numerals.py index 96f266dc..0f3a69f5 100644 --- a/python/roman-numerals/roman_numerals.py +++ b/python/roman-numerals/roman_numerals.py @@ -1,3 +1,33 @@ -def roman(number): - pass +"""Python Roman Numerals Exercism""" +from collections import OrderedDict + +type modern_numeral_t = int # type: ignore[valid-type] +type roman_numeral_t = str # type: ignore[valid-type] +type map_d2r_t = OrderedDict[modern_numeral_t, roman_numeral_t] # type: ignore[valid-type] + + +def roman(number: modern_numeral_t) -> roman_numeral_t: + rn: roman_numeral_t = "" + + d2r: map_d2r_t = OrderedDict() + d2r[1] = "I" + d2r[4] = "IV" + d2r[5] = "V" + d2r[9] = "IX" + d2r[10] = "X" + d2r[40] = "XL" + d2r[50] = "L" + d2r[90] = "XC" + d2r[100] = "C" + d2r[400] = "CD" + d2r[500] = "D" + d2r[900] = "CM" + d2r[1000] = "M" + + for d, r in reversed(d2r.items()): + while number >= d: + rn = f"{rn}{r}" + number -= d + + return rn diff --git a/python/roman-numerals/roman_numerals.py,cover b/python/roman-numerals/roman_numerals.py,cover new file mode 100644 index 00000000..a21910e6 --- /dev/null +++ b/python/roman-numerals/roman_numerals.py,cover @@ -0,0 +1,33 @@ +> """Python Roman Numerals Exercism""" + +> from collections import OrderedDict + +> type modern_numeral_t = int # type: ignore[valid-type] +> type roman_numeral_t = str # type: ignore[valid-type] +> type map_d2r_t = OrderedDict[modern_numeral_t, roman_numeral_t] # type: ignore[valid-type] + + +> def roman(number: modern_numeral_t) -> roman_numeral_t: +> rn: roman_numeral_t = "" + +> d2r: map_d2r_t = OrderedDict() +> d2r[1] = "I" +> d2r[4] = "IV" +> d2r[5] = "V" +> d2r[9] = "IX" +> d2r[10] = "X" +> d2r[40] = "XL" +> d2r[50] = "L" +> d2r[90] = "XC" +> d2r[100] = "C" +> d2r[400] = "CD" +> d2r[500] = "D" +> d2r[900] = "CM" +> d2r[1000] = "M" + +> for d, r in reversed(d2r.items()): +> while number >= d: +> rn = f"{rn}{r}" +> number -= d + +> return rn diff --git a/python/roman-numerals/run-tests-python.txt b/python/roman-numerals/run-tests-python.txt new file mode 100644 index 00000000..c6208626 --- /dev/null +++ b/python/roman-numerals/run-tests-python.txt @@ -0,0 +1,513 @@ +Running automated test file(s): + + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-pylint + +Running Python Lint - PyLint + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: pylint --version + +pylint 3.0.3 +astroid 3.0.2 +Python 3.12.1 (main, Dec 28 2023, 08:22:05) [GCC 10.2.1 20210110] + +real 0m0.221s +user 0m0.162s +sys 0m0.062s + + + ============================================================================== + +Running: pylint ./src + +************* Module roman_numerals.roman_numerals +src/roman_numerals/roman_numerals.py:10:0: C0116: Missing function or method docstring (missing-function-docstring) + +------------------------------------------------------------------ +Your code has been rated at 9.60/10 (previous run: 9.62/10, -0.02) + + +real 0m0.579s +user 0m0.490s +sys 0m0.091s + + + ============================================================================== + +Exit code: -1 + +real 0m1.712s +user 0m1.296s +sys 0m0.440s + +real 0m1.716s +user 0m1.296s +sys 0m0.444s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-ruff + +Running Python Lint - Ruff + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: ruff --version + +ruff 0.3.5 + +real 0m0.079s +user 0m0.030s +sys 0m0.051s + + + ============================================================================== + +Running: ruff check --ignore E501 ./src + +All checks passed! + +real 0m0.097s +user 0m0.040s +sys 0m0.061s + + + ============================================================================== + +Exit code: 0 + +real 0m1.096s +user 0m0.727s +sys 0m0.395s + +real 0m1.098s +user 0m0.728s +sys 0m0.396s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-pyright + +Running Python Lint - PyRight + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: pyright --version + +pyright 1.1.358 + +real 0m1.021s +user 0m0.504s +sys 0m0.132s + + + ============================================================================== + +Running: pyright --stats ./src + +Found 2 source files +pyright 1.1.358 +0 errors, 0 warnings, 0 informations +Completed in 0.617sec + +Analysis stats +Total files parsed and bound: 20 +Total files checked: 2 + +Timing stats +Find Source Files: 0sec +Read Source Files: 0.01sec +Tokenize: 0.05sec +Parse: 0.05sec +Resolve Imports: 0.05sec +Bind: 0.05sec +Check: 0.09sec +Detect Cycles: 0sec + +real 0m1.250s +user 0m1.352s +sys 0m0.177s + + + ============================================================================== + +Exit code: 0 + +real 0m3.209s +user 0m2.501s +sys 0m0.620s + +real 0m3.212s +user 0m2.504s +sys 0m0.620s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-bandit + +Running Python Lint - Bandit + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: bandit --version + +bandit 1.7.7 + python version = 3.12.1 (main, Dec 28 2023, 08:22:05) [GCC 10.2.1 20210110] + +real 0m0.269s +user 0m0.215s +sys 0m0.056s + + + ============================================================================== + +Running: bandit --verbose --recursive ./src + +[main] INFO profile include tests: None +[main] INFO profile exclude tests: None +[main] INFO cli include tests: None +[main] INFO cli exclude tests: None +[main] INFO running on Python 3.12.1 +Run started:2024-04-13 15:41:59.990562 +Files in scope (2): + ./src/roman_numerals/__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) + ./src/roman_numerals/roman_numerals.py (score: {SEVERITY: 0, CONFIDENCE: 0}) +Files excluded (2): + ./src/roman_numerals/__pycache__/__init__.cpython-312.pyc + ./src/roman_numerals/__pycache__/roman_numerals.cpython-312.pyc + +Test results: + No issues identified. + +Code scanned: + Total lines of code: 26 + Total lines skipped (#nosec): 0 + Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 + +Run metrics: + Total issues (by severity): + Undefined: 0 + Low: 0 + Medium: 0 + High: 0 + Total issues (by confidence): + Undefined: 0 + Low: 0 + Medium: 0 + High: 0 +Files skipped (0): + +real 0m0.240s +user 0m0.160s +sys 0m0.082s + + + ============================================================================== + +Exit code: 0 + +real 0m1.395s +user 0m1.024s +sys 0m0.391s + +real 0m1.397s +user 0m1.026s +sys 0m0.391s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-refurb + +Running Python Lint - Refurb + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: refurb --version + +Refurb: v1.26.0 +Mypy: v1.9.0 + +real 0m0.179s +user 0m0.120s +sys 0m0.061s + + + ============================================================================== + +Running: refurb --quiet --ignore 183 ./src + + +real 0m1.133s +user 0m1.037s +sys 0m0.098s + + + ============================================================================== + +Exit code: 0 + +real 0m3.311s +user 0m2.832s +sys 0m0.502s + +real 0m3.313s +user 0m2.833s +sys 0m0.502s + +=============================================================================== + +Running: ../../.github/citools/python/python-test-with-doctests + +Running Python DocTests + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +PYTHONPATH="./src" + + ============================================================================== + +Running: python -m doctest -v ./src/roman_numerals/__init__.py ./src/roman_numerals/roman_numerals.py + +1 items had no tests: + __init__ +0 tests in 1 items. +0 passed and 0 failed. +Test passed. +2 items had no tests: + roman_numerals + roman_numerals.roman +0 tests in 2 items. +0 passed and 0 failed. +Test passed. + +real 0m0.133s +user 0m0.083s +sys 0m0.053s + + + ============================================================================== + +Exit code: 0 + +real 0m1.041s +user 0m0.725s +sys 0m0.334s + +real 0m1.043s +user 0m0.725s +sys 0m0.336s + +=============================================================================== + +Running: ../../.github/citools/python/python-test-with-coverage + +Running Python Tests With Coverage + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: rm -rf ./coverage + + +real 0m0.001s +user 0m0.000s +sys 0m0.001s + + + ============================================================================== + +Running: pytest --version + +pytest 7.4.3 + +real 0m0.771s +user 0m0.842s +sys 0m0.821s + + + ============================================================================== + +PYTHONPATH="./src" + + ============================================================================== + +Running: pytest --verbose --cov=. --cov-branch --cov-report=term-missing --cov-report=xml:.coverage.xml -p no:randomly ./test + +============================= test session starts ============================== +platform linux -- Python 3.12.1, pytest-7.4.3, pluggy-1.3.0 -- /home/vpayno/.pyenv/versions/3.12.1/bin/python +cachedir: .pytest_cache +hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase(PosixPath('/home/vpayno/git_vpayno/exercism-workspace/python/roman-numerals/.hypothesis/examples')) +rootdir: /home/vpayno/git_vpayno/exercism-workspace/python/roman-numerals +configfile: pytest.ini +plugins: anyio-4.2.0, libtmux-0.25.0, pylama-8.4.1, cov-4.1.0, datafiles-3.0.0, docker-2.0.1, subprocess-1.5.0, typeguard-4.1.5, hypothesis-6.98.17, snapshot-0.9.0 +collecting ... collected 26 items + +test/roman_numerals_test.py::RomanNumeralsTest::test_1024_is_mxxiv PASSED [ 3%] +test/roman_numerals_test.py::RomanNumeralsTest::test_141_is_cxli PASSED [ 7%] +test/roman_numerals_test.py::RomanNumeralsTest::test_163_is_clxiii PASSED [ 11%] +test/roman_numerals_test.py::RomanNumeralsTest::test_1666_is_mdclxvi PASSED [ 15%] +test/roman_numerals_test.py::RomanNumeralsTest::test_166_is_clxvi PASSED [ 19%] +test/roman_numerals_test.py::RomanNumeralsTest::test_16_is_xvi PASSED [ 23%] +test/roman_numerals_test.py::RomanNumeralsTest::test_1_is_i PASSED [ 26%] +test/roman_numerals_test.py::RomanNumeralsTest::test_27_is_xxvii PASSED [ 30%] +test/roman_numerals_test.py::RomanNumeralsTest::test_2_is_ii PASSED [ 34%] +test/roman_numerals_test.py::RomanNumeralsTest::test_3000_is_mmm PASSED [ 38%] +test/roman_numerals_test.py::RomanNumeralsTest::test_3001_is_mmmi PASSED [ 42%] +test/roman_numerals_test.py::RomanNumeralsTest::test_3999_is_mmmcmxcix PASSED [ 46%] +test/roman_numerals_test.py::RomanNumeralsTest::test_3_is_iii PASSED [ 50%] +test/roman_numerals_test.py::RomanNumeralsTest::test_402_is_cdii PASSED [ 53%] +test/roman_numerals_test.py::RomanNumeralsTest::test_48_is_xlviii PASSED [ 57%] +test/roman_numerals_test.py::RomanNumeralsTest::test_49_is_xlix PASSED [ 61%] +test/roman_numerals_test.py::RomanNumeralsTest::test_4_is_iv PASSED [ 65%] +test/roman_numerals_test.py::RomanNumeralsTest::test_575_is_dlxxv PASSED [ 69%] +test/roman_numerals_test.py::RomanNumeralsTest::test_59_is_lix PASSED [ 73%] +test/roman_numerals_test.py::RomanNumeralsTest::test_5_is_v PASSED [ 76%] +test/roman_numerals_test.py::RomanNumeralsTest::test_666_is_dclxvi PASSED [ 80%] +test/roman_numerals_test.py::RomanNumeralsTest::test_66_is_lxvi PASSED [ 84%] +test/roman_numerals_test.py::RomanNumeralsTest::test_6_is_vi PASSED [ 88%] +test/roman_numerals_test.py::RomanNumeralsTest::test_911_is_cmxi PASSED [ 92%] +test/roman_numerals_test.py::RomanNumeralsTest::test_93_is_xciii PASSED [ 96%] +test/roman_numerals_test.py::RomanNumeralsTest::test_9_is_ix PASSED [100%] + +=============================== warnings summary =============================== +../../../../.pyenv/versions/3.12.1/lib/python3.12/site-packages/coverage/pytracer.py:164 + /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/coverage/pytracer.py:164: DeprecationWarning: currentThread() is deprecated, use current_thread() instead + self.thread = self.threading.currentThread() + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html + +---------- coverage: platform linux, python 3.12.1-final-0 ----------- +Name Stmts Miss Branch BrPart Cover Missing +--------------------------------------------------------------- +roman_numerals.py 26 1 4 0 97% +test/__init__.py 0 0 0 0 100% +--------------------------------------------------------------- +TOTAL 26 1 4 0 97% +Coverage XML written to file .coverage.xml + +======================== 26 passed, 1 warning in 0.96s ========================= + +real 0m1.803s +user 0m1.682s +sys 0m0.122s + + + ============================================================================== + +Running: coverage report --show-missing + +Name Stmts Miss Branch BrPart Cover Missing +--------------------------------------------------------------- +roman_numerals.py 26 1 4 0 97% +test/__init__.py 0 0 0 0 100% +--------------------------------------------------------------- +TOTAL 26 1 4 0 97% + +real 0m0.145s +user 0m0.094s +sys 0m0.053s + + + ============================================================================== + +Running: coverage annotate + + +real 0m0.163s +user 0m0.093s +sys 0m0.073s + + + ============================================================================== + +Line Coverage: 96.2% +Branch Coverage: 100.0% + + ============================================================================== + +Exit code: 0 + +real 0m3.836s +user 0m3.387s +sys 0m1.366s + +real 0m3.838s +user 0m3.388s +sys 0m1.367s + +=============================================================================== + +tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' + +> def roman(number: modern_numeral_t) -> roman_numeral_t: +> rn: roman_numeral_t = "" + +=============================================================================== + +Running: misspell ./src/roman_numerals/__init__.py ./src/roman_numerals/roman_numerals.py + +real 0m0.018s +user 0m0.024s +sys 0m0.008s + +=============================================================================== + diff --git a/python/roman-numerals/src/roman_numerals/__init__.py b/python/roman-numerals/src/roman_numerals/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/roman-numerals/src/roman_numerals/roman_numerals.py b/python/roman-numerals/src/roman_numerals/roman_numerals.py new file mode 120000 index 00000000..2511d6a9 --- /dev/null +++ b/python/roman-numerals/src/roman_numerals/roman_numerals.py @@ -0,0 +1 @@ +../../roman_numerals.py \ No newline at end of file diff --git a/python/roman-numerals/test/__init__.py b/python/roman-numerals/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/roman-numerals/test/__init__.py,cover b/python/roman-numerals/test/__init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/python/roman-numerals/test/roman_numerals_test.py b/python/roman-numerals/test/roman_numerals_test.py new file mode 120000 index 00000000..d360b56f --- /dev/null +++ b/python/roman-numerals/test/roman_numerals_test.py @@ -0,0 +1 @@ +../roman_numerals_test.py \ No newline at end of file