cmem-cmemc 24.1.1rc1__tar.gz → 24.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. cmem_cmemc-24.1.3/PKG-INFO +87 -0
  2. cmem_cmemc-24.1.3/README-public.md +36 -0
  3. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/__init__.py +4 -9
  4. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/__init__.py +1 -0
  5. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/admin.py +4 -6
  6. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/config.py +1 -0
  7. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/dataset.py +2 -1
  8. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/graph.py +1 -0
  9. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/project.py +1 -0
  10. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/python.py +5 -0
  11. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/query.py +1 -0
  12. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/resource.py +1 -0
  13. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/scheduler.py +1 -0
  14. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/store.py +1 -0
  15. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/user.py +1 -0
  16. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/validation.py +7 -6
  17. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/variable.py +1 -0
  18. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/vocabulary.py +11 -10
  19. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/workflow.py +6 -5
  20. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/workspace.py +1 -0
  21. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/completion.py +1 -0
  22. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/constants.py +1 -0
  23. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/context.py +16 -10
  24. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/manual_helper/graph.py +1 -0
  25. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/manual_helper/multi_page.py +1 -0
  26. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/object_list.py +1 -0
  27. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/utils.py +21 -2
  28. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/pyproject.toml +23 -4
  29. cmem_cmemc-24.1.1rc1/PKG-INFO +0 -68
  30. cmem_cmemc-24.1.1rc1/README-public.md +0 -23
  31. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/LICENSE +0 -0
  32. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/_cmemc.zsh +0 -0
  33. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/acl.py +0 -0
  34. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/client.py +0 -0
  35. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/commands/metrics.py +0 -0
  36. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/exceptions.py +0 -0
  37. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/manual_helper/__init__.py +0 -0
  38. {cmem_cmemc-24.1.1rc1 → cmem_cmemc-24.1.3}/cmem_cmemc/manual_helper/single_page.py +0 -0
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.1
2
+ Name: cmem-cmemc
3
+ Version: 24.1.3
4
+ Summary: Command line client for eccenca Corporate Memory
5
+ Home-page: https://eccenca.com/go/cmemc
6
+ License: Apache 2.0
7
+ Author: eccenca
8
+ Author-email: cmempy-developer@eccenca.com
9
+ Requires-Python: >=3.9,<4.0
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Customer Service
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Information Technology
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: License :: OSI Approved :: Apache Software License
18
+ Classifier: License :: Other/Proprietary License
19
+ Classifier: Natural Language :: English
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3 :: Only
27
+ Classifier: Topic :: Database
28
+ Classifier: Topic :: Software Development :: Testing
29
+ Classifier: Topic :: Utilities
30
+ Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
31
+ Requires-Dist: certifi (>=2023.5.7)
32
+ Requires-Dist: click (>=8.1.7,<9.0.0)
33
+ Requires-Dist: click-didyoumean (>=0.3.0,<0.4.0)
34
+ Requires-Dist: click-help-colors (>=0.9.1,<0.10.0)
35
+ Requires-Dist: cmem-cmempy (==24.1.1)
36
+ Requires-Dist: configparser (>=5.3.0,<6.0.0)
37
+ Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
38
+ Requires-Dist: natsort (>=8.3.1,<9.0.0)
39
+ Requires-Dist: prometheus-client (>=0.16.0,<0.17.0)
40
+ Requires-Dist: pygments (>=2.15.1,<3.0.0)
41
+ Requires-Dist: pyjwt (>=2.7.0,<3.0.0)
42
+ Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
43
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
44
+ Requires-Dist: rich (>=13.7.0,<14.0.0)
45
+ Requires-Dist: six (>=1.16.0,<2.0.0)
46
+ Requires-Dist: timeago (>=1.0.16,<2.0.0)
47
+ Requires-Dist: treelib (>=1.6.4,<2.0.0)
48
+ Requires-Dist: urllib3 (>=2,<3)
49
+ Description-Content-Type: text/markdown
50
+
51
+ # cmemc
52
+
53
+ cmemc is the official command line client for [eccenca Corporate Memory](https://documentation.eccenca.com/).
54
+
55
+ [![version][version-shield]][changelog] [![Python Versions][python-shield]][pypi] [![eccenca Corporate Memory][cmem-shield]][cmem]
56
+
57
+ [![teaser][teaser-image]][cmemc-docu]
58
+
59
+ ## Installation
60
+
61
+ In order to install the cmemc, run:
62
+
63
+ pipx install cmem-cmemc
64
+
65
+ Of course you can install cmemc also with pip, but we recommend [pipx](https://pypa.github.io/pipx/) for normal desktop usage.
66
+
67
+ ## Configuration and Usage
68
+
69
+ cmemc is intended for System Administrators and Linked Data Expert, who wants to automate and remote control activities on eccenca Corporate Memory.
70
+
71
+ The cmemc manual including basic usage pattern, configuration as well as a command reference is available at:
72
+
73
+ [https://eccenca.com/go/cmemc](https://eccenca.com/go/cmemc)
74
+
75
+ cmemc only works with Python 3 and refuses to work with Python 2.x.
76
+ In addition to that, cmemc will warn you in case an untested Python environment is used.
77
+
78
+
79
+ [version-shield]: https://badge.fury.io/py/cmem-cmemc.svg
80
+ [changelog]: https://pypi.org/project/cmem-cmemc/#history
81
+ [python-shield]: https://img.shields.io/pypi/pyversions/cmem-cmemc.svg
82
+ [pypi]: https://pypi.org/project/cmem-cmemc/
83
+ [cmem]: https://documentation.eccenca.com
84
+ [cmem-shield]: https://img.shields.io/badge/made%20for-eccenca%20Corporate%20Memory-blue?logo=data:image/svg%2bxml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgaWQ9IkxheWVyXzEiCiAgIGRhdGEtbmFtZT0iTGF5ZXIgMSIKICAgdmlld0JveD0iMCAwIDgxLjI5MDAwMSA4Mi4yODk4NiIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iODEuMjkwMDAxIgogICBoZWlnaHQ9IjgyLjI4OTg2NCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzODI2Ij4KICAgIDxzdHlsZQogICAgICAgaWQ9InN0eWxlODI0Ij4KICAgICAgLmNscy0xIHsKICAgICAgICBmaWxsOiAjZjM5MjAwOwogICAgICB9CgogICAgICAuY2xzLTIgewogICAgICAgIGZpbGw6IG5vbmU7CiAgICAgICAgc3Ryb2tlOiAjZjM5MjAwOwogICAgICAgIHN0cm9rZS13aWR0aDogMS41cHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxnCiAgICAgaWQ9Imc4NDAiCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMwLjc2LC0zMS4xNDAxMzkpIj4KICAgIDxwYXRoCiAgICAgICBjbGFzcz0iY2xzLTEiCiAgICAgICBkPSJNIDU1LjksODUuMTkgQSAyMC4xNCwyMC4xNCAwIDEgMCAzNS43Niw2NS4wNSAyMC4xNCwyMC4xNCAwIDAgMCA1NS45LDg1LjE5IFoiCiAgICAgICBpZD0icGF0aDgyOCIgLz4KICAgIDxwYXRoCiAgICAgICBjbGFzcz0iY2xzLTEiCiAgICAgICBkPSJtIDk4LDU0LjE0IGEgOSw5IDAgMSAwIC04Ljk1LC05IDguOTUsOC45NSAwIDAgMCA4Ljk1LDkgeiIKICAgICAgIGlkPSJwYXRoODMwIiAvPgogICAgPHBhdGgKICAgICAgIGNsYXNzPSJjbHMtMSIKICAgICAgIGQ9Ik0gODguMzUsMTA4LjQzIEEgMTIuMzEsMTIuMzEgMCAxIDAgNzYsOTYuMTIgMTIuMzEsMTIuMzEgMCAwIDAgODguMzEsMTA4LjQzIFoiCiAgICAgICBpZD0icGF0aDgzMiIgLz4KICAgIDxsaW5lCiAgICAgICBjbGFzcz0iY2xzLTIiCiAgICAgICB4MT0iODYuOTcwMDAxIgogICAgICAgeTE9IjkyLjA1OTk5OCIKICAgICAgIHgyPSI1OC43Nzk5OTkiCiAgICAgICB5Mj0iNjcuMzYwMDAxIgogICAgICAgaWQ9ImxpbmU4MzQiIC8+CiAgICA8bGluZQogICAgICAgY2xhc3M9ImNscy0yIgogICAgICAgeDE9Ijk5LjE4IgogICAgICAgeTE9IjQ1Ljg0IgogICAgICAgeDI9IjU1LjQ4IgogICAgICAgeTI9IjY2LjEyMDAwMyIKICAgICAgIGlkPSJsaW5lODM2IiAvPgogICAgPGxpbmUKICAgICAgIGNsYXNzPSJjbHMtMiIKICAgICAgIHgxPSI5Ny45ODk5OTgiCiAgICAgICB5MT0iNDQuNjUwMDAyIgogICAgICAgeDI9Ijg4LjM0OTk5OCIKICAgICAgIHkyPSI5Mi44Mzk5OTYiCiAgICAgICBpZD0ibGluZTgzOCIgLz4KICA8L2c+Cjwvc3ZnPgo=
85
+ [teaser-image]: https://documentation.eccenca.com/24.1/automate/cmemc-command-line-interface/configuration/completion-setup/22.1-cmemc-create-dataset.gif
86
+ [cmemc-docu]: https://eccenca.com/go/cmemc
87
+
@@ -0,0 +1,36 @@
1
+ # cmemc
2
+
3
+ cmemc is the official command line client for [eccenca Corporate Memory](https://documentation.eccenca.com/).
4
+
5
+ [![version][version-shield]][changelog] [![Python Versions][python-shield]][pypi] [![eccenca Corporate Memory][cmem-shield]][cmem]
6
+
7
+ [![teaser][teaser-image]][cmemc-docu]
8
+
9
+ ## Installation
10
+
11
+ In order to install the cmemc, run:
12
+
13
+ pipx install cmem-cmemc
14
+
15
+ Of course you can install cmemc also with pip, but we recommend [pipx](https://pypa.github.io/pipx/) for normal desktop usage.
16
+
17
+ ## Configuration and Usage
18
+
19
+ cmemc is intended for System Administrators and Linked Data Expert, who wants to automate and remote control activities on eccenca Corporate Memory.
20
+
21
+ The cmemc manual including basic usage pattern, configuration as well as a command reference is available at:
22
+
23
+ [https://eccenca.com/go/cmemc](https://eccenca.com/go/cmemc)
24
+
25
+ cmemc only works with Python 3 and refuses to work with Python 2.x.
26
+ In addition to that, cmemc will warn you in case an untested Python environment is used.
27
+
28
+
29
+ [version-shield]: https://badge.fury.io/py/cmem-cmemc.svg
30
+ [changelog]: https://pypi.org/project/cmem-cmemc/#history
31
+ [python-shield]: https://img.shields.io/pypi/pyversions/cmem-cmemc.svg
32
+ [pypi]: https://pypi.org/project/cmem-cmemc/
33
+ [cmem]: https://documentation.eccenca.com
34
+ [cmem-shield]: https://img.shields.io/badge/made%20for-eccenca%20Corporate%20Memory-blue?logo=data:image/svg%2bxml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgaWQ9IkxheWVyXzEiCiAgIGRhdGEtbmFtZT0iTGF5ZXIgMSIKICAgdmlld0JveD0iMCAwIDgxLjI5MDAwMSA4Mi4yODk4NiIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iODEuMjkwMDAxIgogICBoZWlnaHQ9IjgyLjI4OTg2NCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzODI2Ij4KICAgIDxzdHlsZQogICAgICAgaWQ9InN0eWxlODI0Ij4KICAgICAgLmNscy0xIHsKICAgICAgICBmaWxsOiAjZjM5MjAwOwogICAgICB9CgogICAgICAuY2xzLTIgewogICAgICAgIGZpbGw6IG5vbmU7CiAgICAgICAgc3Ryb2tlOiAjZjM5MjAwOwogICAgICAgIHN0cm9rZS13aWR0aDogMS41cHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxnCiAgICAgaWQ9Imc4NDAiCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMwLjc2LC0zMS4xNDAxMzkpIj4KICAgIDxwYXRoCiAgICAgICBjbGFzcz0iY2xzLTEiCiAgICAgICBkPSJNIDU1LjksODUuMTkgQSAyMC4xNCwyMC4xNCAwIDEgMCAzNS43Niw2NS4wNSAyMC4xNCwyMC4xNCAwIDAgMCA1NS45LDg1LjE5IFoiCiAgICAgICBpZD0icGF0aDgyOCIgLz4KICAgIDxwYXRoCiAgICAgICBjbGFzcz0iY2xzLTEiCiAgICAgICBkPSJtIDk4LDU0LjE0IGEgOSw5IDAgMSAwIC04Ljk1LC05IDguOTUsOC45NSAwIDAgMCA4Ljk1LDkgeiIKICAgICAgIGlkPSJwYXRoODMwIiAvPgogICAgPHBhdGgKICAgICAgIGNsYXNzPSJjbHMtMSIKICAgICAgIGQ9Ik0gODguMzUsMTA4LjQzIEEgMTIuMzEsMTIuMzEgMCAxIDAgNzYsOTYuMTIgMTIuMzEsMTIuMzEgMCAwIDAgODguMzEsMTA4LjQzIFoiCiAgICAgICBpZD0icGF0aDgzMiIgLz4KICAgIDxsaW5lCiAgICAgICBjbGFzcz0iY2xzLTIiCiAgICAgICB4MT0iODYuOTcwMDAxIgogICAgICAgeTE9IjkyLjA1OTk5OCIKICAgICAgIHgyPSI1OC43Nzk5OTkiCiAgICAgICB5Mj0iNjcuMzYwMDAxIgogICAgICAgaWQ9ImxpbmU4MzQiIC8+CiAgICA8bGluZQogICAgICAgY2xhc3M9ImNscy0yIgogICAgICAgeDE9Ijk5LjE4IgogICAgICAgeTE9IjQ1Ljg0IgogICAgICAgeDI9IjU1LjQ4IgogICAgICAgeTI9IjY2LjEyMDAwMyIKICAgICAgIGlkPSJsaW5lODM2IiAvPgogICAgPGxpbmUKICAgICAgIGNsYXNzPSJjbHMtMiIKICAgICAgIHgxPSI5Ny45ODk5OTgiCiAgICAgICB5MT0iNDQuNjUwMDAyIgogICAgICAgeDI9Ijg4LjM0OTk5OCIKICAgICAgIHkyPSI5Mi44Mzk5OTYiCiAgICAgICBpZD0ibGluZTgzOCIgLz4KICA8L2c+Cjwvc3ZnPgo=
35
+ [teaser-image]: https://documentation.eccenca.com/24.1/automate/cmemc-command-line-interface/configuration/completion-setup/22.1-cmemc-create-dataset.gif
36
+ [cmemc-docu]: https://eccenca.com/go/cmemc
@@ -1,4 +1,5 @@
1
1
  """The main command line interface."""
2
+
2
3
  import contextlib
3
4
  import os
4
5
  import sys
@@ -26,7 +27,7 @@ from cmem_cmemc.exceptions import InvalidConfigurationError
26
27
  from cmem_cmemc.manual_helper.graph import print_manual_graph
27
28
  from cmem_cmemc.manual_helper.multi_page import create_multi_page_documentation
28
29
  from cmem_cmemc.manual_helper.single_page import print_manual
29
- from cmem_cmemc.utils import extract_error_message, get_version
30
+ from cmem_cmemc.utils import check_python_version, extract_error_message, get_version
30
31
 
31
32
  CMEMC_VERSION = get_version()
32
33
 
@@ -38,16 +39,10 @@ if os.environ.get("_CMEMC_COMPLETE", "") == "zsh_source":
38
39
 
39
40
  version = sys.version_info
40
41
  PYTHON_VERSION = f"{version.major}.{version.minor}.{version.micro}"
41
- PYTHON_EXPECTED = "3.11"
42
- PYTHON_GOT = f"{version.major}.{version.minor}"
43
- if PYTHON_EXPECTED != PYTHON_GOT and not CONTEXT.is_completing():
44
- CONTEXT.echo_warning(
45
- "Warning: You are running cmemc under a non-tested python "
46
- f"environment (expected {PYTHON_EXPECTED}, got {PYTHON_GOT})"
47
- )
42
+ check_python_version(ctx=CONTEXT)
48
43
 
49
44
  # set the user-agent environment for the http request headers
50
- os.environ["CMEM_USER_AGENT"] = f"cmemc/{CMEMC_VERSION} " f"(Python {PYTHON_VERSION})"
45
+ os.environ["CMEM_USER_AGENT"] = f"cmemc/{CMEMC_VERSION} (Python {PYTHON_VERSION})"
51
46
 
52
47
  # https://github.com/pallets/click/blob/master/examples/complex/complex/cli.py
53
48
  CONTEXT_SETTINGS = {"auto_envvar_prefix": "CMEMC", "help_option_names": ["-h", "--help"]}
@@ -1,4 +1,5 @@
1
1
  """cmemc commands."""
2
+
2
3
  from click_didyoumean import DYMGroup
3
4
  from click_help_colors import HelpColorsCommand, HelpColorsGroup
4
5
 
@@ -1,5 +1,6 @@
1
1
  """admin commands for cmem command line interface."""
2
- from datetime import UTC, datetime
2
+
3
+ from datetime import datetime, timezone
3
4
 
4
5
  import click
5
6
  import jwt
@@ -41,12 +42,9 @@ def _check_graphdb_license(app: ApplicationContext, data: dict, months: int, exi
41
42
  # DP < 24.1 has no graph license information here
42
43
  return
43
44
  expiration_date_str = data["dp"]["info"]["store"]["licenseExpiration"]
44
- if expiration_date_str == "1970-01-01":
45
- # DP = 24.1 outputs this for GraphDB free ...¯\_(ツ)_/¯
46
- return
47
- expiration_date = datetime.strptime(expiration_date_str, "%Y-%m-%d").astimezone(tz=UTC)
45
+ expiration_date = datetime.strptime(expiration_date_str, "%Y-%m-%d").astimezone(tz=timezone.utc)
48
46
  grace_starts = expiration_date - relativedelta(months=months)
49
- if grace_starts < datetime.now(tz=UTC):
47
+ if grace_starts < datetime.now(tz=timezone.utc):
50
48
  graphdb_license_end = data["dp"]["info"]["store"]["licenseExpiration"]
51
49
  output = f"Your GraphDB license expires on {graphdb_license_end}."
52
50
  if exit_1 == "always":
@@ -1,4 +1,5 @@
1
1
  """configuration commands for cmem command line interface."""
2
+
2
3
  import click
3
4
 
4
5
  from cmem_cmemc.commands import CmemcCommand, CmemcGroup
@@ -1,4 +1,5 @@
1
1
  """dataset commands for cmem command line interface."""
2
+
2
3
  import json
3
4
  import re
4
5
  from pathlib import Path
@@ -284,7 +285,7 @@ def _check_or_set_dataset_type(
284
285
 
285
286
  """
286
287
  source = Path(dataset_file).name if dataset_file else ""
287
- target = parameter_dict["file"] if "file" in parameter_dict else ""
288
+ target = parameter_dict.get("file", "")
288
289
  suggestions = (
289
290
  (".ttl", "file"),
290
291
  (".csv", "csv"),
@@ -1,4 +1,5 @@
1
1
  """graph commands for cmem command line interface."""
2
+
2
3
  import hashlib
3
4
  import json
4
5
  import os
@@ -1,4 +1,5 @@
1
1
  """DataIntegration project commands for the cmem command line interface."""
2
+
2
3
  import os
3
4
  import shutil
4
5
  import tempfile
@@ -1,4 +1,5 @@
1
1
  """DataIntegration python management commands."""
2
+
2
3
  import sys
3
4
  from dataclasses import asdict
4
5
  from re import match
@@ -49,6 +50,10 @@ def install_command(app: ApplicationContext, package: str) -> None:
49
50
  .tar.gz file, by uploading a build distribution .whl file, or by
50
51
  specifying a package name, i.e., a pip requirement specifier with a
51
52
  package name available on pypi.org (e.g. `requests==2.27.1`).
53
+
54
+ Note: The tab-completion of this command lists only public packages from
55
+ pypi.org and not from additional or changed python package repositories you
56
+ may have configured on the server.
52
57
  """
53
58
  app.echo_info(f"Install package {package} ... ", nl=False)
54
59
  try:
@@ -1,4 +1,5 @@
1
1
  """query commands for cmem command line interface."""
2
+
2
3
  import json
3
4
  import sys
4
5
  from hashlib import sha1
@@ -1,4 +1,5 @@
1
1
  """DataIntegration dataset resource commands for cmemc."""
2
+
2
3
  import re
3
4
 
4
5
  import click
@@ -1,4 +1,5 @@
1
1
  """DataIntegration scheduler commands for the cmem command line interface."""
2
+
2
3
  from typing import Any
3
4
 
4
5
  import click
@@ -1,4 +1,5 @@
1
1
  """DataPlatform store commands for the cmem command line interface."""
2
+
2
3
  import os
3
4
  from pathlib import Path
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Keycloak user management commands"""
2
+
2
3
  import sys
3
4
  from getpass import getpass
4
5
 
@@ -1,6 +1,7 @@
1
1
  """graph validation command group"""
2
+
2
3
  import time
3
- from datetime import UTC, datetime
4
+ from datetime import datetime, timezone
4
5
 
5
6
  import click
6
7
  import requests
@@ -144,8 +145,8 @@ def _get_batch_validation_option(validation_: dict) -> tuple[str, str]:
144
145
  id_ = validation_["id"]
145
146
  state = validation_["state"]
146
147
  graph = validation_["contextGraphIri"]
147
- stamp = datetime.fromtimestamp(validation_["executionStarted"] / 1000, tz=UTC)
148
- time_ago = timeago.format(stamp, datetime.now(tz=UTC))
148
+ stamp = datetime.fromtimestamp(validation_["executionStarted"] / 1000, tz=timezone.utc)
149
+ time_ago = timeago.format(stamp, datetime.now(tz=timezone.utc))
149
150
  resources = _get_resource_count(validation_)
150
151
  violations = _get_violation_count(validation_)
151
152
  return (
@@ -295,7 +296,7 @@ def _get_resource_count(batch_validation: dict) -> str:
295
296
 
296
297
  def _get_violation_count(process_data: dict) -> str:
297
298
  """Get violation count from validation report"""
298
- if process_data.get("executionStarted", None) is None:
299
+ if process_data.get("executionStarted") is None:
299
300
  return "-"
300
301
  resources = str(process_data.get("resourcesWithViolationsCount", "0"))
301
302
  violations = str(process_data.get("violationsCount", "0"))
@@ -408,8 +409,8 @@ def list_command(ctx: Context, filter_: tuple[tuple[str, str]], id_only: bool, r
408
409
  table = []
409
410
  for _ in validations:
410
411
  if "executionStarted" in _ and _["executionStarted"] is not None:
411
- stamp = datetime.fromtimestamp(_["executionStarted"] / 1000, tz=UTC)
412
- time_ago = timeago.format(stamp, datetime.now(tz=UTC))
412
+ stamp = datetime.fromtimestamp(_["executionStarted"] / 1000, tz=timezone.utc)
413
+ time_ago = timeago.format(stamp, datetime.now(tz=timezone.utc))
413
414
  else:
414
415
  time_ago = f"{_['state']}"
415
416
  row = [
@@ -1,4 +1,5 @@
1
1
  """DataIntegration variable commands for cmemc."""
2
+
2
3
  import re
3
4
 
4
5
  import click
@@ -1,6 +1,7 @@
1
1
  """vocabularies commands for cmem command line interface."""
2
+
2
3
  import io
3
- from datetime import UTC, datetime
4
+ from datetime import datetime, timezone
4
5
  from re import match
5
6
  from urllib.parse import urlparse
6
7
 
@@ -140,7 +141,7 @@ def _insert_catalog_entry(iri: str, prefix: str, namespace: str, label: str, lan
140
141
  iri=iri,
141
142
  prefix=prefix,
142
143
  namespace=namespace,
143
- date=datetime.now(tz=UTC).date(),
144
+ date=datetime.now(tz=timezone.utc).date(),
144
145
  label=label,
145
146
  language=language,
146
147
  description="vocabulary imported with cmemc",
@@ -150,7 +151,7 @@ def _insert_catalog_entry(iri: str, prefix: str, namespace: str, label: str, lan
150
151
 
151
152
 
152
153
  def _get_vocabulary_metadata_from_file(
153
- file: io.StringIO, namespace_given: bool = False
154
+ file: io.BytesIO, namespace_given: bool = False
154
155
  ) -> dict[str, str]:
155
156
  """Get potential graph iri and prefix/namespace from a turtle file."""
156
157
  metadata = {"iri": "", "prefix": "", "namespace": ""}
@@ -345,19 +346,19 @@ def import_command(
345
346
  description which correctly uses the `vann:preferredNamespacePrefix` and
346
347
  `vann:preferredNamespaceUri` properties.
347
348
  """
348
- string_buffer = io.StringIO()
349
+ _buffer = io.BytesIO()
349
350
  with click.open_file(file, "rb") as file_handle:
350
- string_buffer.write(file_handle.read().decode("utf-8"))
351
- string_buffer.seek(0)
351
+ _buffer.write(file_handle.read())
352
+ _buffer.seek(0)
352
353
 
353
354
  # fetch metadata
354
355
  if namespace != (None, None):
355
356
  _validate_namespace(app, namespace)
356
- meta_data = _get_vocabulary_metadata_from_file(string_buffer, True)
357
+ meta_data = _get_vocabulary_metadata_from_file(_buffer, True)
357
358
  meta_data["prefix"] = namespace[0] # type: ignore[assignment]
358
359
  meta_data["namespace"] = namespace[1] # type: ignore[assignment]
359
360
  else:
360
- meta_data = _get_vocabulary_metadata_from_file(string_buffer, False)
361
+ meta_data = _get_vocabulary_metadata_from_file(_buffer, False)
361
362
  iri = meta_data["iri"]
362
363
 
363
364
  success_message = "done"
@@ -368,8 +369,8 @@ def import_command(
368
369
  raise ValueError(f"Proposed graph {iri} does already exist.")
369
370
  app.echo_info(f"Import {file} as vocabulary to {iri} ... ", nl=False)
370
371
  # upload graph
371
- string_buffer.seek(0)
372
- graph_api.post_streamed(iri, string_buffer, replace=True)
372
+ _buffer.seek(0)
373
+ graph_api.post_streamed(iri, _buffer, replace=True)
373
374
 
374
375
  # resolve label
375
376
  resolved_label_object: dict = resolve([iri], graph=iri)[iri]
@@ -1,8 +1,9 @@
1
1
  """workflow commands for cmem command line interface."""
2
+
2
3
  import re
3
4
  import sys
4
5
  import time
5
- from datetime import UTC, datetime
6
+ from datetime import datetime, timezone
6
7
  from pathlib import Path
7
8
 
8
9
  import click
@@ -319,8 +320,8 @@ def _workflow_echo_status(app: ApplicationContext, status: dict) -> None:
319
320
  canceled only exists sometimes
320
321
  """
321
322
  # prepare human friendly relative time
322
- now = datetime.now(tz=UTC)
323
- stamp = datetime.fromtimestamp(status["lastUpdateTime"] / 1000, tz=UTC)
323
+ now = datetime.now(tz=timezone.utc)
324
+ stamp = datetime.fromtimestamp(status["lastUpdateTime"] / 1000, tz=timezone.utc)
324
325
  time_ago = timeago.format(stamp, now, "en")
325
326
  status_name = status["statusName"]
326
327
  status_message = status["message"]
@@ -338,9 +339,9 @@ def _workflow_echo_status(app: ApplicationContext, status: dict) -> None:
338
339
  f"statusName is {status_name}, expecting one of: " "Running, Canceling or Waiting."
339
340
  )
340
341
  # not running can be Idle or Finished
341
- if "failed" in status and status["failed"]:
342
+ if status.get("failed"):
342
343
  app.echo_error(message, nl=True, err=False)
343
- elif "cancelled" in status and status["cancelled"]:
344
+ elif status.get("cancelled"):
344
345
  app.echo_warning(message)
345
346
  elif status["statusName"] == "Idle":
346
347
  app.echo_info(message)
@@ -1,4 +1,5 @@
1
1
  """workspace commands for cmem command line interface."""
2
+
2
3
  import os
3
4
  from pathlib import Path
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Utility functions for CLI auto-completion functionality."""
2
+
2
3
  # ruff: noqa: ARG001
3
4
  import os
4
5
  from contextlib import suppress
@@ -1,4 +1,5 @@
1
1
  """cmemc constants"""
2
+
2
3
  NAMESPACES = {
3
4
  "void": "http://rdfs.org/ns/void#",
4
5
  "di": "https://vocab.eccenca.com/di/",
@@ -1,11 +1,12 @@
1
1
  """The main command line interface."""
2
+
2
3
  import ast
3
4
  import configparser
4
5
  import json
5
6
  import os
6
7
  import re
7
8
  import subprocess # nosec
8
- from datetime import UTC, datetime
9
+ from datetime import datetime, timezone
9
10
  from os import environ as env
10
11
  from os import getenv
11
12
  from pathlib import Path
@@ -21,6 +22,7 @@ from pygments.lexers import get_lexer_by_name
21
22
  from rich import box
22
23
  from rich.console import Console
23
24
  from rich.table import Table
25
+ from urllib3.exceptions import InsecureRequestWarning
24
26
 
25
27
  from cmem_cmemc.exceptions import InvalidConfigurationError
26
28
 
@@ -47,6 +49,8 @@ KNOWN_CONFIG_KEYS = {
47
49
 
48
50
  KNOWN_SECRET_KEYS = ("OAUTH_PASSWORD", "OAUTH_CLIENT_SECRET", "OAUTH_ACCESS_TOKEN")
49
51
 
52
+ SSL_VERIFY_WARNING = "SSL verification is disabled (SSL_VERIFY=False)."
53
+
50
54
 
51
55
  class ApplicationContext:
52
56
  """Context of the command line interface."""
@@ -90,7 +94,7 @@ class ApplicationContext:
90
94
  def get_template_data(self) -> dict[str, str]:
91
95
  """Get the template data dict with vars from the context."""
92
96
  data: dict[str, str] = {}
93
- today = str(datetime.now(tz=UTC).date())
97
+ today = str(datetime.now(tz=timezone.utc).date())
94
98
  data.update(date=today)
95
99
  if self.connection is not None:
96
100
  data.update(connection=self.connection.name)
@@ -142,12 +146,6 @@ class ApplicationContext:
142
146
  self.set_credential_from_process(_, _ + "_PROCESS", config)
143
147
 
144
148
  self.echo_debug(f"CA bundle loaded from {cmempy_config.get_requests_ca_bundle()}")
145
- # If cert validation is disabled, output a warning
146
- # Also disable library warnings:
147
- # https://urllib3.readthedocs.io/en/latest/advanced-usage.html
148
- if not cmempy_config.get_ssl_verify():
149
- self.echo_warning("SSL verification is disabled (SSL_VERIFY=False).")
150
- urllib3.disable_warnings()
151
149
  return
152
150
 
153
151
  def set_connection_from_params(self, params: dict) -> None:
@@ -192,7 +190,7 @@ class ApplicationContext:
192
190
  self.config = self.get_config()
193
191
  self.connection = None
194
192
  if section_string is None or section_string == "":
195
- self.echo_debug("No config given, use API default connection.")
193
+ self.echo_debug("No config given, use API defaults or environment connection.")
196
194
  elif section_string not in self.config:
197
195
  raise InvalidConfigurationError(
198
196
  f"There is no connection '{section_string}' configured in "
@@ -202,6 +200,14 @@ class ApplicationContext:
202
200
  self.echo_debug(f"Use connection config: {section_string}")
203
201
  self.connection = self.config[section_string]
204
202
  self.configure_cmempy(self.connection)
203
+
204
+ # If cert validation is disabled, output a warning
205
+ # Also disable library warnings:
206
+ # https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
207
+ if not cmempy_config.get_ssl_verify():
208
+ self.echo_warning(SSL_VERIFY_WARNING)
209
+ urllib3.disable_warnings(category=InsecureRequestWarning)
210
+
205
211
  return self.connection
206
212
 
207
213
  def get_config_file(self) -> Path:
@@ -262,7 +268,7 @@ class ApplicationContext:
262
268
  """Output a debug message if --debug is enabled."""
263
269
  # pylint: disable=invalid-name
264
270
  if self.debug:
265
- now = datetime.now(tz=UTC)
271
+ now = datetime.now(tz=timezone.utc)
266
272
  click.secho(f"[{now!s}] {message}", err=True, dim=True)
267
273
 
268
274
  def echo_info(self, message: str | list[str] | set[str], nl: bool = True, fg: str = "") -> None:
@@ -1,4 +1,5 @@
1
1
  """Generate a help text and command structure graph."""
2
+
2
3
  import contextlib
3
4
 
4
5
  import click.core
@@ -1,4 +1,5 @@
1
1
  """Generate a multi page documentation for documentation.eccenca.com."""
2
+
2
3
  import re
3
4
  from pathlib import Path
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Filterable object list."""
2
+
2
3
  import re
3
4
  from abc import ABC, abstractmethod
4
5
  from collections.abc import Callable
@@ -1,10 +1,12 @@
1
1
  """Utility functions for CLI interface."""
2
+
2
3
  import json
3
4
  import os
4
5
  import re
6
+ import sys
5
7
  import unicodedata
6
8
  from dataclasses import dataclass
7
- from importlib.metadata import version
9
+ from importlib.metadata import version as cmemc_version
8
10
  from pathlib import Path
9
11
 
10
12
  import requests
@@ -21,7 +23,22 @@ from cmem_cmemc.context import ApplicationContext
21
23
 
22
24
  def get_version() -> str:
23
25
  """Get the current version or SNAPSHOT."""
24
- return version("cmem-cmemc")
26
+ return cmemc_version("cmem-cmemc")
27
+
28
+
29
+ def check_python_version(ctx: ApplicationContext) -> None:
30
+ """Check the runtime python version and warn or error."""
31
+ version = sys.version_info
32
+ major_expected = [3]
33
+ minor_expected = [10, 11, 12]
34
+ if version.major not in major_expected:
35
+ ctx.echo_error(f"Error: cmemc can not be executed with Python {version.major}.")
36
+ sys.exit(1)
37
+ if version.minor not in minor_expected and not ctx.is_completing():
38
+ ctx.echo_warning(
39
+ "Warning: You are running cmemc under a non-tested python "
40
+ f"environment ({version.major}.{version.minor})."
41
+ )
25
42
 
26
43
 
27
44
  def extract_error_message(error: Exception) -> str:
@@ -295,6 +312,8 @@ def get_published_packages() -> list[PublishedPackage]:
295
312
  name = _.findChildren(class_="package-snippet__name")[0].getText()
296
313
  if name == "cmem-plugin-base":
297
314
  continue
315
+ if not name.startswith("cmem-plugin-"):
316
+ continue
298
317
  description = _.findChildren(class_="package-snippet__description")[0].getText()
299
318
  package_version = _.findChildren(class_="package-snippet__version")[0].getText()
300
319
  published = _.findChildren(name="time")[0].attrs["datetime"]
@@ -1,9 +1,27 @@
1
1
  [tool.poetry]
2
2
  name = "cmem-cmemc"
3
- version = "24.1.1rc1"
3
+ version = "24.1.3"
4
4
  description = "Command line client for eccenca Corporate Memory"
5
5
  license = "Apache 2.0"
6
- classifiers = ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3.9", "Topic :: Software Development :: Testing", "Topic :: Database", "Topic :: Utilities"]
6
+ classifiers = [
7
+ "Development Status :: 5 - Production/Stable",
8
+ "Environment :: Console",
9
+ "Intended Audience :: Customer Service",
10
+ "Intended Audience :: Developers",
11
+ "Intended Audience :: Information Technology",
12
+ "Intended Audience :: Science/Research",
13
+ "Intended Audience :: System Administrators",
14
+ "License :: OSI Approved :: Apache Software License",
15
+ "Natural Language :: English",
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Software Development :: Testing",
22
+ "Topic :: Database", "Topic :: Utilities",
23
+ "Topic :: Utilities"
24
+ ]
7
25
  homepage = "https://eccenca.com/go/cmemc"
8
26
  authors = ["eccenca <cmempy-developer@eccenca.com>", "Sebastian Tramp <sebastian.tramp@eccenca.com>"]
9
27
  readme = "README-public.md"
@@ -15,7 +33,7 @@ certifi = ">=2023.5.7"
15
33
  click = "^8.1.7"
16
34
  click-didyoumean = "^0.3.0"
17
35
  click-help-colors = "^0.9.1"
18
- cmem-cmempy = "==24.1.0"
36
+ cmem-cmempy = "==24.1.1"
19
37
  # cmem-cmempy = { path = "cmempy", develop = true }
20
38
  configparser = "^5.3.0"
21
39
  jinja2 = "^3.1.2"
@@ -42,7 +60,7 @@ pytest = "^7.3.1"
42
60
  pytest-cov = "^4.1.0"
43
61
  pytest-dotenv = "^0.5.2"
44
62
  pytest-memray = { version = "^1.5.0", markers = "platform_system != 'Windows'" }
45
- ruff = "^0.1.5"
63
+ ruff = "^0.3.4"
46
64
  safety = "^1.10.3"
47
65
  types-requests = "^2.31.0.10"
48
66
  types-six = "^1.16.21.9"
@@ -92,5 +110,6 @@ ignore = [
92
110
  "PD", # opinionated linting for pandas code
93
111
  "S101", # use of assert detected
94
112
  "TRY003", # Avoid specifying long messages outside the exception class
113
+ "UP017", # We need compatibility 3.10 at the moment
95
114
  ]
96
115
 
@@ -1,68 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: cmem-cmemc
3
- Version: 24.1.1rc1
4
- Summary: Command line client for eccenca Corporate Memory
5
- Home-page: https://eccenca.com/go/cmemc
6
- License: Apache 2.0
7
- Author: eccenca
8
- Author-email: cmempy-developer@eccenca.com
9
- Requires-Python: >=3.9,<4.0
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: Intended Audience :: System Administrators
14
- Classifier: License :: OSI Approved :: Apache Software License
15
- Classifier: License :: Other/Proprietary License
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Classifier: Topic :: Database
22
- Classifier: Topic :: Software Development :: Testing
23
- Classifier: Topic :: Utilities
24
- Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
25
- Requires-Dist: certifi (>=2023.5.7)
26
- Requires-Dist: click (>=8.1.7,<9.0.0)
27
- Requires-Dist: click-didyoumean (>=0.3.0,<0.4.0)
28
- Requires-Dist: click-help-colors (>=0.9.1,<0.10.0)
29
- Requires-Dist: cmem-cmempy (==24.1.0)
30
- Requires-Dist: configparser (>=5.3.0,<6.0.0)
31
- Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
32
- Requires-Dist: natsort (>=8.3.1,<9.0.0)
33
- Requires-Dist: prometheus-client (>=0.16.0,<0.17.0)
34
- Requires-Dist: pygments (>=2.15.1,<3.0.0)
35
- Requires-Dist: pyjwt (>=2.7.0,<3.0.0)
36
- Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
37
- Requires-Dist: requests (>=2.31.0,<3.0.0)
38
- Requires-Dist: rich (>=13.7.0,<14.0.0)
39
- Requires-Dist: six (>=1.16.0,<2.0.0)
40
- Requires-Dist: timeago (>=1.0.16,<2.0.0)
41
- Requires-Dist: treelib (>=1.6.4,<2.0.0)
42
- Requires-Dist: urllib3 (>=2,<3)
43
- Description-Content-Type: text/markdown
44
-
45
- # cmemc
46
-
47
- cmemc is the official command line client for [eccenca Corporate Memory](https://documentation.eccenca.com/).
48
-
49
- ## Installation
50
-
51
- In order to install the cmemc, run:
52
-
53
- pipx install cmem-cmemc
54
-
55
- Of course you can install cmemc also with pip, but we recommend [pipx](https://pypa.github.io/pipx/) for normal desktop usage.
56
-
57
- ## Configuration and Usage
58
-
59
- cmemc is intended for System Administrators and Linked Data Expert, who wants to automate and remote control activities on eccenca Corporate Memory.
60
-
61
- The cmemc manual including basic usage pattern, configuration as well as a command reference is available at:
62
-
63
- [https://eccenca.com/go/cmemc](https://eccenca.com/go/cmemc)
64
-
65
- cmemc only works with Python 3 and refuses to work with Python 2.x.
66
- In addition to that, cmemc will warn you in case an untested Python environment is used.
67
-
68
-
@@ -1,23 +0,0 @@
1
- # cmemc
2
-
3
- cmemc is the official command line client for [eccenca Corporate Memory](https://documentation.eccenca.com/).
4
-
5
- ## Installation
6
-
7
- In order to install the cmemc, run:
8
-
9
- pipx install cmem-cmemc
10
-
11
- Of course you can install cmemc also with pip, but we recommend [pipx](https://pypa.github.io/pipx/) for normal desktop usage.
12
-
13
- ## Configuration and Usage
14
-
15
- cmemc is intended for System Administrators and Linked Data Expert, who wants to automate and remote control activities on eccenca Corporate Memory.
16
-
17
- The cmemc manual including basic usage pattern, configuration as well as a command reference is available at:
18
-
19
- [https://eccenca.com/go/cmemc](https://eccenca.com/go/cmemc)
20
-
21
- cmemc only works with Python 3 and refuses to work with Python 2.x.
22
- In addition to that, cmemc will warn you in case an untested Python environment is used.
23
-
File without changes