meerschaum 2.2.3__tar.gz → 2.2.5.dev0__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 (252) hide show
  1. {meerschaum-2.2.3/meerschaum.egg-info → meerschaum-2.2.5.dev0}/PKG-INFO +5 -1
  2. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/entry.py +2 -4
  3. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/__init__.py +5 -1
  4. meerschaum-2.2.5.dev0/meerschaum/actions/backup.py +43 -0
  5. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/bootstrap.py +246 -0
  6. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/delete.py +62 -0
  7. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/python.py +45 -14
  8. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/show.py +26 -0
  9. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/_oauth2.py +17 -0
  10. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_login.py +23 -7
  11. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_edit.py +1 -1
  12. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_paths.py +3 -0
  13. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_version.py +1 -1
  14. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/stack/__init__.py +3 -1
  15. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/daemon/Daemon.py +14 -3
  16. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/daemon/FileDescriptorInterceptor.py +21 -14
  17. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/daemon/RotatingFile.py +21 -18
  18. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/packages/_packages.py +1 -0
  19. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/prompt.py +53 -17
  20. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/yaml.py +32 -1
  21. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0/meerschaum.egg-info}/PKG-INFO +5 -1
  22. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/SOURCES.txt +1 -0
  23. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/requires.txt +4 -0
  24. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/LICENSE +0 -0
  25. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/NOTICE +0 -0
  26. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/README.md +0 -0
  27. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/__init__.py +0 -0
  28. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/__main__.py +0 -0
  29. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/__init__.py +0 -0
  30. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/arguments/__init__.py +0 -0
  31. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/arguments/_parse_arguments.py +0 -0
  32. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/arguments/_parser.py +0 -0
  33. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/docs/__init__.py +0 -0
  34. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/docs/index.py +0 -0
  35. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/gui/__init__.py +0 -0
  36. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/gui/app/__init__.py +0 -0
  37. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/gui/app/_windows.py +0 -0
  38. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/gui/app/actions.py +0 -0
  39. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/gui/app/pipes.py +0 -0
  40. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/shell/Shell.py +0 -0
  41. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/shell/ShellCompleter.py +0 -0
  42. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/shell/ValidAutoSuggest.py +0 -0
  43. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/shell/__init__.py +0 -0
  44. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/shell/resources/__init__.py +0 -0
  45. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/term/TermPageHandler.py +0 -0
  46. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/term/__init__.py +0 -0
  47. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/_internal/term/tools.py +0 -0
  48. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/api.py +0 -0
  49. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/clear.py +0 -0
  50. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/copy.py +0 -0
  51. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/deduplicate.py +0 -0
  52. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/drop.py +0 -0
  53. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/edit.py +0 -0
  54. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/install.py +0 -0
  55. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/login.py +0 -0
  56. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/os.py +0 -0
  57. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/pause.py +0 -0
  58. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/register.py +0 -0
  59. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/reload.py +0 -0
  60. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/setup.py +0 -0
  61. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/sh.py +0 -0
  62. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/sql.py +0 -0
  63. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/stack.py +0 -0
  64. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/start.py +0 -0
  65. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/stop.py +0 -0
  66. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/sync.py +0 -0
  67. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/tag.py +0 -0
  68. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/uninstall.py +0 -0
  69. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/upgrade.py +0 -0
  70. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/actions/verify.py +0 -0
  71. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/__init__.py +0 -0
  72. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/_chain.py +0 -0
  73. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/_events.py +0 -0
  74. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/_websockets.py +0 -0
  75. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/__init__.py +0 -0
  76. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/actions.py +0 -0
  77. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/__init__.py +0 -0
  78. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/ansi_up.js +0 -0
  79. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/banner_1920x320.png +0 -0
  80. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/favicon.ico +0 -0
  81. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/logo_48x48.png +0 -0
  82. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/assets/logo_500x500.png +0 -0
  83. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/__init__.py +0 -0
  84. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/custom.py +0 -0
  85. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/dashboard.py +0 -0
  86. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/jobs.py +0 -0
  87. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/login.py +0 -0
  88. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/plugins.py +0 -0
  89. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/callbacks/register.py +0 -0
  90. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/components.py +0 -0
  91. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/connectors.py +0 -0
  92. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/graphs.py +0 -0
  93. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/jobs.py +0 -0
  94. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/keys.py +0 -0
  95. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/__init__.py +0 -0
  96. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/dashboard.py +0 -0
  97. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/error.py +0 -0
  98. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/login.py +0 -0
  99. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/plugins.py +0 -0
  100. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pages/register.py +0 -0
  101. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/pipes.py +0 -0
  102. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/plugins.py +0 -0
  103. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/sync.py +0 -0
  104. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/users.py +0 -0
  105. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/websockets.py +0 -0
  106. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/dash/webterm.py +0 -0
  107. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/models/__init__.py +0 -0
  108. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/models/_interfaces.py +0 -0
  109. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/models/_locations.py +0 -0
  110. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/models/_metrics.py +0 -0
  111. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/models/_pipes.py +0 -0
  112. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/__init__.py +0 -0
  113. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/__init__.py +0 -0
  114. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/__init__.py +0 -0
  115. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/bootstrap.min.css +0 -0
  116. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/dash.css +0 -0
  117. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/dbc_dark.css +0 -0
  118. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/styles.css +0 -0
  119. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/css/xterm.css +0 -0
  120. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/ico/__init__.py +0 -0
  121. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/ico/logo.ico +0 -0
  122. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/js/__init__.py +0 -0
  123. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/js/action_button.js +0 -0
  124. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/js/main.js +0 -0
  125. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/js/terminado.js +0 -0
  126. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/js/xterm.js +0 -0
  127. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/static/png/__init__.py +0 -0
  128. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/templates/__init__.py +0 -0
  129. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/templates/index.html +0 -0
  130. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/templates/old_index.html +0 -0
  131. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/templates/secret.html +0 -0
  132. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/resources/templates/termpage.html +0 -0
  133. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/__init__.py +0 -0
  134. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_actions.py +0 -0
  135. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_connectors.py +0 -0
  136. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_index.py +0 -0
  137. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_misc.py +0 -0
  138. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_pipes.py +0 -0
  139. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_plugins.py +0 -0
  140. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_users.py +0 -0
  141. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_version.py +0 -0
  142. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/routes/_webterm.py +0 -0
  143. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/api/tables/__init__.py +0 -0
  144. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/__init__.py +0 -0
  145. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_dash.py +0 -0
  146. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_default.py +0 -0
  147. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_environment.py +0 -0
  148. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_formatting.py +0 -0
  149. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_jobs.py +0 -0
  150. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_patch.py +0 -0
  151. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_preprocess.py +0 -0
  152. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_read_config.py +0 -0
  153. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_shell.py +0 -0
  154. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/_sync.py +0 -0
  155. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/paths.py +0 -0
  156. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/resources/__init__.py +0 -0
  157. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/stack/grafana/__init__.py +0 -0
  158. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/stack/mosquitto/__init__.py +0 -0
  159. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/stack/mosquitto/resources/__init__.py +0 -0
  160. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/stack/resources/__init__.py +0 -0
  161. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/config/static/__init__.py +0 -0
  162. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/Connector.py +0 -0
  163. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/__init__.py +0 -0
  164. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/APIConnector.py +0 -0
  165. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/__init__.py +0 -0
  166. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_actions.py +0 -0
  167. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_fetch.py +0 -0
  168. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_login.py +0 -0
  169. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_misc.py +0 -0
  170. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_pipes.py +0 -0
  171. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_plugins.py +0 -0
  172. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_request.py +0 -0
  173. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_uri.py +0 -0
  174. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/api/_users.py +0 -0
  175. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/parse.py +0 -0
  176. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/plugin/PluginConnector.py +0 -0
  177. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/plugin/__init__.py +0 -0
  178. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/poll.py +0 -0
  179. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/SQLConnector.py +0 -0
  180. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/__init__.py +0 -0
  181. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_cli.py +0 -0
  182. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_create_engine.py +0 -0
  183. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_fetch.py +0 -0
  184. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_instance.py +0 -0
  185. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_pipes.py +0 -0
  186. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_plugins.py +0 -0
  187. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_sql.py +0 -0
  188. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_uri.py +0 -0
  189. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/_users.py +0 -0
  190. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/tables/__init__.py +0 -0
  191. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/tables/types.py +0 -0
  192. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/connectors/sql/tools.py +0 -0
  193. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/__init__.py +0 -0
  194. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_attributes.py +0 -0
  195. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_bootstrap.py +0 -0
  196. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_clear.py +0 -0
  197. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_data.py +0 -0
  198. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_deduplicate.py +0 -0
  199. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_delete.py +0 -0
  200. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_drop.py +0 -0
  201. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_dtypes.py +0 -0
  202. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_edit.py +0 -0
  203. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_fetch.py +0 -0
  204. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_register.py +0 -0
  205. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_show.py +0 -0
  206. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_sync.py +0 -0
  207. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Pipe/_verify.py +0 -0
  208. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/Plugin/__init__.py +0 -0
  209. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/User/_User.py +0 -0
  210. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/User/__init__.py +0 -0
  211. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/core/__init__.py +0 -0
  212. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/plugins/_Plugin.py +0 -0
  213. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/plugins/__init__.py +0 -0
  214. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/__init__.py +0 -0
  215. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/_get_pipes.py +0 -0
  216. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/daemon/__init__.py +0 -0
  217. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/daemon/_names.py +0 -0
  218. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/dataframe.py +0 -0
  219. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/debug.py +0 -0
  220. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/dtypes/__init__.py +0 -0
  221. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/dtypes/sql.py +0 -0
  222. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/formatting/__init__.py +0 -0
  223. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/formatting/_jobs.py +0 -0
  224. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/formatting/_pipes.py +0 -0
  225. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/formatting/_pprint.py +0 -0
  226. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/formatting/_shell.py +0 -0
  227. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/interactive.py +0 -0
  228. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/misc.py +0 -0
  229. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/networking.py +0 -0
  230. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/packages/__init__.py +0 -0
  231. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/packages/lazy_loader.py +0 -0
  232. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/pool.py +0 -0
  233. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/process.py +0 -0
  234. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/schedule.py +0 -0
  235. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/sql.py +0 -0
  236. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/threading.py +0 -0
  237. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/typing.py +0 -0
  238. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/venv/_Venv.py +0 -0
  239. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/venv/__init__.py +0 -0
  240. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum/utils/warnings.py +0 -0
  241. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/dependency_links.txt +0 -0
  242. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/entry_points.txt +0 -0
  243. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/top_level.txt +0 -0
  244. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/meerschaum.egg-info/zip-safe +0 -0
  245. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/setup.cfg +0 -0
  246. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/setup.py +0 -0
  247. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_deduplicate.py +0 -0
  248. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_pipes_dtypes.py +0 -0
  249. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_sql.py +0 -0
  250. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_sync.py +0 -0
  251. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_users.py +0 -0
  252. {meerschaum-2.2.3 → meerschaum-2.2.5.dev0}/tests/test_verify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: meerschaum
