meerschaum 2.2.0.dev1__tar.gz → 2.2.0.dev2__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.
- {meerschaum-2.2.0.dev1/meerschaum.egg-info → meerschaum-2.2.0.dev2}/PKG-INFO +8 -10
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/dashboard.py +18 -12
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pipes.py +44 -25
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_version.py +1 -1
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/stack/__init__.py +0 -1
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/packages/__init__.py +4 -1
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/packages/_packages.py +5 -5
- meerschaum-2.2.0.dev2/meerschaum/utils/schedule.py +304 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2/meerschaum.egg-info}/PKG-INFO +8 -10
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/requires.txt +7 -9
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_sync.py +9 -1
- meerschaum-2.2.0.dev1/meerschaum/utils/schedule.py +0 -65
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/LICENSE +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/NOTICE +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/README.md +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/__main__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/arguments/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/arguments/_parse_arguments.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/arguments/_parser.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/docs/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/docs/index.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/entry.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/gui/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/gui/app/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/gui/app/_windows.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/gui/app/actions.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/gui/app/pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/shell/Shell.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/shell/ShellCompleter.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/shell/ValidAutoSuggest.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/shell/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/shell/resources/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/term/TermPageHandler.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/term/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/_internal/term/tools.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/api.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/bootstrap.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/clear.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/copy.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/deduplicate.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/delete.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/drop.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/edit.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/install.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/login.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/os.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/pause.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/python.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/register.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/reload.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/setup.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/sh.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/show.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/sql.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/stack.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/start.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/stop.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/sync.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/tag.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/uninstall.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/upgrade.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/actions/verify.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/_chain.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/_events.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/_oauth2.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/_websockets.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/actions.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/ansi_up.js +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/banner_1920x320.png +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/favicon.ico +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/logo_48x48.png +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/assets/logo_500x500.png +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/jobs.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/login.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/callbacks/register.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/components.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/connectors.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/graphs.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/jobs.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/keys.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/dashboard.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/error.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/login.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/pages/register.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/sync.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/users.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/websockets.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/dash/webterm.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/models/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/models/_interfaces.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/models/_locations.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/models/_metrics.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/models/_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/bootstrap.min.css +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/dash.css +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/dbc_dark.css +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/styles.css +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/css/xterm.css +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/ico/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/ico/logo.ico +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/js/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/js/action_button.js +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/js/main.js +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/js/terminado.js +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/js/xterm.js +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/static/png/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/templates/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/templates/index.html +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/templates/old_index.html +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/templates/secret.html +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/resources/templates/termpage.html +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_actions.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_connectors.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_index.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_login.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_misc.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_users.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_version.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/routes/_webterm.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/api/tables/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_default.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_edit.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_environment.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_formatting.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_jobs.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_patch.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_paths.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_preprocess.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_read_config.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_shell.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/_sync.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/resources/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/stack/grafana/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/stack/mosquitto/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/stack/mosquitto/resources/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/stack/resources/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/config/static/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/Connector.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/APIConnector.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_actions.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_fetch.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_login.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_misc.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_request.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_uri.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/api/_users.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/parse.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/plugin/PluginConnector.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/plugin/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/poll.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/SQLConnector.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_cli.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_create_engine.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_fetch.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_instance.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_plugins.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_sql.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_uri.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/_users.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/tables/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/tables/types.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/connectors/sql/tools.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_attributes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_bootstrap.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_clear.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_data.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_deduplicate.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_delete.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_drop.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_dtypes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_edit.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_fetch.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_register.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_show.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_sync.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Pipe/_verify.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/Plugin/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/User/_User.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/User/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/core/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/plugins/_Plugin.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/plugins/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/_get_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/daemon/Daemon.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/daemon/RotatingFile.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/daemon/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/daemon/_names.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/dataframe.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/debug.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/dtypes/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/dtypes/sql.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/formatting/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/formatting/_jobs.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/formatting/_pipes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/formatting/_pprint.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/formatting/_shell.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/interactive.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/misc.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/networking.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/packages/lazy_loader.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/pool.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/process.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/prompt.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/sql.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/threading.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/typing.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/venv/_Venv.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/venv/__init__.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/warnings.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum/utils/yaml.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/SOURCES.txt +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/dependency_links.txt +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/entry_points.txt +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/top_level.txt +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/meerschaum.egg-info/zip-safe +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/setup.cfg +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/setup.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_deduplicate.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_pipes_dtypes.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_sql.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_users.py +0 -0
- {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev2}/tests/test_verify.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: meerschaum
|
3
|
-
Version: 2.2.0.
|
3
|
+
Version: 2.2.0.dev2
|
4
4
|
Summary: Sync Time-Series Pipes with Meerschaum
|
5
5
|
Home-page: https://meerschaum.io
|
6
6
|
Author: Bennett Meares
|
@@ -64,7 +64,7 @@ Requires-Dist: psutil>=5.8.0; extra == "required"
|
|
64
64
|
Requires-Dist: watchgod>=0.7.0; extra == "required"
|
65
65
|
Requires-Dist: dill>=0.3.3; extra == "required"
|
66
66
|
Requires-Dist: virtualenv>=20.1.0; extra == "required"
|
67
|
-
Requires-Dist:
|
67
|
+
Requires-Dist: apscheduler>=4.0.0a4; extra == "required"
|
68
68
|
Provides-Extra: drivers
|
69
69
|
Requires-Dist: cryptography>=38.0.1; extra == "drivers"
|
70
70
|
Requires-Dist: psycopg[binary]>=3.1.18; extra == "drivers"
|
@@ -83,10 +83,10 @@ Requires-Dist: litecli>=1.5.0; extra == "cli"
|
|
83
83
|
Requires-Dist: mssql-cli>=1.0.0; extra == "cli"
|
84
84
|
Requires-Dist: gadwall>=0.2.0; extra == "cli"
|
85
85
|
Provides-Extra: stack
|
86
|
-
Requires-Dist: docker-compose>=1.
|
86
|
+
Requires-Dist: docker-compose>=1.29.2; extra == "stack"
|
87
87
|
Provides-Extra: build
|
88
|
-
Requires-Dist: cx_Freeze>=
|
89
|
-
Requires-Dist: pyinstaller
|
88
|
+
Requires-Dist: cx_Freeze>=7.0.0; extra == "build"
|
89
|
+
Requires-Dist: pyinstaller>6.6.0; extra == "build"
|
90
90
|
Provides-Extra: dev-tools
|
91
91
|
Requires-Dist: twine>=3.2.0; extra == "dev-tools"
|
92
92
|
Requires-Dist: tuna>=0.5.3; extra == "dev-tools"
|
@@ -155,7 +155,7 @@ Requires-Dist: psutil>=5.8.0; extra == "sql"
|
|
155
155
|
Requires-Dist: watchgod>=0.7.0; extra == "sql"
|
156
156
|
Requires-Dist: dill>=0.3.3; extra == "sql"
|
157
157
|
Requires-Dist: virtualenv>=20.1.0; extra == "sql"
|
158
|
-
Requires-Dist:
|
158
|
+
Requires-Dist: apscheduler>=4.0.0a4; extra == "sql"
|
159
159
|
Provides-Extra: dash
|
160
160
|
Requires-Dist: Flask-Compress>=1.10.1; extra == "dash"
|
161
161
|
Requires-Dist: dash>=2.6.2; extra == "dash"
|
@@ -174,7 +174,6 @@ Requires-Dist: fastapi>=0.100.0; extra == "api"
|
|
174
174
|
Requires-Dist: passlib>=1.7.4; extra == "api"
|
175
175
|
Requires-Dist: fastapi-login>=1.7.2; extra == "api"
|
176
176
|
Requires-Dist: python-multipart>=0.0.5; extra == "api"
|
177
|
-
Requires-Dist: pydantic<2.0.0; extra == "api"
|
178
177
|
Requires-Dist: httpx>=0.24.1; extra == "api"
|
179
178
|
Requires-Dist: numpy>=1.18.5; extra == "api"
|
180
179
|
Requires-Dist: pandas[parquet]>=2.0.1; extra == "api"
|
@@ -214,7 +213,7 @@ Requires-Dist: psutil>=5.8.0; extra == "api"
|
|
214
213
|
Requires-Dist: watchgod>=0.7.0; extra == "api"
|
215
214
|
Requires-Dist: dill>=0.3.3; extra == "api"
|
216
215
|
Requires-Dist: virtualenv>=20.1.0; extra == "api"
|
217
|
-
Requires-Dist:
|
216
|
+
Requires-Dist: apscheduler>=4.0.0a4; extra == "api"
|
218
217
|
Requires-Dist: pprintpp>=0.4.0; extra == "api"
|
219
218
|
Requires-Dist: asciitree>=0.3.3; extra == "api"
|
220
219
|
Requires-Dist: typing-extensions>=4.7.1; extra == "api"
|
@@ -261,7 +260,7 @@ Requires-Dist: psutil>=5.8.0; extra == "full"
|
|
261
260
|
Requires-Dist: watchgod>=0.7.0; extra == "full"
|
262
261
|
Requires-Dist: dill>=0.3.3; extra == "full"
|
263
262
|
Requires-Dist: virtualenv>=20.1.0; extra == "full"
|
264
|
-
Requires-Dist:
|
263
|
+
Requires-Dist: apscheduler>=4.0.0a4; extra == "full"
|
265
264
|
Requires-Dist: cryptography>=38.0.1; extra == "full"
|
266
265
|
Requires-Dist: psycopg[binary]>=3.1.18; extra == "full"
|
267
266
|
Requires-Dist: PyMySQL>=0.9.0; extra == "full"
|
@@ -298,7 +297,6 @@ Requires-Dist: fastapi>=0.100.0; extra == "full"
|
|
298
297
|
Requires-Dist: passlib>=1.7.4; extra == "full"
|
299
298
|
Requires-Dist: fastapi-login>=1.7.2; extra == "full"
|
300
299
|
Requires-Dist: python-multipart>=0.0.5; extra == "full"
|
301
|
-
Requires-Dist: pydantic<2.0.0; extra == "full"
|
302
300
|
Requires-Dist: httpx>=0.24.1; extra == "full"
|
303
301
|
|
304
302
|
<img src="https://meerschaum.io/assets/banner_1920x320.png" alt="Meerschaum banner" style="width: 100%"/>
|
@@ -516,9 +516,9 @@ def update_keys_options(
|
|
516
516
|
if location_keys:
|
517
517
|
num_filter += 1
|
518
518
|
|
519
|
-
|
520
|
-
|
521
|
-
|
519
|
+
_ck_filter = connector_keys
|
520
|
+
_mk_filter = metric_keys
|
521
|
+
_lk_filter = location_keys
|
522
522
|
_ck_alone = (connector_keys and num_filter == 1) or instance_click
|
523
523
|
_mk_alone = (metric_keys and num_filter == 1) or instance_click
|
524
524
|
_lk_alone = (location_keys and num_filter == 1) or instance_click
|
@@ -528,8 +528,11 @@ def update_keys_options(
|
|
528
528
|
try:
|
529
529
|
_all_keys = fetch_pipes_keys('registered', get_web_connector(ctx.states))
|
530
530
|
_keys = fetch_pipes_keys(
|
531
|
-
'registered',
|
532
|
-
|
531
|
+
'registered',
|
532
|
+
get_web_connector(ctx.states),
|
533
|
+
connector_keys = _ck_filter,
|
534
|
+
metric_keys = _mk_filter,
|
535
|
+
location_keys = _lk_filter,
|
533
536
|
)
|
534
537
|
except Exception as e:
|
535
538
|
instance_alerts += [alert_from_success_tuple((False, str(e)))]
|
@@ -551,30 +554,33 @@ def update_keys_options(
|
|
551
554
|
add_options(_connectors_options, _all_keys if _ck_alone else _keys, 'ck')
|
552
555
|
add_options(_metrics_options, _all_keys if _mk_alone else _keys, 'mk')
|
553
556
|
add_options(_locations_options, _all_keys if _lk_alone else _keys, 'lk')
|
554
|
-
|
557
|
+
_connectors_options.sort(key=lambda x: str(x).lower())
|
558
|
+
_metrics_options.sort(key=lambda x: str(x).lower())
|
559
|
+
_locations_options.sort(key=lambda x: str(x).lower())
|
560
|
+
connector_keys = [
|
555
561
|
ck
|
556
|
-
for ck in connector_keys
|
562
|
+
for ck in connector_keys
|
557
563
|
if ck in [
|
558
564
|
_ck['value']
|
559
565
|
for _ck in _connectors_options
|
560
566
|
]
|
561
|
-
]
|
562
|
-
metric_keys =
|
567
|
+
]
|
568
|
+
metric_keys = [
|
563
569
|
mk
|
564
570
|
for mk in metric_keys
|
565
571
|
if mk in [
|
566
572
|
_mk['value']
|
567
573
|
for _mk in _metrics_options
|
568
574
|
]
|
569
|
-
]
|
570
|
-
location_keys =
|
575
|
+
]
|
576
|
+
location_keys = [
|
571
577
|
lk
|
572
578
|
for lk in location_keys
|
573
579
|
if lk in [
|
574
580
|
_lk['value']
|
575
581
|
for _lk in _locations_options
|
576
582
|
]
|
577
|
-
]
|
583
|
+
]
|
578
584
|
_connectors_datalist = [html.Option(value=o['value']) for o in _connectors_options]
|
579
585
|
_metrics_datalist = [html.Option(value=o['value']) for o in _metrics_options]
|
580
586
|
_locations_datalist = [html.Option(value=o['value']) for o in _locations_options]
|
@@ -124,11 +124,11 @@ def get_pipes_cards(*keys, session_data: Optional[Dict[str, Any]] = None):
|
|
124
124
|
label = "Manage",
|
125
125
|
children = [
|
126
126
|
dbc.DropdownMenuItem(
|
127
|
-
'
|
127
|
+
'Delete',
|
128
128
|
id = {
|
129
129
|
'type': 'manage-pipe-button',
|
130
130
|
'index': meta_str,
|
131
|
-
'action': '
|
131
|
+
'action': 'delete',
|
132
132
|
},
|
133
133
|
),
|
134
134
|
dbc.DropdownMenuItem(
|
@@ -140,15 +140,31 @@ def get_pipes_cards(*keys, session_data: Optional[Dict[str, Any]] = None):
|
|
140
140
|
},
|
141
141
|
),
|
142
142
|
dbc.DropdownMenuItem(
|
143
|
-
'
|
143
|
+
'Clear',
|
144
144
|
id = {
|
145
145
|
'type': 'manage-pipe-button',
|
146
146
|
'index': meta_str,
|
147
|
-
'action': '
|
147
|
+
'action': 'clear',
|
148
|
+
},
|
149
|
+
),
|
150
|
+
dbc.DropdownMenuItem(
|
151
|
+
'Verify',
|
152
|
+
id = {
|
153
|
+
'type': 'manage-pipe-button',
|
154
|
+
'index': meta_str,
|
155
|
+
'action': 'verify',
|
156
|
+
},
|
157
|
+
),
|
158
|
+
dbc.DropdownMenuItem(
|
159
|
+
'Sync',
|
160
|
+
id = {
|
161
|
+
'type': 'manage-pipe-button',
|
162
|
+
'index': meta_str,
|
163
|
+
'action': 'sync',
|
148
164
|
},
|
149
165
|
),
|
150
166
|
],
|
151
|
-
direction = "
|
167
|
+
direction = "up",
|
152
168
|
menu_variant = "dark",
|
153
169
|
size = 'sm',
|
154
170
|
color = 'secondary',
|
@@ -156,21 +172,10 @@ def get_pipes_cards(*keys, session_data: Optional[Dict[str, Any]] = None):
|
|
156
172
|
) if authenticated else [],
|
157
173
|
width = 2,
|
158
174
|
),
|
159
|
-
# dbc.Col(
|
160
|
-
# (
|
161
|
-
# dbc.Button(
|
162
|
-
# 'Sync',
|
163
|
-
# size = 'sm',
|
164
|
-
# style = {'width': '100%'},
|
165
|
-
# id = {'type': 'pipe-sync-button', 'index': meta_str},
|
166
|
-
# ) if authenticated else []
|
167
|
-
# ),
|
168
|
-
# width = 2,
|
169
|
-
# ),
|
170
175
|
dbc.Col(width=6),
|
171
176
|
dbc.Col(
|
172
177
|
dbc.Button(
|
173
|
-
'Download
|
178
|
+
'Download CSV',
|
174
179
|
size = 'sm',
|
175
180
|
color = 'link',
|
176
181
|
style = {'float': 'right'},
|
@@ -244,14 +249,28 @@ def accordion_items_from_pipe(
|
|
244
249
|
overview_header = [html.Thead(html.Tr([html.Th("Attribute"), html.Th("Value")]))]
|
245
250
|
dt_name, id_name, val_name = pipe.get_columns('datetime', 'id', 'value', error=False)
|
246
251
|
overview_rows = [
|
247
|
-
html.Tr([html.Td("Connector"), html.Td(f"{pipe.connector_keys}")]),
|
248
|
-
html.Tr([html.Td("Metric"), html.Td(f"{pipe.metric_key}")]),
|
249
|
-
html.Tr([html.Td("Location"), html.Td(f"{pipe.location_key}")]),
|
250
|
-
html.Tr([html.Td("Instance"), html.Td(f"{pipe.instance_keys}")]),
|
251
|
-
html.Tr([html.Td("Target Table"), html.Td(f"{pipe.target}")]),
|
252
|
+
html.Tr([html.Td("Connector"), html.Td(html.Pre(f"{pipe.connector_keys}"))]),
|
253
|
+
html.Tr([html.Td("Metric"), html.Td(html.Pre(f"{pipe.metric_key}"))]),
|
254
|
+
html.Tr([html.Td("Location"), html.Td(html.Pre(f"{pipe.location_key}"))]),
|
255
|
+
html.Tr([html.Td("Instance"), html.Td(html.Pre(f"{pipe.instance_keys}"))]),
|
256
|
+
html.Tr([html.Td("Target Table"), html.Td(html.Pre(f"{pipe.target}"))]),
|
252
257
|
]
|
253
|
-
|
254
|
-
|
258
|
+
columns = pipe.columns.copy()
|
259
|
+
if columns:
|
260
|
+
datetime_index = columns.pop('datetime', None)
|
261
|
+
columns_items = []
|
262
|
+
if datetime_index:
|
263
|
+
columns_items.append(html.Li(f"{datetime_index} (datetime)"))
|
264
|
+
columns_items.extend([
|
265
|
+
html.Li(f"{col}")
|
266
|
+
for col_key, col in columns.items()
|
267
|
+
])
|
268
|
+
overview_rows.append(
|
269
|
+
html.Tr([
|
270
|
+
html.Td("Indices" if len(columns_items) != 1 else "Index"),
|
271
|
+
html.Td(html.Pre(html.Ul(columns_items))),
|
272
|
+
])
|
273
|
+
)
|
255
274
|
tags = pipe.tags
|
256
275
|
if tags:
|
257
276
|
tags_items = html.Ul([
|
@@ -261,7 +280,7 @@ def accordion_items_from_pipe(
|
|
261
280
|
overview_rows.append(
|
262
281
|
html.Tr([
|
263
282
|
html.Td("Tags"),
|
264
|
-
html.Td(tags_items),
|
283
|
+
html.Td(html.Pre(tags_items)),
|
265
284
|
])
|
266
285
|
)
|
267
286
|
|
@@ -8,7 +8,7 @@ Functions for managing packages and virtual environments reside here.
|
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
10
|
|
11
|
-
import importlib.util, os, pathlib
|
11
|
+
import importlib.util, os, pathlib, re
|
12
12
|
from meerschaum.utils.typing import Any, List, SuccessTuple, Optional, Union, Tuple, Dict, Iterable
|
13
13
|
from meerschaum.utils.threading import Lock, RLock
|
14
14
|
from meerschaum.utils.packages._packages import packages, all_packages, get_install_names
|
@@ -640,6 +640,9 @@ def need_update(
|
|
640
640
|
|
641
641
|
### We might be depending on a prerelease.
|
642
642
|
### Sanity check that the required version is not greater than the installed version.
|
643
|
+
if 'a' in required_version:
|
644
|
+
required_version = required_version.replace('a', '-dev')
|
645
|
+
version = version.replace('a', '-dev')
|
643
646
|
try:
|
644
647
|
return (
|
645
648
|
(not semver.Version.parse(version).match(required_version))
|
@@ -52,7 +52,7 @@ packages: Dict[str, Dict[str, str]] = {
|
|
52
52
|
'watchgod' : 'watchgod>=0.7.0',
|
53
53
|
'dill' : 'dill>=0.3.3',
|
54
54
|
'virtualenv' : 'virtualenv>=20.1.0',
|
55
|
-
'
|
55
|
+
'apscheduler' : 'apscheduler>=4.0.0a4',
|
56
56
|
},
|
57
57
|
'drivers': {
|
58
58
|
'cryptography' : 'cryptography>=38.0.1',
|
@@ -75,11 +75,11 @@ packages: Dict[str, Dict[str, str]] = {
|
|
75
75
|
'gadwall' : 'gadwall>=0.2.0',
|
76
76
|
},
|
77
77
|
'stack': {
|
78
|
-
'compose' : 'docker-compose>=1.
|
78
|
+
'compose' : 'docker-compose>=1.29.2',
|
79
79
|
},
|
80
80
|
'build': {
|
81
|
-
'cx_Freeze' : 'cx_Freeze>=
|
82
|
-
'PyInstaller' : 'pyinstaller
|
81
|
+
'cx_Freeze' : 'cx_Freeze>=7.0.0',
|
82
|
+
'PyInstaller' : 'pyinstaller>6.6.0',
|
83
83
|
},
|
84
84
|
'dev-tools': {
|
85
85
|
'twine' : 'twine>=3.2.0',
|
@@ -149,7 +149,7 @@ packages['api'] = {
|
|
149
149
|
'passlib' : 'passlib>=1.7.4',
|
150
150
|
'fastapi_login' : 'fastapi-login>=1.7.2',
|
151
151
|
'multipart' : 'python-multipart>=0.0.5',
|
152
|
-
'pydantic' : 'pydantic
|
152
|
+
# 'pydantic' : 'pydantic>2.0.0',
|
153
153
|
'httpx' : 'httpx>=0.24.1',
|
154
154
|
'websockets' : 'websockets>=11.0.3',
|
155
155
|
}
|
@@ -0,0 +1,304 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# vim:fenc=utf-8
|
4
|
+
|
5
|
+
"""
|
6
|
+
Schedule processes and threads.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from __future__ import annotations
|
10
|
+
import sys
|
11
|
+
from datetime import datetime, timezone, timedelta, timedelta
|
12
|
+
import meerschaum as mrsm
|
13
|
+
from meerschaum.utils.typing import Callable, Any, Optional, List, Dict
|
14
|
+
|
15
|
+
INTERVAL_UNITS: List[str] = ['months', 'weeks', 'days', 'hours', 'minutes', 'seconds']
|
16
|
+
FREQUENCY_ALIASES: Dict[str, str] = {
|
17
|
+
'daily': 'every 1 day',
|
18
|
+
'hourly': 'every 1 hour',
|
19
|
+
'minutely': 'every 1 minute',
|
20
|
+
'weekly': 'every 1 week',
|
21
|
+
'monthly': 'every 1 month',
|
22
|
+
'secondly': 'every 1 second',
|
23
|
+
}
|
24
|
+
LOGIC_ALIASES: Dict[str, str] = {
|
25
|
+
'and': '&',
|
26
|
+
'or': '|',
|
27
|
+
' through ': '-',
|
28
|
+
' thru ': '-',
|
29
|
+
' - ': '-',
|
30
|
+
'beginning': 'starting',
|
31
|
+
}
|
32
|
+
CRON_DAYS_OF_WEEK: List[str] = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
|
33
|
+
CRON_DAYS_OF_WEEK_ALIASES: Dict[str, str] = {
|
34
|
+
'monday': 'mon',
|
35
|
+
'tuesday': 'tue',
|
36
|
+
'tues': 'tue',
|
37
|
+
'wednesday': 'wed',
|
38
|
+
'thursday': 'thu',
|
39
|
+
'thurs': 'thu',
|
40
|
+
'friday': 'fri',
|
41
|
+
'saturday': 'sat',
|
42
|
+
'sunday': 'sun',
|
43
|
+
}
|
44
|
+
CRON_MONTHS: List[str] = [
|
45
|
+
'jan', 'feb', 'mar', 'apr', 'may', 'jun',
|
46
|
+
'jul', 'aug', 'sep', 'oct', 'nov', 'dec',
|
47
|
+
]
|
48
|
+
CRON_MONTHS_ALIASES: Dict[str, str] = {
|
49
|
+
'january': 'jan',
|
50
|
+
'february': 'feb',
|
51
|
+
'march': 'mar',
|
52
|
+
'april': 'apr',
|
53
|
+
'may': 'may',
|
54
|
+
'june': 'jun',
|
55
|
+
'july': 'jul',
|
56
|
+
'august': 'aug',
|
57
|
+
'september': 'sep',
|
58
|
+
'october': 'oct',
|
59
|
+
'november': 'nov',
|
60
|
+
'december': 'dec',
|
61
|
+
}
|
62
|
+
SCHEDULE_ALIASES: Dict[str, str] = {
|
63
|
+
**FREQUENCY_ALIASES,
|
64
|
+
**LOGIC_ALIASES,
|
65
|
+
**CRON_DAYS_OF_WEEK_ALIASES,
|
66
|
+
**CRON_MONTHS_ALIASES,
|
67
|
+
}
|
68
|
+
STARTING_KEYWORD: str = 'starting'
|
69
|
+
|
70
|
+
def schedule_function(
|
71
|
+
function: Callable[[Any], Any],
|
72
|
+
schedule: str,
|
73
|
+
*args,
|
74
|
+
debug: bool = False,
|
75
|
+
**kw
|
76
|
+
) -> None:
|
77
|
+
"""
|
78
|
+
Block the process and execute the function intermittently according to the frequency.
|
79
|
+
https://rocketry.readthedocs.io/en/stable/condition_syntax/index.html
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
function: Callable[[Any], Any]
|
84
|
+
The function to execute.
|
85
|
+
|
86
|
+
schedule: str
|
87
|
+
The frequency schedule at which `function` should be executed (e.g. `'daily'`).
|
88
|
+
|
89
|
+
"""
|
90
|
+
import warnings
|
91
|
+
from meerschaum.utils.warnings import warn
|
92
|
+
from meerschaum.utils.misc import filter_keywords, round_time
|
93
|
+
kw['debug'] = debug
|
94
|
+
kw = filter_keywords(function, **kw)
|
95
|
+
|
96
|
+
apscheduler = mrsm.attempt_import('apscheduler', lazy=False)
|
97
|
+
now = round_time(datetime.now(timezone.utc), timedelta(minutes=1))
|
98
|
+
trigger = parse_schedule(schedule, now=now)
|
99
|
+
|
100
|
+
with apscheduler.Scheduler() as scheduler:
|
101
|
+
job = scheduler.add_schedule(function, trigger, args=args, kwargs=kw)
|
102
|
+
try:
|
103
|
+
scheduler.run_until_stopped()
|
104
|
+
except KeyboardInterrupt as e:
|
105
|
+
scheduler.stop()
|
106
|
+
scheduler.wait_until_stopped()
|
107
|
+
|
108
|
+
|
109
|
+
def parse_schedule(schedule: str, now: Optional[datetime] = None):
|
110
|
+
"""
|
111
|
+
Parse a schedule string (e.g. 'daily') into a Trigger object.
|
112
|
+
"""
|
113
|
+
from meerschaum.utils.warnings import error
|
114
|
+
from meerschaum.utils.misc import items_str, is_int
|
115
|
+
(
|
116
|
+
apscheduler_triggers_cron,
|
117
|
+
apscheduler_triggers_interval,
|
118
|
+
apscheduler_triggers_calendarinterval,
|
119
|
+
apscheduler_triggers_combining,
|
120
|
+
) = (
|
121
|
+
mrsm.attempt_import(
|
122
|
+
'apscheduler.triggers.cron',
|
123
|
+
'apscheduler.triggers.interval',
|
124
|
+
'apscheduler.triggers.calendarinterval',
|
125
|
+
'apscheduler.triggers.combining',
|
126
|
+
lazy = False,
|
127
|
+
)
|
128
|
+
)
|
129
|
+
|
130
|
+
starting_ts = parse_start_time(schedule, now=now)
|
131
|
+
schedule = schedule.split(STARTING_KEYWORD)[0].strip()
|
132
|
+
for alias_keyword, true_keyword in SCHEDULE_ALIASES.items():
|
133
|
+
schedule = schedule.replace(alias_keyword, true_keyword)
|
134
|
+
|
135
|
+
### TODO Allow for combining `and` + `or` logic.
|
136
|
+
if '&' in schedule and '|' in schedule:
|
137
|
+
error(f"Cannot accept both 'and' + 'or' logic in the schedule frequency.", ValueError)
|
138
|
+
|
139
|
+
join_str = '|' if '|' in schedule else '&'
|
140
|
+
join_trigger = (
|
141
|
+
apscheduler_triggers_combining.OrTrigger
|
142
|
+
if join_str == '|'
|
143
|
+
else apscheduler_triggers_combining.AndTrigger
|
144
|
+
)
|
145
|
+
join_kwargs = {
|
146
|
+
'max_iterations': 1_000_000,
|
147
|
+
'threshold': 0,
|
148
|
+
} if join_str == '&' else {}
|
149
|
+
|
150
|
+
schedule_parts = [part.strip() for part in schedule.split(join_str)]
|
151
|
+
triggers = []
|
152
|
+
|
153
|
+
has_seconds = 'second' in schedule
|
154
|
+
has_minutes = 'minute' in schedule
|
155
|
+
has_days = 'day' in schedule
|
156
|
+
has_weeks = 'week' in schedule
|
157
|
+
has_hours = 'hour' in schedule
|
158
|
+
num_hourly_intervals = schedule.count('hour')
|
159
|
+
divided_days = False
|
160
|
+
divided_hours = False
|
161
|
+
|
162
|
+
for schedule_part in schedule_parts:
|
163
|
+
|
164
|
+
### Intervals must begin with 'every' (after alias substitution).
|
165
|
+
if schedule_part.lower().startswith('every '):
|
166
|
+
schedule_num_str, schedule_unit = (
|
167
|
+
schedule_part[len('every '):].split(' ', maxsplit=1)
|
168
|
+
)
|
169
|
+
schedule_unit = schedule_unit.rstrip('s') + 's'
|
170
|
+
if schedule_unit not in INTERVAL_UNITS:
|
171
|
+
error(
|
172
|
+
f"Invalid interval '{schedule_unit}'.\n"
|
173
|
+
+ f" Accepted values are {items_str(INTERVAL_UNITS)}.",
|
174
|
+
ValueError,
|
175
|
+
)
|
176
|
+
|
177
|
+
schedule_num = (
|
178
|
+
int(schedule_num_str)
|
179
|
+
if is_int(schedule_num_str)
|
180
|
+
else float(schedule_num_str)
|
181
|
+
)
|
182
|
+
|
183
|
+
### NOTE: When combining days or weeks with other schedules,
|
184
|
+
### we must divide one of the day-schedules by 2.
|
185
|
+
### TODO Remove this when APScheduler is patched.
|
186
|
+
if (
|
187
|
+
join_str == '&'
|
188
|
+
and (has_days or has_weeks)
|
189
|
+
and len(schedule_parts) > 1
|
190
|
+
and not divided_days
|
191
|
+
):
|
192
|
+
schedule_num /= 2
|
193
|
+
divided_days = True
|
194
|
+
|
195
|
+
### NOTE: When combining multiple hourly intervals,
|
196
|
+
### one must be divided by 2.
|
197
|
+
if (
|
198
|
+
join_str == '&'
|
199
|
+
# and num_hourly_intervals > 1
|
200
|
+
and len(schedule_parts) > 1
|
201
|
+
and not divided_hours
|
202
|
+
):
|
203
|
+
print("divided hours")
|
204
|
+
schedule_num /= 2
|
205
|
+
# divided_hours = True
|
206
|
+
|
207
|
+
trigger = (
|
208
|
+
apscheduler_triggers_interval.IntervalTrigger(
|
209
|
+
**{
|
210
|
+
schedule_unit: schedule_num,
|
211
|
+
'start_time': starting_ts,
|
212
|
+
}
|
213
|
+
)
|
214
|
+
if schedule_unit != 'months' else (
|
215
|
+
apscheduler_triggers_calendarinterval.CalendarIntervalTrigger(
|
216
|
+
**{
|
217
|
+
schedule_unit: schedule_num,
|
218
|
+
'start_date': starting_ts,
|
219
|
+
# 'timezone': starting_ts.tzinfo, TODO Re-enable once APScheduler updates.
|
220
|
+
}
|
221
|
+
)
|
222
|
+
)
|
223
|
+
)
|
224
|
+
|
225
|
+
### Determine whether this is a pure cron string or a cron subset (e.g. 'may-aug')_.
|
226
|
+
else:
|
227
|
+
first_three_prefix = schedule_part[:3]
|
228
|
+
cron_kw = {}
|
229
|
+
if first_three_prefix in CRON_DAYS_OF_WEEK:
|
230
|
+
cron_kw['day_of_week'] = schedule_part
|
231
|
+
elif first_three_prefix in CRON_MONTHS:
|
232
|
+
cron_kw['month'] = schedule_part
|
233
|
+
trigger = (
|
234
|
+
apscheduler_triggers_cron.CronTrigger(
|
235
|
+
**{
|
236
|
+
**cron_kw,
|
237
|
+
'hour': '*',
|
238
|
+
'minute': '*' if has_minutes else starting_ts.minute,
|
239
|
+
'second': '*' if has_seconds else starting_ts.second,
|
240
|
+
'start_time': starting_ts,
|
241
|
+
'timezone': starting_ts.tzinfo,
|
242
|
+
}
|
243
|
+
)
|
244
|
+
if cron_kw
|
245
|
+
else apscheduler_triggers_cron.CronTrigger.from_crontab(
|
246
|
+
schedule_part,
|
247
|
+
timezone = starting_ts.tzinfo,
|
248
|
+
)
|
249
|
+
)
|
250
|
+
### Explicitly set the `start_time` after building with `from_crontab`.
|
251
|
+
if trigger.start_time != starting_ts:
|
252
|
+
trigger.start_time = starting_ts
|
253
|
+
|
254
|
+
triggers.append(trigger)
|
255
|
+
|
256
|
+
return (
|
257
|
+
join_trigger(triggers, **join_kwargs)
|
258
|
+
if len(triggers) != 1
|
259
|
+
else triggers[0]
|
260
|
+
)
|
261
|
+
|
262
|
+
|
263
|
+
def parse_start_time(schedule: str, now: Optional[datetime] = None) -> datetime:
|
264
|
+
"""
|
265
|
+
Return the datetime to use for the given schedule string.
|
266
|
+
|
267
|
+
Parameters
|
268
|
+
----------
|
269
|
+
schedule: str
|
270
|
+
The schedule frequency to be parsed into a starting datetime.
|
271
|
+
|
272
|
+
now: Optional[datetime], default None
|
273
|
+
If provided, use this value as a default if no start time is explicitly stated.
|
274
|
+
|
275
|
+
Returns
|
276
|
+
-------
|
277
|
+
A `datetime` object, either `now` or the datetime embedded in the schedule string.
|
278
|
+
|
279
|
+
Examples
|
280
|
+
--------
|
281
|
+
>>> parse_start_time('daily starting 2024-01-01')
|
282
|
+
datetime.datetime(2024, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
|
283
|
+
>>> parse_start_time('monthly starting 1st')
|
284
|
+
datetime.datetime(2024, 5, 1, 0, 0, tzinfo=datetime.timezone.utc)
|
285
|
+
>>> parse_start_time('hourly starting 00:30')
|
286
|
+
datetime.datetime(2024, 5, 13, 0, 30, tzinfo=datetime.timezone.utc)
|
287
|
+
"""
|
288
|
+
from meerschaum.utils.misc import round_time
|
289
|
+
from meerschaum.utils.warnings import error, warn
|
290
|
+
dateutil_parser = mrsm.attempt_import('dateutil.parser')
|
291
|
+
starting_parts = schedule.split(STARTING_KEYWORD)
|
292
|
+
starting_str = ('now' if len(starting_parts) == 1 else starting_parts[-1]).strip()
|
293
|
+
now = now or round_time(datetime.now(timezone.utc), timedelta(minutes=1))
|
294
|
+
try:
|
295
|
+
starting_ts = now if starting_str == 'now' else dateutil_parser.parse(starting_str)
|
296
|
+
schedule_parse_error = None
|
297
|
+
except Exception as e:
|
298
|
+
warn(f"Unable to parse starting time from '{starting_str}'.", stack=False)
|
299
|
+
schedule_parse_error = str(e)
|
300
|
+
if schedule_parse_error:
|
301
|
+
error(schedule_parse_error, ValueError, stack=False)
|
302
|
+
if not starting_ts.tzinfo:
|
303
|
+
starting_ts = starting_ts.replace(tzinfo=timezone.utc)
|
304
|
+
return starting_ts
|