From 633628c3cc15e1d413ca03c6f2fad9087d298f27 Mon Sep 17 00:00:00 2001 From: Vladimir Roncevic Date: Thu, 27 Nov 2025 18:33:01 +0100 Subject: [PATCH] [gen_py_module] Updated code coverage, version, docs --- .../gen_py_module_package_checker.yml | 8 +- .../workflows/gen_py_module_python3_build.yml | 4 +- .../gen_py_module_python_checker.yml | 2 +- Dockerfile | 118 ++- README.md | 13 +- docs/build/doctrees/environment.pickle | Bin 249072 -> 249580 bytes docs/build/doctrees/gen_py_module.doctree | Bin 30148 -> 30188 bytes docs/build/doctrees/gen_py_module.pro.doctree | Bin 39236 -> 39276 bytes .../gen_py_module.pro.read_template.doctree | Bin 33307 -> 33347 bytes .../gen_py_module.pro.write_template.doctree | Bin 27300 -> 27340 bytes docs/build/doctrees/index.doctree | Bin 25136 -> 25154 bytes docs/build/doctrees/modules.doctree | Bin 2802 -> 2817 bytes docs/build/html/.buildinfo | 2 +- docs/build/html/_modules/gen_py_module.html | 24 +- .../html/_modules/gen_py_module/pro.html | 24 +- .../gen_py_module/pro/read_template.html | 24 +- .../gen_py_module/pro/write_template.html | 24 +- docs/build/html/_modules/index.html | 2 +- docs/build/html/_sources/index.rst.txt | 2 +- docs/build/html/gen_py_module.html | 4 +- docs/build/html/gen_py_module.pro.html | 4 +- .../html/gen_py_module.pro.read_template.html | 4 +- .../gen_py_module.pro.write_template.html | 4 +- docs/build/html/genindex.html | 2 +- docs/build/html/index.html | 4 +- docs/build/html/modules.html | 2 +- docs/build/html/objects.inv | Bin 550 -> 550 bytes docs/build/html/py-modindex.html | 2 +- docs/build/html/search.html | 2 +- docs/build/html/searchindex.js | 2 +- docs/source/conf.py | 6 +- docs/source/index.rst | 2 +- gen_py_module/__init__.py | 22 +- gen_py_module/conf/gen_py_module.cfg | 2 +- gen_py_module/pro/__init__.py | 22 +- gen_py_module/pro/read_template.py | 22 +- gen_py_module/pro/write_template.py | 22 +- gen_py_module/run/gen_py_module_run.py | 22 +- setup.cfg | 46 -- setup.py | 35 +- tests/.coverage | Bin 53248 -> 53248 bytes tests/ats_coverage.py | 215 +++++ tests/full_simple_new/full_simple_new.py | 4 +- tests/gen_py_module_coverage.json | 2 +- tests/gen_py_module_coverage.xml | 24 +- tests/gen_py_module_sub_test.py | 16 +- tests/gen_py_module_test.py | 16 +- tests/htmlcov/class_index.html | 171 ++++ tests/htmlcov/coverage_html_cb_6fb7b396.js | 733 ++++++++++++++++++ tests/htmlcov/favicon_32_cb_58284776.png | Bin 0 -> 1732 bytes tests/htmlcov/function_index.html | 219 ++++++ tests/htmlcov/index.html | 132 ++++ tests/htmlcov/keybd_closed_cb_ce680311.png | Bin 0 -> 9004 bytes tests/htmlcov/status.json | 1 + tests/htmlcov/style_cb_8e611ae1.css | 337 ++++++++ .../z_1fbd185717e15308___init___py.html | 288 +++++++ .../z_72557b19952452c1___init___py.html | 260 +++++++ .../z_72557b19952452c1_read_template_py.html | 241 ++++++ .../z_72557b19952452c1_write_template_py.html | 229 ++++++ tests/latest_pro/latest_pro.py | 4 +- tests/read_template_test.py | 16 +- tests/run_coverage.sh | 5 +- tests/simple_write/simple_write.py | 4 +- tests/write_template_test.py | 16 +- 64 files changed, 3085 insertions(+), 326 deletions(-) delete mode 100644 setup.cfg create mode 100644 tests/ats_coverage.py create mode 100644 tests/htmlcov/class_index.html create mode 100644 tests/htmlcov/coverage_html_cb_6fb7b396.js create mode 100644 tests/htmlcov/favicon_32_cb_58284776.png create mode 100644 tests/htmlcov/function_index.html create mode 100644 tests/htmlcov/index.html create mode 100644 tests/htmlcov/keybd_closed_cb_ce680311.png create mode 100644 tests/htmlcov/status.json create mode 100644 tests/htmlcov/style_cb_8e611ae1.css create mode 100644 tests/htmlcov/z_1fbd185717e15308___init___py.html create mode 100644 tests/htmlcov/z_72557b19952452c1___init___py.html create mode 100644 tests/htmlcov/z_72557b19952452c1_read_template_py.html create mode 100644 tests/htmlcov/z_72557b19952452c1_write_template_py.html diff --git a/.github/workflows/gen_py_module_package_checker.yml b/.github/workflows/gen_py_module_package_checker.yml index de50d1e..37a5b85 100755 --- a/.github/workflows/gen_py_module_package_checker.yml +++ b/.github/workflows/gen_py_module_package_checker.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 - name: set up python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: install dependencies @@ -33,5 +33,5 @@ jobs: pip install flake8 # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide => strict 79 - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=79 --statistics --max-doc-length 79 \ No newline at end of file + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=79 --statistics --max-doc-length 127 \ No newline at end of file diff --git a/.github/workflows/gen_py_module_python3_build.yml b/.github/workflows/gen_py_module_python3_build.yml index 3ef136a..5207435 100755 --- a/.github/workflows/gen_py_module_python3_build.yml +++ b/.github/workflows/gen_py_module_python3_build.yml @@ -6,7 +6,6 @@ on: - 'gen_py_module/**' - 'MANIFEST.in' - 'pyproject.toml' - - 'setup.cfg' - 'setup.py' pull_request: branches: [ master ] @@ -14,7 +13,6 @@ on: - 'gen_py_module/**' - 'MANIFEST.in' - 'pyproject.toml' - - 'setup.cfg' - 'setup.py' jobs: deploy: @@ -22,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up python3 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies diff --git a/.github/workflows/gen_py_module_python_checker.yml b/.github/workflows/gen_py_module_python_checker.yml index 205e74b..f3082bd 100644 --- a/.github/workflows/gen_py_module_python_checker.yml +++ b/.github/workflows/gen_py_module_python_checker.yml @@ -22,7 +22,7 @@ jobs: run: | modules_ok=0 modules=($(find gen_py_module/ tests/ -type f -name '*.py' -exec echo '{}' \;)) - for mod in "${modules[@]}"; do line_length=$(wc -L < "${mod}"); [[ $line_length -gt 80 ]] && modules_ok=1; done + for mod in "${modules[@]}"; do line_length=$(wc -L < "${mod}"); [[ $line_length -gt 127 ]] && modules_ok=1; done [[ $modules_ok -eq 0 ]] && echo ok || exit 1 - name: Check max number of lines in modules id: num_line_checker diff --git a/Dockerfile b/Dockerfile index e337b13..ac09c34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,60 +1,58 @@ -# Copyright 2017 - 2024 Vladimir Roncevic -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -FROM debian:12 -RUN apt-get update -RUN DEBIAN_FRONTEND=noninteractive \ - apt-get install -yq --no-install-recommends \ - vim \ - nano \ - tree \ - htop \ - unzip \ - ca-certificates \ - openssl \ - python3 \ - python3-pip \ - python3-wheel \ - libyaml-dev - -RUN wget https://bootstrap.pypa.io/get-pip.py -RUN python3 get-pip.py -RUN python3 -m pip install --upgrade setuptools -RUN python3 -m pip install --upgrade pip -RUN python3 -m pip install --upgrade build -RUN rm -f get-pip.py -RUN mkdir /gen_py_module/ -RUN mkdir /tests/ -COPY gen_py_module /gen_py_module/ -COPY setup.py / -COPY setup.cfg / -COPY pyproject.toml / -COPY MANIFEST.in / -COPY README.md / -COPY LICENSE / -COPY requirements.txt / -COPY tests /tests/ -RUN pip3 install -r requirements.txt -RUN rm -f requirements.txt -RUN python3 -m build --no-isolation --wheel -RUN pip3 install /dist/gen_py_module-*-py3-none-any.whl -RUN rm -rf /gen_py_module/ -RUN rm -rf dist/ tests/ -RUN rm -f setup.cfg -RUN rm -f pyproject.toml -RUN rm -f MANIFEST.in -RUN rm -f setup.py -RUN rm -f README.md -RUN rm -f LICENSE +# Copyright 2017 - 2026 Vladimir Roncevic +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM debian:12 +RUN apt-get update +RUN DEBIAN_FRONTEND=noninteractive \ + apt-get install -yq --no-install-recommends \ + vim \ + nano \ + tree \ + htop \ + unzip \ + ca-certificates \ + openssl \ + python3 \ + python3-pip \ + python3-wheel \ + libyaml-dev + +RUN wget https://bootstrap.pypa.io/get-pip.py +RUN python3 get-pip.py +RUN python3 -m pip install --upgrade setuptools +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install --upgrade build +RUN rm -f get-pip.py +RUN mkdir /gen_py_module/ +RUN mkdir /tests/ +COPY gen_py_module /gen_py_module/ +COPY setup.py / +COPY pyproject.toml / +COPY MANIFEST.in / +COPY README.md / +COPY LICENSE / +COPY requirements.txt / +COPY tests /tests/ +RUN pip3 install -r requirements.txt +RUN rm -f requirements.txt +RUN python3 -m build --no-isolation --wheel +RUN pip3 install /dist/gen_py_module-*-py3-none-any.whl +RUN rm -rf /gen_py_module/ +RUN rm -rf dist/ tests/ +RUN rm -f pyproject.toml +RUN rm -f MANIFEST.in +RUN rm -f setup.py +RUN rm -f README.md +RUN rm -f LICENSE diff --git a/README.md b/README.md index 66cfc9d..bc95068 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ other information that should be provided before the modules are installed. - [Install using docker](#install-using-docker) - [Dependencies](#dependencies) - [Tool structure](#tool-structure) +- [Code structure](#code-coverage) - [Docs](#docs) - [Contributing](#contributing) - [Copyright and licence](#copyright-and-licence) @@ -137,11 +138,11 @@ Generator structure | Name | Stmts | Miss | Cover | |------|-------|------|-------| -| `gen_py_module/__init__.py` | 75 | 14 | 81% | -| `gen_py_module/pro/__init__.py` | 62 | 2 | 97% | -| `gen_py_module/pro/read_template.py` | 66 | 13 | 80% | -| `gen_py_module/pro/write_template.py` | 52 | 3 | 94% | -| **Total** | 255 | 32 | 87% | +| `gen_py_module/__init__.py` | 73 | 12 | 84%| +| `gen_py_module/pro/__init__.py` | 60 | 0 | 100%| +| `gen_py_module/pro/read_template.py` | 64 | 11 | 83%| +| `gen_py_module/pro/write_template.py` | 50 | 1 | 98%| +| **Total** | 247 | 24 | 90% | ### Docs @@ -160,7 +161,7 @@ More documentation and info at [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -Copyright (C) 2017 - 2024 by [vroncevic.github.io/gen_py_module](https://vroncevic.github.io/gen_py_module) +Copyright (C) 2017 - 2026 by [vroncevic.github.io/gen_py_module](https://vroncevic.github.io/gen_py_module) **gen_py_module** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index 6e12e1907657bb78168cf0492ba8fbc67d2ffb6a..44ba235741c17681ea54c2e2a44fa258de4048d3 100644 GIT binary patch delta 38273 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 CniJ9h diff --git a/docs/build/doctrees/gen_py_module.doctree b/docs/build/doctrees/gen_py_module.doctree index bbd3b13ebc903300d5014c1df1f24beffc3d9a84..58474f3dc70b751e6cbab1218e850f0ed199826c 100644 GIT binary patch delta 228 zcmX@|n(@tRMwSNFsSh`@NU(FuW~|DP^JdDB&X_hiQAd8V9lIl=+2#iJUrdb5ldHLG z!JKJKll^(68O%=%*n_wQ1DnmUMqB(F3#z9KEZD0fQ7X6`%%M#dYPb@IP4F?MWLDQaNkkmF)t$dK(RnEcSNV6#lg G3Pu3a6-#UY delta 204 zcmaF!n(@eMMwSNFsXI5aNU$?YXH1)1m?b~?wIJtYe|8H-lg$UYrZG*H<4R%Vo!rc2 z3l`YO#Aq`4AeYGIc3vwMpq4W*EkHG21%EOMY<@4)%g7>~rNTJ*VwxhzFjj#K>5Pe! zbF-BBGWvnc+zgov<_y`4Rg(q$tT(HOE{T|YE7wEBo3V$tI5oK>uQWHlA}zltcZxUT tW|KSxM(%5z3=BPdsYONkMUxftg*O-F-(+F}O8OKvFfz()K3go$1ONwCMQi{7 diff --git a/docs/build/doctrees/gen_py_module.pro.doctree b/docs/build/doctrees/gen_py_module.pro.doctree index 3addf658bdc4f68841bbd745c57d079326fc2e3d..20e5841462306253d602a2dfcba865f30e78b0d2 100644 GIT binary patch delta 206 zcmX@IiRsNICYA=)sfim|V%gbcGuC9tc{5E;U{7H*o4kQnWb;k-XH1ODlMis&!UdX` zCQsp&W;ENpfj5u^s)c2ekPc9puFwlc{>@^-*^E$efyoUb`i%UOH;8EQLkwrkkj}`@ zkjY@4TxVmkSwU2=MxZD^za+k(C^ap!VoDFA{*=l36TO5wdU%UdlS}eSbK@)0@{4k( obZqXOsKCgWxq02BZ%m9Go0m;(U}Ra(%fK*MmaS#;y6Mvx0i}dQ_5c6? delta 185 zcmaE}iRs8DCYA=)sg@gAV%eFcGiFR~R8yF|UxZ`w6m|`8-awYgf=po|G*uz_#np~1snj2q{mS2=R i#hY>SwuuUijOm-NPx{8h1mvEZ+Q7)TcC-IMc@t1R5I8Ic)s-b@+N8LpErmdQ{4&Em*tw%L~T7ZW4%WD5>k zFlQRmWFBs5AX9_e8>WQ?sHGaJg%hZDKK~0w{>>c%8I0@@GX*BU7t~?opDZJ!B@7W^ z1Zv^QkjY>!P0G-lJi$tR@&s$%%{@X3(*=t1^Go6jic-@uE2i`?>Q9-hUF9Xz(ZgGu snp~1snj2q{mS2=RrDJnvl>#GU$L3Yl-uiKT&cs=!8;t1OcrvLrK_Og7*a*&NCGjERwVvIB=LT%d_*vIw^{qse9i zZf_Q5>5S^hAF~xWoik)JA~WQ?c_**uf59lQd4@m+BT(`(NRk&ODUczZ;V@aDT$wM! z4#?!mkjY>M>6^U9*n0C)p@r#_BdR<^ycv6Vi&K+J@=9~#E7J0da;JDRZr)U-z{uFP j`EvC)CMF>FR9y@s#~E%0h78%B?#b~A-J5qdbTI+|T@*pg diff --git a/docs/build/doctrees/gen_py_module.pro.write_template.doctree b/docs/build/doctrees/gen_py_module.pro.write_template.doctree index ab04768f68fdd4137b383e446bde7dc7d0ba9255..031cbf497464d644d7afcb601078b50735d3f4d4 100644 GIT binary patch delta 238 zcmZ2-mGR6~MwSNFsRuW*+-KpI&4|p9^JdDB&TyUlFic_c0)CFke5@9XW}6#0rZG*v z%bvo@43w;%yhcD~auSCuSYjg+quJyJ4w21n+~zPNSiq{FMldo@UdjKDk$>|Ffhmko zI|P6VF2n5L!~g7ZjzYWmZh-Vbq^8 zc~6p;P)84MacXi&UTJQ8MOuDQ?v#$rQppO8jDI#;r+i~#?AUCa9>d7!w0S~?2onG> CT2Cne delta 193 zcmX?em2t^cMwSNFsWUgS+-G5y&TyS9s4YKvJwNAUF;)vklg<9DznB<#Cwp<&f;rQe zCd+Y41DRIb-XP`GFy%lsJNf^y3S>xUT%PR5A+!00KnWvI!DYAtfyoU*THMkZJQ*?> z%o(y7k(2itTW|g-^vr+q%OnpGZ^j|xj7`Wf)N0-KRtN> diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree index 78b9146dc950199543403915feb475586d3567a8..8dd6ec6553de6dc9401c899fb4133954dbbfec13 100644 GIT binary patch delta 614 zcmdmRgz?Z3MwSNFspcD5K5{bhZT`kt&crCVIgjTdBcsUX0KS`yj8dDm1l}_;if@(@ zvS#9u&Ctn^^XAKt&hliOe85L+@&akj%?%=p7@;zPK$$dzjIWp*OhyDK(~OYWCtePd z5eLdFfXQ%dj+d;4$w&cZ_9A3hr020PYHnUE9|3cSCQyMB6VxFbn^lz-F)?;*KB=;l z7wR5=paOB`$-W9on`ayOax<21erdahk+Ev?GW+$6+z{WC1J$rk-tQw0^bE)5ddEbV zL={j%1tu|>%ej)xOd+XKAz|`HSH;PzoC6rmHve`$#KzdZd7sx2n5K51rrj`2o7ecX zFf#URHuPHqlkWk_|AEW12k0>iL7XuOD51y7z>p!6!Mxcmcnu>|d@`~)bLcWy;7kFF zPnL5~+I%f6mQkQ6KffftpeQvhvtmjQqyCi1h7n#u9X-6osmUdIrMdAHY57IDQ#v;H zM<_5dvToiG`3)3SD`NgJvN*6YFigI{Eiazs2xRr}re~I9lqM-;78jSM7Ej4?n*1P6 zipiO6^0`)#y1DdqY>j+58 zZd5Is*Z8!6>@oCP1CsrNCd(e6$1EtFrN@eJWQLsIX7}JVj97$OLzgkKK~zsZC?h^O zfmLAh&9GR;$sQ3NBHoNWyv3=>C3&T}@fB(LMY&Uefv_k-fsv7U^Wn&E;4s-0^N*3m zj*Wp~@&#^r<1Bk1tA{r|vm~Q5Ng=bixHPqRN|pmiP#7whoS#=xl$lgol3xUra%7wQ zAXbXWiEZ+qSVbmhw#o8wqOvYv^*Nczsd>ezRtkv)iOCtM3PyScQ?gvyCI`kTFuHAC I5Wk2C0CL)@Z~y=R diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree index a2e1737204f3f5a66346ca7e59dbd9a7a354c487..81fbd458b6c69b1d076a17751b50ddfdcdd2e991 100644 GIT binary patch delta 72 zcmew)+9<}-z&iEYMivDYfuj8UlK6t6)U?csDLst(Qzk31cnNj%@D`^gm*kb^##f}} c7v)ar*xbOPz{uFPc_Hg(CdQ7<(>P+70LmyDasU7T delta 58 zcmZn^`y|TJz&iE$MivE@$!07bBHoNWyv3=>C3&T}@fB(LMY&VF88=U0QD9_j*}ReU NGZPb#yObk_2>?PL6HEXA diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index 56dc97c..22a712b 100644 --- a/docs/build/html/.buildinfo +++ b/docs/build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 37c487715594ac9029a4292119c25613 +config: f0134f3e34050deb1ab63ac77d03eadb tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_modules/gen_py_module.html b/docs/build/html/_modules/gen_py_module.html index 3f845a3..099a2d4 100644 --- a/docs/build/html/_modules/gen_py_module.html +++ b/docs/build/html/_modules/gen_py_module.html @@ -42,7 +42,7 @@