3
- Version: 2.2.3
3
+ Version: 2.2.5.dev0
4
4
  Summary: Sync Time-Series Pipes with Meerschaum
5
5
  Home-page: https://meerschaum.io
6
6
  Author: Bennett Meares
@@ -54,6 +54,7 @@ Requires-Dist: python-dateutil>=2.7.5; extra == "core"
54
54
  Requires-Dist: requests>=2.23.0; extra == "core"
55
55
  Requires-Dist: binaryornot>=0.4.4; extra == "core"
56
56
  Requires-Dist: pyvim>=3.0.2; extra == "core"
57
+ Requires-Dist: ptpython>=3.0.27; extra == "core"
57
58
  Requires-Dist: aiofiles>=0.6.0; extra == "core"
58
59
  Requires-Dist: packaging>=21.3.0; extra == "core"
59
60
  Requires-Dist: prompt-toolkit>=3.0.39; extra == "core"
@@ -147,6 +148,7 @@ Requires-Dist: python-dateutil>=2.7.5; extra == "sql"
147
148
  Requires-Dist: requests>=2.23.0; extra == "sql"
148
149
  Requires-Dist: binaryornot>=0.4.4; extra == "sql"
149
150
  Requires-Dist: pyvim>=3.0.2; extra == "sql"
151
+ Requires-Dist: ptpython>=3.0.27; extra == "sql"
150
152
  Requires-Dist: aiofiles>=0.6.0; extra == "sql"
