meerschaum 2.9.4__py3-none-any.whl → 3.0.0__py3-none-any.whl
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.
- meerschaum/__init__.py +5 -2
- meerschaum/_internal/__init__.py +1 -0
- meerschaum/_internal/arguments/_parse_arguments.py +4 -4
- meerschaum/_internal/arguments/_parser.py +33 -4
- meerschaum/_internal/cli/__init__.py +6 -0
- meerschaum/_internal/cli/daemons.py +103 -0
- meerschaum/_internal/cli/entry.py +220 -0
- meerschaum/_internal/cli/workers.py +435 -0
- meerschaum/_internal/docs/index.py +48 -2
- meerschaum/_internal/entry.py +50 -14
- meerschaum/_internal/shell/Shell.py +121 -29
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +359 -0
- meerschaum/_internal/term/TermPageHandler.py +1 -2
- meerschaum/_internal/term/__init__.py +40 -6
- meerschaum/_internal/term/tools.py +33 -8
- meerschaum/actions/__init__.py +6 -4
- meerschaum/actions/api.py +53 -13
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/bootstrap.py +8 -8
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +171 -25
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +143 -6
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +184 -31
- meerschaum/actions/start.py +166 -17
- meerschaum/actions/stop.py +38 -2
- meerschaum/actions/sync.py +7 -2
- meerschaum/actions/tag.py +9 -8
- meerschaum/actions/verify.py +5 -8
- meerschaum/api/__init__.py +45 -15
- meerschaum/api/_events.py +46 -4
- meerschaum/api/_oauth2.py +162 -9
- meerschaum/api/_tokens.py +102 -0
- meerschaum/api/dash/__init__.py +0 -3
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/custom.py +4 -3
- meerschaum/api/dash/callbacks/dashboard.py +228 -117
- meerschaum/api/dash/callbacks/jobs.py +14 -7
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +194 -14
- meerschaum/api/dash/callbacks/plugins.py +0 -1
- meerschaum/api/dash/callbacks/register.py +10 -3
- meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
- meerschaum/api/dash/callbacks/tokens.py +389 -0
- meerschaum/api/dash/components.py +36 -15
- meerschaum/api/dash/jobs.py +1 -1
- meerschaum/api/dash/keys.py +35 -93
- meerschaum/api/dash/pages/__init__.py +2 -1
- meerschaum/api/dash/pages/dashboard.py +1 -20
- meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +16 -5
- meerschaum/api/dash/pages/settings/password_reset.py +1 -1
- meerschaum/api/dash/pages/tokens.py +53 -0
- meerschaum/api/dash/pipes.py +438 -88
- meerschaum/api/dash/sessions.py +12 -0
- meerschaum/api/dash/tokens.py +603 -0
- meerschaum/api/dash/websockets.py +1 -1
- meerschaum/api/dash/webterm.py +18 -6
- meerschaum/api/models/__init__.py +23 -3
- meerschaum/api/models/_actions.py +22 -0
- meerschaum/api/models/_pipes.py +91 -7
- meerschaum/api/models/_tokens.py +81 -0
- meerschaum/api/resources/static/css/dash.css +16 -0
- meerschaum/api/resources/static/js/terminado.js +3 -0
- meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
- meerschaum/api/resources/templates/termpage.html +13 -0
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +3 -4
- meerschaum/api/routes/_connectors.py +3 -7
- meerschaum/api/routes/_jobs.py +26 -35
- meerschaum/api/routes/_login.py +120 -15
- meerschaum/api/routes/_misc.py +5 -10
- meerschaum/api/routes/_pipes.py +178 -143
- meerschaum/api/routes/_plugins.py +38 -28
- meerschaum/api/routes/_tokens.py +236 -0
- meerschaum/api/routes/_users.py +47 -35
- meerschaum/api/routes/_version.py +3 -3
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +100 -30
- meerschaum/config/_default.py +132 -64
- meerschaum/config/_edit.py +38 -32
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +10 -8
- meerschaum/config/_paths.py +133 -13
- meerschaum/config/_read_config.py +87 -36
- meerschaum/config/_sync.py +6 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +37 -15
- meerschaum/config/static.py +18 -0
- meerschaum/connectors/_Connector.py +11 -6
- meerschaum/connectors/__init__.py +41 -22
- meerschaum/connectors/api/_APIConnector.py +34 -6
- meerschaum/connectors/api/_actions.py +2 -2
- meerschaum/connectors/api/_jobs.py +12 -1
- meerschaum/connectors/api/_login.py +33 -7
- meerschaum/connectors/api/_misc.py +2 -2
- meerschaum/connectors/api/_pipes.py +23 -32
- meerschaum/connectors/api/_plugins.py +2 -2
- meerschaum/connectors/api/_request.py +1 -1
- meerschaum/connectors/api/_tokens.py +146 -0
- meerschaum/connectors/api/_users.py +70 -58
- meerschaum/connectors/instance/_InstanceConnector.py +83 -0
- meerschaum/connectors/instance/__init__.py +10 -0
- meerschaum/connectors/instance/_pipes.py +442 -0
- meerschaum/connectors/instance/_plugins.py +159 -0
- meerschaum/connectors/instance/_tokens.py +317 -0
- meerschaum/connectors/instance/_users.py +188 -0
- meerschaum/connectors/parse.py +5 -2
- meerschaum/connectors/sql/_SQLConnector.py +22 -5
- meerschaum/connectors/sql/_cli.py +12 -11
- meerschaum/connectors/sql/_create_engine.py +12 -168
- meerschaum/connectors/sql/_fetch.py +2 -18
- meerschaum/connectors/sql/_pipes.py +295 -278
- meerschaum/connectors/sql/_plugins.py +29 -0
- meerschaum/connectors/sql/_sql.py +47 -22
- meerschaum/connectors/sql/_users.py +36 -2
- meerschaum/connectors/sql/tables/__init__.py +254 -122
- meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
- meerschaum/connectors/valkey/_pipes.py +60 -31
- meerschaum/connectors/valkey/_plugins.py +2 -26
- meerschaum/core/Pipe/__init__.py +115 -85
- meerschaum/core/Pipe/_attributes.py +425 -124
- meerschaum/core/Pipe/_bootstrap.py +54 -24
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +96 -68
- meerschaum/core/Pipe/_deduplicate.py +0 -13
- meerschaum/core/Pipe/_delete.py +12 -21
- meerschaum/core/Pipe/_drop.py +11 -23
- meerschaum/core/Pipe/_dtypes.py +49 -19
- meerschaum/core/Pipe/_edit.py +14 -4
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_show.py +5 -5
- meerschaum/core/Pipe/_sync.py +123 -204
- meerschaum/core/Pipe/_verify.py +4 -4
- meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
- meerschaum/core/Plugin/__init__.py +1 -1
- meerschaum/core/Token/_Token.py +220 -0
- meerschaum/core/Token/__init__.py +12 -0
- meerschaum/core/User/_User.py +35 -10
- meerschaum/core/User/__init__.py +9 -1
- meerschaum/core/__init__.py +1 -0
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +149 -38
- meerschaum/jobs/__init__.py +3 -2
- meerschaum/jobs/systemd.py +8 -3
- meerschaum/models/__init__.py +35 -0
- meerschaum/models/pipes.py +247 -0
- meerschaum/models/tokens.py +38 -0
- meerschaum/models/users.py +26 -0
- meerschaum/plugins/__init__.py +301 -88
- meerschaum/plugins/bootstrap.py +510 -4
- meerschaum/utils/_get_pipes.py +97 -30
- meerschaum/utils/daemon/Daemon.py +199 -43
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
- meerschaum/utils/daemon/RotatingFile.py +63 -36
- meerschaum/utils/daemon/StdinFile.py +53 -13
- meerschaum/utils/daemon/__init__.py +47 -6
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/dataframe.py +480 -82
- meerschaum/utils/debug.py +49 -19
- meerschaum/utils/dtypes/__init__.py +478 -37
- meerschaum/utils/dtypes/sql.py +369 -29
- meerschaum/utils/formatting/__init__.py +5 -2
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +52 -50
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +44 -18
- meerschaum/utils/misc.py +268 -186
- meerschaum/utils/packages/__init__.py +25 -40
- meerschaum/utils/packages/_packages.py +42 -34
- meerschaum/utils/pipes.py +213 -0
- meerschaum/utils/process.py +2 -2
- meerschaum/utils/prompt.py +175 -144
- meerschaum/utils/schedule.py +2 -1
- meerschaum/utils/sql.py +135 -49
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/typing.py +1 -4
- meerschaum/utils/venv/_Venv.py +2 -2
- meerschaum/utils/venv/__init__.py +7 -7
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
- meerschaum-3.0.0.dist-info/RECORD +289 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
- meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
- meerschaum/api/models/_interfaces.py +0 -15
- meerschaum/api/models/_locations.py +0 -15
- meerschaum/api/models/_metrics.py +0 -15
- meerschaum/config/_environment.py +0 -145
- meerschaum/config/static/__init__.py +0 -186
- meerschaum-2.9.4.dist-info/RECORD +0 -263
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.9.4.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
@@ -75,7 +75,9 @@ def get_module_path(
|
|
75
75
|
|
76
76
|
venv_target_candidate_paths = [vtp]
|
77
77
|
if venv is None:
|
78
|
-
site_user_packages_dirs = [
|
78
|
+
site_user_packages_dirs = [
|
79
|
+
pathlib.Path(site.getusersitepackages())
|
80
|
+
] if not inside_venv() else []
|
79
81
|
site_packages_dirs = [pathlib.Path(path) for path in site.getsitepackages()]
|
80
82
|
|
81
83
|
paths_to_add = [
|
@@ -134,17 +136,17 @@ def get_module_path(
|
|
134
136
|
|
135
137
|
|
136
138
|
def manually_import_module(
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
139
|
+
import_name: str,
|
140
|
+
venv: Optional[str] = 'mrsm',
|
141
|
+
check_update: bool = True,
|
142
|
+
check_pypi: bool = False,
|
143
|
+
install: bool = True,
|
144
|
+
split: bool = True,
|
145
|
+
warn: bool = True,
|
146
|
+
color: bool = True,
|
147
|
+
debug: bool = False,
|
148
|
+
use_sys_modules: bool = True,
|
149
|
+
) -> Union['ModuleType', None]:
|
148
150
|
"""
|
149
151
|
Manually import a module from a virtual environment (or the base environment).
|
150
152
|
|
@@ -755,7 +757,7 @@ def get_pip(
|
|
755
757
|
import subprocess
|
756
758
|
from meerschaum.utils.misc import wget
|
757
759
|
from meerschaum.config._paths import CACHE_RESOURCES_PATH
|
758
|
-
from meerschaum.
|
760
|
+
from meerschaum._internal.static import STATIC_CONFIG
|
759
761
|
url = STATIC_CONFIG['system']['urls']['get-pip.py']
|
760
762
|
dest = CACHE_RESOURCES_PATH / 'get-pip.py'
|
761
763
|
try:
|
@@ -837,7 +839,7 @@ def pip_install(
|
|
837
839
|
|
838
840
|
"""
|
839
841
|
from meerschaum.config._paths import VIRTENV_RESOURCES_PATH
|
840
|
-
from meerschaum.
|
842
|
+
from meerschaum._internal.static import STATIC_CONFIG
|
841
843
|
from meerschaum.utils.warnings import warn
|
842
844
|
if args is None:
|
843
845
|
args = ['--upgrade'] if not _uninstall else []
|
@@ -1177,7 +1179,8 @@ def run_python_package(
|
|
1177
1179
|
Either a return code integer or a `subprocess.Popen` object
|
1178
1180
|
(or `None` if a `KeyboardInterrupt` occurs and as_proc is `True`).
|
1179
1181
|
"""
|
1180
|
-
import sys
|
1182
|
+
import sys
|
1183
|
+
import platform
|
1181
1184
|
import subprocess
|
1182
1185
|
from meerschaum.config._paths import VIRTENV_RESOURCES_PATH
|
1183
1186
|
from meerschaum.utils.process import run_process
|
@@ -1204,7 +1207,7 @@ def run_python_package(
|
|
1204
1207
|
capture_output=capture_output,
|
1205
1208
|
**kw
|
1206
1209
|
)
|
1207
|
-
except Exception
|
1210
|
+
except Exception:
|
1208
1211
|
msg = f"Failed to execute {command}, will try again:\n{traceback.format_exc()}"
|
1209
1212
|
warn(msg, color=False)
|
1210
1213
|
stdout, stderr = (
|
@@ -1216,6 +1219,7 @@ def run_python_package(
|
|
1216
1219
|
command,
|
1217
1220
|
stdout=stdout,
|
1218
1221
|
stderr=stderr,
|
1222
|
+
stdin=sys.stdin,
|
1219
1223
|
env=env_dict,
|
1220
1224
|
)
|
1221
1225
|
to_return = proc if as_proc else proc.wait()
|
@@ -1500,15 +1504,12 @@ def import_pandas(
|
|
1500
1504
|
def import_rich(
|
1501
1505
|
lazy: bool = True,
|
1502
1506
|
debug: bool = False,
|
1503
|
-
**kw
|
1507
|
+
**kw: Any
|
1504
1508
|
) -> 'ModuleType':
|
1505
1509
|
"""
|
1506
1510
|
Quality of life function for importing `rich`.
|
1507
1511
|
"""
|
1508
1512
|
from meerschaum.utils.formatting import ANSI, UNICODE
|
1509
|
-
if not ANSI and not UNICODE:
|
1510
|
-
return None
|
1511
|
-
|
1512
1513
|
## need typing_extensions for `from rich import box`
|
1513
1514
|
typing_extensions = attempt_import(
|
1514
1515
|
'typing_extensions', lazy=False, debug=debug
|
@@ -1773,6 +1774,10 @@ def is_installed(
|
|
1773
1774
|
allow_outside_venv: bool, default True
|
1774
1775
|
If `True`, search outside of the specified virtual environment
|
1775
1776
|
if the package cannot be found.
|
1777
|
+
|
1778
|
+
Returns
|
1779
|
+
-------
|
1780
|
+
A bool indicating whether a package may be imported.
|
1776
1781
|
"""
|
1777
1782
|
if debug:
|
1778
1783
|
from meerschaum.utils.debug import dprint
|
@@ -1864,26 +1869,6 @@ def ensure_readline() -> 'ModuleType':
|
|
1864
1869
|
sys.modules['readline'] = readline
|
1865
1870
|
return readline
|
1866
1871
|
|
1867
|
-
_pkg_resources_get_distribution = None
|
1868
|
-
_custom_distributions = {}
|
1869
|
-
def _monkey_patch_get_distribution(_dist: str, _version: str) -> None:
|
1870
|
-
"""
|
1871
|
-
Monkey patch `pkg_resources.get_distribution` to allow for importing `flask_compress`.
|
1872
|
-
"""
|
1873
|
-
import pkg_resources
|
1874
|
-
from collections import namedtuple
|
1875
|
-
global _pkg_resources_get_distribution
|
1876
|
-
with _locks['_pkg_resources_get_distribution']:
|
1877
|
-
_pkg_resources_get_distribution = pkg_resources.get_distribution
|
1878
|
-
_custom_distributions[_dist] = _version
|
1879
|
-
_Dist = namedtuple('_Dist', ['version'])
|
1880
|
-
def _get_distribution(dist):
|
1881
|
-
"""Hack for flask-compress."""
|
1882
|
-
if dist in _custom_distributions:
|
1883
|
-
return _Dist(_custom_distributions[dist])
|
1884
|
-
return _pkg_resources_get_distribution(dist)
|
1885
|
-
pkg_resources.get_distribution = _get_distribution
|
1886
|
-
|
1887
1872
|
|
1888
1873
|
def _get_pip_os_env(color: bool = True):
|
1889
1874
|
"""
|
@@ -13,8 +13,7 @@ packages dictionary is structured in the following schema:
|
|
13
13
|
}
|
14
14
|
"""
|
15
15
|
|
16
|
-
from
|
17
|
-
from meerschaum.utils.typing import Dict
|
16
|
+
from typing import Dict
|
18
17
|
|
19
18
|
_MRSM_PACKAGE_ARCHIVES_PREFIX: str = "https://meerschaum.io/files/archives/wheels/"
|
20
19
|
|
@@ -54,23 +53,25 @@ packages: Dict[str, Dict[str, str]] = {
|
|
54
53
|
'virtualenv' : 'virtualenv>=20.1.0',
|
55
54
|
'attrs' : 'attrs>=24.2.0',
|
56
55
|
'uv' : 'uv>=0.2.11',
|
56
|
+
'pydantic' : 'pydantic>=2.11.7',
|
57
|
+
'annotated-types' : 'annotated-types>=0.7.0',
|
57
58
|
},
|
58
59
|
'_internal' : {
|
59
60
|
'apscheduler' : (
|
60
61
|
f"{_MRSM_PACKAGE_ARCHIVES_PREFIX}"
|
61
|
-
"
|
62
|
+
"apscheduler-4.0.0a6.post8+mrsm-py3-none-any.whl>=4.0.0a6"
|
62
63
|
),
|
63
|
-
'dataclass_wizard' : 'dataclass-wizard>=0.
|
64
|
+
'dataclass_wizard' : 'dataclass-wizard>=0.35.0',
|
64
65
|
},
|
65
66
|
'jobs': {
|
66
|
-
'dill' : 'dill>=0.
|
67
|
-
'daemon' : 'python-daemon>=
|
68
|
-
'watchfiles' : 'watchfiles>=
|
69
|
-
'psutil' : 'psutil>=
|
67
|
+
'dill' : 'dill>=0.4.0',
|
68
|
+
'daemon' : 'python-daemon>=3.1.2',
|
69
|
+
'watchfiles' : 'watchfiles>=1.1.0',
|
70
|
+
'psutil' : 'psutil>=7.0.0',
|
70
71
|
},
|
71
72
|
'drivers': {
|
72
73
|
'cryptography' : 'cryptography>=38.0.1',
|
73
|
-
'psycopg' : 'psycopg[binary]>=3.2.
|
74
|
+
'psycopg' : 'psycopg[binary]>=3.2.9',
|
74
75
|
'pymysql' : 'PyMySQL>=0.9.0',
|
75
76
|
'aiomysql' : 'aiomysql>=0.0.21',
|
76
77
|
'sqlalchemy_cockroachdb' : 'sqlalchemy-cockroachdb>=2.0.0',
|
@@ -122,7 +123,7 @@ packages: Dict[str, Dict[str, str]] = {
|
|
122
123
|
'mkdocs_section_index' : 'mkdocs-section-index>=0.3.3',
|
123
124
|
'mkdocs_linkcheck' : 'mkdocs-linkcheck>=1.0.6',
|
124
125
|
'mkdocs_redirects' : 'mkdocs-redirects>=1.0.4',
|
125
|
-
'jinja2' : 'jinja2
|
126
|
+
'jinja2' : 'jinja2>=3.1.6',
|
126
127
|
},
|
127
128
|
'gui': {
|
128
129
|
'webview' : 'pywebview>=3.6.3',
|
@@ -137,43 +138,44 @@ packages: Dict[str, Dict[str, str]] = {
|
|
137
138
|
},
|
138
139
|
}
|
139
140
|
packages['sql'] = {
|
140
|
-
'numpy' : 'numpy>=
|
141
|
-
'pandas' : 'pandas[parquet]>=2.
|
142
|
-
'pyarrow' : 'pyarrow>=
|
141
|
+
'numpy' : 'numpy>=2.3.1',
|
142
|
+
'pandas' : 'pandas[parquet]>=2.3.1',
|
143
|
+
'pyarrow' : 'pyarrow>=20.0.0',
|
143
144
|
'dask' : 'dask[complete]>=2024.12.1',
|
144
145
|
'partd' : 'partd>=1.4.2',
|
145
146
|
'pytz' : 'pytz',
|
146
|
-
'joblib' : 'joblib>=
|
147
|
-
'sqlalchemy' : 'SQLAlchemy>=2.0.
|
147
|
+
'joblib' : 'joblib>=1.5.1',
|
148
|
+
'sqlalchemy' : 'SQLAlchemy>=2.0.41',
|
148
149
|
'geoalchemy' : 'GeoAlchemy2>=0.17.1',
|
149
|
-
'databases' : 'databases>=0.
|
150
|
-
'aiosqlite' : 'aiosqlite>=0.
|
151
|
-
'asyncpg' : 'asyncpg>=0.
|
150
|
+
'databases' : 'databases>=0.9.0',
|
151
|
+
'aiosqlite' : 'aiosqlite>=0.21.0',
|
152
|
+
'asyncpg' : 'asyncpg>=0.30.0',
|
152
153
|
}
|
153
154
|
packages['sql'].update(packages['drivers'])
|
154
155
|
packages['sql'].update(packages['core'])
|
155
156
|
packages['sql'].update(packages['gis'])
|
156
157
|
packages['dash'] = {
|
157
|
-
'flask_compress' : 'Flask-Compress>=1.
|
158
|
-
'dash' : 'dash>=
|
158
|
+
'flask_compress' : 'Flask-Compress>=1.17.0',
|
159
|
+
'dash' : 'dash>=3.1.1',
|
159
160
|
'dash_bootstrap_components' : 'dash-bootstrap-components>=1.7.1',
|
160
161
|
'dash_ace' : 'dash-ace>=0.2.1',
|
161
|
-
'dash_extensions' : 'dash-extensions>=
|
162
|
-
'dash_daq' : 'dash-daq>=0.
|
163
|
-
'terminado' : 'terminado>=0.
|
164
|
-
'tornado' : 'tornado>=6.1
|
162
|
+
'dash_extensions' : 'dash-extensions>=2.0.4',
|
163
|
+
'dash_daq' : 'dash-daq>=0.6.0',
|
164
|
+
'terminado' : 'terminado>=0.18.1',
|
165
|
+
'tornado' : 'tornado>=6.5.1',
|
165
166
|
}
|
166
167
|
packages['api'] = {
|
167
|
-
'uvicorn' : 'uvicorn[standard]>=0.
|
168
|
-
'gunicorn' : 'gunicorn>=
|
169
|
-
'dotenv' : 'python-dotenv>=
|
170
|
-
'websockets' : 'websockets>=
|
171
|
-
'fastapi' : 'fastapi>=0.
|
172
|
-
'fastapi_login' : 'fastapi-login>=1.
|
173
|
-
'multipart' : 'python-multipart>=0.0.
|
174
|
-
'httpx' : 'httpx>=0.
|
175
|
-
'httpcore' : 'httpcore>=1.0.
|
176
|
-
'valkey' : 'valkey>=6.
|
168
|
+
'uvicorn' : 'uvicorn[standard]>=0.35.0',
|
169
|
+
'gunicorn' : 'gunicorn>=23.0.0',
|
170
|
+
'dotenv' : 'python-dotenv>=1.1.1',
|
171
|
+
'websockets' : 'websockets>=15.0.1',
|
172
|
+
'fastapi' : 'fastapi>=0.116.0',
|
173
|
+
'fastapi_login' : 'fastapi-login>=1.10.3',
|
174
|
+
'multipart' : 'python-multipart>=0.0.20',
|
175
|
+
'httpx' : 'httpx>=0.28.1',
|
176
|
+
'httpcore' : 'httpcore>=1.0.9',
|
177
|
+
'valkey' : 'valkey>=6.1.0',
|
178
|
+
'jose' : 'python-jose>=3.5.0',
|
177
179
|
}
|
178
180
|
packages['api'].update(packages['sql'])
|
179
181
|
packages['api'].update(packages['formatting'])
|
@@ -216,3 +218,9 @@ for group, import_names in packages.items():
|
|
216
218
|
for import_name, install_name in import_names.items():
|
217
219
|
_full[import_name] = install_name
|
218
220
|
packages['full'] = _full
|
221
|
+
|
222
|
+
extras = {
|
223
|
+
group: list(import_names_install_names_map.values())
|
224
|
+
for group, import_names_install_names_map in packages.items()
|
225
|
+
if not group.startswith('_')
|
226
|
+
}
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define utilities for working with pipes.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
from typing import Any, Dict, Callable
|
11
|
+
import re
|
12
|
+
import json
|
13
|
+
import ast
|
14
|
+
import copy
|
15
|
+
import uuid
|
16
|
+
|
17
|
+
from meerschaum.utils.typing import PipesDict, Optional
|
18
|
+
import meerschaum as mrsm
|
19
|
+
|
20
|
+
|
21
|
+
def evaluate_pipe_access_chain(access_chain: str, pipe: mrsm.Pipe):
|
22
|
+
"""
|
23
|
+
Safely evaluate the access chain on a Pipe.
|
24
|
+
"""
|
25
|
+
expr = f"pipe{access_chain}"
|
26
|
+
tree = ast.parse(expr, mode='eval')
|
27
|
+
|
28
|
+
def _eval(node, context):
|
29
|
+
if isinstance(node, ast.Expression):
|
30
|
+
return _eval(node.body, context)
|
31
|
+
|
32
|
+
elif isinstance(node, ast.Name):
|
33
|
+
if node.id == "pipe":
|
34
|
+
return context
|
35
|
+
raise ValueError(f"Unknown variable: {node.id}")
|
36
|
+
|
37
|
+
elif isinstance(node, ast.Attribute):
|
38
|
+
value = _eval(node.value, context)
|
39
|
+
return getattr(value, node.attr)
|
40
|
+
|
41
|
+
elif isinstance(node, ast.Subscript):
|
42
|
+
value = _eval(node.value, context)
|
43
|
+
key = _eval(node.slice, context) if isinstance(node.slice, ast.Index) else _eval(node.slice, context)
|
44
|
+
return value[key]
|
45
|
+
|
46
|
+
elif isinstance(node, ast.Constant): # Python 3.8+
|
47
|
+
return node.value
|
48
|
+
|
49
|
+
elif isinstance(node, ast.Str): # Older Python
|
50
|
+
return node.s
|
51
|
+
|
52
|
+
elif isinstance(node, ast.Index): # Older Python AST style
|
53
|
+
return _eval(node.value, context)
|
54
|
+
|
55
|
+
else:
|
56
|
+
raise TypeError(f"Unsupported AST node: {ast.dump(node)}")
|
57
|
+
|
58
|
+
return _eval(tree, pipe)
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
def _evaluate_pipe_access_chain_from_match(pipe_match: re.Match) -> Any:
|
63
|
+
"""
|
64
|
+
Helper function to evaluate a pipe from a regex match object.
|
65
|
+
"""
|
66
|
+
from meerschaum.utils.warnings import warn
|
67
|
+
from meerschaum.utils.misc import parse_arguments_str
|
68
|
+
from meerschaum.utils.sql import sql_item_name
|
69
|
+
try:
|
70
|
+
args_str = pipe_match.group(1)
|
71
|
+
access_chain = pipe_match.group(2)
|
72
|
+
args, kwargs = parse_arguments_str(args_str)
|
73
|
+
pipe = mrsm.Pipe(*args, **kwargs)
|
74
|
+
except Exception as e:
|
75
|
+
warn(f"Failed to parse pipe from template string:\n{e}")
|
76
|
+
raise e
|
77
|
+
|
78
|
+
if not access_chain:
|
79
|
+
target = pipe.target
|
80
|
+
schema = (
|
81
|
+
pipe.instance_connector.get_pipe_schema(pipe)
|
82
|
+
if hasattr(pipe.instance_connector, 'get_pipe_schema')
|
83
|
+
else None
|
84
|
+
)
|
85
|
+
return (
|
86
|
+
sql_item_name(target, pipe.instance_connector.flavor, schema)
|
87
|
+
if pipe.instance_connector.type == 'sql'
|
88
|
+
else pipe.target
|
89
|
+
)
|
90
|
+
|
91
|
+
return evaluate_pipe_access_chain(access_chain, pipe)
|
92
|
+
|
93
|
+
|
94
|
+
def replace_pipes_syntax(text: str) -> Any:
|
95
|
+
"""
|
96
|
+
Parse a string containing the `{{ Pipe() }}` syntax.
|
97
|
+
"""
|
98
|
+
from meerschaum.utils.warnings import warn
|
99
|
+
from meerschaum.utils.dtypes import json_serialize_value
|
100
|
+
pattern = r'\{\{\s*(?:mrsm\.)?Pipe\((.*?)\)((?:\.[\w]+|\[[^\]]+\])*)\s*\}\}'
|
101
|
+
|
102
|
+
matches = list(re.finditer(pattern, text))
|
103
|
+
if not matches:
|
104
|
+
return text
|
105
|
+
|
106
|
+
placeholders = {}
|
107
|
+
for match in matches:
|
108
|
+
placeholder = f"__mrsm_pipe_placeholder_{uuid.uuid4().hex}__"
|
109
|
+
placeholders[placeholder] = match
|
110
|
+
|
111
|
+
substituted_text = text
|
112
|
+
for placeholder, match in placeholders.items():
|
113
|
+
substituted_text = substituted_text.replace(match.group(0), placeholder)
|
114
|
+
|
115
|
+
resolved_values = {}
|
116
|
+
for placeholder, match in placeholders.items():
|
117
|
+
try:
|
118
|
+
resolved_values[placeholder] = _evaluate_pipe_access_chain_from_match(match)
|
119
|
+
except Exception as e:
|
120
|
+
warn(f"Failed to resolve pipe syntax '{match.group(0)}': {e}")
|
121
|
+
resolved_values[placeholder] = match.group(0)
|
122
|
+
|
123
|
+
if len(matches) == 1:
|
124
|
+
match = matches[0]
|
125
|
+
placeholder = list(placeholders.keys())[0]
|
126
|
+
if text.strip() == match.group(0):
|
127
|
+
return resolved_values[placeholder]
|
128
|
+
|
129
|
+
final_text = substituted_text
|
130
|
+
for placeholder, value in resolved_values.items():
|
131
|
+
if isinstance(value, (dict, list, bool, int, float)) or value is None:
|
132
|
+
final_text = final_text.replace(placeholder, json.dumps(value, default=json_serialize_value))
|
133
|
+
else:
|
134
|
+
final_text = final_text.replace(placeholder, str(value))
|
135
|
+
|
136
|
+
return final_text
|
137
|
+
|
138
|
+
|
139
|
+
def replace_pipes_in_dict(
|
140
|
+
pipes: Optional[PipesDict] = None,
|
141
|
+
func: Callable[[Any], Any] = str,
|
142
|
+
debug: bool = False,
|
143
|
+
**kw
|
144
|
+
) -> PipesDict:
|
145
|
+
"""
|
146
|
+
Replace the Pipes in a Pipes dict with the result of another function.
|
147
|
+
|
148
|
+
Parameters
|
149
|
+
----------
|
150
|
+
pipes: Optional[PipesDict], default None
|
151
|
+
The pipes dict to be processed.
|
152
|
+
|
153
|
+
func: Callable[[Any], Any], default str
|
154
|
+
The function to be applied to every pipe.
|
155
|
+
Defaults to the string constructor.
|
156
|
+
|
157
|
+
debug: bool, default False
|
158
|
+
Verbosity toggle.
|
159
|
+
|
160
|
+
Returns
|
161
|
+
-------
|
162
|
+
A dictionary where every pipe is replaced with the output of a function.
|
163
|
+
|
164
|
+
"""
|
165
|
+
def change_dict(d: Dict[Any, Any]) -> None:
|
166
|
+
for k, v in d.items():
|
167
|
+
if isinstance(v, dict):
|
168
|
+
change_dict(v)
|
169
|
+
elif isinstance(v, list):
|
170
|
+
d[k] = [func(i) for i in v]
|
171
|
+
elif isinstance(v, tuple):
|
172
|
+
d[k] = tuple([func(i) for i in v])
|
173
|
+
else:
|
174
|
+
d[k] = func(v)
|
175
|
+
|
176
|
+
if pipes is None:
|
177
|
+
from meerschaum import get_pipes
|
178
|
+
pipes = get_pipes(debug=debug, **kw)
|
179
|
+
|
180
|
+
result = copy.deepcopy(pipes)
|
181
|
+
change_dict(result)
|
182
|
+
return result
|
183
|
+
|
184
|
+
|
185
|
+
def is_pipe_registered(
|
186
|
+
pipe: mrsm.Pipe,
|
187
|
+
pipes: PipesDict,
|
188
|
+
debug: bool = False
|
189
|
+
) -> bool:
|
190
|
+
"""
|
191
|
+
Check if a Pipe is inside the pipes dictionary.
|
192
|
+
|
193
|
+
Parameters
|
194
|
+
----------
|
195
|
+
pipe: meerschaum.Pipe
|
196
|
+
The pipe to see if it's in the dictionary.
|
197
|
+
|
198
|
+
pipes: PipesDict
|
199
|
+
The dictionary to search inside.
|
200
|
+
|
201
|
+
debug: bool, default False
|
202
|
+
Verbosity toggle.
|
203
|
+
|
204
|
+
Returns
|
205
|
+
-------
|
206
|
+
A bool indicating whether the pipe is inside the dictionary.
|
207
|
+
"""
|
208
|
+
from meerschaum.utils.debug import dprint
|
209
|
+
ck, mk, lk = pipe.connector_keys, pipe.metric_key, pipe.location_key
|
210
|
+
if debug:
|
211
|
+
dprint(f'{ck}, {mk}, {lk}')
|
212
|
+
dprint(f'{pipe}, {pipes}')
|
213
|
+
return ck in pipes and mk in pipes[ck] and lk in pipes[ck][mk]
|
meerschaum/utils/process.py
CHANGED
@@ -18,7 +18,7 @@ import platform
|
|
18
18
|
|
19
19
|
import meerschaum as mrsm
|
20
20
|
from meerschaum.utils.typing import Union, Optional, Any, Callable, Dict, Tuple
|
21
|
-
from meerschaum.
|
21
|
+
from meerschaum._internal.static import STATIC_CONFIG
|
22
22
|
|
23
23
|
_child_processes = []
|
24
24
|
def signal_handler(sig, frame):
|
@@ -178,7 +178,7 @@ def run_process(
|
|
178
178
|
# make us tty's foreground again
|
179
179
|
try:
|
180
180
|
os.tcsetpgrp(sys.stdin.fileno(), old_pgrp)
|
181
|
-
except Exception
|
181
|
+
except Exception:
|
182
182
|
pass
|
183
183
|
# now restore the handler
|
184
184
|
signal.signal(signal.SIGTTOU, hdlr)
|