From c3a390b282178d64db40c88e7dc91bb4be52dbd1 Mon Sep 17 00:00:00 2001 From: Vladimir Roncevic Date: Fri, 28 Nov 2025 22:28:17 +0100 Subject: [PATCH] [gen_unnamed_pipe] Updated code coverage, version, docs --- .../gen_unnamed_pipe_package_checker.yml | 8 +- .../gen_unnamed_pipe_python3_build.yml | 4 +- .../gen_unnamed_pipe_python_checker.yml | 2 +- Dockerfile | 112 ++- README.md | 12 +- docs/build/doctrees/environment.pickle | Bin 238235 -> 238754 bytes docs/build/doctrees/gen_unnamed_pipe.doctree | Bin 30597 -> 30637 bytes .../doctrees/gen_unnamed_pipe.pro.doctree | Bin 37127 -> 37167 bytes ...gen_unnamed_pipe.pro.read_template.doctree | Bin 28289 -> 28329 bytes ...en_unnamed_pipe.pro.write_template.doctree | Bin 27492 -> 27532 bytes docs/build/doctrees/index.doctree | Bin 24690 -> 24708 bytes docs/build/doctrees/modules.doctree | Bin 2823 -> 2838 bytes docs/build/html/.buildinfo | 2 +- .../build/html/_modules/gen_unnamed_pipe.html | 24 +- .../html/_modules/gen_unnamed_pipe/pro.html | 24 +- .../gen_unnamed_pipe/pro/read_template.html | 24 +- .../gen_unnamed_pipe/pro/write_template.html | 24 +- docs/build/html/_modules/index.html | 2 +- docs/build/html/_sources/index.rst.txt | 2 +- docs/build/html/gen_unnamed_pipe.html | 4 +- docs/build/html/gen_unnamed_pipe.pro.html | 4 +- .../gen_unnamed_pipe.pro.read_template.html | 4 +- .../gen_unnamed_pipe.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 | 2 +- docs/build/html/py-modindex.html | 2 +- docs/build/html/search.html | 2 +- docs/build/html/searchindex.js | 2 +- docs/source/_static/.editorconfig | 3 + docs/source/conf.py | 6 +- docs/source/index.rst | 2 +- gen_unnamed_pipe/__init__.py | 22 +- gen_unnamed_pipe/conf/gen_unnamed_pipe.cfg | 2 +- gen_unnamed_pipe/pro/__init__.py | 22 +- gen_unnamed_pipe/pro/read_template.py | 22 +- gen_unnamed_pipe/pro/write_template.py | 22 +- gen_unnamed_pipe/run/gen_unnamed_pipe_run.py | 22 +- setup.cfg | 46 -- setup.py | 35 +- tests/.coverage | Bin 53248 -> 53248 bytes tests/ats_coverage.py | 215 +++++ tests/gen_unnamed_pipe_coverage.json | 2 +- tests/gen_unnamed_pipe_coverage.xml | 24 +- tests/gen_unnamed_pipe_test.py | 2 +- 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_58479a017d06e93c___init___py.html | 252 ++++++ .../z_58479a017d06e93c_read_template_py.html | 205 +++++ .../z_58479a017d06e93c_write_template_py.html | 226 ++++++ .../z_c59f2450adabd96b___init___py.html | 277 +++++++ tests/mytool/unp.h | 2 +- tests/mytool/unp_close.c | 2 +- tests/mytool/unp_make.c | 2 +- tests/mytool/unp_read.c | 2 +- tests/mytool/unp_write.c | 2 +- tests/run_coverage.sh | 5 +- 64 files changed, 2995 insertions(+), 292 deletions(-) create mode 100644 docs/source/_static/.editorconfig 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_58479a017d06e93c___init___py.html create mode 100644 tests/htmlcov/z_58479a017d06e93c_read_template_py.html create mode 100644 tests/htmlcov/z_58479a017d06e93c_write_template_py.html create mode 100644 tests/htmlcov/z_c59f2450adabd96b___init___py.html diff --git a/.github/workflows/gen_unnamed_pipe_package_checker.yml b/.github/workflows/gen_unnamed_pipe_package_checker.yml index 67842bd..99d642e 100644 --- a/.github/workflows/gen_unnamed_pipe_package_checker.yml +++ b/.github/workflows/gen_unnamed_pipe_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 + # 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 diff --git a/.github/workflows/gen_unnamed_pipe_python3_build.yml b/.github/workflows/gen_unnamed_pipe_python3_build.yml index d01e928..978e309 100644 --- a/.github/workflows/gen_unnamed_pipe_python3_build.yml +++ b/.github/workflows/gen_unnamed_pipe_python3_build.yml @@ -6,7 +6,6 @@ on: - 'gen_unnamed_pipe/**' - 'MANIFEST.in' - 'pyproject.toml' - - 'setup.cfg' - 'setup.py' pull_request: branches: [ master ] @@ -14,7 +13,6 @@ on: - 'gen_unnamed_pipe/**' - '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_unnamed_pipe_python_checker.yml b/.github/workflows/gen_unnamed_pipe_python_checker.yml index b835e46..4dcdf33 100644 --- a/.github/workflows/gen_unnamed_pipe_python_checker.yml +++ b/.github/workflows/gen_unnamed_pipe_python_checker.yml @@ -23,7 +23,7 @@ jobs: echo Checking length of line in modules modules_ok=0 modules=($(find gen_unnamed_pipe/ 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 1f738e8..66d004c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,57 +1,55 @@ -# 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 \ - tree \ - htop \ - wget \ - curl \ - unzip \ - ca-certificates \ - openssl \ - 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 -COPY requirements.txt / -RUN python3 -m venv env -RUN mkdir /gen_unnamed_pipe/ -COPY gen_unnamed_pipe /gen_unnamed_pipe/ -COPY setup.cfg / -COPY pyproject.toml / -COPY MANIFEST.in / -COPY setup.py / -COPY README.md / -COPY LICENSE / -RUN mkdir /tests/ -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_unnamed_pipe-*-py3-none-any.whl -RUN rm -rf /gen_unnamed_pipe/ -RUN rm -f setup.py -RUN rm -f README.md -RUN rm -f setup.cfg -RUN rm -f pyproject.toml -RUN rm -f MANIFEST.in -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 \ + tree \ + htop \ + wget \ + curl \ + unzip \ + ca-certificates \ + openssl \ + 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 +COPY requirements.txt / +RUN python3 -m venv env +RUN mkdir /gen_unnamed_pipe/ +COPY gen_unnamed_pipe /gen_unnamed_pipe/ +COPY pyproject.toml / +COPY MANIFEST.in / +COPY setup.py / +COPY README.md / +COPY LICENSE / +RUN mkdir /tests/ +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_unnamed_pipe-*-py3-none-any.whl +RUN rm -rf /gen_unnamed_pipe/ +RUN rm -f setup.py +RUN rm -f README.md +RUN rm -f pyproject.toml +RUN rm -f MANIFEST.in +RUN rm -f LICENSE diff --git a/README.md b/README.md index 597f4bc..6f67ff3 100644 --- a/README.md +++ b/README.md @@ -140,11 +140,11 @@ Generator structure | Name | Stmts | Miss | Cover | |------|-------|------|-------| -| `gen_unnamed_pipe/__init__.py` | 71 | 14 | 80% | -| `gen_unnamed_pipe/pro/__init__.py` | 60 | 6 | 90% | -| `gen_unnamed_pipe/pro/read_template.py` | 43 | 4 | 91% | -| `gen_unnamed_pipe/pro/write_template.py` | 51 | 5 | 90% | -| **Total** | 225 | 29 | 87% | +| `gen_unnamed_pipe/__init__.py` | 69 | 12 | 83%| +| `gen_unnamed_pipe/pro/__init__.py` | 58 | 4 | 93%| +| `gen_unnamed_pipe/pro/read_template.py` | 41 | 2 | 95%| +| `gen_unnamed_pipe/pro/write_template.py` | 49 | 3 | 94%| +| **Total** | 217 | 21 | 90% | ### Docs @@ -163,7 +163,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_unnamed_pipe](https://vroncevic.github.io/gen_unnamed_pipe/) +Copyright (C) 2017 - 2026 by [vroncevic.github.io/gen_unnamed_pipe](https://vroncevic.github.io/gen_unnamed_pipe/) **gen_unnamed_pipe** 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 26fe7bef4c5cec4751f732b618c1461206138467..1bc6dfad7109c6abe027d4c876761b38454d4917 100644 GIT binary patch literal 238754 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 literal 238235 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 MZKZHx8>`O#KfRvRUjP6A diff --git a/docs/build/doctrees/gen_unnamed_pipe.doctree b/docs/build/doctrees/gen_unnamed_pipe.doctree index 9180073430e59b337341020781faf07090d78772..1acbe593c7389de324ac923e31ad903d66283b9b 100644 GIT binary patch delta 211 zcmZpD&$#wIBTED8)I}Rv4A{A4Ggf8Dc{625XH1)XP)T8OIJ*O*+2R@O%#6&FXL8vx znr)uJK8I;?F|Ra`+0Pro0@c9+)Nux+gL6s-#0=)i{6c>i`8V?jPiAC?2nkG{C!){D zKlz-97C%IU5vVOULnecHa$$tUW;;=}D1oB<{F3;BqSUm^iYYye`coz+<$DQr^zas^ tCYR)u=Ehf~DYWAUxAVF#^#3w-6GlhOL@^4NRp2)}pF;*Z$I!ldl z^2GqT$p=JOCMO7Su<`@-OrBidsw|W-F$1EC5h#?OA(O#8Ip5Y|^HkB`Vu7Ok{F3;B zqSUm^iYYye`co!9>+lll=;19+O)kkR&5f@}%P-2E(y`g4Q-P7&j)#GvhcC6LD8Fd3 bVVCgcrmmYzj2)X}dm9)TTQ=Y8(_{hw2z^zH delta 177 zcmZ3#h^c)M6KezO)ISq8vbM1^OJ~fOY^bgCFHI+iY83i_%3QuI5%qObHC@|SpREt|WBR@kXgE>Ps zW6k8BDb}0Ui3S%>7Vh*A@n-DdEly1?$t%r`uSm-;%AMlPxH-2|fsxT>b6?jtCMF=a XwYPzhrHO}uVX`&bgv~Sir!fKmfRa00 diff --git a/docs/build/doctrees/gen_unnamed_pipe.pro.read_template.doctree b/docs/build/doctrees/gen_unnamed_pipe.pro.read_template.doctree index 826eb7be9f886e9bd7ff2a317c37170d06ea025d..19cfe9694ad092e6b74e6d1ccf0029c3ae993ae6 100644 GIT binary patch delta 233 zcmZp?%ee9`BTED8)Oj0OzOiu2W<+Mlc{625XSh!Os4hR*Pl$7}Dys#f+2S}>W=7`8 z@f@~{W}D+!=P*sS$g^s$sf-YA^A>X5`Prff8 zGr5yPmeFi;2J0NA$NQ)T7FUPl#b2kk`)*k|7?Dr@{NhHWApR$7)A~!P6mby*`Aq`Co(!sZV(Nh NY{0^?`Aud8BLE#>NX7sF delta 178 zcmeCV&iLdSBTED8)X0S_tjy9Gu9GLm$xqf}b!0SIT)@iA$UC`^!F95Q4wm_Z_f8FoM} z4~Ux~n-Q5I=ePNd(ENbObCW$pycv6Vi&K+J@=9~#E7J0da;JDRZvLLEz{vP(vqb7Q TCMF=4KO=^b(P48=rUDZHUe`F| diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree index 55cc6efd305ee30cc29560e4db695b1508e13262..adfb5437fce84f75422e88609adbdd08a9fe59c4 100644 GIT binary patch delta 605 zcmex#fU)HuBTED8)XI%45?qY@n`OBsF)<2l-oW#Lkx_K>LcXVrjMAIi1%5CxN^EWr z3Si=v&Ctn^^XAWx&N838L0WwB1ToIdzeTn%LM4QN5+QJjTVg&i2~nU#AzUI*q6#J< z0hH(iOC+#zZ2l@)2a}KnO00%U%#{vgVbt3EUcP{d2jT`Tpu7gtl8b#RI6|@8o$3%A0TMui|Db+}vWlhmo;lv!m^LMyMHuKqYUP;butLC&FY( zfHGVxFqz3q9V!{kCd)h4Fq&L<+cy94UISCm z22}6}q2Q9Q9@8t_XwrVgT+bXxYOKCY1lQ-jLBh^YSKIyE#AZeKlW{|@se^iyk=QzG(0~*lgaU7&_A*#yF z6<*CClfCS#%Pc6JCBlkuTZWw9W}(0}j97#(1TA9(`UF|^WJhNC%}YWK zF;1=s^APc7?BOj=O)kkR&5f@}%P-2E0`&i-Fa<`&kDEV-e**`{t0*oeCLOlP`=eFG zblDgfdU(?_OEOB66f%p8OH+%dWa&*djFn>4pX?JW&1L{nAUBy&PL6p>mf_^SSTQCe Ww#oT1l8nZa55y`0eg7zS5fcDujGq<& diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree index 7bbadf2f757d303584f0ea5810140aa31ad1eed0..5b3215d973e826bf17321ab91ca610fb276fd81c 100644 GIT binary patch delta 73 zcmZn{n;cY}tH_ O^)nL_kh_Z`h6w;euoHj) diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index 6463ce8..e937050 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: 01e9fc31055a5c79b824eb7084924206 +config: 4c56361541f06da2ad8bfc79b823e3fc tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_modules/gen_unnamed_pipe.html b/docs/build/html/_modules/gen_unnamed_pipe.html index 0ceaf6a..23e79f9 100644 --- a/docs/build/html/_modules/gen_unnamed_pipe.html +++ b/docs/build/html/_modules/gen_unnamed_pipe.html @@ -42,7 +42,7 @@