151
153
  Requires-Dist: packaging>=21.3.0; extra == "sql"
152
154
  Requires-Dist: prompt-toolkit>=3.0.39; extra == "sql"
@@ -205,6 +207,7 @@ Requires-Dist: python-dateutil>=2.7.5; extra == "api"
205
207
  Requires-Dist: requests>=2.23.0; extra == "api"
206
208
  Requires-Dist: binaryornot>=0.4.4; extra == "api"
207
209
  Requires-Dist: pyvim>=3.0.2; extra == "api"
210
+ Requires-Dist: ptpython>=3.0.27; extra == "api"
208
211
  Requires-Dist: aiofiles>=0.6.0; extra == "api"
209
212
  Requires-Dist: packaging>=21.3.0; extra == "api"
210
213
  Requires-Dist: prompt-toolkit>=3.0.39; extra == "api"
@@ -253,6 +256,7 @@ Requires-Dist: python-dateutil>=2.7.5; extra == "full"
253
256
  Requires-Dist: requests>=2.23.0; extra == "full"
254
257
  Requires-Dist: binaryornot>=0.4.4; extra == "full"
255
258
  Requires-Dist: pyvim>=3.0.2; extra == "full"
259
+ Requires-Dist: ptpython>=3.0.27; extra == "full"
256
260
  Requires-Dist: aiofiles>=0.6.0; extra == "full"
257
261
  Requires-Dist: packaging>=21.3.0; extra == "full"
258
262
  Requires-Dist: prompt-toolkit>=3.0.39; extra == "full"
@@ -47,9 +47,6 @@ def entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
47
47
  )
48
48
  )
49
49
 
50
- # if args.get('schedule', None):
51
- # from meerschaum.utils.schedule import schedule_function
52
- # return schedule_function(entry_with_args, **args)
53
50
  return entry_with_args(**args)
54
51
 
55
52
 
