meerschaum 2.2.0.dev1__tar.gz → 2.2.0.dev3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. {meerschaum-2.2.0.dev1/meerschaum.egg-info → meerschaum-2.2.0.dev3}/PKG-INFO +8 -10
  2. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/dashboard.py +18 -12
  3. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pipes.py +44 -25
  4. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_version.py +1 -1
  5. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/stack/__init__.py +0 -1
  6. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/packages/__init__.py +4 -1
  7. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/packages/_packages.py +5 -5
  8. meerschaum-2.2.0.dev3/meerschaum/utils/schedule.py +303 -0
  9. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3/meerschaum.egg-info}/PKG-INFO +8 -10
  10. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/requires.txt +7 -9
  11. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/tests/test_sync.py +9 -1
  12. meerschaum-2.2.0.dev1/meerschaum/utils/schedule.py +0 -65
  13. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/LICENSE +0 -0
  14. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/NOTICE +0 -0
  15. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/README.md +0 -0
  16. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/__init__.py +0 -0
  17. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/__main__.py +0 -0
  18. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/__init__.py +0 -0
  19. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/arguments/__init__.py +0 -0
  20. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/arguments/_parse_arguments.py +0 -0
  21. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/arguments/_parser.py +0 -0
  22. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/docs/__init__.py +0 -0
  23. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/docs/index.py +0 -0
  24. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/entry.py +0 -0
  25. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/gui/__init__.py +0 -0
  26. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/gui/app/__init__.py +0 -0
  27. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/gui/app/_windows.py +0 -0
  28. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/gui/app/actions.py +0 -0
  29. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/gui/app/pipes.py +0 -0
  30. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/shell/Shell.py +0 -0
  31. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/shell/ShellCompleter.py +0 -0
  32. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/shell/ValidAutoSuggest.py +0 -0
  33. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/shell/__init__.py +0 -0
  34. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/shell/resources/__init__.py +0 -0
  35. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/term/TermPageHandler.py +0 -0
  36. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/term/__init__.py +0 -0
  37. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/_internal/term/tools.py +0 -0
  38. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/__init__.py +0 -0
  39. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/api.py +0 -0
  40. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/bootstrap.py +0 -0
  41. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/clear.py +0 -0
  42. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/copy.py +0 -0
  43. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/deduplicate.py +0 -0
  44. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/delete.py +0 -0
  45. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/drop.py +0 -0
  46. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/edit.py +0 -0
  47. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/install.py +0 -0
  48. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/login.py +0 -0
  49. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/os.py +0 -0
  50. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/pause.py +0 -0
  51. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/python.py +0 -0
  52. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/register.py +0 -0
  53. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/reload.py +0 -0
  54. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/setup.py +0 -0
  55. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/sh.py +0 -0
  56. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/show.py +0 -0
  57. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/sql.py +0 -0
  58. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/stack.py +0 -0
  59. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/start.py +0 -0
  60. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/stop.py +0 -0
  61. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/sync.py +0 -0
  62. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/tag.py +0 -0
  63. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/uninstall.py +0 -0
  64. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/upgrade.py +0 -0
  65. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/actions/verify.py +0 -0
  66. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/__init__.py +0 -0
  67. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/_chain.py +0 -0
  68. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/_events.py +0 -0
  69. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/_oauth2.py +0 -0
  70. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/_websockets.py +0 -0
  71. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/__init__.py +0 -0
  72. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/actions.py +0 -0
  73. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/__init__.py +0 -0
  74. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/ansi_up.js +0 -0
  75. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/banner_1920x320.png +0 -0
  76. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/favicon.ico +0 -0
  77. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/logo_48x48.png +0 -0
  78. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/assets/logo_500x500.png +0 -0
  79. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/__init__.py +0 -0
  80. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/jobs.py +0 -0
  81. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/login.py +0 -0
  82. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/plugins.py +0 -0
  83. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/callbacks/register.py +0 -0
  84. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/components.py +0 -0
  85. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/connectors.py +0 -0
  86. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/graphs.py +0 -0
  87. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/jobs.py +0 -0
  88. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/keys.py +0 -0
  89. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/__init__.py +0 -0
  90. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/dashboard.py +0 -0
  91. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/error.py +0 -0
  92. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/login.py +0 -0
  93. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/plugins.py +0 -0
  94. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/pages/register.py +0 -0
  95. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/plugins.py +0 -0
  96. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/sync.py +0 -0
  97. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/users.py +0 -0
  98. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/websockets.py +0 -0
  99. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/dash/webterm.py +0 -0
  100. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/models/__init__.py +0 -0
  101. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/models/_interfaces.py +0 -0
  102. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/models/_locations.py +0 -0
  103. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/models/_metrics.py +0 -0
  104. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/models/_pipes.py +0 -0
  105. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/__init__.py +0 -0
  106. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/__init__.py +0 -0
  107. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/__init__.py +0 -0
  108. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/bootstrap.min.css +0 -0
  109. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/dash.css +0 -0
  110. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/dbc_dark.css +0 -0
  111. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/styles.css +0 -0
  112. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/css/xterm.css +0 -0
  113. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/ico/__init__.py +0 -0
  114. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/ico/logo.ico +0 -0
  115. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/js/__init__.py +0 -0
  116. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/js/action_button.js +0 -0
  117. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/js/main.js +0 -0
  118. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/js/terminado.js +0 -0
  119. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/js/xterm.js +0 -0
  120. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/static/png/__init__.py +0 -0
  121. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/templates/__init__.py +0 -0
  122. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/templates/index.html +0 -0
  123. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/templates/old_index.html +0 -0
  124. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/templates/secret.html +0 -0
  125. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/resources/templates/termpage.html +0 -0
  126. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/__init__.py +0 -0
  127. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_actions.py +0 -0
  128. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_connectors.py +0 -0
  129. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_index.py +0 -0
  130. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_login.py +0 -0
  131. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_misc.py +0 -0
  132. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_pipes.py +0 -0
  133. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_plugins.py +0 -0
  134. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_users.py +0 -0
  135. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_version.py +0 -0
  136. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/routes/_webterm.py +0 -0
  137. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/api/tables/__init__.py +0 -0
  138. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/__init__.py +0 -0
  139. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_default.py +0 -0
  140. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_edit.py +0 -0
  141. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_environment.py +0 -0
  142. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_formatting.py +0 -0
  143. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_jobs.py +0 -0
  144. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_patch.py +0 -0
  145. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_paths.py +0 -0
  146. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_preprocess.py +0 -0
  147. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_read_config.py +0 -0
  148. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_shell.py +0 -0
  149. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/_sync.py +0 -0
  150. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/resources/__init__.py +0 -0
  151. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/stack/grafana/__init__.py +0 -0
  152. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/stack/mosquitto/__init__.py +0 -0
  153. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/stack/mosquitto/resources/__init__.py +0 -0
  154. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/stack/resources/__init__.py +0 -0
  155. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/config/static/__init__.py +0 -0
  156. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/Connector.py +0 -0
  157. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/__init__.py +0 -0
  158. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/APIConnector.py +0 -0
  159. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/__init__.py +0 -0
  160. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_actions.py +0 -0
  161. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_fetch.py +0 -0
  162. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_login.py +0 -0
  163. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_misc.py +0 -0
  164. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_pipes.py +0 -0
  165. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_plugins.py +0 -0
  166. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_request.py +0 -0
  167. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_uri.py +0 -0
  168. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/api/_users.py +0 -0
  169. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/parse.py +0 -0
  170. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/plugin/PluginConnector.py +0 -0
  171. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/plugin/__init__.py +0 -0
  172. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/poll.py +0 -0
  173. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/SQLConnector.py +0 -0
  174. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/__init__.py +0 -0
  175. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_cli.py +0 -0
  176. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_create_engine.py +0 -0
  177. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_fetch.py +0 -0
  178. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_instance.py +0 -0
  179. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_pipes.py +0 -0
  180. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_plugins.py +0 -0
  181. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_sql.py +0 -0
  182. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_uri.py +0 -0
  183. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/_users.py +0 -0
  184. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/tables/__init__.py +0 -0
  185. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/tables/types.py +0 -0
  186. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/connectors/sql/tools.py +0 -0
  187. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/__init__.py +0 -0
  188. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_attributes.py +0 -0
  189. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_bootstrap.py +0 -0
  190. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_clear.py +0 -0
  191. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_data.py +0 -0
  192. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_deduplicate.py +0 -0
  193. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_delete.py +0 -0
  194. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_drop.py +0 -0
  195. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_dtypes.py +0 -0
  196. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_edit.py +0 -0
  197. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_fetch.py +0 -0
  198. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_register.py +0 -0
  199. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_show.py +0 -0
  200. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_sync.py +0 -0
  201. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Pipe/_verify.py +0 -0
  202. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/Plugin/__init__.py +0 -0
  203. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/User/_User.py +0 -0
  204. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/User/__init__.py +0 -0
  205. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/core/__init__.py +0 -0
  206. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/plugins/_Plugin.py +0 -0
  207. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/plugins/__init__.py +0 -0
  208. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/__init__.py +0 -0
  209. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/_get_pipes.py +0 -0
  210. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/daemon/Daemon.py +0 -0
  211. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/daemon/RotatingFile.py +0 -0
  212. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/daemon/__init__.py +0 -0
  213. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/daemon/_names.py +0 -0
  214. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/dataframe.py +0 -0
  215. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/debug.py +0 -0
  216. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/dtypes/__init__.py +0 -0
  217. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/dtypes/sql.py +0 -0
  218. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/formatting/__init__.py +0 -0
  219. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/formatting/_jobs.py +0 -0
  220. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/formatting/_pipes.py +0 -0
  221. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/formatting/_pprint.py +0 -0
  222. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/formatting/_shell.py +0 -0
  223. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/interactive.py +0 -0
  224. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/misc.py +0 -0
  225. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/networking.py +0 -0
  226. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/packages/lazy_loader.py +0 -0
  227. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/pool.py +0 -0
  228. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/process.py +0 -0
  229. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/prompt.py +0 -0
  230. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/sql.py +0 -0
  231. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/threading.py +0 -0
  232. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/typing.py +0 -0
  233. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/venv/_Venv.py +0 -0
  234. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/venv/__init__.py +0 -0
  235. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/warnings.py +0 -0
  236. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum/utils/yaml.py +0 -0
  237. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/SOURCES.txt +0 -0
  238. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/dependency_links.txt +0 -0
  239. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/entry_points.txt +0 -0
  240. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/top_level.txt +0 -0
  241. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/meerschaum.egg-info/zip-safe +0 -0
  242. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/setup.cfg +0 -0
  243. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/setup.py +0 -0
  244. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/tests/test_deduplicate.py +0 -0
  245. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/tests/test_pipes_dtypes.py +0 -0
  246. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/tests/test_sql.py +0 -0
  247. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/tests/test_users.py +0 -0
  248. {meerschaum-2.2.0.dev1 → meerschaum-2.2.0.dev3}/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.dev1
