From 23e0aa92ac1bec8740f42874081abd97ebda140a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Rom=C3=A1n?= Date: Tue, 30 Apr 2024 13:15:45 -0700 Subject: [PATCH] refactor(util): move functions out of util make project installable on Jython add devcontainer add Jython install tests BREAKING CHANGE: deprecate incendium.util functions --- .cz.toml | 2 +- .devcontainer.json | 18 ++ .editorconfig | 3 + .github/workflows/jython.yml | 28 ++ .github/workflows/pip-compile-upgrade.yml | 70 ++++- .github/workflows/pr-build.yml | 8 +- .github/workflows/publish.yml | 13 +- .mailmap | 3 + .pre-commit-config.yaml | 4 + .pylintrc | 22 +- Dockerfile | 56 ++++ LICENSE | 2 +- Makefile | 60 ++++ README.md | 129 +++++--- pyproject.toml | 6 - requirements.txt | 6 +- requirements/build.in | 4 + requirements/build.txt | 359 ++++++++++++++++++++++ requirements/dev.in | 1 + requirements/dev.txt | 20 ++ setup.cfg | 47 --- setup.py | 58 +++- src/incendium/__init__.py | 11 +- src/incendium/__version__.py | 11 + src/incendium/constants.py | 6 + src/incendium/exceptions.py | 126 ++++++-- src/incendium/gui.py | 74 +++++ src/incendium/l10n.py | 24 ++ src/incendium/time.py | 42 +++ src/incendium/util.py | 112 +++---- src/incendium/vision/gui.py | 73 +++-- 31 files changed, 1144 insertions(+), 254 deletions(-) create mode 100644 .devcontainer.json create mode 100644 .github/workflows/jython.yml create mode 100644 .mailmap create mode 100644 Dockerfile create mode 100644 Makefile delete mode 100644 pyproject.toml create mode 100644 requirements/build.in create mode 100644 requirements/build.txt create mode 100644 requirements/dev.in create mode 100644 requirements/dev.txt delete mode 100644 setup.cfg create mode 100644 src/incendium/__version__.py create mode 100644 src/incendium/gui.py create mode 100644 src/incendium/l10n.py create mode 100644 src/incendium/time.py diff --git a/.cz.toml b/.cz.toml index 5d84f48..f9f65bb 100644 --- a/.cz.toml +++ b/.cz.toml @@ -6,5 +6,5 @@ version_scheme = "pep440" version = "2023.4.0" update_changelog_on_bump = true version_files = [ - "setup.cfg:version" + "src/incendium/__version__.py:version" ] diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..d9dc092 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,18 @@ +{ + "name": "incendium", + "build": { + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ], + "settings": { + "python.defaultInterpreterPath": "/opt/python/2/bin/python" + } + } + }, + "onCreateCommand": "pre-commit install && pre-commit install --hook-type commit-msg" +} diff --git a/.editorconfig b/.editorconfig index bfe4581..794e30b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,9 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true +[Makefile] +indent_style = tab + [{*.md,*.yaml,*.yml}] indent_style = space indent_size = 2 diff --git a/.github/workflows/jython.yml b/.github/workflows/jython.yml new file mode 100644 index 0000000..348cb3c --- /dev/null +++ b/.github/workflows/jython.yml @@ -0,0 +1,28 @@ +on: + workflow_call: + +jobs: + pylint: + runs-on: ubuntu-22.04 + env: + JYTHON_VERSION: '2.7.3' + JYTHON_CACHE_DIR: '~/.cache/jython' + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up Jython + uses: coatl-dev/actions/setup-jython@v3 + id: setup-jython + with: + jython-version: ${{ env.JYTHON_VERSION }} + + - name: Cache Jython + uses: actions/cache@v4 + with: + path: ${{ env.JYTHON_CACHE_DIR }} + key: jy-${{ steps.setup-jython.outputs.jython-path }}-${{ runner.os }}-${{ hashFiles('setup.py') }} + + - name: Test installation on Jython + run: | + make install JYTHON_CACHE_DIR=${{ env.JYTHON_CACHE_DIR }} diff --git a/.github/workflows/pip-compile-upgrade.yml b/.github/workflows/pip-compile-upgrade.yml index 1318231..ab26dc5 100644 --- a/.github/workflows/pip-compile-upgrade.yml +++ b/.github/workflows/pip-compile-upgrade.yml @@ -7,11 +7,65 @@ on: jobs: pip-compile-upgrade: - uses: coatl-dev/workflows/.github/workflows/pip-compile-upgrade.yml@v3 - with: - path: requirements.txt - python-version: '2.7' - secrets: - gh-token: ${{ secrets.COATL_BOT_GH_TOKEN }} - gpg-sign-passphrase: ${{ secrets.COATL_BOT_GPG_PASSPHRASE }} - gpg-sign-private-key: ${{ secrets.COATL_BOT_GPG_PRIVATE_KEY }} + runs-on: ubuntu-latest + env: + PYTHON2_VERSION: '2.7' + PYTHON3_VERSION: '3.12' + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: pip-compile-requirements + uses: coatl-dev/actions/pip-compile@v3 + with: + path: requirements.txt + python-version: ${{ env.PYTHON2_VERSION }} + + - name: pip-compile-dev-requirements + uses: coatl-dev/actions/pip-compile@v3 + with: + path: requirements/dev.txt + python-version: ${{ env.PYTHON2_VERSION }} + + - name: pip-compile-build-requirements + uses: coatl-dev/actions/pip-compile@v3 + with: + path: requirements/build.txt + python-version: ${{ env.PYTHON3_VERSION }} + + - name: Detect changes + id: git-diff + uses: coatl-dev/actions/simple-git-diff@v3 + + - name: Import GPG key + if: ${{ steps.git-diff.outputs.diff == 'true' }} + id: gpg-import + uses: coatl-dev/actions/gpg-import@v3 + with: + passphrase: ${{ secrets.COATL_BOT_GPG_PASSPHRASE }} + private-key: ${{ secrets.COATL_BOT_GPG_PRIVATE_KEY }} + + - name: Build commit message + if: ${{ steps.git-diff.outputs.diff == 'true' }} + run: | + echo "chore(requirements): pip-compile upgrade" > "$RUNNER_TEMP/commit.txt" + { + echo "" + echo "updates:" + git status --porcelain | awk 'match($1, "M") {print " - " $2}' + } >> "$RUNNER_TEMP/commit.txt" + + - name: Commit and push changes + if: ${{ steps.git-diff.outputs.diff == 'true' }} + run: | + git checkout -B coatl-dev-pip-compile-upgrade + git add -u + git commit --file="${RUNNER_TEMP}/commit.txt" + git push --force --set-upstream origin coatl-dev-pip-compile-upgrade + + - name: Create pull request + if: ${{ steps.git-diff.outputs.diff == 'true' }} + uses: coatl-dev/actions/pr-create@v3 + with: + gh-token: ${{ secrets.COATL_BOT_GH_TOKEN }} diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 166a9c6..f794c29 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -6,11 +6,15 @@ on: - main paths: - 'src/**' - - pyproject.toml + - Makefile - requirements.txt - - setup.cfg + - setup.py - tox.ini jobs: + jython: + uses: ./.github/workflows/jython.yml + tox: + needs: jython uses: coatl-dev/workflows/.github/workflows/tox-docker.yml@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index afe3d4a..893dbac 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,17 +15,16 @@ jobs: needs: pre-commit uses: coatl-dev/workflows/.github/workflows/pylint.yml@v3 + jython: + needs: pylint + uses: ./.github/workflows/jython.yml + tox: - needs: - - pre-commit - - pylint + needs: jython uses: coatl-dev/workflows/.github/workflows/tox-docker.yml@v3 pypi-publish: - needs: - - pre-commit - - pylint - - tox + needs: tox uses: coatl-dev/workflows/.github/workflows/pypi-upload.yml@v3 with: python-version: '2.7' diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..68dd19e --- /dev/null +++ b/.mailmap @@ -0,0 +1,3 @@ +César Román César Román +César Román César Román +César Román Cesar Roman diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b25acdb..17954d4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,3 +36,7 @@ repos: language: system files: ^src/ types: [python] + - repo: https://github.com/coatl-dev/hadolint-coatl + rev: 2.12.0.3 + hooks: + - id: hadolint diff --git a/.pylintrc b/.pylintrc index f4c5697..350f65c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -88,7 +88,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.10 +py-version=3.12 # Discover python modules and packages in the file system subtree. recursive=no @@ -190,8 +190,7 @@ good-names=i, k, ex, Run, - _, - to + _ # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted @@ -338,7 +337,7 @@ indent-after-paren=4 indent-string=' ' # Maximum number of characters on a single line. -max-line-length=88 +max-line-length=100 # Maximum number of lines in a module. max-module-lines=1000 @@ -426,13 +425,14 @@ disable=consider-using-f-string, no-member, redefined-builtin, super-with-arguments, + unnecessary-pass, useless-object-inheritance, # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member +enable= [METHOD_ARGS] @@ -464,6 +464,11 @@ max-nested-blocks=5 # printed. never-returning-functions=sys.exit,argparse.parse_error +# Let 'consider-using-join' be raised when the separator to join on would be +# non-empty (resulting in expected fixes of the type: ``"- " + " - +# ".join(items)``) +suggest-join-with-non-empty-separator=yes + [REPORTS] @@ -478,8 +483,9 @@ evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor # used to format the message information. See doc for all details. msg-template= -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. #output-format= @@ -514,7 +520,7 @@ min-similarity-lines=4 max-spelling-suggestions=4 # Spelling dictionary name. No available dictionaries : You need to install -# both the python package and the system dependency for enchant to work.. +# both the python package and the system dependency for enchant to work. spelling-dict= # List of comma separated words that should be considered directives if they diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e4187ec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,56 @@ +# hadolint global ignore=DL3008,DL3042 +FROM coatldev/six:3.12 as base + +ENV JYTHON_VERSION 2.7.3 +ENV JYTHON_HOME /opt/jython/${JYTHON_VERSION} + +RUN set -eux; \ + \ + apt-get update --quiet; \ + apt-get install --yes --no-install-recommends \ + openjdk-17-jre \ + ; \ + rm -rf /var/lib/apt/lists/* + +# >============================================================================< + +FROM base as jython + +RUN set -eux; \ + \ + apt-get update --quiet; \ + apt-get install --yes --no-install-recommends \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /tmp + +RUN set -eux; \ + \ + wget -q "https://repo1.maven.org/maven2/org/python/jython-installer/${JYTHON_VERSION}/jython-installer-${JYTHON_VERSION}.jar"; \ + \ + java -jar "jython-installer-${JYTHON_VERSION}.jar" \ + --silent \ + --type standard \ + --directory "$JYTHON_HOME" + +# >============================================================================< + +FROM base as final + +COPY --from=jython ${JYTHON_HOME}/ ${JYTHON_HOME}/ + +ENV PATH ${JYTHON_HOME}/bin:$PATH + +COPY requirements /tmp/requirements/ + +RUN set -eux; \ + \ + python2 -m pip install --requirement \ + /tmp/requirements/dev.txt; \ + \ + python3 -m pip install --requirement \ + /tmp/requirements/build.txt + +CMD ["/bin/bash"] diff --git a/LICENSE b/LICENSE index 78a9e4e..ec70bc1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2021 César Román +Copyright (c) 2020-2024 coatl.dev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3214658 --- /dev/null +++ b/Makefile @@ -0,0 +1,60 @@ +JYTHON_CACHE_DIR := ~/.cache/jython + +.DEFAULT_GOAL := help + +##@ Help + +.PHONY: help clean check init install install-clean install-force install-nocache install-nodeps + +help: ## Display this help message. + @awk \ + 'BEGIN { \ + FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n" \ + } \ + /^[a-zA-Z_-]+:.*?##/ { \ + printf " \033[36m%-16s\033[0m %s\n", $$1, $$2 \ + } \ + /^##@/ { \ + printf "\n\033[1m%s\033[0m\n", substr($$0, 5) \ + } ' \ + $(MAKEFILE_LIST) + +##@ Cleanup + +clean: ## Uninstall all Jython packages. + @ echo "Uninstalling all Jython packages…" + jython -m pip freeze | xargs jython -m pip uninstall -y + +##@ Initialize + +check: ## Check if Jython is installed. + @echo "Cheking if Jython is installed…" + @if ! command -v jython &> /dev/null; then \ + echo "Jython is not installed. Please install Jython before proceeding."; \ + exit 1; \ + fi + +init: ## Run check and create required directories for other targets. + @echo "Initializing…" + @mkdir -p "$(JYTHON_CACHE_DIR)" + +##@ Install +install: check init ## Install this package using Jython with caching enabled. + @echo "Installing package…" + jython -m pip install --cache-dir="$(JYTHON_CACHE_DIR)" . + +install-clean: check init clean ## Perform clean installation using Jython with caching enabled. + @echo "Running clean install…" + jython -m pip install --cache-dir="$(JYTHON_CACHE_DIR)" . + +install-force: check init ## Reinstall all packages using Jython even if they are already up-to-date. + @echo "Reinstalling all packages…" + jython -m pip install --force-reinstall --cache-dir="$(JYTHON_CACHE_DIR)" . + +install-nocache: check ## Install this package using Jython with caching disabled. + @echo "Installing packages (no cache)…" + jython -m pip install --no-cache-dir . + +install-nodeps: check ## Install this package without dependencies. + @echo "Installing package without dependencies…" + jython -m pip install --no-deps . diff --git a/README.md b/README.md index 7cf62f7..66c3b6a 100644 --- a/README.md +++ b/README.md @@ -2,46 +2,42 @@ [![ci](https://github.com/ignition-incendium/incendium/actions/workflows/ci.yml/badge.svg)](https://github.com/ignition-incendium/incendium/actions/workflows/ci.yml) -![GitHub last commit (code)](https://img.shields.io/github/last-commit/ignition-incendium/incendium) -[![GitHub contributors](https://img.shields.io/github/contributors/ignition-incendium/incendium)](https://github.com/ignition-incendium/incendium/graphs/contributors) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Downloads](https://pepy.tech/badge/incendium)](https://pepy.tech/project/incendium) [![Join us on GitHub discussions](https://img.shields.io/badge/github-discussions-informational)](https://github.com/ignition-incendium/incendium/discussions) ->(/inˈken.di.um/) -> ->_noun_. -> ->1. A fire, inferno, conflagration; heat; torch. ->1. (heat of) passion, vehemence +:package: Package that extends and wraps some functions from Ignition's +Scripting API. -:package: Package that extends and wraps some functions from Ignition's Scripting API. - -For more information, please refer to the [Wiki](https://github.com/ignition-incendium/incendium/wiki). - -## `incendium` Project - -We have moved the `project` branch to its own repo, [`incendium-project`](https://github.com/ignition-incendium/incendium-project) +For more information, please refer to the [Wiki]. ## Prerequisites Before you begin, ensure you have met the following requirements: -* You have installed Python 2.7.18 ([download here](https://www.python.org/downloads/release/python-2718/)) -* You are familiar with [Ignition 8.1 System Functions](https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions) +- You are familiar with [Ignition 8.1 System Functions] ## Installation and usage -To use incendium, you may install it by doing any of the following. +### Installing as a dependency for your scripting projects + +To use `incendium` in your scripting projects, you may install it by doing any +of the following. -### Installing with `pip` +> [!TIP] +> To install `incendium` as a Jython package for your Gateway, follow +> [these instructions] -The preferred method is to install it by running `pip`. It requires Python 2.7.18. +The preferred method is to install it by running `pip` on a virtual environment +using [Python 2.7.18]. ```bash python2 -m pip install incendium ``` -This will install it as package to your Python installation, which will allow you to call `incendium`'s Scripting functions from Python's REPL, and get code completion using an IDE (Pycharm or Visual Studio Code). +This will install it as package to your Python installation, which will allow +you to call `incendium`'s Scripting functions from Python's REPL, and get code +completion using an IDE (PyCharm or Visual Studio Code). ```bash $ python2 @@ -64,51 +60,96 @@ And to uninstall: python2 -m pip uninstall incendium ``` -### Downloading from releases +### Using as a dependency in PyCharm -You may also download the code targeted to your desired version from the [releases page](https://github.com/ignition-incendium/incendium/releases) and add it as a dependency to your scripting project. +To include `incendium` as a dependency in PyCharm, you will need to attach it to +your project. -#### Using as a dependency in PyCharm +1. Clone the repo or download from [releases] +2. With your project open where you want to include `incendium`, navigate to + `File > Open` and select the `incendium` project folder +3. Choose `Attach` when prompted +4. Under the `incendium` project folder, right-click on the `src/` folder and + choose `Mark Directory as > Sources Root` -To include `incendium` as a dependency in PyCharm, you will need to attach it to your project. +### Installing `incendium` on your Gateway -1. Clone the repo or download from [releases](https://github.com/ignition-incendium/incendium/releases) -2. With your project open where you want to include `incendium`, navigate to `File > Open` and select the `incendium` project folder -3. Choose `Attach` when prompted -4. Under the `incendium` project folder, right-click on the `src/` folder and choose `Mark Directory as > Sources Root` +#### As a Jython package + +Starting with version 2024.4.0, this package can be installed using Jython. You +may use the [Python in Ignition] guide as reference. But here are the basic +steps: -#### Installing `incendium` as a Project on your Gateway +1. Install [Java 17] +2. Install [Jython 2.7.3] +3. Run `jython -m pip install incendium` +4. Copy the `incendium` directory and `typing.py` from + `$JYTHON_HOME/Lib/site-packages` to + `$IGNITION_DIR/user-lib/pylib/site-packages` +5. Done + +```sh +$ jython +Jython 2.7.3 (tags/v2.7.3:5f29801fe, Sep 10 2022, 18:52:49) +[OpenJDK 64-Bit Server VM (Azul Systems, Inc.)] on java17.0.11 +Type "help", "copyright", "credits" or "license" for more information. +>>> from __future__ import print_function +>>> import incendium +>>> print(incendium.__doc__) +incendium. + +incendium is a package that extends and wraps some functions from +Ignition Scripting API. + +For more information, please refer to the Wiki. +https://github.com/ignition-incendium/incendium/wiki +``` -To install incendium on your Gateway follow these steps: +#### As a Python package -1. Download **incendium.x.x.x.zip** from the [latest release](https://github.com/ignition-incendium/incendium/releases/latest) or from [Ignition Exchange](https://inductiveautomation.com/exchange/2104) -1. Browse to your Ignition Gateway (version 8.0+) -1. Go to **Config > Projects** and click on **Import project...** -1. Click on **Choose File** and select the downloaded ZIP file -1. Enter **incendium** as the **Project Name** - 1. If you're replacing a previous version, make sure to check Allow Overwrite -1. Click on **Import** +To install `incendium` as a Python package on your Gateway, simply follow these +steps: -Alternatively you could follow the instructions for cloning the `project` repo directly into `$IGNITION_DIR/data/projects` found [here](https://github.com/ignition-incendium/project?tab=readme-ov-file#cloning-this-repo). +1. Install [Python 2.7.18] +2. Run `python -m pip install incendium` +3. Copy the `incendium` directory and `typing.py` from + `$PYTHON2_HOME/Lib/site-packages` to + `$IGNITION_DIR/user-lib/pylib/site-packages` +4. Done ## Contributing to `incendium` -See [CONTRIBUTING.md](https://github.com/ignition-incendium/.github/blob/main/CONTRIBUTING.md#contributing-to-incendium). +See [CONTRIBUTING.md]. ## Discussions -Feel free to post your questions and/or ideas at [Discussions](https://github.com/ignition-incendium/incendium/discussions). +Feel free to post your questions and/or ideas at [Discussions]. ## Contributors Thanks to everyone who has contributed to this project. -Up-to-date list of contributors can be found [here](https://github.com/ignition-incendium/incendium/graphs/contributors). +Up-to-date list of [contributors]. ## License -See [LICENSE](./LICENSE). +See [LICENSE]. ## Code of conduct -See [CODE_OF_CONDUCT.md](https://github.com/ignition-incendium/.github/blob/main/CODE_OF_CONDUCT.md). +See [CODE_OF_CONDUCT.md]. + + +[CODE_OF_CONDUCT.md]: https://github.com/ignition-incendium/.github/blob/main/CODE_OF_CONDUCT.md +[CONTRIBUTING.md]: https://github.com/ignition-incendium/.github/blob/main/CONTRIBUTING.md#contributing-to-incendium +[contributors]: https://github.com/ignition-incendium/incendium/graphs/contributors +[Discussions]: https://github.com/ignition-incendium/incendium/discussions +[Ignition 8.1 System Functions]: https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions +[Java 17]: https://www.azul.com/downloads/?version=java-17-lts&package=jre#zulu +[Jython 2.7.3]: https://repo1.maven.org/maven2/org/python/jython-installer/2.7.3/jython-installer-2.7.3.jar +[LICENSE]: ./LICENSE +[Python 2.7.18]: https://www.python.org/downloads/release/python-2718/ +[Python in Ignition]: https://support.inductiveautomation.com/hc/en-us/articles/360056397252-Python-In-Ignition +[releases]: https://github.com/ignition-incendium/incendium/releases +[these instructions]: #as-a-jython-package +[Wiki]: https://github.com/ignition-incendium/incendium/wiki diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 7b52b9b..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build-system] -build-backend = "setuptools.build_meta" -requires = [ - "setuptools>=42", - "wheel", -] diff --git a/requirements.txt b/requirements.txt index 8efcbb9..93172d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,9 +9,9 @@ enum34==1.1.10 \ --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 # via ignition-api -ignition-api==8.1.39 \ - --hash=sha256:55b4f71bf095d2a02163ea33d3ca7398532affbb2aa67006937e58bb3ac3602a \ - --hash=sha256:ef112a8b5831c4f219561b0816da39f2a5a94fc37892b819bb5864dcbec0c2cc +ignition-api==8.1.39.post1 \ + --hash=sha256:356001f831a2da38a817a0de19050924143607726d841f5fab45cbed9555ecb9 \ + --hash=sha256:df88d5e038b1e0557048b652cf0e7d04ac7becb016305daa1b66cc2aae3e8b12 # via -r requirements.in typing==3.10.0.0 \ --hash=sha256:12fbdfbe7d6cca1a42e485229afcb0b0c8259258cfb919b8a5e2a5c953742f89 \ diff --git a/requirements/build.in b/requirements/build.in new file mode 100644 index 0000000..2618e9f --- /dev/null +++ b/requirements/build.in @@ -0,0 +1,4 @@ +commitizen +pre-commit +pylint +tox diff --git a/requirements/build.txt b/requirements/build.txt new file mode 100644 index 0000000..fea9fad --- /dev/null +++ b/requirements/build.txt @@ -0,0 +1,359 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --allow-unsafe --generate-hashes build.in +# +argcomplete==3.3.0 \ + --hash=sha256:c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54 \ + --hash=sha256:fd03ff4a5b9e6580569d34b273f741e85cd9e072f3feeeee3eba4891c70eda62 + # via commitizen +astroid==3.1.0 \ + --hash=sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819 \ + --hash=sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4 + # via pylint +cachetools==5.3.3 \ + --hash=sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945 \ + --hash=sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105 + # via tox +cfgv==3.4.0 \ + --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ + --hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560 + # via pre-commit +chardet==5.2.0 \ + --hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \ + --hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 + # via tox +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 + # via commitizen +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via + # commitizen + # tox +commitizen==3.24.0 \ + --hash=sha256:088e01ae8265f1d6fa5a4d11a05e4fd7092d958c881837c35f6c65aad27331a9 \ + --hash=sha256:d9e28b1dcd97cea64dcb50be25292ceb730470d933f1da37131f9540f762df36 + # via -r build.in +decli==0.6.1 \ + --hash=sha256:7815ac58617764e1a200d7cadac6315fcaacc24d727d182f9878dd6378ccf869 \ + --hash=sha256:ed88ccb947701e8e5509b7945fda56e150e2ac74a69f25d47ac85ef30ab0c0f0 + # via commitizen +dill==0.3.8 \ + --hash=sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca \ + --hash=sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7 + # via pylint +distlib==0.3.8 \ + --hash=sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 \ + --hash=sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64 + # via virtualenv +filelock==3.13.4 \ + --hash=sha256:404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f \ + --hash=sha256:d13f466618bfde72bd2c18255e269f72542c6e70e7bac83a0232d6b1cc5c8cf4 + # via + # tox + # virtualenv +identify==2.5.36 \ + --hash=sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa \ + --hash=sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d + # via pre-commit +importlib-metadata==7.1.0 \ + --hash=sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 \ + --hash=sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2 + # via commitizen +isort==5.13.2 \ + --hash=sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109 \ + --hash=sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6 + # via pylint +jinja2==3.1.3 \ + --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \ + --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90 + # via commitizen +markupsafe==2.1.5 \ + --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \ + --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \ + --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \ + --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \ + --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \ + --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \ + --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \ + --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \ + --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \ + --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \ + --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \ + --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \ + --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \ + --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \ + --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \ + --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \ + --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \ + --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \ + --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \ + --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \ + --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \ + --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \ + --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \ + --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \ + --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \ + --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \ + --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \ + --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \ + --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \ + --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \ + --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \ + --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \ + --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \ + --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \ + --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \ + --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \ + --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \ + --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \ + --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \ + --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \ + --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \ + --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \ + --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \ + --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \ + --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \ + --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \ + --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \ + --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \ + --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \ + --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \ + --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \ + --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \ + --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \ + --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \ + --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \ + --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \ + --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \ + --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \ + --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \ + --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68 + # via jinja2 +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint +nodeenv==1.8.0 \ + --hash=sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2 \ + --hash=sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec + # via pre-commit +packaging==24.0 \ + --hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \ + --hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9 + # via + # commitizen + # pyproject-api + # tox +platformdirs==4.2.1 \ + --hash=sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf \ + --hash=sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1 + # via + # pylint + # tox + # virtualenv +pluggy==1.5.0 \ + --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ + --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 + # via tox +pre-commit==3.7.0 \ + --hash=sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab \ + --hash=sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060 + # via -r build.in +prompt-toolkit==3.0.36 \ + --hash=sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63 \ + --hash=sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305 + # via questionary +pylint==3.1.0 \ + --hash=sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74 \ + --hash=sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23 + # via -r build.in +pyproject-api==1.6.1 \ + --hash=sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538 \ + --hash=sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675 + # via tox +pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f + # via + # commitizen + # pre-commit +questionary==2.0.1 \ + --hash=sha256:8ab9a01d0b91b68444dff7f6652c1e754105533f083cbe27597c8110ecc230a2 \ + --hash=sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b + # via commitizen +termcolor==2.4.0 \ + --hash=sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63 \ + --hash=sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a + # via commitizen +tomlkit==0.12.4 \ + --hash=sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b \ + --hash=sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3 + # via + # commitizen + # pylint +tox==4.14.2 \ + --hash=sha256:0defb44f6dafd911b61788325741cc6b2e12ea71f987ac025ad4d649f1f1a104 \ + --hash=sha256:2900c4eb7b716af4a928a7fdc2ed248ad6575294ed7cfae2ea41203937422847 + # via -r build.in +virtualenv==20.26.0 \ + --hash=sha256:0846377ea76e818daaa3e00a4365c018bc3ac9760cbb3544de542885aad61fb3 \ + --hash=sha256:ec25a9671a5102c8d2657f62792a27b48f016664c6873f6beed3800008577210 + # via + # pre-commit + # tox +wcwidth==0.2.13 \ + --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ + --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 + # via prompt-toolkit +zipp==3.18.1 \ + --hash=sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b \ + --hash=sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +setuptools==69.5.1 \ + --hash=sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987 \ + --hash=sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32 + # via nodeenv diff --git a/requirements/dev.in b/requirements/dev.in new file mode 100644 index 0000000..a37ad77 --- /dev/null +++ b/requirements/dev.in @@ -0,0 +1 @@ +ignition-api diff --git a/requirements/dev.txt b/requirements/dev.txt new file mode 100644 index 0000000..bffa87e --- /dev/null +++ b/requirements/dev.txt @@ -0,0 +1,20 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --generate-hashes dev.in +# +enum34==1.1.10 \ + --hash=sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53 \ + --hash=sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328 \ + --hash=sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248 + # via ignition-api +ignition-api==8.1.39.post1 \ + --hash=sha256:356001f831a2da38a817a0de19050924143607726d841f5fab45cbed9555ecb9 \ + --hash=sha256:df88d5e038b1e0557048b652cf0e7d04ac7becb016305daa1b66cc2aae3e8b12 + # via -r dev.in +typing==3.10.0.0 \ + --hash=sha256:12fbdfbe7d6cca1a42e485229afcb0b0c8259258cfb919b8a5e2a5c953742f89 \ + --hash=sha256:13b4ad211f54ddbf93e5901a9967b1e07720c1d1b78d596ac6a439641aa1b130 \ + --hash=sha256:c7219ef20c5fbf413b4567092adfc46fa6203cb8454eda33c3fc1afe1398a308 + # via ignition-api diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b282c2e..0000000 --- a/setup.cfg +++ /dev/null @@ -1,47 +0,0 @@ -[metadata] -name = incendium -version = 2023.4.0 -description = Package that extends and wraps Ignition Scripting API -long_description = file: README.md, CHANGELOG.md -long_description_content_type = text/markdown -url = https://github.com/thecesrom/incendium -author = César Román -author_email = cesar@thecesrom.dev -license = MIT -license_files = LICENSE -classifiers = - Development Status :: 5 - Production/Stable - Intended Audience :: Developers - Intended Audience :: Information Technology - Intended Audience :: Manufacturing - License :: OSI Approved :: MIT License - Operating System :: MacOS :: MacOS X - Operating System :: Microsoft :: Windows - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2 :: Only - Programming Language :: Python :: 2.7 - Topic :: Software Development :: Libraries :: Python Modules - Topic :: Software Development :: Testing :: Mocking -keywords = - hmi - ignition - inductive automation - scada -project_urls = - Documentation = https://github.com/thecesrom/incendium/wiki - Funding = https://github.com/sponsors/thecesrom - Source = https://github.com/thecesrom/incendium - Tracker = https://github.com/thecesrom/incendium/issues - -[options] -packages = find: -install_requires = - ignition-api>=8.1.0 -python_requires = ==2.7.18 -package_dir = - =src - -[options.packages.find] -where = src diff --git a/setup.py b/setup.py index 027bb99..c28627a 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,58 @@ -#!/usr/bin/env python +#!/usr/bin/env jython + """incendium.""" -from setuptools import setup +from codecs import open +from os import path + +from setuptools import find_packages, setup + +here = path.abspath(path.dirname(__file__)) + +about = {} +with open(path.join(here, "src", "incendium", "__version__.py"), "r") as f: + exec(f.read(), about) + +with open("README.md", "r", "utf-8") as f: + readme = f.read() -setup() +setup( + name=about["__title__"], + version=about["__version__"], + description=about["__description__"], + long_description=readme, + long_description_content_type="text/markdown", + url=about["__url__"], + author=about["__author__"], + author_email=about["__author_email__"], + license=about["__license__"], + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Intended Audience :: Manufacturing", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 2 :: Only", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: Implementation :: Jython", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + keywords="coatl-dev, hmi, ignition, inductive automation, scada", + package_dir={"": "src"}, + packages=find_packages(where="src"), + python_requires=">=2.7, <3", + install_requires=[ + "ignition-api>=8.1.0;platform_python_implementation != 'Jython'", + "typing;platform_python_implementation == 'Jython'", + ], + project_urls={ + "Documentation": "https://github.com/ignition-incendium/incendium/wiki", + "Funding": "https://github.com/sponsors/cesarcoatl", + "Source": "https://github.com/ignition-incendium/incendium", + "Tracker": "https://github.com/ignition-incendium/incendium/issues", + }, +) diff --git a/src/incendium/__init__.py b/src/incendium/__init__.py index 66c20ae..608b7a6 100644 --- a/src/incendium/__init__.py +++ b/src/incendium/__init__.py @@ -1,17 +1,8 @@ -# coding=utf-8 -# Copyright (C) 2020-2022 -# Author: César Román -# Contact: cesar@thecesrom.dev -# -# Licensed under the MIT License. -# -# https://github.com/thecesrom/incendium/blob/HEAD/LICENSE -# """incendium. incendium is a package that extends and wraps some functions from Ignition Scripting API. For more information, please refer to the Wiki. -https://github.com/thecesrom/incendium/wiki +https://github.com/ignition-incendium/incendium/wiki """ diff --git a/src/incendium/__version__.py b/src/incendium/__version__.py new file mode 100644 index 0000000..42d2573 --- /dev/null +++ b/src/incendium/__version__.py @@ -0,0 +1,11 @@ +# coding=utf-8 +"""Package information.""" + +__title__ = "incendium" +__description__ = "Package that extends and wraps Ignition Scripting API" +__url__ = "https://github.com/ignition-incendium/incendium" +__version__ = "2023.4.0" +__author__ = "César Román" +__author_email__ = "cesar@coatl.dev" +__license__ = "MIT" +__copyright__ = "Copyright (C) 2018-2024 coatl.dev" diff --git a/src/incendium/constants.py b/src/incendium/constants.py index b8b33d2..d9ce218 100644 --- a/src/incendium/constants.py +++ b/src/incendium/constants.py @@ -54,3 +54,9 @@ UNEXPECTED_ERROR = "An unexpected error occurred in {}.\n{}" UNEXPECTED_ERROR_CAUSED_BY = "An unexpected error occurred in {}.\n{}\nCaused by: {}" WARNING_WINDOW_TITLE = "Warning" + +# Exceptions +GATEWAY_EXCEPTION = ( + "com.inductiveautomation.ignition.client.gateway_interface.GatewayException: " +) +MSSQL_SERVER_EXCEPTION = "com.microsoft.sqlserver.jdbc.SQLServerException: " diff --git a/src/incendium/exceptions.py b/src/incendium/exceptions.py index 8663e64..5298dd1 100644 --- a/src/incendium/exceptions.py +++ b/src/incendium/exceptions.py @@ -2,17 +2,51 @@ from __future__ import unicode_literals -__all__ = ["ApplicationError", "TagError"] - +__all__ = [ + "ApplicationError", + "Error", + "GatewayError", + "JavaError", + "MSSQLError", + "TagError", + "get_function_name", +] + +import traceback from typing import Optional from java.lang import Throwable +from incendium import constants from incendium.helper.types import AnyStr, InnerException -class ApplicationError(Exception): - """Application Error class.""" +class Error(Exception): + """Error class.""" + + message = None # type: AnyStr + + def __init__(self, message): + # type: (AnyStr) -> None + """Error initializer. + + Args: + message: The error message. + """ + super(Error, self).__init__() + self.message = message + + def __repr__(self): # type: ignore[no-untyped-def] + """Compute the "official" string representation.""" + return "{}(message={!r})".format(self.__class__.__name__, self.message) + + def __str__(self): # type: ignore[no-untyped-def] + """Compute the "informal" string representation.""" + return repr(self.message) + + +class JavaError(Exception): + """Java Error class.""" cause = None # type: Optional[Throwable] inner_exception = None # type: InnerException @@ -23,17 +57,25 @@ def __init__( message, # type: AnyStr inner_exception=None, # type: InnerException cause=None, # type: Optional[Throwable] + remove_substring=None, # type: Optional[AnyStr] ): # type: (...) -> None - """Application Error initializer. + """Java Error initializer. Args: message: The error message. inner_exception: The inner Exception. Optional. cause: The cause of the Exception. Optional. + remove_substring: The substring to be removed from message. + Optional. """ - super(ApplicationError, self).__init__() - self.message = message + super(JavaError, self).__init__() + _message = ( + message + if remove_substring is None + else message.replace(remove_substring, constants.EMPTY_STRING) + ) + self.message = _message self.inner_exception = inner_exception self.cause = cause @@ -51,25 +93,67 @@ def __str__(self): # type: ignore[no-untyped-def] return "{!r}, {!r}, {!r}".format(self.message, self.inner_exception, self.cause) -class TagError(Exception): - """Tag Error class.""" +class ApplicationError(JavaError): + """Application Error class.""" - message = None # type: AnyStr + pass - def __init__(self, message): - # type: (AnyStr) -> None - """Tag Error initializer. + +class GatewayError(JavaError): + """Gateway Error class.""" + + def __init__( + self, + message, # type: AnyStr + inner_exception=None, # type: InnerException + cause=None, # type: Optional[Throwable] + ): + # type: (...) -> None + """Initialize GatewayError instance. Args: message: The error message. + inner_exception: The inner Exception. Optional. + cause: The cause of the Exception. Optional. """ - super(TagError, self).__init__() - self.message = message + super(GatewayError, self).__init__( + message, inner_exception, cause, constants.GATEWAY_EXCEPTION + ) - def __repr__(self): # type: ignore[no-untyped-def] - """Compute the "official" string representation.""" - return "{}(message={!r})".format(self.__class__.__name__, self.message) - def __str__(self): # type: ignore[no-untyped-def] - """Compute the "informal" string representation.""" - return repr(self.message) +class MSSQLError(JavaError): + """MSSQL Error class.""" + + def __init__( + self, + message, # type: AnyStr + inner_exception=None, # type: InnerException + cause=None, # type: Optional[Throwable] + ): + # type: (...) -> None + """Initialize MSSQLError instance. + + Args: + message: The error message. + inner_exception: The inner Exception. Optional. + cause: The cause of the Exception. Optional. + """ + super(MSSQLError, self).__init__( + message, inner_exception, cause, constants.MSSQL_SERVER_EXCEPTION + ) + + +class TagError(Error): + """Tag Error class.""" + + pass + + +def get_function_name(): + # type: () -> AnyStr + """Get the name of the function last called. + + Returns: + Function's name. + """ + return traceback.extract_stack(None, 2)[0][2] diff --git a/src/incendium/gui.py b/src/incendium/gui.py new file mode 100644 index 0000000..85a6503 --- /dev/null +++ b/src/incendium/gui.py @@ -0,0 +1,74 @@ +"""GUI Module.""" + +__all__ = ["validate_form"] + +from typing import Dict, Optional, Tuple + +from incendium import constants +from incendium.helper.types import AnyStr, Number + + +def _format_error_message(counter, error_message, key): + # type: (int, AnyStr, AnyStr) -> AnyStr + """Format error message. + + Args: + counter: Number of detected errors. + error_message: Error message. + key: Dictionary key. + + Returns: + Formatted error message. + """ + error_message += ( + constants.TABBED_LINE + key if counter == 1 else constants.NEW_TABBED_LINE + key + ) + return error_message + + +def validate_form( + strings=None, # type: Optional[Dict[AnyStr, AnyStr]] + numbers=None, # type: Optional[Dict[AnyStr, Number]] + collections=None, # type: Optional[Dict[AnyStr, Number]] +): + # type: (...) -> Tuple[bool, AnyStr] + """Perform a form validation. + + Args: + strings: A dictionary containing all strings which must not be + empty. Optional. + numbers: A dictionary containing all numbers which must be + greater than zero. Optional. + collections: A dictionary containing all collections which must + at least contain an element. Optional. + + Returns: + A tuple (is_valid, error_message), where is_valid is True if all + validation tests have passed, False otherwise, and error_message + is the error message in case any validation test has failed. + """ + is_valid = True + error_message = constants.EMPTY_STRING + counter = 0 + + if strings: + for key, str_val in strings.iteritems(): + if not str_val: + counter += 1 + error_message = _format_error_message(counter, error_message, key) + is_valid = False + + merged_dict = {} + if numbers: + merged_dict.update(numbers) + if collections: + merged_dict.update(collections) + + if merged_dict: + for key, num_val in merged_dict.iteritems(): + if num_val is None or num_val <= 0: + counter += 1 + error_message = _format_error_message(counter, error_message, key) + is_valid = False + + return is_valid, error_message diff --git a/src/incendium/l10n.py b/src/incendium/l10n.py new file mode 100644 index 0000000..534700c --- /dev/null +++ b/src/incendium/l10n.py @@ -0,0 +1,24 @@ +"""Localization module.""" + +__all__ = ["set_locale"] + +import system.util + +from incendium import constants +from incendium.user import IncendiumUser + + +def set_locale(user): + # type: (IncendiumUser) -> None + """Set the Locale to the user's default Language. + + If none is configured, the default will be English (US). + + Args: + user: IncendiumUser instance. + """ + locale = ( + user.locale if user is not None and user.locale else constants.DEFAULT_LANGUAGE + ) + + system.util.setLocale(locale) diff --git a/src/incendium/time.py b/src/incendium/time.py new file mode 100644 index 0000000..a1fd3ab --- /dev/null +++ b/src/incendium/time.py @@ -0,0 +1,42 @@ +"""Time module.""" + +__all__ = ["get_timer", "get_timestamp"] + +from typing import Union + +import system.date +from java.util import Date + +from incendium.helper.types import AnyStr + + +def get_timestamp(value): + # type: (int) -> AnyStr + """Get timestamp in "hh:mm:ss" format. + + Args: + value: Time represented in seconds. + + Returns: + Time elapsed represented by a string in the following format: + "hh:mm:ss". + """ + minutes, seconds = divmod(value, 60) + hours, minutes = divmod(minutes, 60) + return "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds) + + +def get_timer(date): + # type: (Union[Date, long]) -> AnyStr + """Get a timer with the time elapsed from value until now. + + Args: + date: A date or a date represented in milliseconds. + + Returns: + Time elapsed represented by a string in the following + format: "hh:mm:ss". + """ + date_1 = date if isinstance(date, Date) else system.date.fromMillis(date) + date_2 = system.date.now() + return get_timestamp(system.date.secondsBetween(date_1, date_2)) diff --git a/src/incendium/util.py b/src/incendium/util.py index d57698e..558df31 100644 --- a/src/incendium/util.py +++ b/src/incendium/util.py @@ -1,3 +1,4 @@ +# pylint: disable=implicit-str-concat """Utility module.""" __all__ = [ @@ -8,44 +9,48 @@ "validate_form", ] -import traceback +import warnings from typing import Dict, Optional, Tuple, Union -import system.date -import system.util from java.util import Date -from incendium import constants +from incendium import exceptions, gui, l10n, time from incendium.helper.types import AnyStr, Number from incendium.user import IncendiumUser -def _format_error_message(counter, error_message, key): - # type: (int, AnyStr, AnyStr) -> AnyStr - """Format error message. - - Args: - counter: Number of detected errors. - error_message: Error message. - key: Dictionary key. +def get_function_name(): + # type: () -> AnyStr + """Get the name of the function last called. Returns: - Formatted error message. + Function's name. """ - error_message += ( - constants.TABBED_LINE + key if counter == 1 else constants.NEW_TABBED_LINE + key + warnings.warn( + "get_function_name is deprecated and will be removed in a future release. " + "Use incendium.exceptions.get_function_name instead.", + DeprecationWarning, ) - return error_message + return exceptions.get_function_name() -def get_function_name(): - # type: () -> AnyStr - """Get the name of the function last called. +def get_timer(date): + # type: (Union[Date, long]) -> AnyStr + """Get a timer with the time elapsed from value until now. + + Args: + date: A date or a date represented in milliseconds. Returns: - Function's name. + Time elapsed represented by a string in the following + format: "hh:mm:ss". """ - return traceback.extract_stack(None, 2)[0][2] + warnings.warn( + "get_timer is deprecated and will be removed in a future release. " + "Use incendium.time.get_timer instead.", + DeprecationWarning, + ) + return time.get_timer(date) def get_timestamp(value): @@ -59,25 +64,12 @@ def get_timestamp(value): Time elapsed represented by a string in the following format: "hh:mm:ss". """ - minutes, seconds = divmod(value, 60) - hours, minutes = divmod(minutes, 60) - return "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds) - - -def get_timer(date): - # type: (Union[Date, long]) -> AnyStr - """Get a timer with the time elapsed from value until now. - - Args: - date: A date or a date represented in milliseconds. - - Returns: - Time elapsed represented by a string in the following - format: "hh:mm:ss". - """ - date_1 = date if isinstance(date, Date) else system.date.fromMillis(date) - date_2 = system.date.now() - return get_timestamp(system.date.secondsBetween(date_1, date_2)) + warnings.warn( + "get_timestamp is deprecated and will be removed in a future release. " + "Use incendium.time.get_timestamp instead.", + DeprecationWarning, + ) + return time.get_timestamp(value) def set_locale(user): @@ -89,11 +81,12 @@ def set_locale(user): Args: user: IncendiumUser instance. """ - locale = ( - user.locale if user is not None and user.locale else constants.DEFAULT_LANGUAGE + warnings.warn( + "set_locale is deprecated and will be removed in a future release. " + "Use incendium.l10n.set_locale instead.", + DeprecationWarning, ) - - system.util.setLocale(locale) + l10n.set_locale(user) def validate_form( @@ -117,28 +110,9 @@ def validate_form( validation tests have passed, False otherwise, and error_message is the error message in case any validation test has failed. """ - is_valid = True - error_message = constants.EMPTY_STRING - counter = 0 - - if strings: - for key, str_val in strings.iteritems(): - if not str_val: - counter += 1 - error_message = _format_error_message(counter, error_message, key) - is_valid = False - - merged_dict = {} - if numbers: - merged_dict.update(numbers) - if collections: - merged_dict.update(collections) - - if merged_dict: - for key, num_val in merged_dict.iteritems(): - if num_val is None or num_val <= 0: - counter += 1 - error_message = _format_error_message(counter, error_message, key) - is_valid = False - - return is_valid, error_message + warnings.warn( + "validate_form is deprecated and will be removed in a future release. " + "Use incendium.gui.validate_form instead.", + DeprecationWarning, + ) + return gui.validate_form(strings, numbers, collections) diff --git a/src/incendium/vision/gui.py b/src/incendium/vision/gui.py index a73629a..9391438 100644 --- a/src/incendium/vision/gui.py +++ b/src/incendium/vision/gui.py @@ -1,4 +1,4 @@ -"""GUI module.""" +"""Vision GUI module.""" from __future__ import unicode_literals @@ -53,8 +53,13 @@ CURSOR_MOVE = 13 -def authentication(auth_profile="", title="Authentication"): - # type: (AnyStr, AnyStr) -> bool +def authentication( + auth_profile="", # type: AnyStr + title="Authentication", # type: AnyStr + username_label_text="Username", # type: AnyStr + password_label_text="Password", # type: AnyStr +): + # type: (...) -> bool """Open up a popup input dialog box. This dialog box will show a prompt message, and allow the user to @@ -70,6 +75,10 @@ def authentication(auth_profile="", title="Authentication"): profile. Optional. title: A title for the input box. This will be translated to the selected Locale. Optional. + username_label_text: The text to display for the username label. + This will be translated to the selected Locale. Optional. + password_label_text: The text to display for the password label. + This will be translated to the selected Locale. Optional. Returns: ``True`` if the user was validated, ``False`` otherwise. @@ -82,8 +91,8 @@ def authentication(auth_profile="", title="Authentication"): panel = JPanel() labels = JPanel(GridLayout(0, 1, 2, 2)) - labels.add(JLabel("{}: ".format(system.util.translate("Username")))) - labels.add(JLabel("{}: ".format(system.util.translate("Password")))) + labels.add(JLabel("{}: ".format(system.util.translate(username_label_text)))) + labels.add(JLabel("{}: ".format(system.util.translate(password_label_text)))) panel.add(labels) fields = JPanel(GridLayout(0, 1, 2, 2)) @@ -113,8 +122,14 @@ def authentication(auth_profile="", title="Authentication"): return choice == JOptionPane.OK_OPTION and valid -def authorization(role, auth_profile="", title="Athorization"): - # type: (AnyStr, AnyStr, AnyStr) -> bool +def authorization( + role, # type: AnyStr + auth_profile="", # type: AnyStr + title="Authorization", # type: AnyStr + username_label_text="Username", # type: AnyStr + password_label_text="Password", # type: AnyStr +): + # type: (...) -> bool """Open up a popup input dialog box. This dialog box will show a prompt message, and allow the user to @@ -131,22 +146,26 @@ def authorization(role, auth_profile="", title="Athorization"): profile. Optional. title: A title for the input box. This will be translated to the selected Locale. Optional. + username_label_text: The text to display for the username label. + This will be translated to the selected Locale. Optional. + password_label_text: The text to display for the password label. + This will be translated to the selected Locale. Optional. Returns: ``True`` if the user was validated, ``False`` otherwise. """ - has_role = False - options = [ system.util.translate(constants.OK_TEXT), system.util.translate(constants.CANCEL_TEXT), ] + has_role = False + panel = JPanel() labels = JPanel(GridLayout(0, 1, 2, 2)) - labels.add(JLabel("{}: ".format(system.util.translate("Username")))) - labels.add(JLabel("{}: ".format(system.util.translate("Password")))) + labels.add(JLabel("{}: ".format(system.util.translate(username_label_text)))) + labels.add(JLabel("{}: ".format(system.util.translate(password_label_text)))) panel.add(labels) fields = JPanel(GridLayout(0, 1, 2, 2)) @@ -235,10 +254,12 @@ def error(message, title="Error", detail=None): detail: Additional text to display. This will be translated to the selected Locale. Optional. """ - if detail is None: - msg = system.util.translate(message) - else: - msg = "\n".join([system.util.translate(message), system.util.translate(detail)]) + msg = ( + system.util.translate(message) + if detail is None + else "\n".join([system.util.translate(message), system.util.translate(detail)]) + ) + JOptionPane.showMessageDialog( None, msg, system.util.translate(title), JOptionPane.ERROR_MESSAGE ) @@ -256,10 +277,12 @@ def info(message, title="Information", detail=None): detail: Additional text to display. This will be translated to the selected Locale. Optional. """ - if detail is None: - msg = system.util.translate(message) - else: - msg = "\n".join([system.util.translate(message), system.util.translate(detail)]) + msg = ( + system.util.translate(message) + if detail is None + else "\n".join([system.util.translate(message), system.util.translate(detail)]) + ) + JOptionPane.showMessageDialog( None, msg, @@ -293,7 +316,7 @@ def input(message, title="Input"): ] panel = JPanel() - label = JLabel("{}: ".format(system.util.translate(message))) + label = JLabel("{}: ".format(message)) panel.add(label) text_field = JTextField(25) panel.add(text_field) @@ -324,10 +347,12 @@ def warning(message, title="Warning", detail=None): detail: Additional text to display. This will be translated to the selected Locale. Optional. """ - if detail is None: - msg = system.util.translate(message) - else: - msg = "\n".join([system.util.translate(message), system.util.translate(detail)]) + msg = ( + system.util.translate(message) + if detail is None + else "\n".join([system.util.translate(message), system.util.translate(detail)]) + ) + JOptionPane.showMessageDialog( None, msg, system.util.translate(title), JOptionPane.WARNING_MESSAGE )