@@ -122,11 +119,12 @@ def entry_with_args(
122
119
  def _do_action_wrapper(action_function, plugin_name, **kw):
123
120
  from meerschaum.plugins import Plugin
124
121
  from meerschaum.utils.venv import Venv, active_venvs, deactivate_venv
122
+ from meerschaum.utils.misc import filter_keywords
125
123
  plugin = Plugin(plugin_name) if plugin_name else None
126
124
  with Venv(plugin, debug=kw.get('debug', False)):
127
125
  action_name = ' '.join(action_function.__name__.split('_') + kw.get('action', []))
128
126
  try:
129
- result = action_function(**kw)
127
+ result = action_function(**filter_keywords(action_function, **kw))
130
128
  except Exception as e:
131
129
  if kw.get('debug', False):
132
130
  import traceback
@@ -40,7 +40,11 @@ def get_subactions(
40
40
  for name, f in inspect.getmembers(action_module):
41
41
  if not inspect.isfunction(f):
42
42
  continue
43
- if action_function.__name__ + '_' in name and not name.lstrip('_').startswith('complete'):
43
+
44
+ ### Detect subactions which may contain an underscore prefix.
45
+ if (
46
+ name.lstrip('_').startswith(action_function.__name__.lstrip('_') + '_')
47
+ ):
44
48
  _name = name.replace(action_function.__name__, '')
45
49
  _name = _name.lstrip('_')
46
50
  subactions[_name] = f
@@ -0,0 +1,43 @@
1
+ #! /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # vim:fenc=utf-8
4
+
5
+ """
6
+ Backup the stack database.
7
+ """
8
+
9
+ from __future__ import annotations
10
+ from meerschaum.utils.typing import SuccessTuple, Any, List, Optional, Union
11
+
12
+ def backup(
13
+ action: Optional[List[str]] = None,
14
+ **kwargs: Any
15
+ ) -> SuccessTuple:
16
+ """
17
+ Backup the stack database.
18
+ """
19
+ from meerschaum.actions import choose_subaction
20
+ options = {
21
+ 'database' : _backup_database,
22
+ }
23
+ return choose_subaction(action, options, **kwargs)
24
+
25
+
26
+ def _backup_database(
27
+ action: Optional[List[str]] = None,
28
+ ) -> SuccessTuple:
29
+ """
30
+ Backup the stack's database to a sql file.
31
+ """
32
+ from meerschaum.actions import get_action
33
+ from meerschaum.config.paths import BACKUP_RESOURCES_PATH
34
+ do_stack = get_action('stack')
35
+ cmd_list = ['exec', 'db', 'pg']
36
+ stack_success, stack_msg = do_stack(['exec'])
37
+ return True, "Success"
38
+
39
+ ### NOTE: This must be the final statement of the module.
40
+ ### Any subactions added below these lines will not
41
+ ### be added to the `help` docstring.
42
+ from meerschaum.utils.misc import choices_docstring as _choices_docstring
43
+ backup.__doc__ += _choices_docstring('backup')
@@ -25,6 +25,7 @@ def bootstrap(
25
25
  options = {
26
26
  'pipes' : _bootstrap_pipes,
27
27
  'connectors' : _bootstrap_connectors,
28
+ 'plugins' : _bootstrap_plugins,
28
29
  }
29
30
  return choose_subaction(action, options, **kw)
30
31
 
@@ -382,6 +383,251 @@ def _bootstrap_connectors(
382
383
  return True, "Success"
383
384
 
384
385
 
386
+ def _bootstrap_plugins(
387
+ action: Optional[List[str]] = None,
388
+ debug: bool = False,
389
+ **kwargs: Any
390
+ ) -> SuccessTuple:
391
+ """
392
+ Launch an interactive wizard to guide the user to creating a new plugin.
393
+ """
394
+ import pathlib
395
+ import meerschaum as mrsm
396
+ from meerschaum.utils.warnings import info, warn
397
+ from meerschaum.utils.prompt import prompt, choose, yes_no
398
+ from meerschaum.utils.formatting._shell import clear_screen
399
+ from meerschaum.utils.misc import edit_file
400
+ from meerschaum.config.paths import PLUGINS_DIR_PATHS
401
+ from meerschaum._internal.entry import entry
402
+
403
+ if not action:
404
+ action = [prompt("Enter the name of your new plugin:")]
405
+
406
+ if len(PLUGINS_DIR_PATHS) > 1:
407
+ plugins_dir_path = pathlib.Path(
408
+ choose(
409
+ "In which directory do you want to write your plugin?",
410
+ [path.as_posix() for path in PLUGINS_DIR_PATHS],
411
+ numeric = True,
412
+ multiple = False,
413
+ default = PLUGINS_DIR_PATHS[0].as_posix(),
414
+ )
415
+ )
416
+ else:
417
+ plugins_dir_path = PLUGINS_DIR_PATHS[0]
418
+
419
+ clear_screen(debug=debug)
420
+ info(
421
+ "Answer the questions below to pick out features.\n"
422
+ + " See the Writing Plugins guide for documentation:\n"
423
+ + " https://meerschaum.io/reference/plugins/writing-plugins/ for documentation.\n"
424
+ )
425
+
426
+ imports_lines = {
427
+ 'default': (
428
+ "import meerschaum as mrsm\n"
429
+ ),
430
+ 'action': (
431
+ "from meerschaum.actions import make_action\n"
432
+ ),
433
+ 'api': (
434
+ "from meerschaum.plugins import api_plugin\n"
435
+ ),
436
+ 'web': (
437
+ "from meerschaum.plugins import web_page, dash_plugin\n"
438
+ ),
439
+ 'api+web': (
440
+ "from meerschaum.plugins import api_plugin, web_page, dash_plugin\n"
441
+ ),
442
+ }
443
+
444
+ ### TODO: Add feature for custom connectors.
445
+ feature_lines = {
446
+ 'header': (
447
+ "# {plugin_name}.py\n\n"
448
+ ),
449
+ 'default': (
450
+ "__version__ = '0.0.1'\n"
451
+ "\n# Add any depedencies to `required` (similar to `requirements.txt`).\n"
452
+ "required = []\n\n"
453
+ ),
454
+ 'setup': (
455
+ "def setup(**kwargs) -> mrsm.SuccessTuple:\n"
456
+ " \"\"\"Executed during installation and `mrsm setup plugin {plugin_name}`.\"\"\"\n"
457
+ " return True, \"Success\"\n\n\n"
458
+ ),
459
+ 'register': (
460
+ "def register(pipe: mrsm.Pipe):\n"
461
+ " \"\"\"Return the default parameters for a new pipe.\"\"\"\n"
462
+ " return {\n"
463
+ " 'columns': {\n"
464
+ " 'datetime': None,\n"
465
+ " }\n"
466
+ " }\n\n\n"
467
+ ),
468
+ 'fetch': (
469
+ "def fetch(pipe: mrsm.Pipe, **kwargs):\n"
470
+ " \"\"\"Return or yield dataframe-like objects.\"\"\"\n"
471
+ " docs = []\n"
472
+ " # populate docs with dictionaries (rows).\n"
473
+ " return docs\n\n\n"
474
+ ),
475
+ 'action': (
476
+ "@make_action\n"
477
+ "def {action_name}(**kwargs) -> mrsm.SuccessTuple:\n"
478
+ " \"\"\"Run `mrsm {action_spaces}` to trigger.\"\"\"\n"
479
+ " return True, \"Success\"\n\n\n"
480
+ ),
481
+ 'api': (
482
+ "@api_plugin\n"
483
+ "def init_app(fastapi_app):\n"
484
+ " \"\"\"Add new endpoints to the FastAPI app.\"\"\"\n\n"
485
+ " import fastapi\n"
486
+ " from meerschaum.api import manager\n\n"
487
+ " @fastapi_app.get('/my/endpoint')\n"
488
+ " def get_my_endpoint(curr_user=fastapi.Depends(manager)):\n"
489
+ " return {'message': 'Hello, World!'}\n\n\n"
490
+ ),
491
+ 'web': (
492
+ "@dash_plugin\n"
493
+ "def init_dash(dash_app):\n"
494
+ " \"\"\"Initialize the Plotly Dash application.\"\"\"\n"
495
+ " import dash.html as html\n"
496
+ " import dash.dcc as dcc\n"
497
+ " from dash import Input, Output, State, no_update\n"
498
+ " import dash_bootstrap_components as dbc\n\n"
499
+ " # Create a new page at the path `/dash/{plugin_name}`.\n"
500
+ " @web_page('{plugin_name}', login_required=False)\n"
501
+ " def page_layout():\n"
502
+ " \"\"\"Return the layout objects for this page.\"\"\"\n"
503
+ " return dbc.Container([\n"
504
+ " dcc.Location(id='{plugin_name}-location'),\n"
505
+ " html.Div(id='output-div'),\n"
506
+ " ])\n\n"
507
+ " @dash_app.callback(\n"
508
+ " Output('output-div', 'children'),\n"
509
+ " Input('{plugin_name}-location', 'pathname'),\n"
510
+ " )\n"
511
+ " def render_page_on_url_change(pathname: str):\n"
512
+ " \"\"\"Reload page contents when the URL path changes.\"\"\"\n"
513
+ " return html.H1(\"Hello from plugin '{plugin_name}'!\")\n\n\n"
514
+ ),
515
+ }
516
+
517
+ for plugin_name in action:
518
+ plugin_path = plugins_dir_path / (plugin_name + '.py')
519
+ plugin = mrsm.Plugin(plugin_name)
520
+ if plugin.is_installed():
521
+ warn(f"Plugin '{plugin_name}' is already installed!", stack=False)
522
+ uninstall_plugin = yes_no(
523
+ f"Do you want to first uninstall '{plugin}'?",
524
+ default = 'n',
525
+ **kwargs
526
+ )
527
+ if not uninstall_plugin:
528
+ return False, f"Plugin '{plugin_name}' already exists."
529
+
530
+ uninstall_success, uninstall_msg = entry(['uninstall', 'plugin', plugin_name, '-f'])
531
+ if not uninstall_success:
532
+ return uninstall_success, uninstall_msg
533
+ clear_screen(debug=debug)
534
+
535
+ features = choose(
536
+ "Which of the following features would you like to add to your plugin?",
537
+ [
538
+ (
539
+ 'fetch',
540
+ 'Fetch data\n (e.g. extracting from a remote API)\n'
541
+ ),
542
+ (
543
+ 'action',
544
+ 'New actions\n (e.g. `mrsm sing song`)\n'
545
+ ),
546
+ (
547
+ 'api',
548
+ 'New API endpoints\n (e.g. `POST /my/new/endpoint`)\n',
549
+ ),
550
+ (
551
+ 'web',
552
+ 'New web console page\n (e.g. `/dash/my-web-app`)\n',
553
+ ),
554
+ ],
555
+ default = 'fetch',
556
+ multiple = True,
557
+ as_indices = True,
558
+ **kwargs
559
+ )
560
+
561
+ action_name = ''
562
+ if 'action' in features:
563
+ while True:
564
+ try:
565
+ action_name = prompt(
566
+ "What is name of your action?\n "
567
+ + "(separate subactions with spaces, e.g. `sing song`):"
568
+ ).replace(' ', '_')
569
+ except KeyboardInterrupt as e:
570
+ return False, "Aborted plugin creation."
571
+
572
+ if action_name:
573
+ break
574
+ warn("Please enter an action.", stack=False)
575
+
576
+ action_spaces = action_name.replace('_', ' ')
577
+
578
+ plugin_labels = {
579
+ 'plugin_name': plugin_name,
580
+ 'action_name': action_name,
581
+ 'action_spaces': action_spaces,
582
+ }
583
+
584
+ body_text = ""
585
+ body_text += feature_lines['header'].format(**plugin_labels)
586
+ body_text += imports_lines['default'].format(**plugin_labels)
587
+ if 'action' in features:
588
+ body_text += imports_lines['action']
589
+ if 'api' in features and 'web' in features:
590
+ body_text += imports_lines['api+web']
591
+ elif 'api' in features:
592
+ body_text += imports_lines['api']
593
+ elif 'web' in features:
594
+ body_text += imports_lines['web']
595
+
596
+ body_text += "\n"
597
+ body_text += feature_lines['default'].format(**plugin_labels)
598
+ body_text += feature_lines['setup'].format(**plugin_labels)
599
+
600
+ if 'fetch' in features:
601
+ body_text += feature_lines['register']
602
+ body_text += feature_lines['fetch']
603
+
604
+ if 'action' in features:
605
+ body_text += feature_lines['action'].format(**plugin_labels)
606
+
607
+ if 'api' in features:
608
+ body_text += feature_lines['api']
609
+
610
+ if 'web' in features:
611
+ body_text += feature_lines['web'].format(**plugin_labels)
612
+
613
+ try:
614
+ with open(plugin_path, 'w+', encoding='utf-8') as f:
615
+ f.write(body_text.rstrip())
616
+ except Exception as e:
617
+ error_msg = f"Failed to write file '{plugin_path}':\n{e}"
618
+ return False, error_msg
619
+
620
+ mrsm.pprint((True, f"Successfully created file '{plugin_path}'."))
621
+ try:
622
+ _ = prompt(f"Press [Enter] to edit plugin '{plugin_name}', [CTRL+C] to skip.")
623
+ except (KeyboardInterrupt, Exception):
624
+ continue
625
+
626
+ edit_file(plugin_path, debug=debug)
627
+
628
+ return True, "Success"
629
+
630
+
385
631
  ### NOTE: This must be the final statement of the module.
386
632
  ### Any subactions added below these lines will not
387
633
  ### be added to the `help` docstring.
@@ -29,6 +29,7 @@ def delete(
29
29
  'users' : _delete_users,
30
30
  'connectors' : _delete_connectors,
31
31
  'jobs' : _delete_jobs,
32
+ 'venvs' : _delete_venvs,
32
33
  }
33
34
  return choose_subaction(action, options, **kw)
34
35
 
@@ -486,6 +487,67 @@ def _delete_jobs(
486
487
  )
487
488
 
488
489
 
490
+ def _delete_venvs(
491
+ action: Optional[List[str]] = None,
492
+ yes: bool = False,
493
+ force: bool = False,
494
+ **kwargs: Any
495
+ ) -> SuccessTuple:
496
+ """
497
+ Remove virtual environments.
498
+ Specify which venvs to remove, or remove everything at once.
499
+ """
500
+ import os
501
+ import shutil
502
+ import pathlib
503
+ from meerschaum.config.paths import VIRTENV_RESOURCES_PATH
504
+ from meerschaum.utils.venv import venv_exists
505
+ from meerschaum.utils.prompt import yes_no
506
+ from meerschaum.utils.misc import print_options
507
+ from meerschaum.utils.warnings import warn
508
+
509
+ venvs_to_skip = ['mrsm']
510
+ venvs = [
511
+ _venv
512
+ for _venv in action or os.listdir(VIRTENV_RESOURCES_PATH)
513
+ if venv_exists(_venv)
514
+ and _venv not in venvs_to_skip
515
+ ]
516
+
517
+ if not venvs:
518
+ msg = "No venvs to delete."
519
+ if action:
520
+ return False, msg
521
+ return True, msg
522
+
523
+ print_options(
524
+ venvs,
525
+ header = 'Venvs to Delete:',
526
+ **kwargs
527
+ )
528
+ confirm_delete = yes_no(
529
+ (
530
+ "Remove the above venv" + ('s' if len(venvs) != 1 else '') + "?\n "
531
+ + "Run `mrsm upgrade packages` and `mrsm install required` to reinstall dependencies.\n"
532
+ ),
533
+ yes = yes,
534
+ default = 'n',
535
+ force = force,
536
+ )
537
+ if not confirm_delete:
538
+ return True, "Nothing was deleted."
539
+
540
+ for venv in venvs:
541
+ venv_path = pathlib.Path(VIRTENV_RESOURCES_PATH / venv)
542
+ try:
543
+ shutil.rmtree(venv_path)
544
+ except Exception as e:
545
+ error_msg = f"Failed to remove '{venv_path}':\n{e}"
546
+ return False, error_msg
547
+
548
+ msg = f"Removed {len(venvs)} venv" + ('s' if len(venvs) != 1 else '') + '.'
549
+ return True, msg
550
+
489
551
 
490
552
  ### NOTE: This must be the final statement of the module.
491
553
  ### Any subactions added below these lines will not
@@ -10,8 +10,10 @@ from meerschaum.utils.typing import SuccessTuple, Any, List, Optional
10
10
 
11
11
  def python(
12
12
  action: Optional[List[str]] = None,
13
- venv: Optional[str] = 'mrsm',
14
13
  sub_args: Optional[List[str]] = None,
14
+ nopretty: bool = False,
15
+ noask: bool = False,
16
+ venv: Optional[str] = None,
15
17
  debug: bool = False,
16
18
  **kw: Any
17
19
  ) -> SuccessTuple:
@@ -24,8 +26,22 @@ def python(
24
26
 
25
27
  Examples:
26
28
  mrsm python
27
- mrsm python --venv noaa
28
- mrsm python [-i] [-c 'print("hi")']
29
+ mrsm python [-m pip -V]
30
+
31
+ Flags:
32
+ `--nopretty`
33
+ Open a plain Pyhthon REPL rather than ptpython.
34
+
35
+ `--noask`
36
+ Run the supplied Python code and do not open a REPL.
37
+
38
+ `--venv`
39
+ Run the Python interpreter from a virtual environment.
40
+ Will not have Meercshaum imported.
41
+
42
+ `--sub-args` (or flags surrounded by `[]`)
43
+ Rather than run Python code, execute the interpreter with the given sub-flags
44
+ (e.g. `mrsm python [-V]`)
29
45
  """
30
46
  import sys, subprocess, os
31
47
  from meerschaum.utils.debug import dprint
@@ -35,14 +51,16 @@ def python(
35
51
  from meerschaum.config import __version__ as _version
36
52
  from meerschaum.config.paths import VIRTENV_RESOURCES_PATH, PYTHON_RESOURCES_PATH
37
53
  from meerschaum.utils.packages import run_python_package, attempt_import
54
+ from meerschaum.utils.process import run_process
38
55
 
39
56
  if action is None:
40
57
  action = []
41
58
 
42
- if venv == 'None':
43
- venv = None
44
-
45
- joined_actions = ["import meerschaum as mrsm"]
59
+ joined_actions = (
60
+ ["import meerschaum as mrsm"]
61
+ if venv is None and not sub_args
62
+ else []
63
+ )
46
64
  line = ""
47
65
  for i, a in enumerate(action):
48
66
  if a == '':
@@ -73,6 +91,11 @@ def python(
73
91
  '"""); '
74
92
  + 'pts.print_formatted_text(ansi); '
75
93
  )
94
+ if nopretty or venv is not None or sub_args:
95
+ print_command = ""
96
+
97
+ if sub_args:
98
+ nopretty = True
76
99
 
77
100
  command = print_command
78
101
  for a in joined_actions:
@@ -88,19 +111,27 @@ def python(
88
111
  with open(init_script_path, 'w', encoding='utf-8') as f:
89
112
  f.write(command)
90
113
 
91
- env_dict = os.environ.copy()
92
- venv_path = (VIRTENV_RESOURCES_PATH / venv) if venv is not None else None
93
- if venv_path is not None:
94
- env_dict.update({'VIRTUAL_ENV': venv_path.as_posix()})
95
-
96
114
  try:
97
- ptpython = attempt_import('ptpython', venv=venv, allow_outside_venv=False)
115
+ ptpython = attempt_import('ptpython', venv=None)
98
116
  return_code = run_python_package(
99
117
  'ptpython',
100
118
  sub_args or ['--dark-bg', '-i', init_script_path.as_posix()],
119
+ foreground = True,
101
120
  venv = venv,
121
+ ) if not nopretty else run_process(
122
+ (
123
+ [venv_executable(venv)] + (
124
+ sub_args or
125
+ (
126
+ (
127
+ ['-i']
128
+ if not noask
129
+ else []
130
+ ) + [init_script_path.as_posix()]
131
+ )
132
+ )
133
+ ),
102
134
  foreground = True,
103
- env = env_dict,
104
135
  )
105
136
  except KeyboardInterrupt:
106
137
  return_code = 1
@@ -42,6 +42,7 @@ def show(
42
42
  'logs' : _show_logs,
43
43
  'tags' : _show_tags,
44
44
  'schedules' : _show_schedules,
45
+ 'venvs' : _show_venvs,
45
46
  }
46
47
  return choose_subaction(action, show_options, **kw)
47
48
 
@@ -903,6 +904,31 @@ def _show_schedules(
903
904
  return True, "Success"
904
905
 
905
906
 
907
+ def _show_venvs(
908
+ **kwargs: Any
909
+ ):
910
+ """
911
+ Print the available virtual environments in the current MRSM_ROOT_DIR.
912
+ """
913
+ import os
914
+ import pathlib
915
+ from meerschaum.config.paths import VIRTENV_RESOURCES_PATH
916
+ from meerschaum.utils.venv import venv_exists
917
+ from meerschaum.utils.misc import print_options
918
+
919
+ venvs = [
920
+ _venv
921
+ for _venv in os.listdir(VIRTENV_RESOURCES_PATH)
922
+ if venv_exists(_venv)
923
+ ]
924
+ print_options(
925
+ venvs,
926
+ name = 'Venvs:',
927
+ **kwargs
928
+ )
929
+
930
+ return True, "Success"
931
+
906
932
 
907
933
  ### NOTE: This must be the final statement of the module.
908
934
  ### Any subactions added below these lines will not
@@ -13,6 +13,23 @@ fastapi = attempt_import('fastapi', lazy=False, check_update=CHECK_UPDATE)
13
13
  fastapi_responses = attempt_import('fastapi.responses', lazy=False, check_update=CHECK_UPDATE)
14
14
  fastapi_login = attempt_import('fastapi_login', check_update=CHECK_UPDATE)
15
15
 
16
+ class CustomOAuth2PasswordRequestForm:
17
+ def __init__(
18
+ self,
19
+ grant_type: str = fastapi.Form(None, regex="password|client_credentials"),
20
+ username: str = fastapi.Form(...),
21
+ password: str = fastapi.Form(...),
22
+ scope: str = fastapi.Form(""),
23
+ client_id: str = fastapi.Form(None),
24
+ client_secret: str = fastapi.Form(None),
25
+ ):
26
+ self.grant_type = grant_type
27
+ self.username = username
28
+ self.password = password
29
+ self.scope = scope
30
+ self.client_id = client_id
31
+ self.client_secret = client_secret
32
+
16
33
  LoginManager = fastapi_login.LoginManager
17
34
  def generate_secret_key() -> str:
18
35
  """
@@ -8,13 +8,17 @@ Manage access and refresh tokens.
8
8
 
9
9
  from datetime import datetime, timedelta, timezone
10
10
  import fastapi
11
+ from fastapi import Request, status
11
12
  from fastapi_login.exceptions import InvalidCredentialsException
12
- from fastapi.security import OAuth2PasswordRequestForm
13
+ from fastapi.exceptions import RequestValidationError
13
14
  from starlette.responses import Response, JSONResponse
14
15
  from meerschaum.api import endpoints, get_api_connector, app, debug, manager, no_auth
15
16
  from meerschaum.core import User
16
17
  from meerschaum.config.static import STATIC_CONFIG
17
- from meerschaum.utils.typing import Dict, Any
18
+ from meerschaum.utils.typing import Dict, Any, Optional
19
+ from meerschaum.core.User._User import verify_password
20
+ from meerschaum.utils.warnings import warn
21
+ from meerschaum.api._oauth2 import CustomOAuth2PasswordRequestForm
18
22
 
19
23
 
20
24
  @manager.user_loader()
@@ -28,18 +32,18 @@ def load_user(
28
32
 
29
33
 
30
34
  @app.post(endpoints['login'], tags=['Users'])
31
- def login(
32
- data: OAuth2PasswordRequestForm = fastapi.Depends()
35
+ async def login(
36
+ data: CustomOAuth2PasswordRequestForm = fastapi.Depends()
37
+ # data: dict[str, str],
38
+ # request: Request
33
39
  ) -> Dict[str, Any]:
34
40
  """
35
41
  Login and set the session token.
36
42
  """
37
43
  username, password = (
38
- (data['username'], data['password']) if isinstance(data, dict)
39
- else (data.username, data.password)
44
+ (data.username, data.password)
40
45
  ) if not no_auth else ('no-auth', 'no-auth')
41
46
 
42
- from meerschaum.core.User._User import verify_password
43
47
  user = User(username, password)
44
48
  correct_password = no_auth or verify_password(
45
49
  password,
@@ -60,3 +64,15 @@ def login(
60
64
  'token_type': 'bearer',
61
65
  'expires' : expires_dt,
62
66
  }
67
+
68
+
69
+ @app.exception_handler(RequestValidationError)
70
+ async def validation_exception_handler(request: Request, exc: RequestValidationError):
71
+ """
72
+ Log validation errors as warnings.
73
+ """
74
+ warn(f"Validation error: {exc.errors()}", stack=False)
75
+ return JSONResponse(
76
+ status_code = status.HTTP_422_UNPROCESSABLE_ENTITY,
77
+ content = {"detail": exc.errors()},
78
+ )