3
+ Version: 2.2.0.dev3
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: rocketry>=2.5.1; extra == "required"
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.27.4; extra == "stack"
86
+ Requires-Dist: docker-compose>=1.29.2; extra == "stack"
87
87
  Provides-Extra: build
88
- Requires-Dist: cx_Freeze>=6.5.1; extra == "build"
89
- Requires-Dist: pyinstaller>=5.0.0-dev0; extra == "build"
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: rocketry>=2.5.1; extra == "sql"
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: rocketry>=2.5.1; extra == "api"
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: rocketry>=2.5.1; extra == "full"
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
- _ck_alone, _mk_alone, _lk_alone = False, False, False
520
- _ck_filter, _mk_filter, _lk_filter = connector_keys, metric_keys, location_keys
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', get_web_connector(ctx.states),
532
- connector_keys=_ck_filter, metric_keys=_mk_filter, location_keys=_lk_filter
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
- connector_keys = sorted([
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 = sorted([
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 = sorted([
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
- 'Sync',
127
+ 'Delete',
128
128
  id = {
129
129
  'type': 'manage-pipe-button',
130
130
  'index': meta_str,
131
- 'action': 'sync',
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
- 'Delete',
143
+ 'Clear',
144
144
  id = {
145
145
  'type': 'manage-pipe-button',
146
146
  'index': meta_str,
147
- 'action': 'delete',
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 = "end",
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 recent data',
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
- for col_key, col in pipe.columns.items():
254
- overview_rows.append(html.Tr([html.Td(f"'{col_key}' Index"), html.Td(col)]))
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
 
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "2.2.0.dev1"
5
+ __version__ = "2.2.0.dev3"
@@ -97,7 +97,6 @@ compose_header = """
97
97
 
98
98
 
99
99
  default_docker_compose_config = {
100
- 'version': '3.9',
101
100
  'services': {
102
101
  'db': {
103
102
  'environment': {
@@ -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
- 'rocketry' : 'rocketry>=2.5.1',
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.27.4',
78
+ 'compose' : 'docker-compose>=1.29.2',
79
79
  },
80
80
  'build': {
81
- 'cx_Freeze' : 'cx_Freeze>=6.5.1',
82
- 'PyInstaller' : 'pyinstaller>=5.0.0-dev0',
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<2.0.0',
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,303 @@
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
+ schedule_num /= 2
204
+ # divided_hours = True
205
+
206
+ trigger = (
207
+ apscheduler_triggers_interval.IntervalTrigger(
208
+ **{
209
+ schedule_unit: schedule_num,
210
+ 'start_time': starting_ts,
211
+ }
212
+ )
213
+ if schedule_unit != 'months' else (
214
+ apscheduler_triggers_calendarinterval.CalendarIntervalTrigger(
215
+ **{
216
+ schedule_unit: schedule_num,
217
+ 'start_date': starting_ts,
218
+ # 'timezone': starting_ts.tzinfo, TODO Re-enable once APScheduler updates.
219
+ }
220
+ )
221
+ )
222
+ )
223
+
224
+ ### Determine whether this is a pure cron string or a cron subset (e.g. 'may-aug')_.
225
+ else:
226
+ first_three_prefix = schedule_part[:3]
227
+ cron_kw = {}
228
+ if first_three_prefix in CRON_DAYS_OF_WEEK:
229
+ cron_kw['day_of_week'] = schedule_part
230
+ elif first_three_prefix in CRON_MONTHS:
231
+ cron_kw['month'] = schedule_part
232
+ trigger = (
233
+ apscheduler_triggers_cron.CronTrigger(
234
+ **{
235
+ **cron_kw,
236
+ 'hour': '*',
237
+ 'minute': '*' if has_minutes else starting_ts.minute,
238
+ 'second': '*' if has_seconds else starting_ts.second,
239
+ 'start_time': starting_ts,
240
+ 'timezone': starting_ts.tzinfo,
241
+ }
242
+ )
243
+ if cron_kw
244
+ else apscheduler_triggers_cron.CronTrigger.from_crontab(
245
+ schedule_part,
246
+ timezone = starting_ts.tzinfo,
247
+ )
248
+ )
249
+ ### Explicitly set the `start_time` after building with `from_crontab`.
250
+ if trigger.start_time != starting_ts:
251
+ trigger.start_time = starting_ts
252
+
253
+ triggers.append(trigger)
254
+
255
+ return (
256
+ join_trigger(triggers, **join_kwargs)
257
+ if len(triggers) != 1
258
+ else triggers[0]
259
+ )
260
+
261
+
262
+ def parse_start_time(schedule: str, now: Optional[datetime] = None) -> datetime:
263
+ """
264
+ Return the datetime to use for the given schedule string.
265
+
266
+ Parameters
267
+ ----------
268
+ schedule: str
269
+ The schedule frequency to be parsed into a starting datetime.
270
+
271
+ now: Optional[datetime], default None
272
+ If provided, use this value as a default if no start time is explicitly stated.
273
+
274
+ Returns
275
+ -------
276
+ A `datetime` object, either `now` or the datetime embedded in the schedule string.
277
+
278
+ Examples
279
+ --------
280
+ >>> parse_start_time('daily starting 2024-01-01')
281
+ datetime.datetime(2024, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
282
+ >>> parse_start_time('monthly starting 1st')
283
+ datetime.datetime(2024, 5, 1, 0, 0, tzinfo=datetime.timezone.utc)
284
+ >>> parse_start_time('hourly starting 00:30')
285
+ datetime.datetime(2024, 5, 13, 0, 30, tzinfo=datetime.timezone.utc)
286
+ """
287
+ from meerschaum.utils.misc import round_time
288
+ from meerschaum.utils.warnings import error, warn
289
+ dateutil_parser = mrsm.attempt_import('dateutil.parser')
290
+ starting_parts = schedule.split(STARTING_KEYWORD)
291
+ starting_str = ('now' if len(starting_parts) == 1 else starting_parts[-1]).strip()
292
+ now = now or round_time(datetime.now(timezone.utc), timedelta(minutes=1))
293
+ try:
294
+ starting_ts = now if starting_str == 'now' else dateutil_parser.parse(starting_str)
295
+ schedule_parse_error = None
296
+ except Exception as e:
297
+ warn(f"Unable to parse starting time from '{starting_str}'.", stack=False)
298
+ schedule_parse_error = str(e)
299
+ if schedule_parse_error:
300
+ error(schedule_parse_error, ValueError, stack=False)
301
+ if not starting_ts.tzinfo:
302
+ starting_ts = starting_ts.replace(tzinfo=timezone.utc)
303
+ return starting_ts