diff --git a/poetry.lock b/poetry.lock index 6682e7f..6067df7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -22,7 +22,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (> [[package]] name = "certifi" -version = "2022.5.18.1" +version = "2022.6.15" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -41,7 +41,7 @@ unicode_backport = ["unicodedata2"] [[package]] name = "colorama" -version = "0.4.4" +version = "0.4.5" description = "Cross-platform colored terminal text." category = "dev" optional = false @@ -55,23 +55,6 @@ category = "main" optional = false python-versions = ">=3.5" -[[package]] -name = "importlib-metadata" -version = "4.8.3" -description = "Read metadata from Python packages" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] - [[package]] name = "more-itertools" version = "8.13.0" @@ -107,9 +90,6 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - [package.extras] dev = ["pre-commit", "tox"] @@ -123,50 +103,50 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pyparsing" -version = "3.0.7" -description = "Python parsing module" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6.8" [package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +diagrams = ["railroad-diagrams", "jinja2"] [[package]] name = "pyside6" -version = "6.3.0" +version = "6.3.1" description = "Python bindings for the Qt cross-platform application and UI framework" category = "main" optional = false python-versions = "<3.11,>=3.6" [package.dependencies] -PySide6-Addons = "6.3.0" -PySide6-Essentials = "6.3.0" -shiboken6 = "6.3.0" +PySide6-Addons = "6.3.1" +PySide6-Essentials = "6.3.1" +shiboken6 = "6.3.1" [[package]] name = "pyside6-addons" -version = "6.3.0" +version = "6.3.1" description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" category = "main" optional = false python-versions = "<3.11,>=3.6" [package.dependencies] -PySide6-Essentials = "6.3.0" -shiboken6 = "6.3.0" +PySide6-Essentials = "6.3.1" +shiboken6 = "6.3.1" [[package]] name = "pyside6-essentials" -version = "6.3.0" +version = "6.3.1" description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" category = "main" optional = false python-versions = "<3.11,>=3.6" [package.dependencies] -shiboken6 = "6.3.0" +shiboken6 = "6.3.1" [[package]] name = "pytest" @@ -180,7 +160,6 @@ python-versions = ">=3.5" atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=17.4.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} more-itertools = ">=4.0.0" packaging = "*" pluggy = ">=0.12,<1.0" @@ -191,40 +170,40 @@ wcwidth = "*" checkqa-mypy = ["mypy (==v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +[[package]] +name = "pytimeparse" +version = "1.1.8" +description = "Time expression parser" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "requests" -version = "2.27.1" +version = "2.28.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7, <4" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +charset-normalizer = ">=2.0.0,<2.1.0" +idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] [[package]] name = "shiboken6" -version = "6.3.0" +version = "6.3.1" description = "Python/C++ bindings helper module" category = "main" optional = false python-versions = "<3.11,>=3.6" -[[package]] -name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" -category = "dev" -optional = false -python-versions = ">=3.6" - [[package]] name = "urllib3" version = "1.26.9" @@ -246,22 +225,10 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "zipp" -version = "3.6.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] - [metadata] lock-version = "1.1" -python-versions = ">=3.6,<3.11" -content-hash = "07c567f7f0b40b87aa216768d1c3a71862f55486f97c52d941c4100e6f03df2f" +python-versions = ">=3.8,<3.10" +content-hash = "f19b4734e5b57967296c71c28b0da0fa440f0e6b687b8261809c49e75d9821f0" [metadata.files] atomicwrites = [ @@ -273,25 +240,21 @@ attrs = [ {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] certifi = [ - {file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"}, - {file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"}, + {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, + {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, ] charset-normalizer = [ {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] -importlib-metadata = [ - {file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"}, - {file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"}, -] more-itertools = [ {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, @@ -312,40 +275,40 @@ py = [ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pyparsing = [ - {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, - {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pyside6 = [ - {file = "PySide6-6.3.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:2517377c49b5d5c66afc51dab02814d76af1fc7545bf6b76b3d1de86ce9a4507"}, - {file = "PySide6-6.3.0-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:53d61ff66bb81a099e71e43e7470060a9141a8e6782d6eb6cc52b9a9cf38730c"}, - {file = "PySide6-6.3.0-cp36-abi3-win_amd64.whl", hash = "sha256:c2368a0f346935167bf741712772b63dee130b29a9270e018cf9474eef1948a0"}, + {file = "PySide6-6.3.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:58b824cb41d549a149a17786326f79a2fa46a1ce94e06397e78ea5707757b052"}, + {file = "PySide6-6.3.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:bc749968d641af1c516b6b0e00264bffea9cfc2d56dc04766f36e1a313e93a3a"}, + {file = "PySide6-6.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:947185379c181d5e51b7b6bf2df8d8127c675ea57604d41265c67444d226db26"}, ] pyside6-addons = [ - {file = "PySide6_Addons-6.3.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:4937fc42aec85d5dde62b2d47e29d76a63722d2a0d72e11772baa3e9925bf234"}, - {file = "PySide6_Addons-6.3.0-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:59e96866abbe468087575b63a697c4b1cc97e65f20874d26d8f0d10f5c8c8728"}, - {file = "PySide6_Addons-6.3.0-cp36-abi3-win_amd64.whl", hash = "sha256:143228bde402426df9d2b97ac4d8de8e97b7c8d51c76362bcd439dc9e2ab3e86"}, + {file = "PySide6_Addons-6.3.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:7a6bb180e41a4c599aa0e93d11e60570d0ebc79c197afccd9c227566dad5d5ef"}, + {file = "PySide6_Addons-6.3.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:14f4171b15dbdd7d120dc125c84f2eca53bc197182295bfdfdb3bb95b58a46c7"}, + {file = "PySide6_Addons-6.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:9a933fac75c85bea3a9e31b24926e06b1afebae23cd164f10f2001999ea2692c"}, ] pyside6-essentials = [ - {file = "PySide6_Essentials-6.3.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:1c2a2a2b26fc923b3527907462ae5828b7e50a2c0fcf9923b086781af3911060"}, - {file = "PySide6_Essentials-6.3.0-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a486abe04be6270da798eae9c78b40f605008f19d5d9c880b1683783c715882d"}, - {file = "PySide6_Essentials-6.3.0-cp36-abi3-win_amd64.whl", hash = "sha256:7304353ab13cc9b5b0a86b3487f24b133a68c5b8c1312516510c0d49469f80d8"}, + {file = "PySide6_Essentials-6.3.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:55696693325a2de7bf5b56274b534f191032d218d61a948baa95933f6e642e59"}, + {file = "PySide6_Essentials-6.3.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e27962beb2cc45fe13a1a1c24a454c3c3c3c3082c4a84bc5dcf6b306979ba013"}, + {file = "PySide6_Essentials-6.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:fa825c5396a5dfedf59635e904239187e2f2225c7f65917d4e973062c9a6b916"}, ] pytest = [ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, ] +pytimeparse = [ + {file = "pytimeparse-1.1.8-py2.py3-none-any.whl", hash = "sha256:04b7be6cc8bd9f5647a6325444926c3ac34ee6bc7e69da4367ba282f076036bd"}, + {file = "pytimeparse-1.1.8.tar.gz", hash = "sha256:e86136477be924d7e670646a98561957e8ca7308d44841e21f5ddea757556a0a"}, +] requests = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, + {file = "requests-2.28.0-py3-none-any.whl", hash = "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f"}, + {file = "requests-2.28.0.tar.gz", hash = "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b"}, ] shiboken6 = [ - {file = "shiboken6-6.3.0-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:ead1cee2fea2566321e725a50070c40a9e67aaa015a20a84a39a9e72ff9b426e"}, - {file = "shiboken6-6.3.0-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e68e3cbb595c3047c4d893b84ef88eb5b23dea4e94241e80f5509dcb6613ad3d"}, - {file = "shiboken6-6.3.0-cp36-abi3-win_amd64.whl", hash = "sha256:096e6b2254e59729ae61acbb80d09c31ad7ea35b6624ec120c15a35b95c70b69"}, -] -typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "shiboken6-6.3.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:6393aa330101b098631a88dfb99b6b46794046c7f63b5c1ac93ae2fcef4773ff"}, + {file = "shiboken6-6.3.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:aad9aa8e7ecd3c889cc789e41abf3990101126b5b02edfcf87f1ef331c9dc45a"}, + {file = "shiboken6-6.3.1-cp36-abi3-win_amd64.whl", hash = "sha256:cb9cf4ad858e59237642bf6b8be1fe6f19cb090799ff00e4c2643768d73e8ebe"}, ] urllib3 = [ {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, @@ -355,7 +318,3 @@ wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] -zipp = [ - {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, - {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, -] diff --git a/pyproject.toml b/pyproject.toml index a1fcb3b..f386050 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ timebot = 'timebot.app:run' python = ">=3.8,<3.10" requests = "^2.27.1" PySide6 = "^6.3.0" +pytimeparse = "^1.1.8" [tool.poetry.dev-dependencies] pytest = "^5.2" diff --git a/timebot.ini.ex b/timebot.ini.ex index 8436d09..ae45097 100644 --- a/timebot.ini.ex +++ b/timebot.ini.ex @@ -1,3 +1,21 @@ [general] + +# The url to mobatime ... same as in Browser. (required!) baseurl=https://host/mobatime/ -system_ca_store=/etc/ssl/certs/ca-certificates.crt + +# The mobatime user to log in. Can also be set by using `-u` on cmdline. (required!) +mobatime_user=hansi + +# Wether to uses the systems CA store or not. Same as `-a` on cmdline. (default: no) +#use_system_ca_store=no + +# Location of the systems CA store. (default: /etc/ssl/certs/ca-certificates.crt) +#system_ca_store=/etc/ssl/certs/ca-certificates.crt + +# Wether to save the session cookies in `./.kekse` or not. (default: no) +#save_cookies=no + +[gui] + +# The Mobatime api refresh interval. (default: 1m) +#refresh_interval=1m diff --git a/timebot/app.py b/timebot/app.py index d1bb45d..f843d88 100644 --- a/timebot/app.py +++ b/timebot/app.py @@ -16,7 +16,7 @@ logging.basicConfig(level=logging.INFO) def run(): parser = argparse.ArgumentParser() parser.add_argument("-v", help="enable debug logging", action="store_true") - parser.add_argument("-u", help="mobatime login user", required=True) + parser.add_argument("-u", help="mobatime login user", default=None) parser.add_argument("-p", help="mobatime login user password", default=None) parser.add_argument("-c", help="config file", default="timebot.ini") parser.add_argument("-a", "--use-system-ca-store", help="use system ca store for ssl connections", @@ -68,12 +68,20 @@ def run(): config = configparser.ConfigParser() config.read(args.c) - if args.use_system_ca_store: + if args.use_system_ca_store or config.get(section="general", option="use_system_ca_store", fallback="no") == "yes": os.environ["REQUESTS_CA_BUNDLE"] = config["general"]["system_ca_store"] \ if "system_ca_store" in config["general"] else "/etc/ssl/certs/ca-certificates.crt" - ma = MobatimeApi(baseurl=config["general"]["baseurl"], user=args.u, password=args.p, ask_for_password=True, - save_session=args.save_cookies) + user = args.u if args.u is not None else config.get(section="general", option="mobatime_user", fallback=None) + if user is None: + logger.fatal("could not get username for mobatime...") + sys.exit(1) + + save_cookies = True if args.save_cookies is True else config.get(section="general", option="save_cookies", + fallback="no") == "yes" + + ma = MobatimeApi(baseurl=config["general"]["baseurl"], user=user, password=args.p, ask_for_password=True, + save_session=save_cookies) tb = TimeBot(mobatime_api=ma) if args.subparser_name == "punch": if args.s == "now": @@ -110,7 +118,9 @@ def run(): from timebot.gui import TimebotMainWindow signal.signal(signal.SIGINT, lambda *_args: QApplication.quit()) app = QApplication(sys.argv) - main_window = TimebotMainWindow(timebot=tb) + main_window = TimebotMainWindow(timebot=tb, refresh_interval=config.get(section="gui", + option="refresh_interval", + fallback="1m")) main_window.show() sys.exit(app.exec()) else: diff --git a/timebot/gui.py b/timebot/gui.py index 79fe1a0..99775d6 100644 --- a/timebot/gui.py +++ b/timebot/gui.py @@ -9,6 +9,8 @@ from PySide6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QMessag from timebot.timebot import TimeBot, TimebotObtainPasswordError +from pytimeparse.timeparse import timeparse + package_logger = logging.getLogger(__name__) @@ -55,7 +57,7 @@ class HoursPresentLabelArea(QWidget): class TimebotMainWindow(QWidget): - def __init__(self, timebot: TimeBot, parent=None): + def __init__(self, timebot: TimeBot, refresh_interval="1m", parent=None): super().__init__(parent) self.timebot = timebot @@ -79,7 +81,7 @@ class TimebotMainWindow(QWidget): self.btn_update_status.clicked.connect(self.update_status) - self.status_timer_time = 60000 # msec -> 60s + self.status_timer_time = timeparse(refresh_interval) * 1000 self.status_timer = QTimer() self.status_timer.timeout.connect(self.update_status) self.status_timer.start(self.status_timer_time)