Source code for gen_unnamed_pipe

diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index cfd7094..90e4087 100644 --- a/docs/build/html/objects.inv +++ b/docs/build/html/objects.inv @@ -1,6 +1,6 @@ # Sphinx inventory version 2 # Project: gen_unnamed_pipe -# Version: 1.0.7 +# Version: 1.0.8 # The remainder of this file is compressed using zlib. xÚ½•_o‚0ÅßùM¶WÌöêÛæ1Q!€Û#éàFÉøÓ”’Ío?JqEhµÙí=÷w®ö@w‡Užã â$9̳"®R@hwRœíY–Þ‰²yLãL`C¾k·…E).Kôx%™… góº´9 3F“ŠÁm@ÛÚ„o–÷ìø–FêʱõÒ8ÇõõÑ-"¨O•gؾˆÕhuûxÌjÁtÔ¸H6k¿@’Z>Ñ®ç„~àmÁÖÓ ç‚XEÆFÊB 8ª›úEv;•Ï2ÈHŠLǪ'— Y¿Å«WAÇn4snWبR—o`­ÝÕS`…/Kï?yi:*fMØrÒ×Ëå¤ç/¥£2dx•“zZôY7Å郓5D%‹çq!óÂýr¶‹Ž>ñ†/1ÜñKƒ†¯«ìÉ'hÊä<µ:$²'•í©þ}ag„$á»ñIñ¤­S³+pKþhüÉÚq:Šö2@Í¡ÕÍ@1+¨Q{ ÀÉÁ<D÷Z¼»ÂFÌUvÚ­áßftp>qÞ·+Óhßo{¢Çu—ÇåÞ¡.î \ No newline at end of file diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html index 471744b..f1c4867 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 e57823d..357f383 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 0cd1420..48cd52f 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["gen_unnamed_pipe", "gen_unnamed_pipe.pro", "gen_unnamed_pipe.pro.read_template", "gen_unnamed_pipe.pro.write_template", "index", "modules"], "filenames": ["gen_unnamed_pipe.rst", "gen_unnamed_pipe.pro.rst", "gen_unnamed_pipe.pro.read_template.rst", "gen_unnamed_pipe.pro.write_template.rst", "index.rst", "modules.rst"], "titles": ["gen_unnamed_pipe package", "gen_unnamed_pipe.pro package", "gen_unnamed_pipe.pro.read_template module", "gen_unnamed_pipe.pro.write_template module", "Unnamed pipe generator", "gen_unnamed_pipe"], "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], "unnamedpip": [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], "__init__": [0, 1, 2, 3, 4], "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], "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], "genunnamedpip": [0, 4, 5], "attribut": [0, 1, 2, 3], "": [0, 1, 2, 3], "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], "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, 3], "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], "type": [0, 1, 2, 3, 4], "except": [0, 1, 2, 3], "none": [0, 1, 3], "_template_dir": [1, 2], "read": [1, 2], "write": [1, 3], "vhost": 1, "virtual": 1, "host": 1, "configur": [1, 2], "templat": [1, 2, 3, 4], "filecheck": [1, 2, 3], "proconfig": 1, "pronam": 1, "project": [1, 2, 3, 4], "setup": [1, 3, 4], "_reader": 1, "reader": 1, "_writer": 1, "writer": 1, "get": 1, "gen_model": 1, "data": 1, "model": 1, "yaml": [1, 4], "module_nam": 1, "atstypeerror": [1, 2, 3], "atsvalueerror": [1, 2, 3], "an": [2, 3], "unnam": 2, "pipe": 2, "prefix": 2, "config": 2, "dict": [2, 3], "atribut": 3, "content": [3, 5], "template_cont": 3, "pro_nam": 3, "gen_unnamed_pip": 4, "toolset": 4, "skeleton": 4, "develop": 4, "embed": 4, "applic": 4, "python": 4, "code": 4, "The": 4, "readm": 4, "introduc": 4, "modul": [4, 5], "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, "install_lib": 4, "install_data": 4, "install_egg_info": 4, "docker": 4, "imag": 4, "contain": 4, "pip": 4, "pip3": 4, "gen": 4, "requir": 4, "librari": 4, "ats": 4, "util": 4, "app": 4, "script": 4, "mechan": 4, "gen_unnamed_pipe_util": 4, "unp_clos": 4, "unp_mak": 4, "unp_read": 4, "unp": 4, "unp_writ": 4, "gen_unnamed_pipe_run": 4, "6": 4, "directori": 4, "16": 4, "vroncev": 4, "github": 4, "io": 4, "same": 4, "itself": 4, "avail": 4, "let": 4, "help": 4, "support": 4, "psf": 4, "index": 4, "search": 4}, "objects": {"": [[0, 0, 0, "-", "gen_unnamed_pipe"]], "gen_unnamed_pipe": [[0, 1, 1, "", "GenUnnamedPipe"], [1, 0, 0, "-", "pro"]], "gen_unnamed_pipe.GenUnnamedPipe": [[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_unnamed_pipe.pro": [[1, 1, 1, "", "UnnamedPipe"], [2, 0, 0, "-", "read_template"], [3, 0, 0, "-", "write_template"]], "gen_unnamed_pipe.pro.UnnamedPipe": [[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_unnamed_pipe.pro.read_template": [[2, 1, 1, "", "ReadTemplate"]], "gen_unnamed_pipe.pro.read_template.ReadTemplate": [[2, 2, 1, "", "_GEN_VERBOSE"], [2, 2, 1, "", "_TEMPLATE_DIR"], [2, 3, 1, "", "read"]], "gen_unnamed_pipe.pro.write_template": [[3, 1, 1, "", "WriteTemplate"]], "gen_unnamed_pipe.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_unnamed_pip": [0, 1, 2, 3, 5], "packag": [0, 1], "subpackag": 0, "modul": [0, 1, 2, 3], "content": [0, 1, 4], "pro": [1, 2, 3], "submodul": 1, "read_templ": 2, "write_templ": 3, "unnam": 4, "pipe": 4, "gener": 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_unnamed_pipe package": [[0, "gen-unnamed-pipe-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-gen_unnamed_pipe"], [1, "module-gen_unnamed_pipe.pro"]], "gen_unnamed_pipe.pro package": [[1, "gen-unnamed-pipe-pro-package"]], "Submodules": [[1, "submodules"]], "gen_unnamed_pipe.pro.read_template module": [[2, "module-gen_unnamed_pipe.pro.read_template"]], "gen_unnamed_pipe.pro.write_template module": [[3, "module-gen_unnamed_pipe.pro.write_template"]], "Unnamed pipe generator": [[4, "unnamed-pipe-generator"]], "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_unnamed_pipe": [[5, "gen-unnamed-pipe"]]}, "indexentries": {"genunnamedpipe (class in gen_unnamed_pipe)": [[0, "gen_unnamed_pipe.GenUnnamedPipe"]], "_config (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._CONFIG"]], "_gen_verbose (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._GEN_VERBOSE"]], "_log (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._LOG"]], "_logo (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._LOGO"]], "_ops (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._OPS"]], "gen_unnamed_pipe": [[0, "module-gen_unnamed_pipe"]], "module": [[0, "module-gen_unnamed_pipe"], [1, "module-gen_unnamed_pipe.pro"], [2, "module-gen_unnamed_pipe.pro.read_template"], [3, "module-gen_unnamed_pipe.pro.write_template"]], "process() (gen_unnamed_pipe.genunnamedpipe method)": [[0, "gen_unnamed_pipe.GenUnnamedPipe.process"]], "unnamedpipe (class in gen_unnamed_pipe.pro)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe"]], "_gen_verbose (gen_unnamed_pipe.pro.unnamedpipe attribute)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe._GEN_VERBOSE"]], "_pro_structure (gen_unnamed_pipe.pro.unnamedpipe attribute)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe._PRO_STRUCTURE"]], "gen_setup() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.gen_setup"]], "gen_unnamed_pipe.pro": [[1, "module-gen_unnamed_pipe.pro"]], "get_reader() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.get_reader"]], "get_writer() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.get_writer"]], "readtemplate (class in gen_unnamed_pipe.pro.read_template)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate"]], "_gen_verbose (gen_unnamed_pipe.pro.read_template.readtemplate attribute)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate._GEN_VERBOSE"]], "_template_dir (gen_unnamed_pipe.pro.read_template.readtemplate attribute)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate._TEMPLATE_DIR"]], "gen_unnamed_pipe.pro.read_template": [[2, "module-gen_unnamed_pipe.pro.read_template"]], "read() (gen_unnamed_pipe.pro.read_template.readtemplate method)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate.read"]], "writetemplate (class in gen_unnamed_pipe.pro.write_template)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate"]], "_gen_verbose (gen_unnamed_pipe.pro.write_template.writetemplate attribute)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate._GEN_VERBOSE"]], "gen_unnamed_pipe.pro.write_template": [[3, "module-gen_unnamed_pipe.pro.write_template"]], "write() (gen_unnamed_pipe.pro.write_template.writetemplate method)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate.write"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["gen_unnamed_pipe", "gen_unnamed_pipe.pro", "gen_unnamed_pipe.pro.read_template", "gen_unnamed_pipe.pro.write_template", "index", "modules"], "filenames": ["gen_unnamed_pipe.rst", "gen_unnamed_pipe.pro.rst", "gen_unnamed_pipe.pro.read_template.rst", "gen_unnamed_pipe.pro.write_template.rst", "index.rst", "modules.rst"], "titles": ["gen_unnamed_pipe package", "gen_unnamed_pipe.pro package", "gen_unnamed_pipe.pro.read_template module", "gen_unnamed_pipe.pro.write_template module", "Unnamed pipe generator", "gen_unnamed_pipe"], "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], "unnamedpip": [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], "__init__": [0, 1, 2, 3, 4], "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], "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], "genunnamedpip": [0, 4, 5], "attribut": [0, 1, 2, 3], "": [0, 1, 2, 3], "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], "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, 3], "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], "type": [0, 1, 2, 3, 4], "except": [0, 1, 2, 3], "none": [0, 1, 3], "_template_dir": [1, 2], "read": [1, 2], "write": [1, 3], "vhost": 1, "virtual": 1, "host": 1, "configur": [1, 2], "templat": [1, 2, 3, 4], "filecheck": [1, 2, 3], "proconfig": 1, "pronam": 1, "project": [1, 2, 3, 4], "setup": [1, 3, 4], "_reader": 1, "reader": 1, "_writer": 1, "writer": 1, "get": 1, "gen_model": 1, "data": 1, "model": 1, "yaml": [1, 4], "module_nam": 1, "atstypeerror": [1, 2, 3], "atsvalueerror": [1, 2, 3], "an": [2, 3], "unnam": 2, "pipe": 2, "prefix": 2, "config": 2, "dict": [2, 3], "atribut": 3, "content": [3, 5], "template_cont": 3, "pro_nam": 3, "gen_unnamed_pip": 4, "toolset": 4, "skeleton": 4, "develop": 4, "embed": 4, "applic": 4, "python": 4, "code": 4, "The": 4, "readm": 4, "introduc": 4, "modul": [4, 5], "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, "install_lib": 4, "install_data": 4, "install_egg_info": 4, "docker": 4, "imag": 4, "contain": 4, "pip": 4, "pip3": 4, "gen": 4, "requir": 4, "librari": 4, "ats": 4, "util": 4, "app": 4, "script": 4, "mechan": 4, "gen_unnamed_pipe_util": 4, "unp_clos": 4, "unp_mak": 4, "unp_read": 4, "unp": 4, "unp_writ": 4, "gen_unnamed_pipe_run": 4, "6": 4, "directori": 4, "16": 4, "vroncev": 4, "github": 4, "io": 4, "same": 4, "itself": 4, "avail": 4, "let": 4, "help": 4, "support": 4, "psf": 4, "index": 4, "search": 4}, "objects": {"": [[0, 0, 0, "-", "gen_unnamed_pipe"]], "gen_unnamed_pipe": [[0, 1, 1, "", "GenUnnamedPipe"], [1, 0, 0, "-", "pro"]], "gen_unnamed_pipe.GenUnnamedPipe": [[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_unnamed_pipe.pro": [[1, 1, 1, "", "UnnamedPipe"], [2, 0, 0, "-", "read_template"], [3, 0, 0, "-", "write_template"]], "gen_unnamed_pipe.pro.UnnamedPipe": [[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_unnamed_pipe.pro.read_template": [[2, 1, 1, "", "ReadTemplate"]], "gen_unnamed_pipe.pro.read_template.ReadTemplate": [[2, 2, 1, "", "_GEN_VERBOSE"], [2, 2, 1, "", "_TEMPLATE_DIR"], [2, 3, 1, "", "read"]], "gen_unnamed_pipe.pro.write_template": [[3, 1, 1, "", "WriteTemplate"]], "gen_unnamed_pipe.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_unnamed_pip": [0, 1, 2, 3, 5], "packag": [0, 1], "subpackag": 0, "modul": [0, 1, 2, 3], "content": [0, 1, 4], "pro": [1, 2, 3], "submodul": 1, "read_templ": 2, "write_templ": 3, "unnam": 4, "pipe": 4, "gener": 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_unnamed_pipe package": [[0, "gen-unnamed-pipe-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-gen_unnamed_pipe"], [1, "module-gen_unnamed_pipe.pro"]], "gen_unnamed_pipe.pro package": [[1, "gen-unnamed-pipe-pro-package"]], "Submodules": [[1, "submodules"]], "gen_unnamed_pipe.pro.read_template module": [[2, "module-gen_unnamed_pipe.pro.read_template"]], "gen_unnamed_pipe.pro.write_template module": [[3, "module-gen_unnamed_pipe.pro.write_template"]], "Unnamed pipe generator": [[4, "unnamed-pipe-generator"]], "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_unnamed_pipe": [[5, "gen-unnamed-pipe"]]}, "indexentries": {"genunnamedpipe (class in gen_unnamed_pipe)": [[0, "gen_unnamed_pipe.GenUnnamedPipe"]], "_config (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._CONFIG"]], "_gen_verbose (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._GEN_VERBOSE"]], "_log (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._LOG"]], "_logo (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._LOGO"]], "_ops (gen_unnamed_pipe.genunnamedpipe attribute)": [[0, "gen_unnamed_pipe.GenUnnamedPipe._OPS"]], "gen_unnamed_pipe": [[0, "module-gen_unnamed_pipe"]], "module": [[0, "module-gen_unnamed_pipe"], [1, "module-gen_unnamed_pipe.pro"], [2, "module-gen_unnamed_pipe.pro.read_template"], [3, "module-gen_unnamed_pipe.pro.write_template"]], "process() (gen_unnamed_pipe.genunnamedpipe method)": [[0, "gen_unnamed_pipe.GenUnnamedPipe.process"]], "unnamedpipe (class in gen_unnamed_pipe.pro)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe"]], "_gen_verbose (gen_unnamed_pipe.pro.unnamedpipe attribute)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe._GEN_VERBOSE"]], "_pro_structure (gen_unnamed_pipe.pro.unnamedpipe attribute)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe._PRO_STRUCTURE"]], "gen_setup() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.gen_setup"]], "gen_unnamed_pipe.pro": [[1, "module-gen_unnamed_pipe.pro"]], "get_reader() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.get_reader"]], "get_writer() (gen_unnamed_pipe.pro.unnamedpipe method)": [[1, "gen_unnamed_pipe.pro.UnnamedPipe.get_writer"]], "readtemplate (class in gen_unnamed_pipe.pro.read_template)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate"]], "_gen_verbose (gen_unnamed_pipe.pro.read_template.readtemplate attribute)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate._GEN_VERBOSE"]], "_template_dir (gen_unnamed_pipe.pro.read_template.readtemplate attribute)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate._TEMPLATE_DIR"]], "gen_unnamed_pipe.pro.read_template": [[2, "module-gen_unnamed_pipe.pro.read_template"]], "read() (gen_unnamed_pipe.pro.read_template.readtemplate method)": [[2, "gen_unnamed_pipe.pro.read_template.ReadTemplate.read"]], "writetemplate (class in gen_unnamed_pipe.pro.write_template)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate"]], "_gen_verbose (gen_unnamed_pipe.pro.write_template.writetemplate attribute)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate._GEN_VERBOSE"]], "gen_unnamed_pipe.pro.write_template": [[3, "module-gen_unnamed_pipe.pro.write_template"]], "write() (gen_unnamed_pipe.pro.write_template.writetemplate method)": [[3, "gen_unnamed_pipe.pro.write_template.WriteTemplate.write"]]}}) \ No newline at end of file diff --git a/docs/source/_static/.editorconfig b/docs/source/_static/.editorconfig new file mode 100644 index 0000000..72716a4 --- /dev/null +++ b/docs/source/_static/.editorconfig @@ -0,0 +1,3 @@ +[**.*] +indent_style = tab +tab_width = 4 diff --git a/docs/source/conf.py b/docs/source/conf.py index 4f15d29..e35777f 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_unnamed_pipe 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_unnamed_pipe' -project_copyright: str = '2024, Vladimir Roncevic ' +project_copyright: str = '2026, Vladimir Roncevic ' author: str = 'Vladimir Roncevic ' -version: str = '1.0.7' +version: str = '1.0.8' release: str = 'https://github.com/vroncevic/gen_unnamed_pipe/releases' extensions: List[str] = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', diff --git a/docs/source/index.rst b/docs/source/index.rst index 3107099..d00f7e1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -116,7 +116,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_unnamed_pipe `_ +Copyright (C) 2017 - 2026 by `vroncevic.github.io/gen_unnamed_pipe `_ **gen_unnamed_pipe** 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_unnamed_pipe/__init__.py b/gen_unnamed_pipe/__init__.py index 6b2bee8..6a14c39 100644 --- a/gen_unnamed_pipe/__init__.py +++ b/gen_unnamed_pipe/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_unnamed_pipe 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_unnamed_pipe.pro import UnnamedPipe -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_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class GenUnnamedPipe(ATSCli): diff --git a/gen_unnamed_pipe/conf/gen_unnamed_pipe.cfg b/gen_unnamed_pipe/conf/gen_unnamed_pipe.cfg index c33e897..0ca6d01 100644 --- a/gen_unnamed_pipe/conf/gen_unnamed_pipe.cfg +++ b/gen_unnamed_pipe/conf/gen_unnamed_pipe.cfg @@ -1,4 +1,4 @@ ats_name = gen_unnamed_pipe -ats_version = v1.0.7 +ats_version = v1.0.8 ats_build_date = 2020 ats_licence = https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE diff --git a/gen_unnamed_pipe/pro/__init__.py b/gen_unnamed_pipe/pro/__init__.py index 79c0dff..a7ced67 100644 --- a/gen_unnamed_pipe/pro/__init__.py +++ b/gen_unnamed_pipe/pro/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_unnamed_pipe 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_unnamed_pipe.pro.read_template import ReadTemplate from gen_unnamed_pipe.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__ = '(C) 2024, https://vroncevic.github.io/gen_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class UnnamedPipe(FileCheck, ProConfig, ProName): diff --git a/gen_unnamed_pipe/pro/read_template.py b/gen_unnamed_pipe/pro/read_template.py index d86e900..6ed4103 100644 --- a/gen_unnamed_pipe/pro/read_template.py +++ b/gen_unnamed_pipe/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_unnamed_pipe 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_form_model' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_form_model' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class ReadTemplate(FileCheck): diff --git a/gen_unnamed_pipe/pro/write_template.py b/gen_unnamed_pipe/pro/write_template.py index 80c12b8..17aeeb8 100644 --- a/gen_unnamed_pipe/pro/write_template.py +++ b/gen_unnamed_pipe/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_unnamed_pipe 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_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class WriteTemplate(FileCheck): diff --git a/gen_unnamed_pipe/run/gen_unnamed_pipe_run.py b/gen_unnamed_pipe/run/gen_unnamed_pipe_run.py index cc88fa0..fed959d 100644 --- a/gen_unnamed_pipe/run/gen_unnamed_pipe_run.py +++ b/gen_unnamed_pipe/run/gen_unnamed_pipe_run.py @@ -5,7 +5,7 @@ Module gen_unnamed_pipe_run.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_unnamed_pipe 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_unnamed_pipe import GenUnnamedPipe -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_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' if __name__ == '__main__': TOOL: GenUnnamedPipe = GenUnnamedPipe(verbose=False) diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 77480e8..0000000 --- a/setup.cfg +++ /dev/null @@ -1,46 +0,0 @@ -# -# Module -# setup.cfg -# Copyright -# Copyright (C) 2017 - 2024 Vladimir Roncevic -# gen_unnamed_pipe 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_unnamed_pipe 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_unnamed_pipe. -# - -[metadata] -name = gen_unnamed_pipe -version = 1.0.7 -author = Vladimir Roncevic -author_email = elektron.ronca@gmail.com -description = Unnamed Pipe Module generator -license=GPL 2017 - 2024 Free software to use and distributed it. -long_description = file: README.md -long_description_content_type = text/markdown -keywords=unnamed pipe, configuration, generator, skeleton -platforms = any -url = https://vroncevic.github.io/gen_unnamed_pipe -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 3c2668f..b80c255 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_unnamed_pipe 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) 2017, https://vroncevic.github.io/gen_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' TOOL_DIR: str = 'gen_unnamed_pipe/' 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_unnamed_pipe', - version='1.0.7', + version='1.0.8', description='Generating Unnamed Pipe Modules', author='Vladimir Roncevic', author_email='elektron.ronca@gmail.com', url='https://vroncevic.github.io/gen_unnamed_pipe', - license='GPL 2017 - 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, Unnamed Pipe, Modules', diff --git a/tests/.coverage b/tests/.coverage index 78790abe75f3065c7e9493a935f65b52f57b6157..6025183b8b85376f9ca30bceb44902c5a57a586d 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/gen_unnamed_pipe_coverage.json b/tests/gen_unnamed_pipe_coverage.json index cdeb1c9..ddfd400 100644 --- a/tests/gen_unnamed_pipe_coverage.json +++ b/tests/gen_unnamed_pipe_coverage.json @@ -1 +1 @@ -{"meta": {"format": 2, "version": "7.5.3", "timestamp": "2024-07-09T21:36:04.051703", "branch_coverage": false, "show_contexts": false}, "files": {"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__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, 114, 124, 125, 126, 127, 128, 129, 132, 133, 139, 142, 143, 150, 157, 158, 159, 180], "summary": {"covered_lines": 57, "num_statements": 71, "percent_covered": 80.28169014084507, "percent_covered_display": "80", "missing_lines": 14, "excluded_lines": 0}, "missing_lines": [39, 41, 134, 138, 154, 155, 156, 164, 165, 168, 169, 172, 174, 177], "excluded_lines": []}, "/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 108, 118, 134, 135, 136, 139, 141, 143, 146, 147, 148, 151, 152, 155], "summary": {"covered_lines": 54, "num_statements": 60, "percent_covered": 90.0, "percent_covered_display": "90", "missing_lines": 6, "excluded_lines": 0}, "missing_lines": [37, 39, 106, 116, 140, 142], "excluded_lines": []}, "/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 89, 90, 91, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 108], "summary": {"covered_lines": 39, "num_statements": 43, "percent_covered": 90.69767441860465, "percent_covered_display": "91", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [32, 34, 93, 95], "excluded_lines": []}, "/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 102, 104, 106, 107, 108, 109, 110, 113, 116, 117, 118, 121, 122, 123, 124, 127, 128, 129], "summary": {"covered_lines": 46, "num_statements": 51, "percent_covered": 90.19607843137256, "percent_covered_display": "90", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [34, 36, 101, 103, 105], "excluded_lines": []}}, "totals": {"covered_lines": 196, "num_statements": 225, "percent_covered": 87.11111111111111, "percent_covered_display": "87", "missing_lines": 29, "excluded_lines": 0}} \ No newline at end of file +{"meta": {"format": 3, "version": "7.6.10", "timestamp": "2025-11-28T22:28:01.875897", "branch_coverage": false, "show_contexts": false}, "files": {"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__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, 114, 124, 125, 126, 127, 128, 129, 132, 133, 139, 142, 143, 150, 157, 158, 159, 180], "summary": {"covered_lines": 57, "num_statements": 69, "percent_covered": 82.6086956521739, "percent_covered_display": "83", "missing_lines": 12, "excluded_lines": 2}, "missing_lines": [134, 138, 154, 155, 156, 164, 165, 168, 169, 172, 174, 177], "excluded_lines": [39, 41], "functions": {"GenUnnamedPipe.__init__": {"executed_lines": [86, 87, 94, 95, 96, 97, 100, 103, 104, 108], "summary": {"covered_lines": 10, "num_statements": 10, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "GenUnnamedPipe.process": {"executed_lines": [124, 125, 126, 127, 128, 129, 132, 133, 139, 142, 143, 150, 157, 158, 159, 180], "summary": {"covered_lines": 16, "num_statements": 28, "percent_covered": 57.142857142857146, "percent_covered_display": "57", "missing_lines": 12, "excluded_lines": 0}, "missing_lines": [134, 138, 154, 155, 156, 164, 165, 168, 169, 172, 174, 177], "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, 114], "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": {"GenUnnamedPipe": {"executed_lines": [86, 87, 94, 95, 96, 97, 100, 103, 104, 108, 124, 125, 126, 127, 128, 129, 132, 133, 139, 142, 143, 150, 157, 158, 159, 180], "summary": {"covered_lines": 26, "num_statements": 38, "percent_covered": 68.42105263157895, "percent_covered_display": "68", "missing_lines": 12, "excluded_lines": 0}, "missing_lines": [134, 138, 154, 155, 156, 164, 165, 168, 169, 172, 174, 177], "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, 114], "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_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 108, 118, 134, 135, 136, 139, 141, 143, 146, 147, 148, 151, 152, 155], "summary": {"covered_lines": 54, "num_statements": 58, "percent_covered": 93.10344827586206, "percent_covered_display": "93", "missing_lines": 4, "excluded_lines": 2}, "missing_lines": [106, 116, 140, 142], "excluded_lines": [37, 39], "functions": {"UnnamedPipe.__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": []}, "UnnamedPipe.get_reader": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [106], "excluded_lines": []}, "UnnamedPipe.get_writer": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [116], "excluded_lines": []}, "UnnamedPipe.gen_setup": {"executed_lines": [134, 135, 136, 139, 141, 143, 146, 147, 148, 151, 152, 155], "summary": {"covered_lines": 12, "num_statements": 14, "percent_covered": 85.71428571428571, "percent_covered_display": "86", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [140, 142], "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": {"UnnamedPipe": {"executed_lines": [81, 82, 83, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 134, 135, 136, 139, 141, 143, 146, 147, 148, 151, 152, 155], "summary": {"covered_lines": 26, "num_statements": 30, "percent_covered": 86.66666666666667, "percent_covered_display": "87", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [106, 116, 140, 142], "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_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 89, 90, 91, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 108], "summary": {"covered_lines": 39, "num_statements": 41, "percent_covered": 95.1219512195122, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 2}, "missing_lines": [93, 95], "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": [89, 90, 91, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 108], "summary": {"covered_lines": 16, "num_statements": 18, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [93, 95], "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, 89, 90, 91, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 108], "summary": {"covered_lines": 18, "num_statements": 20, "percent_covered": 90.0, "percent_covered_display": "90", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [93, 95], "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_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/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, 102, 104, 106, 107, 108, 109, 110, 113, 116, 117, 118, 121, 122, 123, 124, 127, 128, 129], "summary": {"covered_lines": 46, "num_statements": 49, "percent_covered": 93.87755102040816, "percent_covered_display": "94", "missing_lines": 3, "excluded_lines": 2}, "missing_lines": [101, 103, 105], "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, 102, 104, 106, 107, 108, 109, 110, 113, 116, 117, 118, 121, 122, 123, 124, 127, 128, 129], "summary": {"covered_lines": 22, "num_statements": 25, "percent_covered": 88.0, "percent_covered_display": "88", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [101, 103, 105], "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, 102, 104, 106, 107, 108, 109, 110, 113, 116, 117, 118, 121, 122, 123, 124, 127, 128, 129], "summary": {"covered_lines": 24, "num_statements": 27, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [101, 103, 105], "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": 196, "num_statements": 217, "percent_covered": 90.3225806451613, "percent_covered_display": "90", "missing_lines": 21, "excluded_lines": 8}} \ No newline at end of file diff --git a/tests/gen_unnamed_pipe_coverage.xml b/tests/gen_unnamed_pipe_coverage.xml index 79ca5e7..7a2374d 100644 --- a/tests/gen_unnamed_pipe_coverage.xml +++ b/tests/gen_unnamed_pipe_coverage.xml @@ -1,14 +1,14 @@ - - + + - + - + @@ -26,8 +26,6 @@ - - @@ -86,9 +84,9 @@ - + - + @@ -104,8 +102,6 @@ - - @@ -153,7 +149,7 @@ - + @@ -164,8 +160,6 @@ - - @@ -201,7 +195,7 @@ - + @@ -214,8 +208,6 @@ - - diff --git a/tests/gen_unnamed_pipe_test.py b/tests/gen_unnamed_pipe_test.py index a09c42c..9a1e103 100644 --- a/tests/gen_unnamed_pipe_test.py +++ b/tests/gen_unnamed_pipe_test.py @@ -4,7 +4,7 @@ Module gen_unnamed_pipe_test.py Copyright - Copyright (C) 2017 - 2024 Vladimir Roncevic + Copyright (C) 2017 - 2026 Vladimir Roncevic gen_unnamed_pipe 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 diff --git a/tests/htmlcov/class_index.html b/tests/htmlcov/class_index.html new file mode 100644 index 0000000..f00b069 --- /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-28 22:28 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fileclassstatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.pyGenUnnamedPipe3812068%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py(no class)3102100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.pyUnnamedPipe304087%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.py(no class)2802100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.pyReadTemplate202090%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.py(no class)2102100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.pyWriteTemplate273089%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.py(no class)2202100%
Total 21721890%
+