Source code for gen_py_module

 Module
     gen_py_module.py
 Copyright
-    Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com>
     gen_py_module is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -74,18 +74,18 @@ 

Source code for gen_py_module

     from ats_utilities.exceptions.ats_type_error import ATSTypeError
     from ats_utilities.exceptions.ats_value_error import ATSValueError
     from gen_py_module.pro import GenModule
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = 'Copyright 2017, https://vroncevic.github.io/gen_form_model'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE'
-__version__ = '1.5.6'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE'
+__version__: str = '1.5.7'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -270,7 +270,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_py_module/pro.html b/docs/build/html/_modules/gen_py_module/pro.html index 93be5a3..b4528d9 100644 --- a/docs/build/html/_modules/gen_py_module/pro.html +++ b/docs/build/html/_modules/gen_py_module/pro.html @@ -43,7 +43,7 @@

Source code for gen_py_module.pro

 Module
     __init__.py
 Copyright
-    Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com>
     gen_py_module is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -73,18 +73,18 @@ 

Source code for gen_py_module.pro

     from ats_utilities.exceptions.ats_value_error import ATSValueError
     from gen_py_module.pro.read_template import ReadTemplate
     from gen_py_module.pro.write_template import WriteTemplate
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = 'Copyright 2017, https://vroncevic.github.io/gen_form_model'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE'
-__version__ = '1.5.6'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE'
+__version__: str = '1.5.7'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -250,7 +250,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_py_module/pro/read_template.html b/docs/build/html/_modules/gen_py_module/pro/read_template.html index 5229025..0100f27 100644 --- a/docs/build/html/_modules/gen_py_module/pro/read_template.html +++ b/docs/build/html/_modules/gen_py_module/pro/read_template.html @@ -44,7 +44,7 @@

Source code for gen_py_module.pro.read_template

< Module read_template.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> + Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -69,18 +69,18 @@

Source code for gen_py_module.pro.read_template

< from ats_utilities.console_io.verbose import verbose_message from ats_utilities.exceptions.ats_type_error import ATSTypeError from ats_utilities.exceptions.ats_value_error import ATSValueError -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -227,7 +227,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_py_module/pro/write_template.html b/docs/build/html/_modules/gen_py_module/pro/write_template.html index 0f11a91..0844f13 100644 --- a/docs/build/html/_modules/gen_py_module/pro/write_template.html +++ b/docs/build/html/_modules/gen_py_module/pro/write_template.html @@ -44,7 +44,7 @@

Source code for gen_py_module.pro.write_template

Module write_template.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> + Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -71,18 +71,18 @@

Source code for gen_py_module.pro.write_template

from ats_utilities.console_io.verbose import verbose_message from ats_utilities.exceptions.ats_type_error import ATSTypeError from ats_utilities.exceptions.ats_value_error import ATSValueError -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -215,7 +215,7 @@

Navigation

diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html index 50bb7d4..113b61f 100644 --- a/docs/build/html/_modules/index.html +++ b/docs/build/html/_modules/index.html @@ -75,7 +75,7 @@

Navigation

diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt index 05b833c..fe0eff4 100644 --- a/docs/build/html/_sources/index.rst.txt +++ b/docs/build/html/_sources/index.rst.txt @@ -122,7 +122,7 @@ Copyright and licence .. |license: apache 2.0| image:: https://img.shields.io/badge/license-apache%202.0-blue.svg :target: https://opensource.org/licenses/apache-2.0 -Copyright (C) 2017 - 2024 by `vroncevic.github.io/gen_py_module `_ +Copyright (C) 2017 - 2026 by `vroncevic.github.io/gen_py_module `_ **gen_py_module** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/docs/build/html/gen_py_module.html b/docs/build/html/gen_py_module.html index 6947ad7..f215fe7 100644 --- a/docs/build/html/gen_py_module.html +++ b/docs/build/html/gen_py_module.html @@ -83,7 +83,7 @@

Subpackages
Module

gen_py_module.py

-
Copyright

Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -257,7 +257,7 @@

Navigation

diff --git a/docs/build/html/gen_py_module.pro.html b/docs/build/html/gen_py_module.pro.html index 3b317fb..1cb0573 100644 --- a/docs/build/html/gen_py_module.pro.html +++ b/docs/build/html/gen_py_module.pro.html @@ -76,7 +76,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -273,7 +273,7 @@

Navigation

diff --git a/docs/build/html/gen_py_module.pro.read_template.html b/docs/build/html/gen_py_module.pro.read_template.html index 2165395..1808cb0 100644 --- a/docs/build/html/gen_py_module.pro.read_template.html +++ b/docs/build/html/gen_py_module.pro.read_template.html @@ -51,7 +51,7 @@

Navigation

Module

read_template.py

-
Copyright

Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -205,7 +205,7 @@

Navigation

diff --git a/docs/build/html/gen_py_module.pro.write_template.html b/docs/build/html/gen_py_module.pro.write_template.html index 332e011..28fd736 100644 --- a/docs/build/html/gen_py_module.pro.write_template.html +++ b/docs/build/html/gen_py_module.pro.write_template.html @@ -47,7 +47,7 @@

Navigation

Module

write_template.py

-
Copyright

Copyright (C) 2017 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -185,7 +185,7 @@

Navigation

diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html index 190ac8b..b50fd0f 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -209,7 +209,7 @@

Navigation

diff --git a/docs/build/html/index.html b/docs/build/html/index.html index a2600bd..d299ea0 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -135,7 +135,7 @@

Tool structure

Copyright and licence¶

license: gpl v3 license: apache 2.0

-

Copyright (C) 2017 - 2024 by vroncevic.github.io/gen_py_module

+

Copyright (C) 2017 - 2026 by vroncevic.github.io/gen_py_module

gen_py_module is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, at your option, any later version of Python 3 you may have available.

@@ -214,7 +214,7 @@

Navigation

diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html index 1ff3c50..01b01c5 100644 --- a/docs/build/html/modules.html +++ b/docs/build/html/modules.html @@ -132,7 +132,7 @@

Navigation

diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index 569d2e9301278fe4700a07800fb37fcf9ec9183b..5f804191466e446e9b007ed0c21d5b3b266cebc5 100644 GIT binary patch delta 12 TcmZ3+vW#VdE2H^Fw+D;>8*>CY delta 12 TcmZ3+vW#VdE2G&)w+D;>8*T(S diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html index 1262e76..ce6bc3b 100644 --- a/docs/build/html/py-modindex.html +++ b/docs/build/html/py-modindex.html @@ -106,7 +106,7 @@

Navigation

diff --git a/docs/build/html/search.html b/docs/build/html/search.html index ad12259..2d269d1 100644 --- a/docs/build/html/search.html +++ b/docs/build/html/search.html @@ -95,7 +95,7 @@

Navigation

diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index a30fb26..360c1ae 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["gen_py_module", "gen_py_module.pro", "gen_py_module.pro.read_template", "gen_py_module.pro.write_template", "index", "modules"], "filenames": ["gen_py_module.rst", "gen_py_module.pro.rst", "gen_py_module.pro.read_template.rst", "gen_py_module.pro.write_template.rst", "index.rst", "modules.rst"], "titles": ["gen_py_module package", "gen_py_module.pro package", "gen_py_module.pro.read_template module", "gen_py_module.pro.write_template module", "Generate Python Module", "gen_py_module"], "terms": {"pro": [0, 4, 5], "submodul": [0, 5], "read_templ": [0, 1, 4], "readtempl": [0, 1, 2], "write_templ": [0, 1, 4], "writetempl": [0, 1, 3], "genmodul": [0, 1], "_gen_verbos": [0, 1, 2, 3, 5], "_pro_structur": [0, 1], "gen_setup": [0, 1], "get_read": [0, 1], "get_writ": [0, 1], "py": [0, 1, 2, 3, 4], "copyright": [0, 1, 2, 3], "c": [0, 1, 2, 3, 4], "2017": [0, 1, 2, 3, 4], "2024": [0, 1, 2, 3, 4], "vladimir": [0, 1, 2, 3], "roncev": [0, 1, 2, 3], "elektron": [0, 1, 2, 3], "ronca": [0, 1, 2, 3], "gmail": [0, 1, 2, 3], "com": [0, 1, 2, 3], "i": [0, 1, 2, 3, 4], "free": [0, 1, 2, 3, 4], "softwar": [0, 1, 2, 3, 4], "you": [0, 1, 2, 3, 4], "can": [0, 1, 2, 3, 4], "redistribut": [0, 1, 2, 3, 4], "modifi": [0, 1, 2, 3, 4], "under": [0, 1, 2, 3, 4], "term": [0, 1, 2, 3, 4], "gnu": [0, 1, 2, 3], "gener": [0, 1, 2, 3], "public": [0, 1, 2, 3], "licens": [0, 1, 2, 3], "publish": [0, 1, 2, 3], "foundat": [0, 1, 2, 3], "either": [0, 1, 2, 3, 4], "version": [0, 1, 2, 3, 4], "3": [0, 1, 2, 3, 4], "your": [0, 1, 2, 3, 4], "option": [0, 1, 2, 3, 4], "ani": [0, 1, 2, 3, 4], "later": [0, 1, 2, 3, 4], "distribut": [0, 1, 2, 3], "hope": [0, 1, 2, 3], "us": [0, 1, 2, 3, 4], "without": [0, 1, 2, 3], "warranti": [0, 1, 2, 3], "even": [0, 1, 2, 3], "impli": [0, 1, 2, 3], "merchant": [0, 1, 2, 3], "fit": [0, 1, 2, 3], "FOR": [0, 1, 2, 3], "A": [0, 1, 2, 3], "particular": [0, 1, 2, 3], "purpos": [0, 1, 2, 3], "see": [0, 1, 2, 3], "more": [0, 1, 2, 3], "detail": [0, 1, 2, 3], "should": [0, 1, 2, 3, 4], "have": [0, 1, 2, 3, 4], "receiv": [0, 1, 2, 3], "copi": [0, 1, 2, 3], "along": [0, 1, 2, 3], "thi": [0, 1, 2, 3], "program": [0, 1, 2, 3], "If": [0, 1, 2, 3], "http": [0, 1, 2, 3, 4], "www": [0, 1, 2, 3], "org": [0, 1, 2, 3], "info": [0, 1, 2, 3], "defin": [0, 1, 2, 3], "class": [0, 1, 2, 3, 4], "genpymodul": [0, 4, 5], "attribut": [0, 1, 2, 3], "": [0, 1, 2, 3, 4], "method": [0, 1, 2, 3], "load": [0, 2], "base": [0, 1, 2, 3, 4], "creat": [0, 2, 3, 4], "cli": 0, "interfac": 0, "run": [0, 4], "oper": [0, 1, 3], "verbos": [0, 1, 2, 3], "bool": [0, 1, 2, 3], "fals": [0, 1, 2, 3], "sourc": [0, 1, 2, 3], "atscli": 0, "It": [0, 1, 2, 3], "consol": [0, 1, 2, 3], "text": [0, 1, 2, 3], "indic": [0, 1, 2, 3], "process": [0, 1, 2, 3, 5], "phase": [0, 1, 2, 3], "_config": [0, 5], "tool": 0, "file": [0, 3, 4], "path": [0, 2], "_log": [0, 5], "log": [0, 4], "_logo": [0, 5], "logo": [0, 4], "splash": 0, "screen": 0, "_op": [0, 5], "list": 0, "_logger": 0, "logger": 0, "object": [0, 1], "api": [0, 1, 2, 3], "__init__": [0, 1, 2, 3, 4], "initi": [0, 1, 2, 3], "constructor": [0, 1, 2, 3], "str": [0, 1, 2, 3], "conf": [0, 1, 2, 4], "cfg": [0, 4], "n": 0, "name": [0, 1, 2, 3], "t": 0, "type": [0, 1, 2, 3, 4], "v": 0, "paramet": [0, 1, 2, 3], "enabl": [0, 1, 2, 3], "disabl": [0, 1, 2, 3], "return": [0, 1, 2, 3], "true": [0, 1, 3], "success": [0, 1, 3], "except": [0, 1, 2, 3], "none": [0, 1, 2, 3, 4], "_template_dir": [1, 2], "read": [1, 2], "write": [1, 3], "templat": [1, 2, 3, 4], "filecheck": [1, 2, 3], "proconfig": 1, "pronam": 1, "project": [1, 3, 4], "setup": [1, 3], "_reader": 1, "reader": 1, "_writer": 1, "writer": 1, "get": [1, 4], "gen_modul": 1, "yaml": [1, 4], "pro_nam": [1, 2, 3], "pro_typ": [1, 2], "atstypeerror": [1, 2, 3], "atsvalueerror": [1, 2, 3], "an": [2, 3], "prefix": 2, "config": 2, "dict": [2, 3], "configur": 2, "atribut": 3, "content": [3, 5], "template_cont": 3, "gen_py_modul": 4, "develop": 4, "code": 4, "100": 4, "The": 4, "readm": 4, "introduc": 4, "provid": 4, "instruct": 4, "how": 4, "machin": 4, "mai": 4, "other": 4, "inform": 4, "befor": 4, "ar": 4, "packag": [4, 5], "subpackag": [4, 5], "navig": 4, "releas": 4, "page": 4, "download": 4, "extract": 4, "archiv": 4, "To": 4, "follow": 4, "tar": 4, "xvzf": 4, "x": 4, "y": 4, "z": 4, "gz": 4, "cd": 4, "python3": 4, "wget": 4, "bootstrap": 4, "pypa": 4, "io": 4, "pip": 4, "m": 4, "upgrad": 4, "setuptool": 4, "build": 4, "pip3": 4, "r": 4, "requir": 4, "txt": 4, "isol": 4, "wheel": 4, "dist": 4, "py3": 4, "whl": 4, "rm": 4, "f": 4, "chmod": 4, "755": 4, "usr": 4, "local": 4, "lib": 4, "10": 4, "bin": 4, "gen_py_module_run": 4, "ln": 4, "docker": 4, "imag": 4, "contain": 4, "pyton3": 4, "gen": 4, "next": 4, "librari": 4, "ats": 4, "util": 4, "app": 4, "script": 4, "oop": 4, "gen_py_module_util": 4, "abstract_abc_class": 4, "abstract_base_class": 4, "empti": 4, "main": 4, "6": 4, "directori": 4, "15": 4, "vroncev": 4, "github": 4, "same": 4, "itself": 4, "avail": 4, "let": 4, "help": 4, "support": 4, "psf": 4, "index": 4, "search": 4, "modul": 5}, "objects": {"": [[0, 0, 0, "-", "gen_py_module"]], "gen_py_module": [[0, 1, 1, "", "GenPyModule"], [1, 0, 0, "-", "pro"]], "gen_py_module.GenPyModule": [[0, 2, 1, "", "_CONFIG"], [0, 2, 1, "", "_GEN_VERBOSE"], [0, 2, 1, "", "_LOG"], [0, 2, 1, "", "_LOGO"], [0, 2, 1, "", "_OPS"], [0, 3, 1, "", "process"]], "gen_py_module.pro": [[1, 1, 1, "", "GenModule"], [2, 0, 0, "-", "read_template"], [3, 0, 0, "-", "write_template"]], "gen_py_module.pro.GenModule": [[1, 2, 1, "", "_GEN_VERBOSE"], [1, 2, 1, "", "_PRO_STRUCTURE"], [1, 3, 1, "", "gen_setup"], [1, 3, 1, "", "get_reader"], [1, 3, 1, "", "get_writer"]], "gen_py_module.pro.read_template": [[2, 1, 1, "", "ReadTemplate"]], "gen_py_module.pro.read_template.ReadTemplate": [[2, 2, 1, "", "_GEN_VERBOSE"], [2, 2, 1, "", "_TEMPLATE_DIR"], [2, 3, 1, "", "read"]], "gen_py_module.pro.write_template": [[3, 1, 1, "", "WriteTemplate"]], "gen_py_module.pro.write_template.WriteTemplate": [[3, 2, 1, "", "_GEN_VERBOSE"], [3, 3, 1, "", "write"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:attribute", "3": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"]}, "titleterms": {"gen_py_modul": [0, 1, 2, 3, 5], "packag": [0, 1], "subpackag": 0, "modul": [0, 1, 2, 3, 4], "content": [0, 1, 4], "pro": [1, 2, 3], "submodul": 1, "read_templ": 2, "write_templ": 3, "gener": 4, "python": 4, "instal": 4, "depend": 4, "tool": 4, "structur": 4, "copyright": 4, "licenc": 4, "indic": 4, "tabl": 4}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"gen_py_module package": [[0, "gen-py-module-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-gen_py_module"], [1, "module-gen_py_module.pro"]], "gen_py_module.pro package": [[1, "gen-py-module-pro-package"]], "Submodules": [[1, "submodules"]], "gen_py_module.pro.read_template module": [[2, "module-gen_py_module.pro.read_template"]], "gen_py_module.pro.write_template module": [[3, "module-gen_py_module.pro.write_template"]], "Generate Python Module": [[4, "generate-python-module"]], "Contents": [[4, null]], "Installation": [[4, "installation"]], "Dependencies": [[4, "dependencies"]], "Tool structure": [[4, "tool-structure"]], "Copyright and licence": [[4, "copyright-and-licence"]], "Indices and tables": [[4, "indices-and-tables"]], "gen_py_module": [[5, "gen-py-module"]]}, "indexentries": {"genpymodule (class in gen_py_module)": [[0, "gen_py_module.GenPyModule"]], "_config (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._CONFIG"]], "_gen_verbose (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._GEN_VERBOSE"]], "_log (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._LOG"]], "_logo (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._LOGO"]], "_ops (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._OPS"]], "gen_py_module": [[0, "module-gen_py_module"]], "module": [[0, "module-gen_py_module"], [1, "module-gen_py_module.pro"], [2, "module-gen_py_module.pro.read_template"], [3, "module-gen_py_module.pro.write_template"]], "process() (gen_py_module.genpymodule method)": [[0, "gen_py_module.GenPyModule.process"]], "genmodule (class in gen_py_module.pro)": [[1, "gen_py_module.pro.GenModule"]], "_gen_verbose (gen_py_module.pro.genmodule attribute)": [[1, "gen_py_module.pro.GenModule._GEN_VERBOSE"]], "_pro_structure (gen_py_module.pro.genmodule attribute)": [[1, "gen_py_module.pro.GenModule._PRO_STRUCTURE"]], "gen_py_module.pro": [[1, "module-gen_py_module.pro"]], "gen_setup() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.gen_setup"]], "get_reader() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.get_reader"]], "get_writer() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.get_writer"]], "readtemplate (class in gen_py_module.pro.read_template)": [[2, "gen_py_module.pro.read_template.ReadTemplate"]], "_gen_verbose (gen_py_module.pro.read_template.readtemplate attribute)": [[2, "gen_py_module.pro.read_template.ReadTemplate._GEN_VERBOSE"]], "_template_dir (gen_py_module.pro.read_template.readtemplate attribute)": [[2, "gen_py_module.pro.read_template.ReadTemplate._TEMPLATE_DIR"]], "gen_py_module.pro.read_template": [[2, "module-gen_py_module.pro.read_template"]], "read() (gen_py_module.pro.read_template.readtemplate method)": [[2, "gen_py_module.pro.read_template.ReadTemplate.read"]], "writetemplate (class in gen_py_module.pro.write_template)": [[3, "gen_py_module.pro.write_template.WriteTemplate"]], "_gen_verbose (gen_py_module.pro.write_template.writetemplate attribute)": [[3, "gen_py_module.pro.write_template.WriteTemplate._GEN_VERBOSE"]], "gen_py_module.pro.write_template": [[3, "module-gen_py_module.pro.write_template"]], "write() (gen_py_module.pro.write_template.writetemplate method)": [[3, "gen_py_module.pro.write_template.WriteTemplate.write"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["gen_py_module", "gen_py_module.pro", "gen_py_module.pro.read_template", "gen_py_module.pro.write_template", "index", "modules"], "filenames": ["gen_py_module.rst", "gen_py_module.pro.rst", "gen_py_module.pro.read_template.rst", "gen_py_module.pro.write_template.rst", "index.rst", "modules.rst"], "titles": ["gen_py_module package", "gen_py_module.pro package", "gen_py_module.pro.read_template module", "gen_py_module.pro.write_template module", "Generate Python Module", "gen_py_module"], "terms": {"pro": [0, 4, 5], "submodul": [0, 5], "read_templ": [0, 1, 4], "readtempl": [0, 1, 2], "write_templ": [0, 1, 4], "writetempl": [0, 1, 3], "genmodul": [0, 1], "_gen_verbos": [0, 1, 2, 3, 5], "_pro_structur": [0, 1], "gen_setup": [0, 1], "get_read": [0, 1], "get_writ": [0, 1], "py": [0, 1, 2, 3, 4], "copyright": [0, 1, 2, 3], "c": [0, 1, 2, 3, 4], "2017": [0, 1, 2, 3, 4], "2026": [0, 1, 2, 3, 4], "vladimir": [0, 1, 2, 3], "roncev": [0, 1, 2, 3], "elektron": [0, 1, 2, 3], "ronca": [0, 1, 2, 3], "gmail": [0, 1, 2, 3], "com": [0, 1, 2, 3], "i": [0, 1, 2, 3, 4], "free": [0, 1, 2, 3, 4], "softwar": [0, 1, 2, 3, 4], "you": [0, 1, 2, 3, 4], "can": [0, 1, 2, 3, 4], "redistribut": [0, 1, 2, 3, 4], "modifi": [0, 1, 2, 3, 4], "under": [0, 1, 2, 3, 4], "term": [0, 1, 2, 3, 4], "gnu": [0, 1, 2, 3], "gener": [0, 1, 2, 3], "public": [0, 1, 2, 3], "licens": [0, 1, 2, 3], "publish": [0, 1, 2, 3], "foundat": [0, 1, 2, 3], "either": [0, 1, 2, 3, 4], "version": [0, 1, 2, 3, 4], "3": [0, 1, 2, 3, 4], "your": [0, 1, 2, 3, 4], "option": [0, 1, 2, 3, 4], "ani": [0, 1, 2, 3, 4], "later": [0, 1, 2, 3, 4], "distribut": [0, 1, 2, 3], "hope": [0, 1, 2, 3], "us": [0, 1, 2, 3, 4], "without": [0, 1, 2, 3], "warranti": [0, 1, 2, 3], "even": [0, 1, 2, 3], "impli": [0, 1, 2, 3], "merchant": [0, 1, 2, 3], "fit": [0, 1, 2, 3], "FOR": [0, 1, 2, 3], "A": [0, 1, 2, 3], "particular": [0, 1, 2, 3], "purpos": [0, 1, 2, 3], "see": [0, 1, 2, 3], "more": [0, 1, 2, 3], "detail": [0, 1, 2, 3], "should": [0, 1, 2, 3, 4], "have": [0, 1, 2, 3, 4], "receiv": [0, 1, 2, 3], "copi": [0, 1, 2, 3], "along": [0, 1, 2, 3], "thi": [0, 1, 2, 3], "program": [0, 1, 2, 3], "If": [0, 1, 2, 3], "http": [0, 1, 2, 3, 4], "www": [0, 1, 2, 3], "org": [0, 1, 2, 3], "info": [0, 1, 2, 3], "defin": [0, 1, 2, 3], "class": [0, 1, 2, 3, 4], "genpymodul": [0, 4, 5], "attribut": [0, 1, 2, 3], "": [0, 1, 2, 3, 4], "method": [0, 1, 2, 3], "load": [0, 2], "base": [0, 1, 2, 3, 4], "creat": [0, 2, 3, 4], "cli": 0, "interfac": 0, "run": [0, 4], "oper": [0, 1, 3], "verbos": [0, 1, 2, 3], "bool": [0, 1, 2, 3], "fals": [0, 1, 2, 3], "sourc": [0, 1, 2, 3], "atscli": 0, "It": [0, 1, 2, 3], "consol": [0, 1, 2, 3], "text": [0, 1, 2, 3], "indic": [0, 1, 2, 3], "process": [0, 1, 2, 3, 5], "phase": [0, 1, 2, 3], "_config": [0, 5], "tool": 0, "file": [0, 3, 4], "path": [0, 2], "_log": [0, 5], "log": [0, 4], "_logo": [0, 5], "logo": [0, 4], "splash": 0, "screen": 0, "_op": [0, 5], "list": 0, "_logger": 0, "logger": 0, "object": [0, 1], "api": [0, 1, 2, 3], "__init__": [0, 1, 2, 3, 4], "initi": [0, 1, 2, 3], "constructor": [0, 1, 2, 3], "str": [0, 1, 2, 3], "conf": [0, 1, 2, 4], "cfg": [0, 4], "n": 0, "name": [0, 1, 2, 3], "t": 0, "type": [0, 1, 2, 3, 4], "v": 0, "paramet": [0, 1, 2, 3], "enabl": [0, 1, 2, 3], "disabl": [0, 1, 2, 3], "return": [0, 1, 2, 3], "true": [0, 1, 3], "success": [0, 1, 3], "except": [0, 1, 2, 3], "none": [0, 1, 2, 3, 4], "_template_dir": [1, 2], "read": [1, 2], "write": [1, 3], "templat": [1, 2, 3, 4], "filecheck": [1, 2, 3], "proconfig": 1, "pronam": 1, "project": [1, 3, 4], "setup": [1, 3], "_reader": 1, "reader": 1, "_writer": 1, "writer": 1, "get": [1, 4], "gen_modul": 1, "yaml": [1, 4], "pro_nam": [1, 2, 3], "pro_typ": [1, 2], "atstypeerror": [1, 2, 3], "atsvalueerror": [1, 2, 3], "an": [2, 3], "prefix": 2, "config": 2, "dict": [2, 3], "configur": 2, "atribut": 3, "content": [3, 5], "template_cont": 3, "gen_py_modul": 4, "develop": 4, "code": 4, "100": 4, "The": 4, "readm": 4, "introduc": 4, "provid": 4, "instruct": 4, "how": 4, "machin": 4, "mai": 4, "other": 4, "inform": 4, "befor": 4, "ar": 4, "packag": [4, 5], "subpackag": [4, 5], "navig": 4, "releas": 4, "page": 4, "download": 4, "extract": 4, "archiv": 4, "To": 4, "follow": 4, "tar": 4, "xvzf": 4, "x": 4, "y": 4, "z": 4, "gz": 4, "cd": 4, "python3": 4, "wget": 4, "bootstrap": 4, "pypa": 4, "io": 4, "pip": 4, "m": 4, "upgrad": 4, "setuptool": 4, "build": 4, "pip3": 4, "r": 4, "requir": 4, "txt": 4, "isol": 4, "wheel": 4, "dist": 4, "py3": 4, "whl": 4, "rm": 4, "f": 4, "chmod": 4, "755": 4, "usr": 4, "local": 4, "lib": 4, "10": 4, "bin": 4, "gen_py_module_run": 4, "ln": 4, "docker": 4, "imag": 4, "contain": 4, "pyton3": 4, "gen": 4, "next": 4, "librari": 4, "ats": 4, "util": 4, "app": 4, "script": 4, "oop": 4, "gen_py_module_util": 4, "abstract_abc_class": 4, "abstract_base_class": 4, "empti": 4, "main": 4, "6": 4, "directori": 4, "15": 4, "vroncev": 4, "github": 4, "same": 4, "itself": 4, "avail": 4, "let": 4, "help": 4, "support": 4, "psf": 4, "index": 4, "search": 4, "modul": 5}, "objects": {"": [[0, 0, 0, "-", "gen_py_module"]], "gen_py_module": [[0, 1, 1, "", "GenPyModule"], [1, 0, 0, "-", "pro"]], "gen_py_module.GenPyModule": [[0, 2, 1, "", "_CONFIG"], [0, 2, 1, "", "_GEN_VERBOSE"], [0, 2, 1, "", "_LOG"], [0, 2, 1, "", "_LOGO"], [0, 2, 1, "", "_OPS"], [0, 3, 1, "", "process"]], "gen_py_module.pro": [[1, 1, 1, "", "GenModule"], [2, 0, 0, "-", "read_template"], [3, 0, 0, "-", "write_template"]], "gen_py_module.pro.GenModule": [[1, 2, 1, "", "_GEN_VERBOSE"], [1, 2, 1, "", "_PRO_STRUCTURE"], [1, 3, 1, "", "gen_setup"], [1, 3, 1, "", "get_reader"], [1, 3, 1, "", "get_writer"]], "gen_py_module.pro.read_template": [[2, 1, 1, "", "ReadTemplate"]], "gen_py_module.pro.read_template.ReadTemplate": [[2, 2, 1, "", "_GEN_VERBOSE"], [2, 2, 1, "", "_TEMPLATE_DIR"], [2, 3, 1, "", "read"]], "gen_py_module.pro.write_template": [[3, 1, 1, "", "WriteTemplate"]], "gen_py_module.pro.write_template.WriteTemplate": [[3, 2, 1, "", "_GEN_VERBOSE"], [3, 3, 1, "", "write"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:attribute", "3": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"]}, "titleterms": {"gen_py_modul": [0, 1, 2, 3, 5], "packag": [0, 1], "subpackag": 0, "modul": [0, 1, 2, 3, 4], "content": [0, 1, 4], "pro": [1, 2, 3], "submodul": 1, "read_templ": 2, "write_templ": 3, "gener": 4, "python": 4, "instal": 4, "depend": 4, "tool": 4, "structur": 4, "copyright": 4, "licenc": 4, "indic": 4, "tabl": 4}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"gen_py_module package": [[0, "gen-py-module-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-gen_py_module"], [1, "module-gen_py_module.pro"]], "gen_py_module.pro package": [[1, "gen-py-module-pro-package"]], "Submodules": [[1, "submodules"]], "gen_py_module.pro.read_template module": [[2, "module-gen_py_module.pro.read_template"]], "gen_py_module.pro.write_template module": [[3, "module-gen_py_module.pro.write_template"]], "Generate Python Module": [[4, "generate-python-module"]], "Contents": [[4, null]], "Installation": [[4, "installation"]], "Dependencies": [[4, "dependencies"]], "Tool structure": [[4, "tool-structure"]], "Copyright and licence": [[4, "copyright-and-licence"]], "Indices and tables": [[4, "indices-and-tables"]], "gen_py_module": [[5, "gen-py-module"]]}, "indexentries": {"genpymodule (class in gen_py_module)": [[0, "gen_py_module.GenPyModule"]], "_config (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._CONFIG"]], "_gen_verbose (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._GEN_VERBOSE"]], "_log (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._LOG"]], "_logo (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._LOGO"]], "_ops (gen_py_module.genpymodule attribute)": [[0, "gen_py_module.GenPyModule._OPS"]], "gen_py_module": [[0, "module-gen_py_module"]], "module": [[0, "module-gen_py_module"], [1, "module-gen_py_module.pro"], [2, "module-gen_py_module.pro.read_template"], [3, "module-gen_py_module.pro.write_template"]], "process() (gen_py_module.genpymodule method)": [[0, "gen_py_module.GenPyModule.process"]], "genmodule (class in gen_py_module.pro)": [[1, "gen_py_module.pro.GenModule"]], "_gen_verbose (gen_py_module.pro.genmodule attribute)": [[1, "gen_py_module.pro.GenModule._GEN_VERBOSE"]], "_pro_structure (gen_py_module.pro.genmodule attribute)": [[1, "gen_py_module.pro.GenModule._PRO_STRUCTURE"]], "gen_py_module.pro": [[1, "module-gen_py_module.pro"]], "gen_setup() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.gen_setup"]], "get_reader() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.get_reader"]], "get_writer() (gen_py_module.pro.genmodule method)": [[1, "gen_py_module.pro.GenModule.get_writer"]], "readtemplate (class in gen_py_module.pro.read_template)": [[2, "gen_py_module.pro.read_template.ReadTemplate"]], "_gen_verbose (gen_py_module.pro.read_template.readtemplate attribute)": [[2, "gen_py_module.pro.read_template.ReadTemplate._GEN_VERBOSE"]], "_template_dir (gen_py_module.pro.read_template.readtemplate attribute)": [[2, "gen_py_module.pro.read_template.ReadTemplate._TEMPLATE_DIR"]], "gen_py_module.pro.read_template": [[2, "module-gen_py_module.pro.read_template"]], "read() (gen_py_module.pro.read_template.readtemplate method)": [[2, "gen_py_module.pro.read_template.ReadTemplate.read"]], "writetemplate (class in gen_py_module.pro.write_template)": [[3, "gen_py_module.pro.write_template.WriteTemplate"]], "_gen_verbose (gen_py_module.pro.write_template.writetemplate attribute)": [[3, "gen_py_module.pro.write_template.WriteTemplate._GEN_VERBOSE"]], "gen_py_module.pro.write_template": [[3, "module-gen_py_module.pro.write_template"]], "write() (gen_py_module.pro.write_template.writetemplate method)": [[3, "gen_py_module.pro.write_template.WriteTemplate.write"]]}}) \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index a0bec9c..1d8651a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,7 +4,7 @@ Module conf.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -27,9 +27,9 @@ sys.path.insert(0, os.path.abspath('../../')) project: str = 'gen_py_module' -project_copyright: str = '2024, Vladimir Roncevic ' +project_copyright: str = '2026, Vladimir Roncevic ' author: str = 'Vladimir Roncevic ' -version: str = '1.5.6' +version: str = '1.5.7' release: str = 'https://github.com/vroncevic/gen_py_module/releases' extensions: List[str] = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] templates_path: List[str] = ['_templates'] diff --git a/docs/source/index.rst b/docs/source/index.rst index 05b833c..fe0eff4 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -122,7 +122,7 @@ Copyright and licence .. |license: apache 2.0| image:: https://img.shields.io/badge/license-apache%202.0-blue.svg :target: https://opensource.org/licenses/apache-2.0 -Copyright (C) 2017 - 2024 by `vroncevic.github.io/gen_py_module `_ +Copyright (C) 2017 - 2026 by `vroncevic.github.io/gen_py_module `_ **gen_py_module** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/gen_py_module/__init__.py b/gen_py_module/__init__.py index 125d9f8..ec2e04e 100755 --- a/gen_py_module/__init__.py +++ b/gen_py_module/__init__.py @@ -4,7 +4,7 @@ Module gen_py_module.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -36,18 +36,18 @@ from ats_utilities.exceptions.ats_type_error import ATSTypeError from ats_utilities.exceptions.ats_value_error import ATSValueError from gen_py_module.pro import GenModule -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = 'Copyright 2017, https://vroncevic.github.io/gen_form_model' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class GenPyModule(ATSCli): diff --git a/gen_py_module/conf/gen_py_module.cfg b/gen_py_module/conf/gen_py_module.cfg index a6387d7..1d80c7f 100755 --- a/gen_py_module/conf/gen_py_module.cfg +++ b/gen_py_module/conf/gen_py_module.cfg @@ -1,4 +1,4 @@ ats_name = gen_py_module -ats_version = 1.5.6 +ats_version = 1.5.7 ats_build_date = 03 May 2017 ats_licence = https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE diff --git a/gen_py_module/pro/__init__.py b/gen_py_module/pro/__init__.py index 0014836..fa493f7 100755 --- a/gen_py_module/pro/__init__.py +++ b/gen_py_module/pro/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -34,18 +34,18 @@ from ats_utilities.exceptions.ats_value_error import ATSValueError from gen_py_module.pro.read_template import ReadTemplate from gen_py_module.pro.write_template import WriteTemplate -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = 'Copyright 2017, https://vroncevic.github.io/gen_form_model' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class GenModule(FileCheck, ProConfig, ProName): diff --git a/gen_py_module/pro/read_template.py b/gen_py_module/pro/read_template.py index 10f89e9..3839bd3 100755 --- a/gen_py_module/pro/read_template.py +++ b/gen_py_module/pro/read_template.py @@ -4,7 +4,7 @@ Module read_template.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -29,18 +29,18 @@ from ats_utilities.console_io.verbose import verbose_message from ats_utilities.exceptions.ats_type_error import ATSTypeError from ats_utilities.exceptions.ats_value_error import ATSValueError -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class ReadTemplate(FileCheck): diff --git a/gen_py_module/pro/write_template.py b/gen_py_module/pro/write_template.py index 5c4625b..3d9373b 100755 --- a/gen_py_module/pro/write_template.py +++ b/gen_py_module/pro/write_template.py @@ -4,7 +4,7 @@ Module write_template.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -31,18 +31,18 @@ from ats_utilities.console_io.verbose import verbose_message from ats_utilities.exceptions.ats_type_error import ATSTypeError from ats_utilities.exceptions.ats_value_error import ATSValueError -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class WriteTemplate(FileCheck): diff --git a/gen_py_module/run/gen_py_module_run.py b/gen_py_module/run/gen_py_module_run.py index 3359afb..3bb58f8 100755 --- a/gen_py_module/run/gen_py_module_run.py +++ b/gen_py_module/run/gen_py_module_run.py @@ -5,7 +5,7 @@ Module gen_py_module_run.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -25,18 +25,18 @@ try: from gen_py_module import GenPyModule -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = 'Copyright 2017, https://vroncevic.github.io/gen_form_model' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' if __name__ == '__main__': TOOL: GenPyModule = GenPyModule(verbose=False) diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 4f772b2..0000000 --- a/setup.cfg +++ /dev/null @@ -1,46 +0,0 @@ -# -# Module -# setup.cfg -# Copyright -# Copyright (C) 2017 - 2024 Vladimir Roncevic -# gen_py_module is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# gen_py_module is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# Info -# Defines setup for package gen_py_module. -# - -[metadata] -name = gen_py_module -version = 1.5.6 -author = Vladimir Roncevic -author_email = elektron.ronca@gmail.com -description = Python Code Generator -license=GPL 2024 Free software to use and distributed it. -long_description = file: README.md -long_description_content_type = text/markdown -keywords=unix, linux, development, py, module -platforms = any -url = https://vroncevic.github.io/gen_py_module -classifiers = - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2) - License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) - License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) - License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) - License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) - Operating System :: OS Independent - -[options] -packages = find: -python_requires = >=3.10 -install_requires= - ats-utilities diff --git a/setup.py b/setup.py index 1fa7475..53a837c 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ Module setup.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -25,14 +25,14 @@ from os.path import abspath, dirname, join from setuptools import setup -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' TOOL_DIR = 'gen_py_module/' CONF: str = 'conf' @@ -43,30 +43,19 @@ with open(join(THIS_DIR, 'README.md'), encoding='utf-8') as readme: long_description = readme.read() PROGRAMMING_LANG: str = 'Programming Language :: Python ::' -VERSIONS: List[str] = ['3.10', '3.11'] +VERSIONS: List[str] = ['3.10', '3.11', '3.12'] SUPPORTED_PY_VERSIONS: List[str] = [ f'{PROGRAMMING_LANG} {VERSION}' for VERSION in VERSIONS ] -LICENSE_PREFIX: str = 'License :: OSI Approved ::' -LICENSES: List[str] = [ - 'GNU Lesser General Public License v2 (LGPLv2)', - 'GNU Lesser General Public License v2 or later (LGPLv2+)', - 'GNU Lesser General Public License v3 (LGPLv3)', - 'GNU Lesser General Public License v3 or later (LGPLv3+)', - 'GNU Library or Lesser General Public License (LGPL)' -] -APPROVED_LICENSES: List[str] = [ - f'{LICENSE_PREFIX} {LICENSE}' for LICENSE in LICENSES -] -PYP_CLASSIFIERS: List[str] = SUPPORTED_PY_VERSIONS + APPROVED_LICENSES +PYP_CLASSIFIERS: List[str] = SUPPORTED_PY_VERSIONS setup( name='gen_py_module', - version='1.5.6', + version='1.5.7', description='Generating PY module', author='Vladimir Roncevic', author_email='elektron.ronca@gmail.com', url='https://vroncevic.github.io/gen_py_module', - license='GPL 2024 Free software to use and distributed it.', + license='GPL-3.0-or-later', long_description=long_description, long_description_content_type='text/markdown', keywords='Unix, Linux, Development, PY, module', diff --git a/tests/.coverage b/tests/.coverage index d75a83d5e276e5f0f25b37faf312068f7c9031f2..7a47dd17b80696924c6c29b559bde69a6734ad1c 100644 GIT binary patch delta 57 zcmZozz}&Eac>|jQ+XDvvcl-}F3kqD}SKwh{mgUb#ERIhsN-j1KU}Tn-EK4ma&dkp< N*E7>IG+1P?000Hl5n%uT delta 46 zcmZozz}&Eac>|jQ+d~Ha_xukx3kqE2pZq|dPmrIHSz5d-wWv5VKhIpxRL^*k!2$qq CS`Q-t diff --git a/tests/ats_coverage.py b/tests/ats_coverage.py new file mode 100644 index 0000000..0235ec1 --- /dev/null +++ b/tests/ats_coverage.py @@ -0,0 +1,215 @@ +# -*- coding: UTF-8 -*- + +''' +Module + ats_coverage.py +Copyright + Copyright (C) 2026 Vladimir Roncevic + ats_coverage is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ats_coverage is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along + with this program. If not, see . +Info + Defines attribute(s) and method(s) for coverage support. +''' + +import sys +from typing import Any, Dict, List, Optional +from os.path import exists, basename +from json import load +from unittest import TestLoader, TestSuite, TextTestRunner +from argparse import Namespace + +try: + from pathlib import Path + from ats_utilities.checker import ATSChecker + from ats_utilities.console_io.success import success_message + from ats_utilities.console_io.error import error_message + from ats_utilities.option import ATSOptionParser + from ats_utilities.exceptions.ats_type_error import ATSTypeError + from ats_utilities.exceptions.ats_file_error import ATSFileError + from coverage import Coverage +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover + +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/ats_coverage' +__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] +__license__: str = 'https://github.com/vroncevic/ats_coverage/blob/dev/LICENSE' +__version__: str = '1.0.0' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' + + +def run_coverage(pro_name: str) -> str: + ''' + Runs coverage for project and generates report. + + :param pro_name: Project name + :type pro_name: + :exceptions: ATSTypeError | ATSFileError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([('str:pro_name', pro_name)]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + if not exists(f'../{pro_name}'): + raise ATSFileError(f'missing ../{pro_name}') + cov = Coverage(source=[f'../{pro_name}']) + cov.start() + tests: TestSuite = TestLoader().discover('.', pattern='*_test.py') + test_runner = TextTestRunner(verbosity=2) + test_runner.run(tests) + cov.stop() + cov.save() + report_file_name: str = f'{pro_name}_coverage.json' + cov.json_report(outfile=report_file_name) + success_message([f'\nats_coverage: generated coverage {report_file_name}']) + return report_file_name + + +def load_report(report_file_path: str) -> Dict[str, Any]: + ''' + Loads report from report file. + + :param report_file_path: Report file path + :type report_file_path: + :exceptions: ATSTypeError | ATSFileError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([( + 'str:report_file_path', report_file_path + )]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + if not exists(report_file_path): + raise ATSFileError(f'{report_file_path} does not exist.') + data: Dict[str, Any] = {} + with open(report_file_path, 'r', encoding='utf-8') as loaded_file: + data = load(loaded_file) + return data + + +def find_root_package(module_path: str) -> Optional[Path]: + ''' + Finds root package for project structure. + + :param module_path: Absolute path + :type module_path: + :exceptions: ATSTypeError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([( + 'str:module_path', module_path + )]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + root: Optional[Path] = None + path: Path = Path(module_path).resolve() + while path.parent != path: + if (path / '__init__.py').exists(): + root = path + path = path.parent + return root + + +def update_readme(coverage: Dict[str, Any]) -> None: + ''' + Updates README.md file with code coverage report table. + + :param coverage: Coverage data report + :type coverage: + :exceptions: ATSTypeError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([('dict:coverage', coverage)]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + readme_path: str = '../README.md' + start_marker: str = '### Code coverage' + end_marker: str = '### Docs' + lines: List[str] = [] + with open(readme_path, 'r', encoding='utf-8') as current_file: + lines = current_file.readlines() + new_lines: List[str] = [] + inside_block: bool = False + stmts: str = 'num_statements' + miss: str = 'missing_lines' + cover: str = 'percent_covered_display' + for line in lines: + if start_marker in line: + inside_block = True + new_lines.append(line) + new_lines.append('\n') + new_lines.append('| Name | Stmts | Miss | Cover |\n') + new_lines.append('|------|-------|------|-------|\n') + file_names: List[str] = coverage['files'] + for name in file_names: + root_package: Optional[Path] = find_root_package(name) + module: str = '' + if name.startswith(str(root_package)): + result: str = name[len(str(root_package)):] + result = result.lstrip('/') + module = f'{basename(str(root_package))}/{result}' + file_summary: Dict[str, Any] = coverage['files'][name] + statements: str = file_summary['summary'][stmts] + missing: str = file_summary['summary'][miss] + covered: str = file_summary['summary'][cover] + new_lines.append( + f'| `{module}` | {statements} | {missing} | {covered}%|\n' + ) + total: str = '| **Total** |' + total_statements: str = coverage['totals'][stmts] + total_missing: str = coverage['totals'][miss] + total_covered: str = coverage['totals'][cover] + total += f' {total_statements} |' + total += f' {total_missing} |' + total += f' {total_covered}% |\n' + new_lines.append(total) + continue + elif end_marker in line: + inside_block = False + new_lines.append('\n') + new_lines.append(line) + continue + if not inside_block: + new_lines.append(line) + with open(readme_path, 'w', encoding='utf-8') as update_file: + update_file.writelines(new_lines) + + +if __name__ == "__main__": + cli: ATSOptionParser = ATSOptionParser( + 'ats_coverage 2025', '1.0.0', 'GPLv3', False + ) + cli.add_operation( + '-n', '--name', dest='name', + help='generate coverage report for project (provide name)' + ) + args: Namespace = cli.parse_args(sys.argv) + if not bool(getattr(args, "name")): + error_message(['ats_coverage: missing name argument']) + sys.exit(127) + try: + pro_report_file: str = f'{getattr(args, "name")}_coverage.json' + report_data: Dict[str, Any] = load_report(pro_report_file) + update_readme(report_data) + except (ATSTypeError, ATSFileError) as e: + error_message([f'ats_coverage: {e}']) + sys.exit(128) diff --git a/tests/full_simple_new/full_simple_new.py b/tests/full_simple_new/full_simple_new.py index d8f5ec0..60be64c 100644 --- a/tests/full_simple_new/full_simple_new.py +++ b/tests/full_simple_new/full_simple_new.py @@ -4,7 +4,7 @@ Module full_simple_new.py Copyright - Copyright (C) 2024 Vladimir Roncevic + Copyright (C) 2025 Vladimir Roncevic full_simple_new is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -22,7 +22,7 @@ from typing import List __author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, Free software to use and distributed it.' +__copyright__ = '(C) 2025, Free software to use and distributed it.' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] __license__ = 'GNU General Public License (GPL)' __version__ = '1.0.0' diff --git a/tests/gen_py_module_coverage.json b/tests/gen_py_module_coverage.json index 8257775..f2c01be 100644 --- a/tests/gen_py_module_coverage.json +++ b/tests/gen_py_module_coverage.json @@ -1 +1 @@ -{"meta": {"format": 2, "version": "7.5.3", "timestamp": "2024-07-09T17:29:41.976994", "branch_coverage": false, "show_contexts": false}, "files": {"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 48, 49, 50, 53, 54, 72, 73, 74, 75, 76, 78, 86, 87, 94, 95, 96, 97, 100, 103, 104, 108, 112, 118, 128, 129, 130, 131, 132, 133, 136, 137, 142, 143, 147, 148, 149, 150, 157, 165, 166, 167, 191], "summary": {"covered_lines": 61, "num_statements": 75, "percent_covered": 81.33333333333333, "percent_covered_display": "81", "missing_lines": 14, "excluded_lines": 0}, "missing_lines": [39, 41, 138, 141, 162, 163, 164, 172, 173, 176, 177, 183, 185, 188], "excluded_lines": []}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 70, 71, 73, 81, 82, 83, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 106, 108, 116, 118, 137, 138, 139, 142, 143, 144, 145, 146, 147, 148, 149, 155, 156, 159, 160, 163], "summary": {"covered_lines": 60, "num_statements": 62, "percent_covered": 96.7741935483871, "percent_covered_display": "97", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [37, 39], "excluded_lines": []}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 46, 47, 61, 62, 64, 72, 73, 75, 97, 98, 99, 104, 105, 106, 107, 108, 110, 112, 113, 114, 115, 116, 117, 119, 121, 122, 129, 130, 131, 132, 133, 134, 135, 136, 138, 140, 141, 144], "summary": {"covered_lines": 53, "num_statements": 66, "percent_covered": 80.3030303030303, "percent_covered_display": "80", "missing_lines": 13, "excluded_lines": 0}, "missing_lines": [32, 34, 109, 111, 118, 120, 123, 124, 125, 126, 128, 137, 139], "excluded_lines": []}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 62, 64, 72, 73, 75, 94, 95, 96, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 120, 121, 122, 123, 126, 127, 130], "summary": {"covered_lines": 49, "num_statements": 52, "percent_covered": 94.23076923076923, "percent_covered_display": "94", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [34, 36, 129], "excluded_lines": []}}, "totals": {"covered_lines": 223, "num_statements": 255, "percent_covered": 87.45098039215686, "percent_covered_display": "87", "missing_lines": 32, "excluded_lines": 0}} \ No newline at end of file +{"meta": {"format": 3, "version": "7.6.10", "timestamp": "2025-11-27T18:32:24.451277", "branch_coverage": false, "show_contexts": false}, "files": {"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 48, 49, 50, 53, 54, 72, 73, 74, 75, 76, 78, 86, 87, 94, 95, 96, 97, 100, 103, 104, 108, 112, 118, 128, 129, 130, 131, 132, 133, 136, 137, 142, 143, 147, 148, 149, 150, 157, 165, 166, 167, 191], "summary": {"covered_lines": 61, "num_statements": 73, "percent_covered": 83.56164383561644, "percent_covered_display": "84", "missing_lines": 12, "excluded_lines": 2}, "missing_lines": [138, 141, 162, 163, 164, 172, 173, 176, 177, 183, 185, 188], "excluded_lines": [39, 41], "functions": {"GenPyModule.__init__": {"executed_lines": [86, 87, 94, 95, 96, 97, 100, 103, 104, 108, 112], "summary": {"covered_lines": 11, "num_statements": 11, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GenPyModule.process": {"executed_lines": [128, 129, 130, 131, 132, 133, 136, 137, 142, 143, 147, 148, 149, 150, 157, 165, 166, 167, 191], "summary": {"covered_lines": 19, "num_statements": 31, "percent_covered": 61.29032258064516, "percent_covered_display": "61", "missing_lines": 12, "excluded_lines": 0}, "missing_lines": [138, 141, 162, 163, 164, 172, 173, 176, 177, 183, 185, 188], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 48, 49, 50, 53, 54, 72, 73, 74, 75, 76, 78, 118], "summary": {"covered_lines": 31, "num_statements": 31, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [39, 41]}}, "classes": {"GenPyModule": {"executed_lines": [86, 87, 94, 95, 96, 97, 100, 103, 104, 108, 112, 128, 129, 130, 131, 132, 133, 136, 137, 142, 143, 147, 148, 149, 150, 157, 165, 166, 167, 191], "summary": {"covered_lines": 30, "num_statements": 42, "percent_covered": 71.42857142857143, "percent_covered_display": "71", "missing_lines": 12, "excluded_lines": 0}, "missing_lines": [138, 141, 162, 163, 164, 172, 173, 176, 177, 183, 185, 188], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 43, 44, 45, 46, 47, 48, 49, 50, 53, 54, 72, 73, 74, 75, 76, 78, 118], "summary": {"covered_lines": 31, "num_statements": 31, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [39, 41]}}}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 70, 71, 73, 81, 82, 83, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 106, 108, 116, 118, 137, 138, 139, 142, 143, 144, 145, 146, 147, 148, 149, 155, 156, 159, 160, 163], "summary": {"covered_lines": 60, "num_statements": 60, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [37, 39], "functions": {"GenModule.__init__": {"executed_lines": [81, 82, 83, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96], "summary": {"covered_lines": 14, "num_statements": 14, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GenModule.get_reader": {"executed_lines": [106], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GenModule.get_writer": {"executed_lines": [116], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GenModule.gen_setup": {"executed_lines": [137, 138, 139, 142, 143, 144, 145, 146, 147, 148, 149, 155, 156, 159, 160, 163], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 70, 71, 73, 98, 108, 118], "summary": {"covered_lines": 28, "num_statements": 28, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [37, 39]}}, "classes": {"GenModule": {"executed_lines": [81, 82, 83, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 106, 116, 137, 138, 139, 142, 143, 144, 145, 146, 147, 148, 149, 155, 156, 159, 160, 163], "summary": {"covered_lines": 32, "num_statements": 32, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 70, 71, 73, 98, 108, 118], "summary": {"covered_lines": 28, "num_statements": 28, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [37, 39]}}}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 46, 47, 61, 62, 64, 72, 73, 75, 97, 98, 99, 104, 105, 106, 107, 108, 110, 112, 113, 114, 115, 116, 117, 119, 121, 122, 129, 130, 131, 132, 133, 134, 135, 136, 138, 140, 141, 144], "summary": {"covered_lines": 53, "num_statements": 64, "percent_covered": 82.8125, "percent_covered_display": "83", "missing_lines": 11, "excluded_lines": 2}, "missing_lines": [109, 111, 118, 120, 123, 124, 125, 126, 128, 137, 139], "excluded_lines": [32, 34], "functions": {"ReadTemplate.__init__": {"executed_lines": [72, 73], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ReadTemplate.read": {"executed_lines": [97, 98, 99, 104, 105, 106, 107, 108, 110, 112, 113, 114, 115, 116, 117, 119, 121, 122, 129, 130, 131, 132, 133, 134, 135, 136, 138, 140, 141, 144], "summary": {"covered_lines": 30, "num_statements": 41, "percent_covered": 73.17073170731707, "percent_covered_display": "73", "missing_lines": 11, "excluded_lines": 0}, "missing_lines": [109, 111, 118, 120, 123, 124, 125, 126, 128, 137, 139], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 46, 47, 61, 62, 64, 75], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [32, 34]}}, "classes": {"ReadTemplate": {"executed_lines": [72, 73, 97, 98, 99, 104, 105, 106, 107, 108, 110, 112, 113, 114, 115, 116, 117, 119, 121, 122, 129, 130, 131, 132, 133, 134, 135, 136, 138, 140, 141, 144], "summary": {"covered_lines": 32, "num_statements": 43, "percent_covered": 74.4186046511628, "percent_covered_display": "74", "missing_lines": 11, "excluded_lines": 0}, "missing_lines": [109, 111, 118, 120, 123, 124, 125, 126, 128, 137, 139], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 46, 47, 61, 62, 64, 75], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [32, 34]}}}, "/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 62, 64, 72, 73, 75, 94, 95, 96, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 120, 121, 122, 123, 126, 127, 130], "summary": {"covered_lines": 49, "num_statements": 50, "percent_covered": 98.0, "percent_covered_display": "98", "missing_lines": 1, "excluded_lines": 2}, "missing_lines": [129], "excluded_lines": [34, 36], "functions": {"WriteTemplate.__init__": {"executed_lines": [72, 73], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "WriteTemplate.write": {"executed_lines": [94, 95, 96, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 120, 121, 122, 123, 126, 127, 130], "summary": {"covered_lines": 25, "num_statements": 26, "percent_covered": 96.15384615384616, "percent_covered_display": "96", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [129], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 62, 64, 75], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [34, 36]}}, "classes": {"WriteTemplate": {"executed_lines": [72, 73, 94, 95, 96, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 120, 121, 122, 123, 126, 127, 130], "summary": {"covered_lines": 27, "num_statements": 28, "percent_covered": 96.42857142857143, "percent_covered_display": "96", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [129], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 62, 64, 75], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [34, 36]}}}}, "totals": {"covered_lines": 223, "num_statements": 247, "percent_covered": 90.2834008097166, "percent_covered_display": "90", "missing_lines": 24, "excluded_lines": 8}} \ No newline at end of file diff --git a/tests/gen_py_module_coverage.xml b/tests/gen_py_module_coverage.xml index 9fccca3..75663b8 100644 --- a/tests/gen_py_module_coverage.xml +++ b/tests/gen_py_module_coverage.xml @@ -1,14 +1,14 @@ - - + + - + - + @@ -26,8 +26,6 @@ - - @@ -90,9 +88,9 @@ - + - + @@ -108,8 +106,6 @@ - - @@ -159,7 +155,7 @@ - + @@ -170,8 +166,6 @@ - - @@ -230,7 +224,7 @@ - + @@ -243,8 +237,6 @@ - - diff --git a/tests/gen_py_module_sub_test.py b/tests/gen_py_module_sub_test.py index c69fa18..986841d 100644 --- a/tests/gen_py_module_sub_test.py +++ b/tests/gen_py_module_sub_test.py @@ -4,7 +4,7 @@ Module gen_py_module_sub_test.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -34,14 +34,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class GenModuleTestCase(TestCase): diff --git a/tests/gen_py_module_test.py b/tests/gen_py_module_test.py index 0122913..44d4962 100644 --- a/tests/gen_py_module_test.py +++ b/tests/gen_py_module_test.py @@ -4,7 +4,7 @@ Module gen_py_module_test.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -33,14 +33,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.5.6' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.5.7' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class GenMessageQueueTestCase(TestCase): diff --git a/tests/htmlcov/class_index.html b/tests/htmlcov/class_index.html new file mode 100644 index 0000000..67dbbc2 --- /dev/null +++ b/tests/htmlcov/class_index.html @@ -0,0 +1,171 @@ + + + + + Coverage report + + + + + +
+
+

