meerschaum 2.1.5__tar.gz → 2.1.7__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.1.5/meerschaum.egg-info → meerschaum-2.1.7}/PKG-INFO +1 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/shell/Shell.py +1 -6
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/api.py +1 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/sync.py +49 -21
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_shell.py +0 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_version.py +1 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_fetch.py +8 -11
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_pipes.py +47 -9
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/tables/__init__.py +0 -16
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_data.py +5 -4
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_dtypes.py +2 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_sync.py +26 -13
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/dataframe.py +183 -8
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/formatting/_pipes.py +44 -10
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/misc.py +34 -2
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/packages/__init__.py +4 -3
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/sql.py +27 -7
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/typing.py +11 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7/meerschaum.egg-info}/PKG-INFO +1 -1
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_sync.py +31 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/LICENSE +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/NOTICE +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/README.md +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/__main__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/arguments/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/arguments/_parse_arguments.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/arguments/_parser.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/docs/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/docs/index.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/entry.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/gui/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/gui/app/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/gui/app/_windows.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/gui/app/actions.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/gui/app/pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/shell/ShellCompleter.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/shell/ValidAutoSuggest.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/shell/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/shell/resources/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/term/TermPageHandler.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/term/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/_internal/term/tools.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/bootstrap.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/clear.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/copy.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/deduplicate.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/delete.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/drop.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/edit.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/install.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/login.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/os.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/pause.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/python.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/register.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/reload.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/setup.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/sh.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/show.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/sql.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/stack.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/start.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/stop.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/tag.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/uninstall.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/upgrade.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/actions/verify.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/_chain.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/_events.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/_oauth2.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/_websockets.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/actions.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/ansi_up.js +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/banner_1920x320.png +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/favicon.ico +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/logo_48x48.png +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/assets/logo_500x500.png +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/dashboard.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/jobs.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/login.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/callbacks/register.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/components.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/connectors.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/graphs.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/jobs.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/keys.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/dashboard.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/error.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/login.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pages/register.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/sync.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/users.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/websockets.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/dash/webterm.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/models/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/models/_interfaces.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/models/_locations.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/models/_metrics.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/models/_pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/bootstrap.min.css +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/dash.css +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/dbc_dark.css +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/styles.css +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/css/xterm.css +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/ico/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/ico/logo.ico +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/js/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/js/action_button.js +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/js/main.js +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/js/terminado.js +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/js/xterm.js +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/static/png/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/templates/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/templates/index.html +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/templates/old_index.html +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/templates/secret.html +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/resources/templates/termpage.html +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_actions.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_connectors.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_index.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_login.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_misc.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_users.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_version.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/routes/_webterm.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/api/tables/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_default.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_edit.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_environment.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_formatting.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_jobs.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_patch.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_paths.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_preprocess.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_read_config.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/_sync.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/resources/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/stack/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/stack/grafana/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/stack/mosquitto/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/stack/mosquitto/resources/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/stack/resources/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/config/static/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/Connector.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/APIConnector.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_actions.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_fetch.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_login.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_misc.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_request.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_uri.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/api/_users.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/parse.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/plugin/PluginConnector.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/plugin/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/poll.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/SQLConnector.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_cli.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_create_engine.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_instance.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_plugins.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_sql.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_uri.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/_users.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/tables/types.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/connectors/sql/tools.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_attributes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_bootstrap.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_clear.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_deduplicate.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_delete.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_drop.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_edit.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_fetch.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_register.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_show.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Pipe/_verify.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/Plugin/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/User/_User.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/User/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/core/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/plugins/_Plugin.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/plugins/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/_get_pipes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/daemon/Daemon.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/daemon/RotatingFile.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/daemon/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/daemon/_names.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/debug.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/dtypes/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/dtypes/sql.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/formatting/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/formatting/_jobs.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/formatting/_pprint.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/formatting/_shell.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/interactive.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/networking.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/packages/_packages.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/packages/lazy_loader.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/pool.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/process.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/prompt.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/schedule.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/threading.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/venv/_Venv.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/venv/__init__.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/warnings.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum/utils/yaml.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/SOURCES.txt +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/dependency_links.txt +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/entry_points.txt +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/requires.txt +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/top_level.txt +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/meerschaum.egg-info/zip-safe +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/setup.cfg +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/setup.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_deduplicate.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_pipes_dtypes.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_sql.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_users.py +0 -0
- {meerschaum-2.1.5 → meerschaum-2.1.7}/tests/test_verify.py +0 -0
@@ -11,11 +11,7 @@ from copy import deepcopy
|
|
11
11
|
from meerschaum.utils.typing import Union, SuccessTuple, Any, Callable, Optional, List, Dict
|
12
12
|
from meerschaum.utils.packages import attempt_import
|
13
13
|
from meerschaum.config import __doc__, __version__ as version, get_config
|
14
|
-
|
15
|
-
cmd_venv = None if cmd_import_name == 'cmd' else 'mrsm'
|
16
|
-
cmd = attempt_import(cmd_import_name, venv=cmd_venv, warn=False, lazy=False)
|
17
|
-
if cmd is None or isinstance(cmd, dict):
|
18
|
-
cmd = attempt_import('cmd', lazy=False, warn=False)
|
14
|
+
import cmd
|
19
15
|
_old_input = cmd.__builtins__['input']
|
20
16
|
prompt_toolkit = attempt_import('prompt_toolkit', lazy=False, warn=False, install=True)
|
21
17
|
(
|
@@ -53,7 +49,6 @@ hidden_commands = {
|
|
53
49
|
'os',
|
54
50
|
'sh',
|
55
51
|
'pass',
|
56
|
-
'exit',
|
57
52
|
'quit',
|
58
53
|
'eof',
|
59
54
|
'exit',
|
@@ -44,7 +44,7 @@ def api(
|
|
44
44
|
sysargs = []
|
45
45
|
if len(action) == 0:
|
46
46
|
info(api.__doc__)
|
47
|
-
return False, "Please provide a command to
|
47
|
+
return False, "Please provide a command to execute (see above)."
|
48
48
|
|
49
49
|
boot_keywords = {'start', 'boot', 'init'}
|
50
50
|
if action[0] in boot_keywords:
|
@@ -9,7 +9,7 @@ NOTE: `sync` required a SQL connection and is not intended for client use
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
from __future__ import annotations
|
12
|
-
from datetime import timedelta
|
12
|
+
from datetime import timedelta, datetime, timezone
|
13
13
|
import meerschaum as mrsm
|
14
14
|
from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Tuple, Union
|
15
15
|
|
@@ -39,7 +39,7 @@ def sync(
|
|
39
39
|
|
40
40
|
def _pipes_lap(
|
41
41
|
workers: Optional[int] = None,
|
42
|
-
debug: bool = None,
|
42
|
+
debug: Optional[bool] = None,
|
43
43
|
unblock: bool = False,
|
44
44
|
force: bool = False,
|
45
45
|
min_seconds: int = 1,
|
@@ -52,7 +52,7 @@ def _pipes_lap(
|
|
52
52
|
nopretty: bool = False,
|
53
53
|
_progress: Optional['rich.progress.Progress'] = None,
|
54
54
|
**kw: Any
|
55
|
-
) -> Tuple[List[
|
55
|
+
) -> Tuple[List[mrsm.Pipe], List[mrsm.Pipe]]:
|
56
56
|
"""
|
57
57
|
Do a lap of syncing pipes.
|
58
58
|
"""
|
@@ -402,11 +402,20 @@ def _wrap_pipe(
|
|
402
402
|
Wrapper function for handling exceptions.
|
403
403
|
"""
|
404
404
|
import time
|
405
|
+
import traceback
|
406
|
+
from datetime import datetime, timedelta, timezone
|
407
|
+
import meerschaum as mrsm
|
408
|
+
from meerschaum.utils.typing import is_success_tuple, SuccessTuple
|
405
409
|
from meerschaum.connectors import get_connector_plugin
|
406
410
|
from meerschaum.utils.venv import Venv
|
407
411
|
from meerschaum.plugins import _pre_sync_hooks, _post_sync_hooks
|
408
412
|
from meerschaum.utils.misc import filter_keywords
|
413
|
+
from meerschaum.utils.pool import get_pool
|
414
|
+
from meerschaum.utils.warnings import warn
|
415
|
+
|
416
|
+
pool = get_pool(workers=workers)
|
409
417
|
|
418
|
+
sync_timestamp = datetime.now(timezone.utc)
|
410
419
|
sync_start = time.perf_counter()
|
411
420
|
sync_kwargs = {k: v for k, v in kw.items() if k != 'blocking'}
|
412
421
|
sync_kwargs.update({
|
@@ -415,8 +424,9 @@ def _wrap_pipe(
|
|
415
424
|
'debug': debug,
|
416
425
|
'min_seconds': min_seconds,
|
417
426
|
'workers': workers,
|
418
|
-
'bounded':
|
427
|
+
'bounded': bounded,
|
419
428
|
'chunk_interval': chunk_interval,
|
429
|
+
'sync_timestamp': sync_timestamp,
|
420
430
|
})
|
421
431
|
if not verify and not deduplicate:
|
422
432
|
sync_method = pipe.sync
|
@@ -427,12 +437,32 @@ def _wrap_pipe(
|
|
427
437
|
sync_kwargs['deduplicate'] = deduplicate
|
428
438
|
sync_kwargs['sync_method'] = sync_method
|
429
439
|
|
430
|
-
|
431
|
-
plugin_name = module_name.split('.')[-1] if module_name.startswith('plugins.') else None
|
440
|
+
def call_sync_hook(plugin_name: str, sync_hook) -> SuccessTuple:
|
432
441
|
plugin = mrsm.Plugin(plugin_name) if plugin_name else None
|
433
|
-
with Venv(plugin):
|
434
|
-
|
435
|
-
|
442
|
+
with mrsm.Venv(plugin):
|
443
|
+
try:
|
444
|
+
sync_hook_result = sync_hook(pipe, **filter_keywords(sync_hook, **sync_kwargs))
|
445
|
+
if is_success_tuple(sync_hook_result):
|
446
|
+
return sync_hook_result
|
447
|
+
except Exception as e:
|
448
|
+
msg = (
|
449
|
+
f"Failed to execute sync hook '{sync_hook.__name__}' "
|
450
|
+
+ f"from plugin '{plugin}':\n{traceback.format_exc()}"
|
451
|
+
)
|
452
|
+
warn(msg, stack=False)
|
453
|
+
return False, msg
|
454
|
+
return True, "Success"
|
455
|
+
|
456
|
+
hook_results = []
|
457
|
+
def apply_hooks(is_pre_sync: bool):
|
458
|
+
_sync_hooks = (_pre_sync_hooks if is_pre_sync else _post_sync_hooks)
|
459
|
+
for module_name, sync_hooks in _sync_hooks.items():
|
460
|
+
plugin_name = module_name.split('.')[-1] if module_name.startswith('plugins.') else None
|
461
|
+
for sync_hook in sync_hooks:
|
462
|
+
hook_result = pool.apply_async(call_sync_hook, (plugin_name, sync_hook))
|
463
|
+
hook_results.append(hook_result)
|
464
|
+
|
465
|
+
apply_hooks(True)
|
436
466
|
|
437
467
|
try:
|
438
468
|
with Venv(get_connector_plugin(pipe.connector), debug=debug):
|
@@ -444,18 +474,16 @@ def _wrap_pipe(
|
|
444
474
|
return_tuple = (False, f"Failed to sync {pipe} with exception:" + "\n" + str(e))
|
445
475
|
|
446
476
|
duration = time.perf_counter() - sync_start
|
447
|
-
sync_kwargs
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
)
|
458
|
-
|
477
|
+
sync_kwargs.update({
|
478
|
+
'success_tuple': return_tuple,
|
479
|
+
'sync_duration': duration,
|
480
|
+
'sync_complete_timestamp': datetime.now(timezone.utc),
|
481
|
+
})
|
482
|
+
apply_hooks(False)
|
483
|
+
for hook_result in hook_results:
|
484
|
+
hook_success, hook_msg = hook_result.get()
|
485
|
+
mrsm.pprint((hook_success, hook_msg))
|
486
|
+
|
459
487
|
return return_tuple
|
460
488
|
|
461
489
|
|
@@ -174,9 +174,6 @@ def get_pipe_metadef(
|
|
174
174
|
)
|
175
175
|
|
176
176
|
|
177
|
-
if 'order by' in definition.lower() and 'over' not in definition.lower():
|
178
|
-
error("Cannot fetch with an ORDER clause in the definition")
|
179
|
-
|
180
177
|
apply_backtrack = begin == '' and check_existing
|
181
178
|
backtrack_interval = pipe.get_backtrack_interval(check_existing=check_existing, debug=debug)
|
182
179
|
btm = (
|
@@ -308,9 +305,9 @@ def _simple_fetch_query(pipe, debug: bool=False, **kw) -> str:
|
|
308
305
|
def_name = 'definition'
|
309
306
|
definition = get_pipe_query(pipe)
|
310
307
|
return (
|
311
|
-
f"WITH {def_name} AS ({definition}) SELECT * FROM {def_name}"
|
308
|
+
f"WITH {def_name} AS (\n{definition}\n) SELECT * FROM {def_name}"
|
312
309
|
if pipe.connector.flavor not in ('mysql', 'mariadb')
|
313
|
-
else f"SELECT * FROM ({definition}) AS {def_name}"
|
310
|
+
else f"SELECT * FROM (\n{definition}\n) AS {def_name}"
|
314
311
|
)
|
315
312
|
|
316
313
|
def _join_fetch_query(
|
@@ -363,10 +360,10 @@ def _join_fetch_query(
|
|
363
360
|
)
|
364
361
|
+ f") AS {id_remote_name}, "
|
365
362
|
+ dateadd_str(
|
366
|
-
flavor=pipe.connector.flavor,
|
367
|
-
begin=_st,
|
368
|
-
datepart='minute',
|
369
|
-
number=pipe.parameters.get('fetch', {}).get('backtrack_minutes', 0)
|
363
|
+
flavor = pipe.connector.flavor,
|
364
|
+
begin = _st,
|
365
|
+
datepart = 'minute',
|
366
|
+
number = pipe.parameters.get('fetch', {}).get('backtrack_minutes', 0)
|
370
367
|
) + " AS " + dt_remote_name + "\nUNION ALL\n"
|
371
368
|
)
|
372
369
|
_sync_times_q = _sync_times_q[:(-1 * len('UNION ALL\n'))] + ")"
|
@@ -374,13 +371,13 @@ def _join_fetch_query(
|
|
374
371
|
definition = get_pipe_query(pipe)
|
375
372
|
query = (
|
376
373
|
f"""
|
377
|
-
WITH definition AS ({definition}){_sync_times_q}
|
374
|
+
WITH definition AS (\n{definition}\n){_sync_times_q}
|
378
375
|
SELECT definition.*
|
379
376
|
FROM definition"""
|
380
377
|
if pipe.connector.flavor not in ('mysql', 'mariadb')
|
381
378
|
else (
|
382
379
|
f"""
|
383
|
-
SELECT * FROM ({definition}) AS definition"""
|
380
|
+
SELECT * FROM (\n{definition}\n) AS definition"""
|
384
381
|
)
|
385
382
|
) + f"""
|
386
383
|
LEFT OUTER JOIN {sync_times_remote_name} AS st
|
@@ -385,7 +385,13 @@ def get_create_index_queries(
|
|
385
385
|
-------
|
386
386
|
A dictionary of column names mapping to lists of queries.
|
387
387
|
"""
|
388
|
-
from meerschaum.utils.sql import
|
388
|
+
from meerschaum.utils.sql import (
|
389
|
+
sql_item_name,
|
390
|
+
get_distinct_col_count,
|
391
|
+
update_queries,
|
392
|
+
get_null_replacement,
|
393
|
+
COALESCE_UNIQUE_INDEX_FLAVORS,
|
394
|
+
)
|
389
395
|
from meerschaum.config import get_config
|
390
396
|
index_queries = {}
|
391
397
|
|
@@ -497,15 +503,37 @@ def get_create_index_queries(
|
|
497
503
|
if ix and ix in existing_cols_types
|
498
504
|
]
|
499
505
|
)
|
506
|
+
coalesce_indices_cols_str = ', '.join(
|
507
|
+
[
|
508
|
+
(
|
509
|
+
"COALESCE("
|
510
|
+
+ sql_item_name(ix, self.flavor)
|
511
|
+
+ ", "
|
512
|
+
+ get_null_replacement(existing_cols_types[ix], self.flavor)
|
513
|
+
+ ") "
|
514
|
+
) if ix_key != 'datetime' else (sql_item_name(ix, self.flavor))
|
515
|
+
for ix_key, ix in pipe.columns.items()
|
516
|
+
if ix and ix in existing_cols_types
|
517
|
+
]
|
518
|
+
)
|
519
|
+
unique_index_name = sql_item_name(pipe.target + '_unique_index', self.flavor)
|
500
520
|
constraint_name = sql_item_name(pipe.target + '_constraint', self.flavor)
|
501
|
-
|
521
|
+
add_constraint_query = (
|
502
522
|
f"ALTER TABLE {_pipe_name} ADD CONSTRAINT {constraint_name} UNIQUE ({indices_cols_str})"
|
503
|
-
if self.flavor != 'sqlite'
|
504
|
-
else f"CREATE UNIQUE INDEX {constraint_name} ON {_pipe_name} ({indices_cols_str})"
|
505
523
|
)
|
524
|
+
unique_index_cols_str = (
|
525
|
+
indices_cols_str
|
526
|
+
if self.flavor not in COALESCE_UNIQUE_INDEX_FLAVORS
|
527
|
+
else coalesce_indices_cols_str
|
528
|
+
)
|
529
|
+
create_unique_index_query = (
|
530
|
+
f"CREATE UNIQUE INDEX {unique_index_name} ON {_pipe_name} ({unique_index_cols_str})"
|
531
|
+
)
|
532
|
+
constraint_queries = [create_unique_index_query]
|
533
|
+
if self.flavor != 'sqlite':
|
534
|
+
constraint_queries.append(add_constraint_query)
|
506
535
|
if upsert and indices_cols_str:
|
507
|
-
index_queries[
|
508
|
-
|
536
|
+
index_queries[unique_index_name] = constraint_queries
|
509
537
|
return index_queries
|
510
538
|
|
511
539
|
|
@@ -1074,7 +1102,7 @@ def get_pipe_attributes(
|
|
1074
1102
|
def sync_pipe(
|
1075
1103
|
self,
|
1076
1104
|
pipe: mrsm.Pipe,
|
1077
|
-
df: Union[
|
1105
|
+
df: Union[pd.DataFrame, str, Dict[Any, Any], None] = None,
|
1078
1106
|
begin: Optional[datetime] = None,
|
1079
1107
|
end: Optional[datetime] = None,
|
1080
1108
|
chunksize: Optional[int] = -1,
|
@@ -1154,7 +1182,12 @@ def sync_pipe(
|
|
1154
1182
|
dprint("Fetched data:\n" + str(df))
|
1155
1183
|
|
1156
1184
|
if not isinstance(df, pd.DataFrame):
|
1157
|
-
df = pipe.enforce_dtypes(
|
1185
|
+
df = pipe.enforce_dtypes(
|
1186
|
+
df,
|
1187
|
+
chunksize = chunksize,
|
1188
|
+
safe_copy = kw.get('safe_copy', False),
|
1189
|
+
debug = debug,
|
1190
|
+
)
|
1158
1191
|
|
1159
1192
|
### if table does not exist, create it with indices
|
1160
1193
|
is_new = False
|
@@ -1198,6 +1231,7 @@ def sync_pipe(
|
|
1198
1231
|
upsert = pipe.parameters.get('upsert', False) and (self.flavor + '-upsert') in update_queries
|
1199
1232
|
if upsert:
|
1200
1233
|
check_existing = False
|
1234
|
+
kw['safe_copy'] = kw.get('safe_copy', False)
|
1201
1235
|
|
1202
1236
|
unseen_df, update_df, delta_df = (
|
1203
1237
|
pipe.filter_existing(
|
@@ -1286,7 +1320,11 @@ def sync_pipe(
|
|
1286
1320
|
temp_pipe = Pipe(
|
1287
1321
|
pipe.connector_keys.replace(':', '_') + '_', pipe.metric_key, pipe.location_key,
|
1288
1322
|
instance = pipe.instance_keys,
|
1289
|
-
columns =
|
1323
|
+
columns = {
|
1324
|
+
ix_key: ix
|
1325
|
+
for ix_key, ix in pipe.columns.items()
|
1326
|
+
if ix and ix in update_df.columns
|
1327
|
+
},
|
1290
1328
|
dtypes = pipe.dtypes,
|
1291
1329
|
target = temp_target,
|
1292
1330
|
temporary = True,
|
@@ -214,22 +214,6 @@ def create_tables(
|
|
214
214
|
from meerschaum.utils.sql import get_rename_table_queries, table_exists
|
215
215
|
_tables = tables if tables is not None else get_tables(conn)
|
216
216
|
|
217
|
-
rename_queries = []
|
218
|
-
for table_key, table in _tables.items():
|
219
|
-
if table_exists(
|
220
|
-
table_key,
|
221
|
-
conn,
|
222
|
-
schema = conn.instance_schema,
|
223
|
-
):
|
224
|
-
rename_queries.extend(get_rename_table_queries(
|
225
|
-
table_key,
|
226
|
-
table.name,
|
227
|
-
schema = conn.instance_schema,
|
228
|
-
flavor = conn.flavor,
|
229
|
-
))
|
230
|
-
if rename_queries:
|
231
|
-
conn.exec_queries(rename_queries)
|
232
|
-
|
233
217
|
try:
|
234
218
|
conn.metadata.create_all(bind=conn.engine)
|
235
219
|
except Exception as e:
|
@@ -8,7 +8,7 @@ Retrieve Pipes' data from instances.
|
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
10
|
from datetime import datetime, timedelta
|
11
|
-
from meerschaum.utils.typing import Optional, Dict, Any, Union, Generator, List, Tuple
|
11
|
+
from meerschaum.utils.typing import Optional, Dict, Any, Union, Generator, List, Tuple, Iterator
|
12
12
|
from meerschaum.config import get_config
|
13
13
|
|
14
14
|
def get_data(
|
@@ -247,7 +247,7 @@ def _get_data_as_iterator(
|
|
247
247
|
fresh: bool = False,
|
248
248
|
debug: bool = False,
|
249
249
|
**kw: Any
|
250
|
-
) ->
|
250
|
+
) -> Iterator['pd.DataFrame']:
|
251
251
|
"""
|
252
252
|
Return a pipe's data as a generator.
|
253
253
|
"""
|
@@ -267,16 +267,17 @@ def _get_data_as_iterator(
|
|
267
267
|
|
268
268
|
_ = kw.pop('as_chunks', None)
|
269
269
|
_ = kw.pop('as_iterator', None)
|
270
|
+
dt_col = self.columns.get('datetime', None)
|
270
271
|
min_dt = (
|
271
272
|
begin
|
272
273
|
if begin is not None
|
273
274
|
else self.get_sync_time(round_down=False, newest=False, params=params, debug=debug)
|
274
|
-
)
|
275
|
+
) if dt_col else None
|
275
276
|
max_dt = (
|
276
277
|
end
|
277
278
|
if end is not None
|
278
279
|
else self.get_sync_time(round_down=False, newest=True, params=params, debug=debug)
|
279
|
-
)
|
280
|
+
) if dt_col else None
|
280
281
|
|
281
282
|
### We want to search just past the maximum value.
|
282
283
|
if end is None:
|
@@ -14,6 +14,7 @@ def enforce_dtypes(
|
|
14
14
|
self,
|
15
15
|
df: 'pd.DataFrame',
|
16
16
|
chunksize: Optional[int] = -1,
|
17
|
+
safe_copy: bool = True,
|
17
18
|
debug: bool = False,
|
18
19
|
) -> 'pd.DataFrame':
|
19
20
|
"""
|
@@ -71,7 +72,7 @@ def enforce_dtypes(
|
|
71
72
|
)
|
72
73
|
return df
|
73
74
|
|
74
|
-
return _enforce_dtypes(df, pipe_dtypes, debug=debug)
|
75
|
+
return _enforce_dtypes(df, pipe_dtypes, safe_copy=safe_copy, debug=debug)
|
75
76
|
|
76
77
|
|
77
78
|
def infer_dtypes(self, persist: bool=False, debug: bool=False) -> Dict[str, Any]:
|
@@ -12,6 +12,7 @@ import json
|
|
12
12
|
import time
|
13
13
|
import threading
|
14
14
|
import multiprocessing
|
15
|
+
import functools
|
15
16
|
from datetime import datetime, timedelta
|
16
17
|
|
17
18
|
from meerschaum.utils.typing import (
|
@@ -518,6 +519,8 @@ def exists(
|
|
518
519
|
def filter_existing(
|
519
520
|
self,
|
520
521
|
df: 'pd.DataFrame',
|
522
|
+
safe_copy: bool = True,
|
523
|
+
date_bound_only: bool = False,
|
521
524
|
chunksize: Optional[int] = -1,
|
522
525
|
debug: bool = False,
|
523
526
|
**kw
|
@@ -530,6 +533,14 @@ def filter_existing(
|
|
530
533
|
df: 'pd.DataFrame'
|
531
534
|
The dataframe to inspect and filter.
|
532
535
|
|
536
|
+
safe_copy: bool, default True
|
537
|
+
If `True`, create a copy before comparing and modifying the dataframes.
|
538
|
+
Setting to `False` may mutate the DataFrames.
|
539
|
+
See `meerschaum.utils.dataframe.filter_unseen_df`.
|
540
|
+
|
541
|
+
date_bound_only: bool, default False
|
542
|
+
If `True`, only use the datetime index to fetch the sample dataframe.
|
543
|
+
|
533
544
|
chunksize: Optional[int], default -1
|
534
545
|
The `chunksize` used when fetching existing data.
|
535
546
|
|
@@ -567,7 +578,8 @@ def filter_existing(
|
|
567
578
|
else:
|
568
579
|
merge = pd.merge
|
569
580
|
NA = pd.NA
|
570
|
-
|
581
|
+
if df is None:
|
582
|
+
return df, df, df
|
571
583
|
if (df.empty if not is_dask else len(df) == 0):
|
572
584
|
return df, df, df
|
573
585
|
|
@@ -617,7 +629,7 @@ def filter_existing(
|
|
617
629
|
traceback.print_exc()
|
618
630
|
max_dt = None
|
619
631
|
|
620
|
-
if
|
632
|
+
if ('datetime' not in str(type(max_dt))) or str(min_dt) == 'NaT':
|
621
633
|
if 'int' not in str(type(max_dt)).lower():
|
622
634
|
max_dt = None
|
623
635
|
|
@@ -645,7 +657,7 @@ def filter_existing(
|
|
645
657
|
col: df[col].unique()
|
646
658
|
for col in self.columns
|
647
659
|
if col in df.columns and col != dt_col
|
648
|
-
}
|
660
|
+
} if not date_bound_only else {}
|
649
661
|
filter_params_index_limit = get_config('pipes', 'sync', 'filter_params_index_limit')
|
650
662
|
_ = kw.pop('params', None)
|
651
663
|
params = {
|
@@ -655,7 +667,7 @@ def filter_existing(
|
|
655
667
|
]
|
656
668
|
for col, unique_vals in unique_index_vals.items()
|
657
669
|
if len(unique_vals) <= filter_params_index_limit
|
658
|
-
}
|
670
|
+
} if not date_bound_only else {}
|
659
671
|
|
660
672
|
if debug:
|
661
673
|
dprint(f"Looking at data between '{begin}' and '{end}':", **kw)
|
@@ -698,18 +710,23 @@ def filter_existing(
|
|
698
710
|
col: to_pandas_dtype(typ)
|
699
711
|
for col, typ in self_dtypes.items()
|
700
712
|
},
|
713
|
+
safe_copy = safe_copy,
|
701
714
|
debug = debug
|
702
715
|
),
|
703
716
|
on_cols_dtypes,
|
704
717
|
)
|
705
718
|
|
706
719
|
### Cast dicts or lists to strings so we can merge.
|
720
|
+
serializer = functools.partial(json.dumps, sort_keys=True, separators=(',', ':'), default=str)
|
721
|
+
def deserializer(x):
|
722
|
+
return json.loads(x) if isinstance(x, str) else x
|
723
|
+
|
707
724
|
unhashable_delta_cols = get_unhashable_cols(delta_df)
|
708
725
|
unhashable_backtrack_cols = get_unhashable_cols(backtrack_df)
|
709
726
|
for col in unhashable_delta_cols:
|
710
|
-
delta_df[col] = delta_df[col].apply(
|
727
|
+
delta_df[col] = delta_df[col].apply(serializer)
|
711
728
|
for col in unhashable_backtrack_cols:
|
712
|
-
backtrack_df[col] = backtrack_df[col].apply(
|
729
|
+
backtrack_df[col] = backtrack_df[col].apply(serializer)
|
713
730
|
casted_cols = set(unhashable_delta_cols + unhashable_backtrack_cols)
|
714
731
|
|
715
732
|
joined_df = merge(
|
@@ -722,13 +739,9 @@ def filter_existing(
|
|
722
739
|
) if on_cols else delta_df
|
723
740
|
for col in casted_cols:
|
724
741
|
if col in joined_df.columns:
|
725
|
-
joined_df[col] = joined_df[col].apply(
|
726
|
-
|
727
|
-
|
728
|
-
if isinstance(x, str)
|
729
|
-
else x
|
730
|
-
)
|
731
|
-
)
|
742
|
+
joined_df[col] = joined_df[col].apply(deserializer)
|
743
|
+
if col in delta_df.columns:
|
744
|
+
delta_df[col] = delta_df[col].apply(deserializer)
|
732
745
|
|
733
746
|
### Determine which rows are completely new.
|
734
747
|
new_rows_mask = (joined_df['_merge'] == 'left_only') if on_cols else None
|