+ 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-28 22:28 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filefunctionstatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.pyGenUnnamedPipe.__init__1000100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.pyGenUnnamedPipe.process2812057%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py(no function)3102100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.pyUnnamedPipe.__init__1400100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.pyUnnamedPipe.get_reader1100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.pyUnnamedPipe.get_writer1100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.pyUnnamedPipe.gen_setup142086%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.py(no function)2802100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.pyReadTemplate.__init__200100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.pyReadTemplate.read182089%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.py(no function)2102100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.pyWriteTemplate.__init__200100%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.pyWriteTemplate.write253088%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.py(no function)2202100%
Total 21721890%
+

+ 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..37008d7 --- /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-28 22:28 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filestatementsmissingexcludedcoverage
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py6912283%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.py584293%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.py412295%
/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.py493294%
Total21721890%
+

+ 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..8280f80 --- /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":"5a9ded48be654859114eb6a78043c0a1","files":{"z_c59f2450adabd96b___init___py":{"hash":"74d6ebf6142f5d5690b9056b4688a9a4","index":{"url":"z_c59f2450adabd96b___init___py.html","file":"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":69,"n_excluded":2,"n_missing":12,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_58479a017d06e93c___init___py":{"hash":"420d9715f5d665743bcdf878f056a4b1","index":{"url":"z_58479a017d06e93c___init___py.html","file":"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":58,"n_excluded":2,"n_missing":4,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_58479a017d06e93c_read_template_py":{"hash":"51e22747cdb1eacc9b9b6cf84756f7a3","index":{"url":"z_58479a017d06e93c_read_template_py.html","file":"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":41,"n_excluded":2,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_58479a017d06e93c_write_template_py":{"hash":"fbe535a180aaf9fc1c34ff1b65652f27","index":{"url":"z_58479a017d06e93c_write_template_py.html","file":"/data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":49,"n_excluded":2,"n_missing":3,"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_58479a017d06e93c___init___py.html b/tests/htmlcov/z_58479a017d06e93c___init___py.html new file mode 100644 index 0000000..33b3928 --- /dev/null +++ b/tests/htmlcov/z_58479a017d06e93c___init___py.html @@ -0,0 +1,252 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/__init__.py: 93% + + + + + +
+
+

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

+ +

+ 58 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-28 22:28 +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_unnamed_pipe 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_unnamed_pipe 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 Defines class VHost with attribute(s) and method(s). 

+

20 Generates virtual host configuration module by template 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_unnamed_pipe.pro.read_template import ReadTemplate 

+

36 from gen_unnamed_pipe.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 = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' 

+

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

+

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

+

45__version__: str = '1.0.8' 

+

46__maintainer__: str = 'Vladimir Roncevic' 

+

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

+

48__status__: str = 'Updated' 

+

49 

+

50 

+

51class UnnamedPipe(FileCheck, ProConfig, ProName): 

+

52 ''' 

+

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

+

54 Generates virtual host configuration module by template 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 VHost constructor. 

+

65 | get_reader - Gets template reader. 

+

66 | get_writer - Gets template writer. 

+

67 | gen_model - Generates data model. 

+

68 ''' 

+

69 

+

70 _GEN_VERBOSE: str = 'GEN_UNNAMED_PIPE::PRO::VHOST' 

+

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

+

72 

+

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

+

74 ''' 

+

75 Initial 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 module_name: Optional[str], 

+

121 verbose: bool = False 

+

122 ) -> bool: 

+

123 ''' 

+

124 Generates virtual host module. 

+

125 

+

126 :param module_name: Parameter module name 

+

127 :type module_name: <Optional[str]> 

+

128 :param verbose: Enable/Disable verbose option 

+

129 :type verbose: <bool> 

+

130 :return: True (success operation) | False 

+

131 :rtype: <bool> 

+

132 :exceptions: ATSTypeError | ATSValueError 

+

133 ''' 

+

134 error_msg: Optional[str] = None 

+

135 error_id: Optional[int] = None 

+

136 error_msg, error_id = self.check_params([ 

+

137 ('str:model_name', module_name) 

+

138 ]) 

+

139 if error_id == self.TYPE_ERROR: 

+

140 raise ATSTypeError(error_msg) 

+

141 if not bool(module_name): 

+

142 raise ATSValueError('missing module name') 

+

143 verbose_message( 

+

144 verbose, [f'{self._GEN_VERBOSE.lower()} generate {module_name}'] 

+

145 ) 

+

146 status: bool = False 

+

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

+

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

+

149 self.config, verbose 

+

150 ) 

+

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

+

152 status = self._writer.write( 

+

153 template_content, module_name, verbose 

+

154 ) 

+

155 return status 

+
+ + + diff --git a/tests/htmlcov/z_58479a017d06e93c_read_template_py.html b/tests/htmlcov/z_58479a017d06e93c_read_template_py.html new file mode 100644 index 0000000..0d161c2 --- /dev/null +++ b/tests/htmlcov/z_58479a017d06e93c_read_template_py.html @@ -0,0 +1,205 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/read_template.py: 95% + + + + + +
+
+

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

+ +

+ 41 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-28 22:28 +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_unnamed_pipe 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_unnamed_pipe 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 Defines class ReadTemplate with attribute(s) and method(s). 

+

20 Creates an API for reading a UNNAMED PIPE 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_form_model' 

+

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

+

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

+

40__version__: str = '1.0.8' 

+

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_UNNAMED_PIPE::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, config: Dict[Any, Any], verbose: bool = False 

+

77 ) -> Dict[str, str]: 

+

78 ''' 

+

79 Reads a template. 

+

80 

+

81 :param config: Project configuration 

+

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

+

83 :param verbose: Enable/Disable verbose option 

+

84 :type verbose: <bool> 

+

85 :return: Loaded templates 

+

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

+

87 :exceptions: ATSTypeError | ATSValueError 

+

88 ''' 

+

89 error_msg: Optional[str] = None 

+

90 error_id: Optional[int] = None 

+

91 error_msg, error_id = self.check_params([('dict:config', config)]) 

+

92 if error_id == self.TYPE_ERROR: 

+

93 raise ATSTypeError(error_msg) 

+

94 if not bool(config): 

+

95 raise ATSValueError('missing project templates') 

+

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

+

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

+

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

+

99 modules: List[str] = config['modules'] 

+

100 templates: List[str] = config['templates'] 

+

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

+

102 template_file: str = f'{pro_structure}/{template}' 

+

103 with open(template_file, 'r', encoding='utf-8') as unp_template: 

+

104 template_content[module] = unp_template.read() 

+

105 verbose_message( 

+

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

+

107 ) 

+

108 return template_content 

+
+ + + diff --git a/tests/htmlcov/z_58479a017d06e93c_write_template_py.html b/tests/htmlcov/z_58479a017d06e93c_write_template_py.html new file mode 100644 index 0000000..b386c8b --- /dev/null +++ b/tests/htmlcov/z_58479a017d06e93c_write_template_py.html @@ -0,0 +1,226 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/pro/write_template.py: 94% + + + + + +
+
+

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

+ +

+ 49 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-28 22:28 +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_unnamed_pipe 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_unnamed_pipe 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 Defines 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 os import getcwd, chmod, mkdir 

+

26from string import Template 

+

27from datetime import date 

+

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_unnamed_pipe' 

+

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

+

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

+

42__version__: str = '1.0.8' 

+

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_UNNAMED_PIPE::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 readme content') 

+

104 if not bool(pro_name): 

+

105 raise ATSValueError('missing project name') 

+

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

+

107 mkdir(module_pro_dir) 

+

108 status: bool = False 

+

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

+

110 template_module: Template = Template( 

+

111 f'{module_pro_dir}{module_name}' 

+

112 ) 

+

113 module_path: str = template_module.substitute({ 

+

114 'PRO_NAME': pro_name 

+

115 }) 

+

116 template: Template = Template(module_content) 

+

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

+

118 module_file.write(template.substitute({ 

+

119 'PRO': pro_name, 'YEAR': f'{str(date.today().year)}' 

+

120 })) 

+

121 chmod(module_path, 0o644) 

+

122 self.check_path(module_path, verbose) 

+

123 self.check_mode('w', verbose) 

+

124 self.check_format( 

+

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

+

126 ) 

+

127 if self.is_file_ok(): 

+

128 status = True 

+

129 return status 

+
+ + + diff --git a/tests/htmlcov/z_c59f2450adabd96b___init___py.html b/tests/htmlcov/z_c59f2450adabd96b___init___py.html new file mode 100644 index 0000000..e271622 --- /dev/null +++ b/tests/htmlcov/z_c59f2450adabd96b___init___py.html @@ -0,0 +1,277 @@ + + + + + Coverage for /data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py: 83% + + + + + +
+
+

+ Coverage for /data/dev/python/3_tools/gen_unnamed_pipe/github/gen_unnamed_pipe/gen_unnamed_pipe/__init__.py: + 83% +

+ +

+ 69 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-28 22:28 +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_unnamed_pipe 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_unnamed_pipe 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 Defines class GenUnnamedPipe with attribute(s) and method(s). 

+

20 Loads a base info, create a CLI interface and run operation(s). 

+

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_unnamed_pipe.pro import UnnamedPipe 

+

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 = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' 

+

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

+

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

+

47__version__: str = '1.0.8' 

+

48__maintainer__: str = 'Vladimir Roncevic' 

+

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

+

50__status__: str = 'Updated' 

+

51 

+

52 

+

53class GenUnnamedPipe(ATSCli): 

+

54 ''' 

+

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

+

56 Loads a base info, creates a CLI interface and run operation(s). 

+

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 GenUnnamedPipe constructor. 

+

69 | process - Processes and runs tool operation. 

+

70 ''' 

+

71 

+

72 _GEN_VERBOSE: str = 'GEN_UNNAMED_PIPE' 

+

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

+

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

+

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

+

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

+

77 

+

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

+

79 ''' 

+

80 Initials GenVHost 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_unnamed_pipe_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_unnamed_pipe_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 unnamed pipe skeleton (provide name)' 

+

107 ) 

+

108 self.add_new_option( 

+

109 self._OPS[2], self._OPS[3], 

+

110 action='store_true', default=False, 

+

111 help='activate verbose mode for generation' 

+

112 ) 

+

113 

+

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

+

115 ''' 

+

116 Processes and runs tool operation. 

+

117 

+

118 :param verbose: Enable/Disable verbose option 

+

119 :type verbose: <bool> 

+

120 :return: True (success operation) | False 

+

121 :rtype: <bool> 

+

122 :exceptions: None 

+

123 ''' 

+

124 status: bool = False 

+

125 if self.is_operational(): 

+

126 try: 

+

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

+

128 if not bool(getattr(args, "name")): 

+

129 error_message( 

+

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

+

131 ) 

+

132 return status 

+

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

+

134 error_message([ 

+

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

+

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

+

137 ]) 

+

138 return status 

+

139 gen: UnnamedPipe = UnnamedPipe( 

+

140 getattr(args, 'verbose') or verbose 

+

141 ) 

+

142 try: 

+

143 print( 

+

144 " ".join([ 

+

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

+

146 'generate unnamed pipe skeleton', 

+

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

+

148 ]) 

+

149 ) 

+

150 status: bool = gen.gen_setup( 

+

151 str(getattr(args, "name")), 

+

152 getattr(args, 'verbose') or verbose 

+

153 ) 

+

154 except (ATSTypeError, ATSValueError) as e: 

+

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

+

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

+

157 if status: 

+

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

+

159 self._logger.write_log( 

+

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

+

161 self._logger.ATS_INFO 

+

162 ) 

+

163 else: 

+

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

+

165 self._logger.write_log( 

+

166 'generation failed', self._logger.ATS_ERROR 

+

167 ) 

+

168 except SystemExit: 

+

169 error_message( 

+

170 [f'{self._GEN_VERBOSE.lower()} expected argument name'] 

+

171 ) 

+

172 return status 

+

173 else: 

+

174 error_message( 

+

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

+

176 ) 

+

177 self._logger.write_log( 

+

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

+

179 ) 

+

180 return status 

+
+ + + diff --git a/tests/mytool/unp.h b/tests/mytool/unp.h index 20026fb..b29b392 100644 --- a/tests/mytool/unp.h +++ b/tests/mytool/unp.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * unp.h - * Copyright (C) 2024 Vladimir Roncevic + * Copyright (C) 2025 Vladimir Roncevic * * mytool is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/tests/mytool/unp_close.c b/tests/mytool/unp_close.c index 8ab49ff..e64642d 100644 --- a/tests/mytool/unp_close.c +++ b/tests/mytool/unp_close.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * unp_close.c - * Copyright (C) 2024 Vladimir Roncevic + * Copyright (C) 2025 Vladimir Roncevic * * mytool is free software: you can redistribute it and/or modify it * under terms of GNU General Public License as published by the diff --git a/tests/mytool/unp_make.c b/tests/mytool/unp_make.c index 4b750e7..4d7be7e 100644 --- a/tests/mytool/unp_make.c +++ b/tests/mytool/unp_make.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * unp_make.c - * Copyright (C) 2024 Vladimir Roncevic + * Copyright (C) 2025 Vladimir Roncevic * * mytool is free software: you can redistribute it and/or modify it * under terms of GNU General Public License as published by the diff --git a/tests/mytool/unp_read.c b/tests/mytool/unp_read.c index aed8177..5712fef 100644 --- a/tests/mytool/unp_read.c +++ b/tests/mytool/unp_read.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * unp_read.c - * Copyright (C) 2024 Vladimir Roncevic + * Copyright (C) 2025 Vladimir Roncevic * * mytool is free software: you can redistribute it and/or modify it * under terms of GNU General Public License as published by diff --git a/tests/mytool/unp_write.c b/tests/mytool/unp_write.c index 3df9553..ac58614 100644 --- a/tests/mytool/unp_write.c +++ b/tests/mytool/unp_write.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * unp_write.c - * Copyright (C) 2024 Vladimir Roncevic + * Copyright (C) 2025 Vladimir Roncevic * * mytool is free software: you can redistribute it and/or modify it * under terms of GNU General Public License as published by the diff --git a/tests/run_coverage.sh b/tests/run_coverage.sh index 36e90e5..9428465 100755 --- a/tests/run_coverage.sh +++ b/tests/run_coverage.sh @@ -9,10 +9,11 @@ rm -rf htmlcov gen_unnamed_pipe_coverage.xml gen_unnamed_pipe_coverage.json .coverage rm -rf mytool -ats_coverage_run.py -n gen_unnamed_pipe -p ../README.md -rm -rf mytool python3 -m coverage run -m --source=../gen_unnamed_pipe unittest discover -s ./ -p '*_test.py' -vvv python3 -m coverage html -d htmlcov python3 -m coverage xml -o gen_unnamed_pipe_coverage.xml python3 -m coverage json -o gen_unnamed_pipe_coverage.json python3 -m coverage report --format=markdown -m +python3 ats_coverage.py -n gen_unnamed_pipe +rm htmlcov/.gitignore +echo "Done" \ No newline at end of file
 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_unnamed_pipe 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_unnamed_pipe

     from ats_utilities.exceptions.ats_type_error import ATSTypeError
     from ats_utilities.exceptions.ats_value_error import ATSValueError
     from gen_unnamed_pipe.pro import UnnamedPipe
-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_unnamed_pipe'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE'
-__version__ = '1.0.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE'
+__version__: str = '1.0.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -259,7 +259,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_unnamed_pipe/pro.html b/docs/build/html/_modules/gen_unnamed_pipe/pro.html index 9a4bb6a..d6eed6b 100644 --- a/docs/build/html/_modules/gen_unnamed_pipe/pro.html +++ b/docs/build/html/_modules/gen_unnamed_pipe/pro.html @@ -43,7 +43,7 @@

Source code for gen_unnamed_pipe.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_unnamed_pipe 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_unnamed_pipe.pro

     from ats_utilities.exceptions.ats_value_error import ATSValueError
     from gen_unnamed_pipe.pro.read_template import ReadTemplate
     from gen_unnamed_pipe.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__ = '(C) 2024, https://vroncevic.github.io/gen_unnamed_pipe'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE'
-__version__ = '1.0.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE'
+__version__: str = '1.0.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -242,7 +242,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_unnamed_pipe/pro/read_template.html b/docs/build/html/_modules/gen_unnamed_pipe/pro/read_template.html index 6ef31cf..fe719be 100644 --- a/docs/build/html/_modules/gen_unnamed_pipe/pro/read_template.html +++ b/docs/build/html/_modules/gen_unnamed_pipe/pro/read_template.html @@ -44,7 +44,7 @@

Source code for gen_unnamed_pipe.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_unnamed_pipe 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_unnamed_pipe.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_form_model' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_form_model' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -191,7 +191,7 @@

Navigation

diff --git a/docs/build/html/_modules/gen_unnamed_pipe/pro/write_template.html b/docs/build/html/_modules/gen_unnamed_pipe/pro/write_template.html index 610a8b9..adb10ce 100644 --- a/docs/build/html/_modules/gen_unnamed_pipe/pro/write_template.html +++ b/docs/build/html/_modules/gen_unnamed_pipe/pro/write_template.html @@ -44,7 +44,7 @@

Source code for gen_unnamed_pipe.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_unnamed_pipe 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_unnamed_pipe.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_unnamed_pipe' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2026, https://vroncevic.github.io/gen_unnamed_pipe' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' -__version__ = '1.0.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/vroncevic/gen_unnamed_pipe/blob/dev/LICENSE' +__version__: str = '1.0.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -212,7 +212,7 @@

Navigation

diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html index 75bad5f..37594e7 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 3107099..d00f7e1 100644 --- a/docs/build/html/_sources/index.rst.txt +++ b/docs/build/html/_sources/index.rst.txt @@ -116,7 +116,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_unnamed_pipe `_ +Copyright (C) 2017 - 2026 by `vroncevic.github.io/gen_unnamed_pipe `_ **gen_unnamed_pipe** 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_unnamed_pipe.html b/docs/build/html/gen_unnamed_pipe.html index 0bc28e2..b1013a7 100644 --- a/docs/build/html/gen_unnamed_pipe.html +++ b/docs/build/html/gen_unnamed_pipe.html @@ -83,7 +83,7 @@

Subpackages
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_unnamed_pipe 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_unnamed_pipe.pro.html b/docs/build/html/gen_unnamed_pipe.pro.html index 0902785..b24aee6 100644 --- a/docs/build/html/gen_unnamed_pipe.pro.html +++ b/docs/build/html/gen_unnamed_pipe.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_unnamed_pipe 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 @@ -272,7 +272,7 @@

Navigation

diff --git a/docs/build/html/gen_unnamed_pipe.pro.read_template.html b/docs/build/html/gen_unnamed_pipe.pro.read_template.html index 1acab3c..605eab7 100644 --- a/docs/build/html/gen_unnamed_pipe.pro.read_template.html +++ b/docs/build/html/gen_unnamed_pipe.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_unnamed_pipe 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 @@ -203,7 +203,7 @@

Navigation

diff --git a/docs/build/html/gen_unnamed_pipe.pro.write_template.html b/docs/build/html/gen_unnamed_pipe.pro.write_template.html index 75b1d3d..95252f6 100644 --- a/docs/build/html/gen_unnamed_pipe.pro.write_template.html +++ b/docs/build/html/gen_unnamed_pipe.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_unnamed_pipe 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 3d1a306..1714122 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -216,7 +216,7 @@

Navigation

diff --git a/docs/build/html/index.html b/docs/build/html/index.html index ec6fec3..bed8ac4 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -128,7 +128,7 @@

Tool structure

Copyright and licence¶

license: gpl v3 license: apache 2.0

-

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

+

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

gen_unnamed_pipe 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.

@@ -210,7 +210,7 @@

Navigation

diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html index 4851f86..462c1b2 100644 --- a/docs/build/html/modules.html +++ b/docs/build/html/modules.html @@ -132,7 +132,7 @@

Navigation