Coverage report: + 90% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fileclassstatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.pyGenPyModule4212071%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py(no class)3102100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.pyGenModule3200100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py(no class)2802100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.pyReadTemplate4311074%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py(no class)2102100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.pyWriteTemplate281096%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py(no class)2202100%
Total 24724890%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/coverage_html_cb_6fb7b396.js b/tests/htmlcov/coverage_html_cb_6fb7b396.js new file mode 100644 index 0000000..1face13 --- /dev/null +++ b/tests/htmlcov/coverage_html_cb_6fb7b396.js @@ -0,0 +1,733 @@ +// Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +// For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt + +// Coverage.py HTML report browser code. +/*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ +/*global coverage: true, document, window, $ */ + +coverage = {}; + +// General helpers +function debounce(callback, wait) { + let timeoutId = null; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + callback.apply(this, args); + }, wait); + }; +}; + +function checkVisible(element) { + const rect = element.getBoundingClientRect(); + const viewBottom = Math.max(document.documentElement.clientHeight, window.innerHeight); + const viewTop = 30; + return !(rect.bottom < viewTop || rect.top >= viewBottom); +} + +function on_click(sel, fn) { + const elt = document.querySelector(sel); + if (elt) { + elt.addEventListener("click", fn); + } +} + +// Helpers for table sorting +function getCellValue(row, column = 0) { + const cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (cell.childElementCount == 1) { + var child = cell.firstElementChild; + if (child.tagName === "A") { + child = child.firstElementChild; + } + if (child instanceof HTMLDataElement && child.value) { + return child.value; + } + } + return cell.innerText || cell.textContent; +} + +function rowComparator(rowA, rowB, column = 0) { + let valueA = getCellValue(rowA, column); + let valueB = getCellValue(rowB, column); + if (!isNaN(valueA) && !isNaN(valueB)) { + return valueA - valueB; + } + return valueA.localeCompare(valueB, undefined, {numeric: true}); +} + +function sortColumn(th) { + // Get the current sorting direction of the selected header, + // clear state on other headers and then set the new sorting direction. + const currentSortOrder = th.getAttribute("aria-sort"); + [...th.parentElement.cells].forEach(header => header.setAttribute("aria-sort", "none")); + var direction; + if (currentSortOrder === "none") { + direction = th.dataset.defaultSortOrder || "ascending"; + } + else if (currentSortOrder === "ascending") { + direction = "descending"; + } + else { + direction = "ascending"; + } + th.setAttribute("aria-sort", direction); + + const column = [...th.parentElement.cells].indexOf(th) + + // Sort all rows and afterwards append them in order to move them in the DOM. + Array.from(th.closest("table").querySelectorAll("tbody tr")) + .sort((rowA, rowB) => rowComparator(rowA, rowB, column) * (direction === "ascending" ? 1 : -1)) + .forEach(tr => tr.parentElement.appendChild(tr)); + + // Save the sort order for next time. + if (th.id !== "region") { + let th_id = "file"; // Sort by file if we don't have a column id + let current_direction = direction; + const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE); + if (stored_list) { + ({th_id, direction} = JSON.parse(stored_list)) + } + localStorage.setItem(coverage.INDEX_SORT_STORAGE, JSON.stringify({ + "th_id": th.id, + "direction": current_direction + })); + if (th.id !== th_id || document.getElementById("region")) { + // Sort column has changed, unset sorting by function or class. + localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({ + "by_region": false, + "region_direction": current_direction + })); + } + } + else { + // Sort column has changed to by function or class, remember that. + localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({ + "by_region": true, + "region_direction": direction + })); + } +} + +// Find all the elements with data-shortcut attribute, and use them to assign a shortcut key. +coverage.assign_shortkeys = function () { + document.querySelectorAll("[data-shortcut]").forEach(element => { + document.addEventListener("keypress", event => { + if (event.target.tagName.toLowerCase() === "input") { + return; // ignore keypress from search filter + } + if (event.key === element.dataset.shortcut) { + element.click(); + } + }); + }); +}; + +// Create the events for the filter box. +coverage.wire_up_filter = function () { + // Populate the filter and hide100 inputs if there are saved values for them. + const saved_filter_value = localStorage.getItem(coverage.FILTER_STORAGE); + if (saved_filter_value) { + document.getElementById("filter").value = saved_filter_value; + } + const saved_hide100_value = localStorage.getItem(coverage.HIDE100_STORAGE); + if (saved_hide100_value) { + document.getElementById("hide100").checked = JSON.parse(saved_hide100_value); + } + + // Cache elements. + const table = document.querySelector("table.index"); + const table_body_rows = table.querySelectorAll("tbody tr"); + const no_rows = document.getElementById("no_rows"); + + // Observe filter keyevents. + const filter_handler = (event => { + // Keep running total of each metric, first index contains number of shown rows + const totals = new Array(table.rows[0].cells.length).fill(0); + // Accumulate the percentage as fraction + totals[totals.length - 1] = { "numer": 0, "denom": 0 }; // nosemgrep: eslint.detect-object-injection + + var text = document.getElementById("filter").value; + // Store filter value + localStorage.setItem(coverage.FILTER_STORAGE, text); + const casefold = (text === text.toLowerCase()); + const hide100 = document.getElementById("hide100").checked; + // Store hide value. + localStorage.setItem(coverage.HIDE100_STORAGE, JSON.stringify(hide100)); + + // Hide / show elements. + table_body_rows.forEach(row => { + var show = false; + // Check the text filter. + for (let column = 0; column < totals.length; column++) { + cell = row.cells[column]; + if (cell.classList.contains("name")) { + var celltext = cell.textContent; + if (casefold) { + celltext = celltext.toLowerCase(); + } + if (celltext.includes(text)) { + show = true; + } + } + } + + // Check the "hide covered" filter. + if (show && hide100) { + const [numer, denom] = row.cells[row.cells.length - 1].dataset.ratio.split(" "); + show = (numer !== denom); + } + + if (!show) { + // hide + row.classList.add("hidden"); + return; + } + + // show + row.classList.remove("hidden"); + totals[0]++; + + for (let column = 0; column < totals.length; column++) { + // Accumulate dynamic totals + cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (cell.classList.contains("name")) { + continue; + } + if (column === totals.length - 1) { + // Last column contains percentage + const [numer, denom] = cell.dataset.ratio.split(" "); + totals[column]["numer"] += parseInt(numer, 10); // nosemgrep: eslint.detect-object-injection + totals[column]["denom"] += parseInt(denom, 10); // nosemgrep: eslint.detect-object-injection + } + else { + totals[column] += parseInt(cell.textContent, 10); // nosemgrep: eslint.detect-object-injection + } + } + }); + + // Show placeholder if no rows will be displayed. + if (!totals[0]) { + // Show placeholder, hide table. + no_rows.style.display = "block"; + table.style.display = "none"; + return; + } + + // Hide placeholder, show table. + no_rows.style.display = null; + table.style.display = null; + + const footer = table.tFoot.rows[0]; + // Calculate new dynamic sum values based on visible rows. + for (let column = 0; column < totals.length; column++) { + // Get footer cell element. + const cell = footer.cells[column]; // nosemgrep: eslint.detect-object-injection + if (cell.classList.contains("name")) { + continue; + } + + // Set value into dynamic footer cell element. + if (column === totals.length - 1) { + // Percentage column uses the numerator and denominator, + // and adapts to the number of decimal places. + const match = /\.([0-9]+)/.exec(cell.textContent); + const places = match ? match[1].length : 0; + const { numer, denom } = totals[column]; // nosemgrep: eslint.detect-object-injection + cell.dataset.ratio = `${numer} ${denom}`; + // Check denom to prevent NaN if filtered files contain no statements + cell.textContent = denom + ? `${(numer * 100 / denom).toFixed(places)}%` + : `${(100).toFixed(places)}%`; + } + else { + cell.textContent = totals[column]; // nosemgrep: eslint.detect-object-injection + } + } + }); + + document.getElementById("filter").addEventListener("input", debounce(filter_handler)); + document.getElementById("hide100").addEventListener("input", debounce(filter_handler)); + + // Trigger change event on setup, to force filter on page refresh + // (filter value may still be present). + document.getElementById("filter").dispatchEvent(new Event("input")); + document.getElementById("hide100").dispatchEvent(new Event("input")); +}; +coverage.FILTER_STORAGE = "COVERAGE_FILTER_VALUE"; +coverage.HIDE100_STORAGE = "COVERAGE_HIDE100_VALUE"; + +// Set up the click-to-sort columns. +coverage.wire_up_sorting = function () { + document.querySelectorAll("[data-sortable] th[aria-sort]").forEach( + th => th.addEventListener("click", e => sortColumn(e.target)) + ); + + // Look for a localStorage item containing previous sort settings: + let th_id = "file", direction = "ascending"; + const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE); + if (stored_list) { + ({th_id, direction} = JSON.parse(stored_list)); + } + let by_region = false, region_direction = "ascending"; + const sorted_by_region = localStorage.getItem(coverage.SORTED_BY_REGION); + if (sorted_by_region) { + ({ + by_region, + region_direction + } = JSON.parse(sorted_by_region)); + } + + const region_id = "region"; + if (by_region && document.getElementById(region_id)) { + direction = region_direction; + } + // If we are in a page that has a column with id of "region", sort on + // it if the last sort was by function or class. + let th; + if (document.getElementById(region_id)) { + th = document.getElementById(by_region ? region_id : th_id); + } + else { + th = document.getElementById(th_id); + } + th.setAttribute("aria-sort", direction === "ascending" ? "descending" : "ascending"); + th.click() +}; + +coverage.INDEX_SORT_STORAGE = "COVERAGE_INDEX_SORT_2"; +coverage.SORTED_BY_REGION = "COVERAGE_SORT_REGION"; + +// Loaded on index.html +coverage.index_ready = function () { + coverage.assign_shortkeys(); + coverage.wire_up_filter(); + coverage.wire_up_sorting(); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + + on_click(".button_show_hide_help", coverage.show_hide_help); +}; + +// -- pyfile stuff -- + +coverage.LINE_FILTERS_STORAGE = "COVERAGE_LINE_FILTERS"; + +coverage.pyfile_ready = function () { + // If we're directed to a particular line number, highlight the line. + var frag = location.hash; + if (frag.length > 2 && frag[1] === "t") { + document.querySelector(frag).closest(".n").classList.add("highlight"); + coverage.set_sel(parseInt(frag.substr(2), 10)); + } + else { + coverage.set_sel(0); + } + + on_click(".button_toggle_run", coverage.toggle_lines); + on_click(".button_toggle_mis", coverage.toggle_lines); + on_click(".button_toggle_exc", coverage.toggle_lines); + on_click(".button_toggle_par", coverage.toggle_lines); + + on_click(".button_next_chunk", coverage.to_next_chunk_nicely); + on_click(".button_prev_chunk", coverage.to_prev_chunk_nicely); + on_click(".button_top_of_page", coverage.to_top); + on_click(".button_first_chunk", coverage.to_first_chunk); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + on_click(".button_to_index", coverage.to_index); + + on_click(".button_show_hide_help", coverage.show_hide_help); + + coverage.filters = undefined; + try { + coverage.filters = localStorage.getItem(coverage.LINE_FILTERS_STORAGE); + } catch(err) {} + + if (coverage.filters) { + coverage.filters = JSON.parse(coverage.filters); + } + else { + coverage.filters = {run: false, exc: true, mis: true, par: true}; + } + + for (cls in coverage.filters) { + coverage.set_line_visibilty(cls, coverage.filters[cls]); // nosemgrep: eslint.detect-object-injection + } + + coverage.assign_shortkeys(); + coverage.init_scroll_markers(); + coverage.wire_up_sticky_header(); + + document.querySelectorAll("[id^=ctxs]").forEach( + cbox => cbox.addEventListener("click", coverage.expand_contexts) + ); + + // Rebuild scroll markers when the window height changes. + window.addEventListener("resize", coverage.build_scroll_markers); +}; + +coverage.toggle_lines = function (event) { + const btn = event.target.closest("button"); + const category = btn.value + const show = !btn.classList.contains("show_" + category); + coverage.set_line_visibilty(category, show); + coverage.build_scroll_markers(); + coverage.filters[category] = show; + try { + localStorage.setItem(coverage.LINE_FILTERS_STORAGE, JSON.stringify(coverage.filters)); + } catch(err) {} +}; + +coverage.set_line_visibilty = function (category, should_show) { + const cls = "show_" + category; + const btn = document.querySelector(".button_toggle_" + category); + if (btn) { + if (should_show) { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.add(cls)); + btn.classList.add(cls); + } + else { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.remove(cls)); + btn.classList.remove(cls); + } + } +}; + +// Return the nth line div. +coverage.line_elt = function (n) { + return document.getElementById("t" + n)?.closest("p"); +}; + +// Set the selection. b and e are line numbers. +coverage.set_sel = function (b, e) { + // The first line selected. + coverage.sel_begin = b; + // The next line not selected. + coverage.sel_end = (e === undefined) ? b+1 : e; +}; + +coverage.to_top = function () { + coverage.set_sel(0, 1); + coverage.scroll_window(0); +}; + +coverage.to_first_chunk = function () { + coverage.set_sel(0, 1); + coverage.to_next_chunk(); +}; + +coverage.to_prev_file = function () { + window.location = document.getElementById("prevFileLink").href; +} + +coverage.to_next_file = function () { + window.location = document.getElementById("nextFileLink").href; +} + +coverage.to_index = function () { + location.href = document.getElementById("indexLink").href; +} + +coverage.show_hide_help = function () { + const helpCheck = document.getElementById("help_panel_state") + helpCheck.checked = !helpCheck.checked; +} + +// Return a string indicating what kind of chunk this line belongs to, +// or null if not a chunk. +coverage.chunk_indicator = function (line_elt) { + const classes = line_elt?.className; + if (!classes) { + return null; + } + const match = classes.match(/\bshow_\w+\b/); + if (!match) { + return null; + } + return match[0]; +}; + +coverage.to_next_chunk = function () { + const c = coverage; + + // Find the start of the next colored chunk. + var probe = c.sel_end; + var chunk_indicator, probe_line; + while (true) { + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + if (chunk_indicator) { + break; + } + probe++; + } + + // There's a next chunk, `probe` points to it. + var begin = probe; + + // Find the end of this chunk. + var next_indicator = chunk_indicator; + while (next_indicator === chunk_indicator) { + probe++; + probe_line = c.line_elt(probe); + next_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(begin, probe); + c.show_selection(); +}; + +coverage.to_prev_chunk = function () { + const c = coverage; + + // Find the end of the prev colored chunk. + var probe = c.sel_begin-1; + var probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + var chunk_indicator = c.chunk_indicator(probe_line); + while (probe > 1 && !chunk_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + } + + // There's a prev chunk, `probe` points to its last line. + var end = probe+1; + + // Find the beginning of this chunk. + var prev_indicator = chunk_indicator; + while (prev_indicator === chunk_indicator) { + probe--; + if (probe <= 0) { + return; + } + probe_line = c.line_elt(probe); + prev_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(probe+1, end); + c.show_selection(); +}; + +// Returns 0, 1, or 2: how many of the two ends of the selection are on +// the screen right now? +coverage.selection_ends_on_screen = function () { + if (coverage.sel_begin === 0) { + return 0; + } + + const begin = coverage.line_elt(coverage.sel_begin); + const end = coverage.line_elt(coverage.sel_end-1); + + return ( + (checkVisible(begin) ? 1 : 0) + + (checkVisible(end) ? 1 : 0) + ); +}; + +coverage.to_next_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the top line on the screen as selection. + + // This will select the top-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(0, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(1); + } + else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_next_chunk(); +}; + +coverage.to_prev_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the lowest line on the screen as selection. + + // This will select the bottom-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(document.documentElement.clientHeight-1, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(coverage.lines_len); + } + else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_prev_chunk(); +}; + +// Select line number lineno, or if it is in a colored chunk, select the +// entire chunk +coverage.select_line_or_chunk = function (lineno) { + var c = coverage; + var probe_line = c.line_elt(lineno); + if (!probe_line) { + return; + } + var the_indicator = c.chunk_indicator(probe_line); + if (the_indicator) { + // The line is in a highlighted chunk. + // Search backward for the first line. + var probe = lineno; + var indicator = the_indicator; + while (probe > 0 && indicator === the_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + break; + } + indicator = c.chunk_indicator(probe_line); + } + var begin = probe + 1; + + // Search forward for the last line. + probe = lineno; + indicator = the_indicator; + while (indicator === the_indicator) { + probe++; + probe_line = c.line_elt(probe); + indicator = c.chunk_indicator(probe_line); + } + + coverage.set_sel(begin, probe); + } + else { + coverage.set_sel(lineno); + } +}; + +coverage.show_selection = function () { + // Highlight the lines in the chunk + document.querySelectorAll("#source .highlight").forEach(e => e.classList.remove("highlight")); + for (let probe = coverage.sel_begin; probe < coverage.sel_end; probe++) { + coverage.line_elt(probe).querySelector(".n").classList.add("highlight"); + } + + coverage.scroll_to_selection(); +}; + +coverage.scroll_to_selection = function () { + // Scroll the page if the chunk isn't fully visible. + if (coverage.selection_ends_on_screen() < 2) { + const element = coverage.line_elt(coverage.sel_begin); + coverage.scroll_window(element.offsetTop - 60); + } +}; + +coverage.scroll_window = function (to_pos) { + window.scroll({top: to_pos, behavior: "smooth"}); +}; + +coverage.init_scroll_markers = function () { + // Init some variables + coverage.lines_len = document.querySelectorAll("#source > p").length; + + // Build html + coverage.build_scroll_markers(); +}; + +coverage.build_scroll_markers = function () { + const temp_scroll_marker = document.getElementById("scroll_marker") + if (temp_scroll_marker) temp_scroll_marker.remove(); + // Don't build markers if the window has no scroll bar. + if (document.body.scrollHeight <= window.innerHeight) { + return; + } + + const marker_scale = window.innerHeight / document.body.scrollHeight; + const line_height = Math.min(Math.max(3, window.innerHeight / coverage.lines_len), 10); + + let previous_line = -99, last_mark, last_top; + + const scroll_marker = document.createElement("div"); + scroll_marker.id = "scroll_marker"; + document.getElementById("source").querySelectorAll( + "p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par" + ).forEach(element => { + const line_top = Math.floor(element.offsetTop * marker_scale); + const line_number = parseInt(element.querySelector(".n a").id.substr(1)); + + if (line_number === previous_line + 1) { + // If this solid missed block just make previous mark higher. + last_mark.style.height = `${line_top + line_height - last_top}px`; + } + else { + // Add colored line in scroll_marker block. + last_mark = document.createElement("div"); + last_mark.id = `m${line_number}`; + last_mark.classList.add("marker"); + last_mark.style.height = `${line_height}px`; + last_mark.style.top = `${line_top}px`; + scroll_marker.append(last_mark); + last_top = line_top; + } + + previous_line = line_number; + }); + + // Append last to prevent layout calculation + document.body.append(scroll_marker); +}; + +coverage.wire_up_sticky_header = function () { + const header = document.querySelector("header"); + const header_bottom = ( + header.querySelector(".content h2").getBoundingClientRect().top - + header.getBoundingClientRect().top + ); + + function updateHeader() { + if (window.scrollY > header_bottom) { + header.classList.add("sticky"); + } + else { + header.classList.remove("sticky"); + } + } + + window.addEventListener("scroll", updateHeader); + updateHeader(); +}; + +coverage.expand_contexts = function (e) { + var ctxs = e.target.parentNode.querySelector(".ctxs"); + + if (!ctxs.classList.contains("expanded")) { + var ctxs_text = ctxs.textContent; + var width = Number(ctxs_text[0]); + ctxs.textContent = ""; + for (var i = 1; i < ctxs_text.length; i += width) { + key = ctxs_text.substring(i, i + width).trim(); + ctxs.appendChild(document.createTextNode(contexts[key])); + ctxs.appendChild(document.createElement("br")); + } + ctxs.classList.add("expanded"); + } +}; + +document.addEventListener("DOMContentLoaded", () => { + if (document.body.classList.contains("indexfile")) { + coverage.index_ready(); + } + else { + coverage.pyfile_ready(); + } +}); diff --git a/tests/htmlcov/favicon_32_cb_58284776.png b/tests/htmlcov/favicon_32_cb_58284776.png new file mode 100644 index 0000000000000000000000000000000000000000..8649f0475d8d20793b2ec431fe25a186a414cf10 GIT binary patch literal 1732 zcmV;#20QtQP)K2KOkBOVxIZChq#W-v7@TU%U6P(wycKT1hUJUToW3ke1U1ONa4 z000000000000000bb)GRa9mqwR9|UWHy;^RUrt?IT__Y0JUcxmBP0(51q1>E00030 z|NrOz)aw7%8sJzM<5^g%z7^qE`}_Ot|JUUG(NUkWzR|7K?Zo%@_v-8G-1N%N=D$;; zw;keH4dGY$`1t4M=HK_s*zm^0#KgqfwWhe3qO_HtvXYvtjgX>;-~C$L`&k>^R)9)7 zdPh2TL^pCnHC#0+_4D)M`p?qp!pq{jO_{8;$fbaflbx`Tn52n|n}8VFRTA1&ugOP< zPd{uvFjz7t*Vot1&d$l-xWCk}s;sQL&#O(Bskh6gqNJv>#iB=ypG1e3K!K4yc7!~M zfj4S*g^zZ7eP$+_Sl07Z646l;%urinP#D8a6TwRtnLIRcI!r4f@bK~9-`~;E(N?Lv zSEst7s;rcxsi~}{Nsytfz@MtUoR*iFc8!#vvx}Umhm4blk(_~MdVD-@dW&>!Nn~ro z_E~-ESVQAj6Wmn;(olz(O&_{U2*pZBc1aYjMh>Dq3z|6`jW`RDHV=t3I6yRKJ~LOX zz_z!!vbVXPqob#=pj3^VMT?x6t(irRmSKsMo1~LLkB&=#j!=M%NP35mfqim$drWb9 zYIb>no_LUwc!r^NkDzs4YHu@=ZHRzrafWDZd1EhEVq=tGX?tK$pIa)DTh#bkvh!J- z?^%@YS!U*0E8$q$_*aOTQ&)Ra64g>ep;BdcQgvlg8qQHrP*E$;P{-m=A*@axn@$bO zO-Y4JzS&EAi%YG}N?cn?YFS7ivPY=EMV6~YH;+Xxu|tefLS|Aza)Cg6us#)=JW!uH zQa?H>d^j+YHCtyjL^LulF*05|F$RG!AX_OHVI&MtA~_@=5_lU|0000rbW%=J06GH4 z^5LD8b8apw8vNh1ua1mF{{Hy)_U`NA;Nacc+sCpuHXa-V{r&yz?c(9#+}oX+NmiRW z+W-IqK1oDDR5;6GfCDCOP5}iL5fK(cB~ET81`MFgF2kGa9AjhSIk~-E-4&*tPPKdiilQJ11k_J082ZS z>@TvivP!5ZFG?t@{t+GpR3XR&@*hA_VE1|Lo8@L@)l*h(Z@=?c-NS$Fk&&61IzUU9 z*nPqBM=OBZ-6ka1SJgGAS-Us5EN)r#dUX%>wQZLa2ytPCtMKp)Ob z*xcu38Z&d5<-NBS)@jRD+*!W*cf-m_wmxDEqBf?czI%3U0J$Xik;lA`jg}VH?(S(V zE!M3;X2B8w0TnnW&6(8;_Uc)WD;Ms6PKP+s(sFgO!}B!^ES~GDt4qLPxwYB)^7)XA zZwo9zDy-B0B+jT6V=!=bo(zs_8{eBA78gT9GH$(DVhz;4VAYwz+bOIdZ-PNb|I&rl z^XG=vFLF)1{&nT2*0vMz#}7^9hXzzf&ZdKlEj{LihP;|;Ywqn35ajP?H?7t|i-Un% z&&kxee@9B{nwgv1+S-~0)E1{ob1^Wn`F2isurqThKK=3%&;`@{0{!D- z&CSj80t;uPu&FaJFtSXKH#ajgGj}=sEad7US6jP0|Db@0j)?(5@sf<7`~a9>s;wCa zm^)spe{uxGFmrJYI9cOh7s$>8Npkt-5EWB1UKc`{W{y5Ce$1+nM9Cr;);=Ju#N^62OSlJMn7omiUgP&ErsYzT~iGxcW aE(`!K@+CXylaC4j0000 + + + + Coverage report + + + + + +
+
+

Coverage report: + 90% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filefunctionstatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.pyGenPyModule.__init__1100100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.pyGenPyModule.process3112061%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py(no function)3102100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.pyGenModule.__init__1400100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.pyGenModule.get_reader100100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.pyGenModule.get_writer100100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.pyGenModule.gen_setup1600100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py(no function)2802100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.pyReadTemplate.__init__200100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.pyReadTemplate.read4111073%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py(no function)2102100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.pyWriteTemplate.__init__200100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.pyWriteTemplate.write261096%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py(no function)2202100%
Total 24724890%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/index.html b/tests/htmlcov/index.html new file mode 100644 index 0000000..9cc82b1 --- /dev/null +++ b/tests/htmlcov/index.html @@ -0,0 +1,132 @@ + + + + + Coverage report + + + + + +
+
+

Coverage report: + 90% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filestatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py7312284%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py6002100%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py6411283%
/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py501298%
Total24724890%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/keybd_closed_cb_ce680311.png b/tests/htmlcov/keybd_closed_cb_ce680311.png new file mode 100644 index 0000000000000000000000000000000000000000..ba119c47df81ed2bbd27a06988abf700139c4f99 GIT binary patch literal 9004 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 literal 0 HcmV?d00001 diff --git a/tests/htmlcov/status.json b/tests/htmlcov/status.json new file mode 100644 index 0000000..daba9e4 --- /dev/null +++ b/tests/htmlcov/status.json @@ -0,0 +1 @@ +{"note":"This file is an internal implementation detail to speed up HTML report generation. Its format can change at any time. You might be looking for the JSON report: https://coverage.rtfd.io/cmd.html#cmd-json","format":5,"version":"7.6.10","globals":"0c4539a53d93fb2149acf2cdcc3adc0e","files":{"z_1fbd185717e15308___init___py":{"hash":"fd9ba433d3e95fb9e5821758b7d63082","index":{"url":"z_1fbd185717e15308___init___py.html","file":"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":73,"n_excluded":2,"n_missing":12,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_72557b19952452c1___init___py":{"hash":"1d5cb3fc3344b6e3f0b8e2f5b52ee242","index":{"url":"z_72557b19952452c1___init___py.html","file":"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":60,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_72557b19952452c1_read_template_py":{"hash":"fc58db486a82e12c9e6252e8f83984e4","index":{"url":"z_72557b19952452c1_read_template_py.html","file":"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":64,"n_excluded":2,"n_missing":11,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_72557b19952452c1_write_template_py":{"hash":"4e4d6916c0e77ac89fe1c8ea5e9b9bb5","index":{"url":"z_72557b19952452c1_write_template_py.html","file":"/data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":50,"n_excluded":2,"n_missing":1,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}}}} \ No newline at end of file diff --git a/tests/htmlcov/style_cb_8e611ae1.css b/tests/htmlcov/style_cb_8e611ae1.css new file mode 100644 index 0000000..3cdaf05 --- /dev/null +++ b/tests/htmlcov/style_cb_8e611ae1.css @@ -0,0 +1,337 @@ +@charset "UTF-8"; +/* Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 */ +/* For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt */ +/* Don't edit this .css file. Edit the .scss file instead! */ +html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } + +body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 1em; background: #fff; color: #000; } + +@media (prefers-color-scheme: dark) { body { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { body { color: #eee; } } + +html > body { font-size: 16px; } + +a:active, a:focus { outline: 2px dashed #007acc; } + +p { font-size: .875em; line-height: 1.4em; } + +table { border-collapse: collapse; } + +td { vertical-align: top; } + +table tr.hidden { display: none !important; } + +p#no_rows { display: none; font-size: 1.15em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } + +a.nav { text-decoration: none; color: inherit; } + +a.nav:hover { text-decoration: underline; color: inherit; } + +.hidden { display: none; } + +header { background: #f8f8f8; width: 100%; z-index: 2; border-bottom: 1px solid #ccc; } + +@media (prefers-color-scheme: dark) { header { background: black; } } + +@media (prefers-color-scheme: dark) { header { border-color: #333; } } + +header .content { padding: 1rem 3.5rem; } + +header h2 { margin-top: .5em; font-size: 1em; } + +header h2 a.button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; } + +@media (prefers-color-scheme: dark) { header h2 a.button { background: #333; } } + +@media (prefers-color-scheme: dark) { header h2 a.button { border-color: #444; } } + +header h2 a.button.current { border: 2px solid; background: #fff; border-color: #999; cursor: default; } + +@media (prefers-color-scheme: dark) { header h2 a.button.current { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { header h2 a.button.current { border-color: #777; } } + +header p.text { margin: .5em 0 -.5em; color: #666; font-style: italic; } + +@media (prefers-color-scheme: dark) { header p.text { color: #aaa; } } + +header.sticky { position: fixed; left: 0; right: 0; height: 2.5em; } + +header.sticky .text { display: none; } + +header.sticky h1, header.sticky h2 { font-size: 1em; margin-top: 0; display: inline-block; } + +header.sticky .content { padding: 0.5rem 3.5rem; } + +header.sticky .content p { font-size: 1em; } + +header.sticky ~ #source { padding-top: 6.5em; } + +main { position: relative; z-index: 1; } + +footer { margin: 1rem 3.5rem; } + +footer .content { padding: 0; color: #666; font-style: italic; } + +@media (prefers-color-scheme: dark) { footer .content { color: #aaa; } } + +#index { margin: 1rem 0 0 3.5rem; } + +h1 { font-size: 1.25em; display: inline-block; } + +#filter_container { float: right; margin: 0 2em 0 0; line-height: 1.66em; } + +#filter_container #filter { width: 10em; padding: 0.2em 0.5em; border: 2px solid #ccc; background: #fff; color: #000; } + +@media (prefers-color-scheme: dark) { #filter_container #filter { border-color: #444; } } + +@media (prefers-color-scheme: dark) { #filter_container #filter { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { #filter_container #filter { color: #eee; } } + +#filter_container #filter:focus { border-color: #007acc; } + +#filter_container :disabled ~ label { color: #ccc; } + +@media (prefers-color-scheme: dark) { #filter_container :disabled ~ label { color: #444; } } + +#filter_container label { font-size: .875em; color: #666; } + +@media (prefers-color-scheme: dark) { #filter_container label { color: #aaa; } } + +header button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; } + +@media (prefers-color-scheme: dark) { header button { background: #333; } } + +@media (prefers-color-scheme: dark) { header button { border-color: #444; } } + +header button:active, header button:focus { outline: 2px dashed #007acc; } + +header button.run { background: #eeffee; } + +@media (prefers-color-scheme: dark) { header button.run { background: #373d29; } } + +header button.run.show_run { background: #dfd; border: 2px solid #00dd00; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.run.show_run { background: #373d29; } } + +header button.mis { background: #ffeeee; } + +@media (prefers-color-scheme: dark) { header button.mis { background: #4b1818; } } + +header button.mis.show_mis { background: #fdd; border: 2px solid #ff0000; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.mis.show_mis { background: #4b1818; } } + +header button.exc { background: #f7f7f7; } + +@media (prefers-color-scheme: dark) { header button.exc { background: #333; } } + +header button.exc.show_exc { background: #eee; border: 2px solid #808080; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.exc.show_exc { background: #333; } } + +header button.par { background: #ffffd5; } + +@media (prefers-color-scheme: dark) { header button.par { background: #650; } } + +header button.par.show_par { background: #ffa; border: 2px solid #bbbb00; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.par.show_par { background: #650; } } + +#help_panel, #source p .annotate.long { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; color: #333; padding: .25em .5em; } + +#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; } + +#help_panel_wrapper { float: right; position: relative; } + +#keyboard_icon { margin: 5px; } + +#help_panel_state { display: none; } + +#help_panel { top: 25px; right: 0; padding: .75em; border: 1px solid #883; color: #333; } + +#help_panel .keyhelp p { margin-top: .75em; } + +#help_panel .legend { font-style: italic; margin-bottom: 1em; } + +.indexfile #help_panel { width: 25em; } + +.pyfile #help_panel { width: 18em; } + +#help_panel_state:checked ~ #help_panel { display: block; } + +kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-weight: bold; background: #eee; border-radius: 3px; } + +#source { padding: 1em 0 1em 3.5rem; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; } + +#source p { position: relative; white-space: pre; } + +#source p * { box-sizing: border-box; } + +#source p .n { float: left; text-align: right; width: 3.5rem; box-sizing: border-box; margin-left: -3.5rem; padding-right: 1em; color: #999; user-select: none; } + +@media (prefers-color-scheme: dark) { #source p .n { color: #777; } } + +#source p .n.highlight { background: #ffdd00; } + +#source p .n a { scroll-margin-top: 6em; text-decoration: none; color: #999; } + +@media (prefers-color-scheme: dark) { #source p .n a { color: #777; } } + +#source p .n a:hover { text-decoration: underline; color: #999; } + +@media (prefers-color-scheme: dark) { #source p .n a:hover { color: #777; } } + +#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid #fff; } + +@media (prefers-color-scheme: dark) { #source p .t { border-color: #1e1e1e; } } + +#source p .t:hover { background: #f2f2f2; } + +@media (prefers-color-scheme: dark) { #source p .t:hover { background: #282828; } } + +#source p .t:hover ~ .r .annotate.long { display: block; } + +#source p .t .com { color: #008000; font-style: italic; line-height: 1px; } + +@media (prefers-color-scheme: dark) { #source p .t .com { color: #6a9955; } } + +#source p .t .key { font-weight: bold; line-height: 1px; } + +#source p .t .str { color: #0451a5; } + +@media (prefers-color-scheme: dark) { #source p .t .str { color: #9cdcfe; } } + +#source p.mis .t { border-left: 0.2em solid #ff0000; } + +#source p.mis.show_mis .t { background: #fdd; } + +@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t { background: #4b1818; } } + +#source p.mis.show_mis .t:hover { background: #f2d2d2; } + +@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } } + +#source p.run .t { border-left: 0.2em solid #00dd00; } + +#source p.run.show_run .t { background: #dfd; } + +@media (prefers-color-scheme: dark) { #source p.run.show_run .t { background: #373d29; } } + +#source p.run.show_run .t:hover { background: #d2f2d2; } + +@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } } + +#source p.exc .t { border-left: 0.2em solid #808080; } + +#source p.exc.show_exc .t { background: #eee; } + +@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t { background: #333; } } + +#source p.exc.show_exc .t:hover { background: #e2e2e2; } + +@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } } + +#source p.par .t { border-left: 0.2em solid #bbbb00; } + +#source p.par.show_par .t { background: #ffa; } + +@media (prefers-color-scheme: dark) { #source p.par.show_par .t { background: #650; } } + +#source p.par.show_par .t:hover { background: #f2f2a2; } + +@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } } + +#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } + +#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; } + +@media (prefers-color-scheme: dark) { #source p .annotate { color: #ddd; } } + +#source p .annotate.short:hover ~ .long { display: block; } + +#source p .annotate.long { width: 30em; right: 2.5em; } + +#source p input { display: none; } + +#source p input ~ .r label.ctx { cursor: pointer; border-radius: .25em; } + +#source p input ~ .r label.ctx::before { content: "â–¶ "; } + +#source p input ~ .r label.ctx:hover { background: #e8f4ff; color: #666; } + +@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { background: #0f3a42; } } + +@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { color: #aaa; } } + +#source p input:checked ~ .r label.ctx { background: #d0e8ff; color: #666; border-radius: .75em .75em 0 0; padding: 0 .5em; margin: -.25em 0; } + +@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { background: #056; } } + +@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { color: #aaa; } } + +#source p input:checked ~ .r label.ctx::before { content: "â–¼ "; } + +#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; } + +#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; } + +@media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } } + +#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; text-align: right; } + +@media (prefers-color-scheme: dark) { #source p .ctxs { background: #056; } } + +#index { font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875em; } + +#index table.index { margin-left: -.5em; } + +#index td, #index th { text-align: right; padding: .25em .5em; border-bottom: 1px solid #eee; } + +@media (prefers-color-scheme: dark) { #index td, #index th { border-color: #333; } } + +#index td.name, #index th.name { text-align: left; width: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; min-width: 15em; } + +#index th { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-style: italic; color: #333; cursor: pointer; } + +@media (prefers-color-scheme: dark) { #index th { color: #ddd; } } + +#index th:hover { background: #eee; } + +@media (prefers-color-scheme: dark) { #index th:hover { background: #333; } } + +#index th .arrows { color: #666; font-size: 85%; font-family: sans-serif; font-style: normal; pointer-events: none; } + +#index th[aria-sort="ascending"], #index th[aria-sort="descending"] { white-space: nowrap; background: #eee; padding-left: .5em; } + +@media (prefers-color-scheme: dark) { #index th[aria-sort="ascending"], #index th[aria-sort="descending"] { background: #333; } } + +#index th[aria-sort="ascending"] .arrows::after { content: " â–²"; } + +#index th[aria-sort="descending"] .arrows::after { content: " â–¼"; } + +#index td.name { font-size: 1.15em; } + +#index td.name a { text-decoration: none; color: inherit; } + +#index td.name .no-noun { font-style: italic; } + +#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } + +#index tr.region:hover { background: #eee; } + +@media (prefers-color-scheme: dark) { #index tr.region:hover { background: #333; } } + +#index tr.region:hover td.name { text-decoration: underline; color: inherit; } + +#scroll_marker { position: fixed; z-index: 3; right: 0; top: 0; width: 16px; height: 100%; background: #fff; border-left: 1px solid #eee; will-change: transform; } + +@media (prefers-color-scheme: dark) { #scroll_marker { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { #scroll_marker { border-color: #333; } } + +#scroll_marker .marker { background: #ccc; position: absolute; min-height: 3px; width: 100%; } + +@media (prefers-color-scheme: dark) { #scroll_marker .marker { background: #444; } } diff --git a/tests/htmlcov/z_1fbd185717e15308___init___py.html b/tests/htmlcov/z_1fbd185717e15308___init___py.html new file mode 100644 index 0000000..6754bac --- /dev/null +++ b/tests/htmlcov/z_1fbd185717e15308___init___py.html @@ -0,0 +1,288 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py: 84% + + + + + +
+
+

+ Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/__init__.py: + 84% +

+ +

+ 73 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 gen_py_module.py 

+

6Copyright 

+

7 Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 gen_py_module is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 gen_py_module is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defined class GenPyModule with attribute(s) and method(s). 

+

20 Loads a base info, creates a CLI interface and runs operations. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List, Dict, Optional 

+

25from os.path import exists, dirname, realpath 

+

26from os import getcwd 

+

27from argparse import Namespace 

+

28 

+

29try: 

+

30 from ats_utilities.splash import Splash 

+

31 from ats_utilities.logging import ATSLogger 

+

32 from ats_utilities.cli import ATSCli 

+

33 from ats_utilities.console_io.error import error_message 

+

34 from ats_utilities.console_io.verbose import verbose_message 

+

35 from ats_utilities.console_io.success import success_message 

+

36 from ats_utilities.exceptions.ats_type_error import ATSTypeError 

+

37 from ats_utilities.exceptions.ats_value_error import ATSValueError 

+

38 from gen_py_module.pro import GenModule 

+

39except ImportError as ats_error_message: # pragma: no cover 

+

40 # Force exit python ####################################################### 

+

41 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

42 

+

43__author__: str = 'Vladimir Roncevic' 

+

44__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model' 

+

45__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

46__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' 

+

47__version__: str = '1.5.7' 

+

48__maintainer__: str = 'Vladimir Roncevic' 

+

49__email__: str = 'elektron.ronca@gmail.com' 

+

50__status__: str = 'Updated' 

+

51 

+

52 

+

53class GenPyModule(ATSCli): 

+

54 ''' 

+

55 Defines class GenPyModule with attribute(s) and method(s). 

+

56 Loads a base info, creates a CLI interface and runs operations. 

+

57 

+

58 It defines: 

+

59 

+

60 :attributes: 

+

61 | _GEN_VERBOSE - Console text indicator for process-phase. 

+

62 | _CONFIG - Tool info file path. 

+

63 | _LOG - Tool log file path. 

+

64 | _LOGO - Logo for splash screen. 

+

65 | _OPS - List of tool options. 

+

66 | _logger - Logger object API. 

+

67 :methods: 

+

68 | __init__ - Initials GenPyModule constructor. 

+

69 | process - Processes and runs operations. 

+

70 ''' 

+

71 

+

72 _GEN_VERBOSE: str = 'GEN_PY_MODULE' 

+

73 _CONFIG: str = '/conf/gen_py_module.cfg' 

+

74 _LOG: str = '/log/gen_py_module.log' 

+

75 _LOGO: str = '/conf/gen_py_module.logo' 

+

76 _OPS: List[str] = ['-n', '--name', '-t', '--type', '-v', '--verbose'] 

+

77 

+

78 def __init__(self, verbose: bool = False) -> None: 

+

79 ''' 

+

80 Initials GenMessageQueue constructor. 

+

81 

+

82 :param verbose: Enable/Disable verbose option 

+

83 :type verbose: <bool> 

+

84 :exceptions: None 

+

85 ''' 

+

86 current_dir: str = dirname(realpath(__file__)) 

+

87 gen_autoconf_property: Dict[str, str | bool] = { 

+

88 'ats_organization': 'vroncevic', 

+

89 'ats_repository': f'{self._GEN_VERBOSE.lower()}', 

+

90 'ats_name': f'{self._GEN_VERBOSE.lower()}', 

+

91 'ats_logo_path': f'{current_dir}{self._LOGO}', 

+

92 'ats_use_github_infrastructure': True 

+

93 } 

+

94 Splash(gen_autoconf_property, verbose) 

+

95 base_info: str = f'{current_dir}{self._CONFIG}' 

+

96 super().__init__(base_info, verbose) 

+

97 verbose_message( 

+

98 verbose, [f'{self._GEN_VERBOSE.lower()} init tool info'] 

+

99 ) 

+

100 self._logger: ATSLogger = ATSLogger( 

+

101 self._GEN_VERBOSE.lower(), True, None, True, verbose 

+

102 ) 

+

103 if self.is_operational(): 

+

104 self.add_new_option( 

+

105 self._OPS[0], self._OPS[1], dest='name', 

+

106 help='generate module (provide project name)' 

+

107 ) 

+

108 self.add_new_option( 

+

109 self._OPS[2], self._OPS[3], dest='type', 

+

110 help='type (abc | base | empty | main | class)' 

+

111 ) 

+

112 self.add_new_option( 

+

113 self._OPS[4], self._OPS[5], 

+

114 action='store_true', default=False, 

+

115 help='activate verbose mode for generation' 

+

116 ) 

+

117 

+

118 def process(self, verbose: bool = False) -> bool: 

+

119 ''' 

+

120 Process and run operation. 

+

121 

+

122 :param verbose: Enable/Disable verbose option 

+

123 :type verbose: <bool> 

+

124 :return: True (success operation) | False 

+

125 :rtype: <bool> 

+

126 :exceptions: None 

+

127 ''' 

+

128 status: bool = False 

+

129 if self.is_operational(): 

+

130 try: 

+

131 args: Optional[Namespace] = self.parse_args(sys.argv) 

+

132 if not bool(getattr(args, 'name')): 

+

133 error_message( 

+

134 [f'{self._GEN_VERBOSE.lower()} missing name argument'] 

+

135 ) 

+

136 return status 

+

137 if not bool(getattr(args, 'type')): 

+

138 error_message( 

+

139 [f'{self._GEN_VERBOSE.lower()} missing type argument'] 

+

140 ) 

+

141 return status 

+

142 if exists(f'{getcwd()}/{str(getattr(args, "name"))}'): 

+

143 error_message([ 

+

144 f'{self._GEN_VERBOSE.lower()}', 

+

145 f'project with name [{getattr(args, "name")}] exists' 

+

146 ]) 

+

147 return status 

+

148 gen: GenModule = GenModule(getattr(args, 'verbose') or verbose) 

+

149 try: 

+

150 print( 

+

151 " ".join([ 

+

152 f'[{self._GEN_VERBOSE.lower()}]', 

+

153 'generate python module skeleton', 

+

154 str(getattr(args, 'name')) 

+

155 ]) 

+

156 ) 

+

157 status = gen.gen_setup( 

+

158 f'{getattr(args, "name")}', 

+

159 f'{getattr(args, "type")}', 

+

160 getattr(args, 'verbose') or verbose 

+

161 ) 

+

162 except (ATSTypeError, ATSValueError) as e: 

+

163 error_message([f'{self._GEN_VERBOSE.lower()} {str(e)}']) 

+

164 self._logger.write_log(f'{str(e)}', self._logger.ATS_ERROR) 

+

165 if status: 

+

166 success_message([f'{self._GEN_VERBOSE.lower()} done\n']) 

+

167 self._logger.write_log( 

+

168 f'generation {getattr(args, "name")} done', 

+

169 self._logger.ATS_INFO 

+

170 ) 

+

171 else: 

+

172 error_message([f'{self._GEN_VERBOSE.lower()} failed']) 

+

173 self._logger.write_log( 

+

174 'generation failed', self._logger.ATS_ERROR 

+

175 ) 

+

176 except SystemExit: 

+

177 error_message( 

+

178 [ 

+

179 f'{self._GEN_VERBOSE.lower()}', 

+

180 'expected arguments name and type' 

+

181 ] 

+

182 ) 

+

183 return status 

+

184 else: 

+

185 error_message( 

+

186 [f'{self._GEN_VERBOSE.lower()} tool is not operational'] 

+

187 ) 

+

188 self._logger.write_log( 

+

189 'tool is not operational', self._logger.ATS_ERROR 

+

190 ) 

+

191 return status 

+
+ + + diff --git a/tests/htmlcov/z_72557b19952452c1___init___py.html b/tests/htmlcov/z_72557b19952452c1___init___py.html new file mode 100644 index 0000000..4439c6b --- /dev/null +++ b/tests/htmlcov/z_72557b19952452c1___init___py.html @@ -0,0 +1,260 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/__init__.py: + 100% +

+ +

+ 60 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 gen_py_module is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 gen_py_module is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defined class GenModule with attribute(s) and method(s). 

+

20 Generates PY MODULE by templates and parameters. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List, Dict, Optional 

+

25from os.path import dirname, realpath 

+

26 

+

27try: 

+

28 from ats_utilities.pro_config import ProConfig 

+

29 from ats_utilities.pro_config.pro_name import ProName 

+

30 from ats_utilities.config_io.file_check import FileCheck 

+

31 from ats_utilities.console_io.verbose import verbose_message 

+

32 from ats_utilities.config_io.yaml.yaml2object import Yaml2Object 

+

33 from ats_utilities.exceptions.ats_type_error import ATSTypeError 

+

34 from ats_utilities.exceptions.ats_value_error import ATSValueError 

+

35 from gen_py_module.pro.read_template import ReadTemplate 

+

36 from gen_py_module.pro.write_template import WriteTemplate 

+

37except ImportError as ats_error_message: # pragma: no cover 

+

38 # Force exit python ####################################################### 

+

39 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

40 

+

41__author__: str = 'Vladimir Roncevic' 

+

42__copyright__: str = 'Copyright 2026, https://vroncevic.github.io/gen_form_model' 

+

43__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

44__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' 

+

45__version__: str = '1.5.7' 

+

46__maintainer__: str = 'Vladimir Roncevic' 

+

47__email__: str = 'elektron.ronca@gmail.com' 

+

48__status__: str = 'Updated' 

+

49 

+

50 

+

51class GenModule(FileCheck, ProConfig, ProName): 

+

52 ''' 

+

53 Defines class GenModule with attribute(s) and method(s). 

+

54 Generates PY MODULE by templates and parameters. 

+

55 

+

56 It defines: 

+

57 

+

58 :attributes: 

+

59 | _GEN_VERBOSE - Console text indicator for process-phase. 

+

60 | _PRO_STRUCTURE - Project setup (templates, modules). 

+

61 | _reader - Reader API. 

+

62 | _writer - Writer API. 

+

63 :methods: 

+

64 | __init__ - Initials GenModule constructor. 

+

65 | get_reader - Gets template reader. 

+

66 | get_writer - Gets template writer. 

+

67 | gen_module - Generates PY MODULE. 

+

68 ''' 

+

69 

+

70 _GEN_VERBOSE: str = 'GEN_PY_MODULE::PRO::GEN_MODULE' 

+

71 _PRO_STRUCTURE: str = '/../conf/project.yaml' 

+

72 

+

73 def __init__(self, verbose: bool = False) -> None: 

+

74 ''' 

+

75 Initials GenModule constructor. 

+

76 

+

77 :param verbose: Enable/Disable verbose option 

+

78 :type verbose: <bool> 

+

79 :exceptions: None 

+

80 ''' 

+

81 FileCheck.__init__(self, verbose) 

+

82 ProConfig.__init__(self, verbose) 

+

83 ProName.__init__(self, verbose) 

+

84 verbose_message( 

+

85 verbose, [f'{self._GEN_VERBOSE.lower()} init generator'] 

+

86 ) 

+

87 self._reader: Optional[ReadTemplate] = ReadTemplate(verbose) 

+

88 self._writer: Optional[WriteTemplate] = WriteTemplate(verbose) 

+

89 current_dir: str = dirname(realpath(__file__)) 

+

90 pro_structure: str = f'{current_dir}{self._PRO_STRUCTURE}' 

+

91 self.check_path(pro_structure, verbose) 

+

92 self.check_mode('r', verbose) 

+

93 self.check_format(pro_structure, 'yaml', verbose) 

+

94 if self.is_file_ok(): 

+

95 yml2obj: Optional[Yaml2Object] = Yaml2Object(pro_structure) 

+

96 self.config = yml2obj.read_configuration() 

+

97 

+

98 def get_reader(self) -> Optional[ReadTemplate]: 

+

99 ''' 

+

100 Gets template reader. 

+

101 

+

102 :return: Template reader object | None 

+

103 :rtype: <Optional[ReadTemplate]> 

+

104 :exceptions: None 

+

105 ''' 

+

106 return self._reader 

+

107 

+

108 def get_writer(self) -> Optional[WriteTemplate]: 

+

109 ''' 

+

110 Gets template writer. 

+

111 

+

112 :return: Template writer object | none 

+

113 :rtype: <Optional[WriteTemplate]> 

+

114 :exceptions: None 

+

115 ''' 

+

116 return self._writer 

+

117 

+

118 def gen_setup( 

+

119 self, 

+

120 pro_name: Optional[str], 

+

121 pro_type: Optional[str], 

+

122 verbose: bool = False 

+

123 ) -> bool: 

+

124 ''' 

+

125 Generates PY MODULE. 

+

126 

+

127 :param pro_name: Project name | None 

+

128 :type pro_name: <Optional[str]> 

+

129 :param pro_type: Project type | None 

+

130 :type pro_type: <Optional[str]> 

+

131 :param verbose: Enable/Disable verbose option 

+

132 :type verbose: <bool> 

+

133 :return: True (success operation) | False 

+

134 :rtype: <bool> 

+

135 :exceptions: ATSTypeError | ATSValueError 

+

136 ''' 

+

137 error_msg: Optional[str] = None 

+

138 error_id: Optional[int] = None 

+

139 error_msg, error_id = self.check_params([ 

+

140 ('str:pro_name', pro_name), ('str:pro_type', pro_type) 

+

141 ]) 

+

142 if error_id == self.TYPE_ERROR: 

+

143 raise ATSTypeError(error_msg) 

+

144 if not bool(pro_name): 

+

145 raise ATSValueError('missing project name') 

+

146 if not bool(pro_type): 

+

147 raise ATSValueError('missing project type') 

+

148 status: bool = False 

+

149 verbose_message( 

+

150 verbose, [ 

+

151 f'{self._GEN_VERBOSE.lower()}', 

+

152 'generate', pro_type, 'form', pro_name 

+

153 ] 

+

154 ) 

+

155 if bool(self._reader) and bool(self.config): 

+

156 template_content: Dict[str, str] = self._reader.read( 

+

157 self.config, pro_name, pro_type, verbose 

+

158 ) 

+

159 if bool(template_content) and bool(self._writer): 

+

160 status = self._writer.write( 

+

161 template_content, pro_name, verbose 

+

162 ) 

+

163 return status 

+
+ + + diff --git a/tests/htmlcov/z_72557b19952452c1_read_template_py.html b/tests/htmlcov/z_72557b19952452c1_read_template_py.html new file mode 100644 index 0000000..0474faf --- /dev/null +++ b/tests/htmlcov/z_72557b19952452c1_read_template_py.html @@ -0,0 +1,241 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py: 83% + + + + + +
+
+

+ Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/read_template.py: + 83% +

+ +

+ 64 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 read_template.py 

+

6Copyright 

+

7 Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 gen_py_module is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 gen_py_module is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defined class ReadTemplate with attribute(s) and method(s). 

+

20 Creates an API for reading a PY MODULE template. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import Any, List, Dict, Optional 

+

25from os.path import dirname, realpath 

+

26 

+

27try: 

+

28 from ats_utilities.config_io.file_check import FileCheck 

+

29 from ats_utilities.console_io.verbose import verbose_message 

+

30 from ats_utilities.exceptions.ats_type_error import ATSTypeError 

+

31 from ats_utilities.exceptions.ats_value_error import ATSValueError 

+

32except ImportError as ats_error_message: # pragma: no cover 

+

33 # Force exit python ####################################################### 

+

34 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

35 

+

36__author__: str = 'Vladimir Roncevic' 

+

37__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' 

+

38__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

39__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' 

+

40__version__: str = '1.5.7' 

+

41__maintainer__: str = 'Vladimir Roncevic' 

+

42__email__: str = 'elektron.ronca@gmail.com' 

+

43__status__: str = 'Updated' 

+

44 

+

45 

+

46class ReadTemplate(FileCheck): 

+

47 ''' 

+

48 Defines class ReadTemplate with attribute(s) and method(s). 

+

49 Creates an API for reading a PY MODULE template. 

+

50 

+

51 It defines: 

+

52 

+

53 :attributes: 

+

54 | _GEN_VERBOSE - Console text indicator for process-phase. 

+

55 | _TEMPLATE_DIR - Prefix path to templates. 

+

56 :methods: 

+

57 | __init__ - Initials ReadTemplate constructor. 

+

58 | read - Reads a template. 

+

59 ''' 

+

60 

+

61 _GEN_VERBOSE: str = 'GEN_PY_MODULE::PRO::READ_TEMPLATE' 

+

62 _TEMPLATE_DIR: str = '/../conf/template/' 

+

63 

+

64 def __init__(self, verbose: bool = False) -> None: 

+

65 ''' 

+

66 Initials ReadTemplate constructor. 

+

67 

+

68 :param verbose: Enable/Disable verbose option 

+

69 :type verbose: <bool> 

+

70 :exceptions: None 

+

71 ''' 

+

72 super().__init__(verbose) 

+

73 verbose_message(verbose, [f'{self._GEN_VERBOSE.lower()} init reader']) 

+

74 

+

75 def read( 

+

76 self, 

+

77 config: Dict[Any, Any], 

+

78 pro_name: Optional[str], 

+

79 pro_type: Optional[str], 

+

80 verbose: bool = False 

+

81 ) -> Dict[str, str]: 

+

82 ''' 

+

83 Reads a template. 

+

84 

+

85 :param config: Module configuration 

+

86 :type config: <Dict[Any, Any]> 

+

87 :param pro_name: Module name | None 

+

88 :type pro_name: <Optional[str]> 

+

89 :param pro_type: Module type | None 

+

90 :type pro_type: <Optional[str]> 

+

91 :param verbose: Enable/Disable verbose option 

+

92 :type verbose: <bool> 

+

93 :return: Loaded templates 

+

94 :rtype: <Dict[str, str]> 

+

95 :exceptions: ATSTypeError | ATSValueError 

+

96 ''' 

+

97 error_msg: Optional[str] = None 

+

98 error_id: Optional[int] = None 

+

99 error_msg, error_id = self.check_params([ 

+

100 ('dict:config', config), 

+

101 ('str:pro_name', pro_name), 

+

102 ('str:pro_type', pro_type) 

+

103 ]) 

+

104 if error_id == self.TYPE_ERROR: 

+

105 raise ATSTypeError(error_msg) 

+

106 if not bool(config): 

+

107 raise ATSValueError('missing project templates') 

+

108 if not bool(pro_name): 

+

109 raise ATSValueError('missing project name') 

+

110 if not bool(pro_type): 

+

111 raise ATSValueError('missing project type') 

+

112 current_dir: str = dirname(realpath(__file__)) 

+

113 pro_structure: str = f'{current_dir}{self._TEMPLATE_DIR}' 

+

114 template_dir: str = f'{pro_structure}/' 

+

115 template_content: Dict[str, str] = {} 

+

116 index: int = -1 

+

117 if pro_type in config['modules'][0]: 

+

118 index = 0 

+

119 elif pro_type in config['modules'][1]: 

+

120 index = 1 

+

121 elif pro_type in config['modules'][2]: 

+

122 index = 2 

+

123 elif pro_type in config['modules'][3]: 

+

124 index = 3 

+

125 elif pro_type in config['modules'][4]: 

+

126 index = 4 

+

127 else: 

+

128 return template_content 

+

129 modules: List[str] = config['modules'][index][pro_type] 

+

130 templates: List[str] = config['templates'][index][pro_type] 

+

131 for module, template in zip(modules, templates): 

+

132 template_file: str = f'{template_dir}{template}' 

+

133 with open(template_file, 'r', encoding='utf-8') as module_file: 

+

134 if 'class.py' == module: 

+

135 module: str = f'{pro_name}.py' 

+

136 if 'abstract_base.py' == module: 

+

137 module = f'{pro_name}_base.py' 

+

138 if 'abstract_abc.py' == module: 

+

139 module = f'{pro_name}_abc.py' 

+

140 template_content[module] = module_file.read() 

+

141 verbose_message( 

+

142 verbose, [f'{self._GEN_VERBOSE.lower()} {template_content}'] 

+

143 ) 

+

144 return template_content 

+
+ + + diff --git a/tests/htmlcov/z_72557b19952452c1_write_template_py.html b/tests/htmlcov/z_72557b19952452c1_write_template_py.html new file mode 100644 index 0000000..93a5ed2 --- /dev/null +++ b/tests/htmlcov/z_72557b19952452c1_write_template_py.html @@ -0,0 +1,229 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py: 98% + + + + + +
+
+

+ Coverage for /data/dev/python/3_tools/gen_py_module/github/gen_py_module/gen_py_module/pro/write_template.py: + 98% +

+ +

+ 50 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-27 18:32 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 write_template.py 

+

6Copyright 

+

7 Copyright (C) 2017 - 2026 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 gen_py_module is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 gen_py_module is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defined class WriteTemplate with atribute(s) and method(s). 

+

20 Creates an API for write a template content with parameters to a file. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List, Dict, Optional 

+

25from datetime import date 

+

26from os import getcwd, chmod, mkdir 

+

27from string import Template 

+

28 

+

29try: 

+

30 from ats_utilities.config_io.file_check import FileCheck 

+

31 from ats_utilities.console_io.verbose import verbose_message 

+

32 from ats_utilities.exceptions.ats_type_error import ATSTypeError 

+

33 from ats_utilities.exceptions.ats_value_error import ATSValueError 

+

34except ImportError as ats_error_message: # pragma: no cover 

+

35 # Force exit python ####################################################### 

+

36 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

37 

+

38__author__: str = 'Vladimir Roncevic' 

+

39__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' 

+

40__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

41__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' 

+

42__version__: str = '1.5.7' 

+

43__maintainer__: str = 'Vladimir Roncevic' 

+

44__email__: str = 'elektron.ronca@gmail.com' 

+

45__status__: str = 'Updated' 

+

46 

+

47 

+

48class WriteTemplate(FileCheck): 

+

49 ''' 

+

50 Defines class WriteTemplate with attribute(s) and method(s). 

+

51 Creates an API for write a template content with parameters to a file. 

+

52 

+

53 It defines: 

+

54 

+

55 :attributes: 

+

56 | _GEN_VERBOSE - Console text indicator for process-phase. 

+

57 :methods: 

+

58 | __init__ - Initials WriteTemplate constructor. 

+

59 | write - write a template content with parameters to a file. 

+

60 ''' 

+

61 

+

62 _GEN_VERBOSE: str = 'GEN_PY_MODULE::PRO::WRITE_TEMPLATE' 

+

63 

+

64 def __init__(self, verbose: bool = False) -> None: 

+

65 ''' 

+

66 Initials WriteTemplate constructor. 

+

67 

+

68 :param verbose: Enable/Disable verbose option 

+

69 :type verbose: <bool> 

+

70 :excptions: None 

+

71 ''' 

+

72 super().__init__(verbose) 

+

73 verbose_message(verbose, [f'{self._GEN_VERBOSE.lower()} init writer']) 

+

74 

+

75 def write( 

+

76 self, 

+

77 template_content: Dict[str, str], 

+

78 pro_name: Optional[str], 

+

79 verbose: bool = False 

+

80 ) -> bool: 

+

81 ''' 

+

82 Write setup content to file. 

+

83 

+

84 :param template_content: Template content 

+

85 :type template_content: <Dict[str, str]> 

+

86 :param pro_name: Project name | None 

+

87 :type pro_name: <Optional[str]> 

+

88 :param verbose: Enable/Disable verbose option 

+

89 :type verbose: <bool> 

+

90 :return: True (success operation) | False 

+

91 :rtype: <bool> 

+

92 :exception: ATSTypeError | ATSValueError 

+

93 ''' 

+

94 error_msg: Optional[str] = None 

+

95 error_id: Optional[int] = None 

+

96 error_msg, error_id = self.check_params([ 

+

97 ('dict:template_content', template_content), 

+

98 ('str:pro_name', pro_name) 

+

99 ]) 

+

100 if error_id == self.TYPE_ERROR: 

+

101 raise ATSTypeError(error_msg) 

+

102 if not bool(template_content): 

+

103 raise ATSValueError('missing model content') 

+

104 if not bool(pro_name): 

+

105 raise ATSValueError('missing model name') 

+

106 all_stat: List[bool] = [] 

+

107 num_of_modules: int = len(template_content) 

+

108 module_pro_dir: str = f'{getcwd()}/{pro_name}/' 

+

109 mkdir(module_pro_dir) 

+

110 for module_name, module_content in template_content.items(): 

+

111 module_path: str = f'{module_pro_dir}{module_name}' 

+

112 template: Template = Template(module_content) 

+

113 with open(module_path, 'w', encoding='utf-8') as module_file: 

+

114 module_file.write(template.substitute({ 

+

115 'MOD': pro_name, 

+

116 'MODCL': f'{pro_name.capitalize()}', 

+

117 'PRO': pro_name, 

+

118 'YEAR': f'{date.today().year}' 

+

119 })) 

+

120 chmod(module_path, 0o644) 

+

121 self.check_path(module_path, verbose) 

+

122 self.check_mode('w', verbose) 

+

123 self.check_format( 

+

124 module_path, module_path.split('.')[1], verbose 

+

125 ) 

+

126 if self.is_file_ok(): 

+

127 all_stat.append(True) 

+

128 else: 

+

129 all_stat.append(False) 

+

130 return all([ 

+

131 bool(all_stat), all(all_stat), num_of_modules == len(all_stat) 

+

132 ]) 

+
+ + + diff --git a/tests/latest_pro/latest_pro.py b/tests/latest_pro/latest_pro.py index 2b7cc5f..fa8bb83 100644 --- a/tests/latest_pro/latest_pro.py +++ b/tests/latest_pro/latest_pro.py @@ -4,7 +4,7 @@ Module latest_pro.py Copyright - Copyright (C) 2024 Vladimir Roncevic + Copyright (C) 2025 Vladimir Roncevic latest_pro is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -22,7 +22,7 @@ from typing import List __author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, Free software to use and distributed it.' +__copyright__ = '(C) 2025, Free software to use and distributed it.' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] __license__ = 'GNU General Public License (GPL)' __version__ = '1.0.0' diff --git a/tests/read_template_test.py b/tests/read_template_test.py index 6991382..5969240 100644 --- a/tests/read_template_test.py +++ b/tests/read_template_test.py @@ -4,7 +4,7 @@ Module read_template_test.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -36,14 +36,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.1.3' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.1.3' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class ReadTemplateTestCase(TestCase): diff --git a/tests/run_coverage.sh b/tests/run_coverage.sh index 7fa02e3..30deeb3 100755 --- a/tests/run_coverage.sh +++ b/tests/run_coverage.sh @@ -9,10 +9,11 @@ rm -rf htmlcov gen_py_module_coverage.xml gen_py_module_coverage.json .coverage rm -rf fresh_new/ full_simple_new/ latest_pro/ simple_read/ simple_write/ -ats_coverage_run.py -n gen_py_module -p ../README.md -rm -rf fresh_new/ full_simple_new/ latest_pro/ simple_read/ simple_write/ python3 -m coverage run -m --source=../gen_py_module unittest discover -s ./ -p '*_test.py' -vvv python3 -m coverage html -d htmlcov python3 -m coverage xml -o gen_py_module_coverage.xml python3 -m coverage json -o gen_py_module_coverage.json python3 -m coverage report --format=markdown -m +python3 ats_coverage.py -n gen_py_module +rm htmlcov/.gitignore +echo "Done" \ No newline at end of file diff --git a/tests/simple_write/simple_write.py b/tests/simple_write/simple_write.py index acad6be..721f1af 100644 --- a/tests/simple_write/simple_write.py +++ b/tests/simple_write/simple_write.py @@ -4,7 +4,7 @@ Module simple_write.py Copyright - Copyright (C) 2024 Vladimir Roncevic + Copyright (C) 2025 Vladimir Roncevic simple_write is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -22,7 +22,7 @@ from typing import List __author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, Free software to use and distributed it.' +__copyright__ = '(C) 2025, Free software to use and distributed it.' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] __license__ = 'GNU General Public License (GPL)' __version__ = '1.0.0' diff --git a/tests/write_template_test.py b/tests/write_template_test.py index ac71826..28f2883 100644 --- a/tests/write_template_test.py +++ b/tests/write_template_test.py @@ -4,7 +4,7 @@ Module write_template_test.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_py_module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -37,14 +37,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://vroncevic.github.io/gen_py_module' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_py_module' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' -__version__ = '1.1.3' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_py_module/blob/dev/LICENSE' +__version__: str = '1.1.3' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class WriteTemplateTestCase(TestCase):