meerschaum 2.2.5.dev2__py3-none-any.whl → 2.2.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. meerschaum/__init__.py +4 -1
  2. meerschaum/_internal/arguments/_parser.py +13 -3
  3. meerschaum/_internal/docs/index.py +513 -110
  4. meerschaum/_internal/term/__init__.py +2 -2
  5. meerschaum/actions/bootstrap.py +13 -14
  6. meerschaum/actions/python.py +11 -8
  7. meerschaum/actions/register.py +130 -32
  8. meerschaum/actions/show.py +92 -75
  9. meerschaum/actions/stack.py +12 -12
  10. meerschaum/actions/stop.py +11 -11
  11. meerschaum/api/__init__.py +0 -1
  12. meerschaum/api/dash/__init__.py +0 -1
  13. meerschaum/api/dash/callbacks/custom.py +1 -1
  14. meerschaum/api/dash/callbacks/login.py +21 -13
  15. meerschaum/api/dash/pages/login.py +2 -2
  16. meerschaum/api/dash/plugins.py +5 -6
  17. meerschaum/api/routes/_login.py +5 -5
  18. meerschaum/config/__init__.py +8 -1
  19. meerschaum/config/_paths.py +20 -2
  20. meerschaum/config/_version.py +1 -1
  21. meerschaum/config/paths.py +21 -2
  22. meerschaum/config/static/__init__.py +1 -0
  23. meerschaum/connectors/Connector.py +7 -2
  24. meerschaum/connectors/__init__.py +7 -5
  25. meerschaum/connectors/api/APIConnector.py +7 -2
  26. meerschaum/connectors/api/_actions.py +23 -31
  27. meerschaum/connectors/api/_uri.py +5 -5
  28. meerschaum/core/Pipe/__init__.py +7 -3
  29. meerschaum/core/Pipe/_data.py +23 -15
  30. meerschaum/core/Pipe/_deduplicate.py +1 -1
  31. meerschaum/core/Pipe/_dtypes.py +5 -0
  32. meerschaum/core/Pipe/_fetch.py +18 -16
  33. meerschaum/core/Pipe/_sync.py +20 -15
  34. meerschaum/plugins/_Plugin.py +6 -6
  35. meerschaum/plugins/__init__.py +1 -1
  36. meerschaum/utils/daemon/RotatingFile.py +15 -16
  37. meerschaum/utils/dataframe.py +12 -4
  38. meerschaum/utils/debug.py +9 -15
  39. meerschaum/utils/formatting/__init__.py +13 -12
  40. meerschaum/utils/misc.py +117 -11
  41. meerschaum/utils/packages/__init__.py +7 -1
  42. meerschaum/utils/typing.py +1 -0
  43. meerschaum/utils/venv/__init__.py +5 -1
  44. meerschaum/utils/warnings.py +9 -1
  45. meerschaum/utils/yaml.py +2 -2
  46. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/METADATA +1 -1
  47. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/RECORD +53 -54
  48. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/WHEEL +1 -1
  49. meerschaum/actions/backup.py +0 -43
  50. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/LICENSE +0 -0
  51. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/NOTICE +0 -0
  52. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/entry_points.txt +0 -0
  53. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/top_level.txt +0 -0
  54. {meerschaum-2.2.5.dev2.dist-info → meerschaum-2.2.6.dist-info}/zip-safe +0 -0
@@ -3,132 +3,535 @@
3
3
  # vim:fenc=utf-8
4
4
 
5
5
  """
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <style>
8
+
9
+ .container {
10
+ display: flex;
11
+ justify-content: space-between;
12
+ }
13
+ .left, .right {
14
+ width: 45%; /* Adjust width as needed */
15
+ }
16
+
17
+ </style>
18
+
6
19
  <img src="https://meerschaum.io/assets/banner_1920x320.png" alt="Meerschaum banner" style="width: 100%;"/>
7
20
 
8
- | PyPI | GitHub | Info | Stats |
9
- |---|---|---|---|
10
- | ![PyPI]( https://img.shields.io/pypi/v/meerschaum?color=%2300cc66&label=Version ) | ![GitHub Repo stars](https://img.shields.io/github/stars/bmeares/Meerschaum?style=social) | ![License](https://img.shields.io/github/license/bmeares/Meerschaum?label=License) | ![Number of plugins]( https://img.shields.io/badge/dynamic/json?color=3098c1&label=Public%20Plugins&query=num_plugins&url=https%3A%2F%2Fapi.mrsm.io%2Finfo ) |
11
- | ![PyPI - Python Version]( https://img.shields.io/pypi/pyversions/meerschaum?label=Python&logo=python&logoColor=%23ffffff ) | ![GitHub Sponsors](https://img.shields.io/github/sponsors/bmeares?color=eadf15&label=Sponsors) | [![meerschaum Tutorials](https://badges.openbase.com/python/tutorials/meerschaum.svg?token=2Yi8Oav9UZYWocO1ncwnIOnpUN5dTnUMWai7lAKTB+k=)](https://openbase.com/python/meerschaum?utm_source=embedded&amp;utm_medium=badge&amp;utm_campaign=rate-badge) | ![Number of registered users]( https://img.shields.io/badge/dynamic/json?color=3098c1&label=Registered%20Users&query=num_users&url=https%3A%2F%2Fapi.mrsm.io%2Finfo ) |
12
-
13
- <p align="center">
14
- <img src="https://meerschaum.io/files/images/demo.gif" alt="Meerschaum demo" style="width: 100%;">
15
- </p>
16
-
17
- ## What is Meerschaum?
18
- Meerschaum is a tool for quickly synchronizing time-series data streams called **pipes**. With Meerschaum, you can have a data visualization stack running in minutes.
19
-
20
- <p align="center">
21
- <img src="https://meerschaum.io/assets/screenshots/weather_pipes.png" style="width: 100%;"/>
22
- </p>
23
-
24
- ## Why Meerschaum?
25
-
26
- If you've worked with time-series data, you know the headaches that come with ETL.
27
- Data engineering often gets in analysts' way, and when work needs to get done, every minute spent on pipelining is time taken away from real analysis.
28
-
29
- Rather than copy / pasting your ETL scripts, simply build pipes with Meerschaum! [Meerschaum gives you the tools to design your data streams how you like](https://towardsdatascience.com/easy-time-series-etl-for-data-scientists-with-meerschaum-5aade339b398) ― and don't worry — you can always incorporate Meerschaum into your existing systems!
30
-
31
- ## Features
32
-
33
- - 📊 **Built for Data Scientists and Analysts**
34
- - Integrate with Pandas, Grafana and other popular [data analysis tools](https://meerschaum.io/reference/data-analysis-tools/).
35
- - Persist your dataframes and always get the latest data.
36
- - ⚡️ **Production-Ready, Batteries Included**
37
- - [Synchronization engine](https://meerschaum.io/reference/pipes/syncing/) concurrently updates many time-series data streams.
38
- - One-click deploy a [TimescaleDB and Grafana stack](https://meerschaum.io/reference/stack/) for prototyping.
39
- - Serve data to your entire organization through the power of `uvicorn`, `gunicorn`, and `FastAPI`.
40
- - 🔌 **Easily Expandable**
41
- - Ingest any data source with a simple [plugin](https://meerschaum.io/reference/plugins/writing-plugins/). Just return a DataFrame, and Meerschaum handles the rest.
42
- - [Add any function as a command](https://meerschaum.io/reference/plugins/types-of-plugins/#action-plugins) to the Meerschaum system.
43
- - Include Meerschaum in your projects with its [easy-to-use Python API](https://docs.meerschaum.io).
44
- - ✨ **Tailored for Your Experience**
45
- - Rich CLI makes managing your data streams surprisingly enjoyable!
46
- - Web dashboard for those who prefer a more graphical experience.
47
- - Manage your database connections with [Meerschaum connectors](https://meerschaum.io/reference/connectors/)
48
- - Utility commands with sensible syntax let you control many pipes with grace.
49
- - 💼 **Portable from the Start**
50
- - The environment variables `$MRSM_ROOT_DIR`, `$MRSM_PLUGINS_DIR`, and `$MRSM_VENVS_DIR` let you emulate multiple installations and group together your [instances](https://meerschaum.io/reference/connectors/#instances-and-repositories).
51
- - No dependencies required; anything needed will be installed into virtual environments.
52
- - [Specify required packages for your plugins](https://meerschaum.io/reference/plugins/writing-plugins/), and users will get those packages in a virtual environment.
53
-
54
- ## Installation
55
-
56
- For a more thorough setup guide, visit the [Getting Started](https://meerschaum.io/get-started/) page at [meerschaum.io](https://meerschaum.io).
57
-
58
- ### TL;DR
59
-
60
- ```bash
61
- pip install -U --user meerschaum
62
- mrsm stack up -d db grafana
63
- mrsm bootstrap pipes
21
+ # Meerschaum Python API
22
+
23
+ Welcome to the Meerschaum Python API technical documentation! Here you can find information about the classes and functions provided by the `meerschaum` package. Visit [meerschaum.io](https://meerschaum.io) for general usage documentation.
24
+
25
+ ## Root Module
26
+
27
+ For your convenience, the following classes and functions may be imported from the root `meerschaum` namespace:
28
+
29
+ <div class="container" style="display: flex; justify-content: space-between">
30
+
31
+ <div class="left" style="width: 45%;">
32
+
33
+ <h3>Classes</h3>
34
+
35
+ <ul>
36
+ <li><code>meerschaum.Connector</code></li>
37
+ <li><code>meerschaum.Pipe</code></li>
38
+ <li><code>meerschaum.Plugin</code></li>
39
+ <li><code>meerschaum.SuccessTuple</code></li>
40
+ <li><code>meerschaum.Venv</code></li>
41
+ </ul>
42
+
43
+ </div>
44
+
45
+
46
+ <div class="right" style="width: 45%">
47
+
48
+ <h3>Functions</h3>
49
+
50
+ <ul>
51
+ <li><code>meerschaum.get_config()</code></li>
52
+ <li><code>meerschaum.get_connector()</code></li>
53
+ <li><code>meerschaum.get_pipes()</code></li>
54
+ <li><code>meerschaum.make_connector()</code></li>
55
+ <li><code>meerschaum.pprint()</code></li>
56
+ <li><code>meerschaum.attempt_import()</code></li>
57
+ </ul>
58
+
59
+ </div>
60
+ </div>
61
+
62
+ ### Examples
63
+
64
+ #### Build a Connector
65
+
66
+ ```python
67
+ import meerschaum as mrsm
68
+
69
+ sql_conn = mrsm.get_connector(
70
+ 'sql:temp',
71
+ flavor='sqlite',
72
+ database='/tmp/tmp.db',
73
+ )
74
+ df = sql_conn.read("SELECT 1 AS foo")
75
+ print(df)
76
+ # foo
77
+ # 0 1
78
+
79
+ sql_conn.to_sql(df, 'foo')
80
+ print(sql_conn.read('foo'))
81
+ # foo
82
+ # 0 1
64
83
  ```
65
84
 
66
- ## Usage Documentation
85
+ #### Create a Custom Connector Class
67
86
 
68
- Please visit [meerschaum.io](https://meerschaum.io) for setup, usage, and troubleshooting information. You can find technical documentation at [docs.meerschaum.io](https://docs.meerschaum.io), and here is a complete list of the [Meerschaum actions](https://meerschaum.io/reference/actions/).
87
+ ```python
88
+ from datetime import datetime, timezone
89
+ from random import randint
90
+ import meerschaum as mrsm
91
+ from meerschaum.utils.misc import round_time
92
+
93
+ @mrsm.make_connector
94
+ class FooConnector(mrsm.Connector):
95
+ REQUIRED_ATTRIBUTES = ['username', 'password']
96
+
97
+ def fetch(
98
+ self,
99
+ begin: datetime | None = None,
100
+ end: datetime | None = None,
101
+ ):
102
+ now = begin or round_time(datetime.now(timezone.utc))
103
+ return [
104
+ {'ts': now, 'id': 1, 'vl': randint(1, 100)},
105
+ {'ts': now, 'id': 2, 'vl': randint(1, 100)},
106
+ {'ts': now, 'id': 3, 'vl': randint(1, 100)},
107
+ ]
108
+
109
+ foo_conn = mrsm.get_connector(
110
+ 'foo:bar',
111
+ username='foo',
112
+ password='bar',
113
+ )
114
+ docs = foo_conn.fetch()
115
+ ```
116
+
117
+ #### Build a Pipe
69
118
 
70
119
  ```python
71
- >>> import meerschaum as mrsm
72
- >>> pipe = mrsm.Pipe("plugin:noaa", "weather")
73
- >>> cols_to_select = ['timestamp', 'station', 'temperature (degC)']
74
- >>> df = pipe.get_data(cols_to_select, begin='2023-11-15', end='2023-11-20')
75
- >>> df
76
- timestamp station temperature (degC)
77
- 0 2023-11-15 00:52:00 KATL 16.1
78
- 1 2023-11-15 00:52:00 KCLT 11.7
79
- 2 2023-11-15 00:53:00 KGMU 15.0
80
- 3 2023-11-15 00:54:00 KCEU 13.9
81
- 4 2023-11-15 01:52:00 KATL 15.6
82
- .. ... ... ...
83
- 535 2023-11-19 22:54:00 KCEU 15.6
84
- 536 2023-11-19 23:52:00 KATL 16.7
85
- 537 2023-11-19 23:52:00 KCLT 13.9
86
- 538 2023-11-19 23:53:00 KGMU 15.6
87
- 539 2023-11-19 23:54:00 KCEU 15.0
88
-
89
- [540 rows x 3 columns]
90
- >>>
120
+ from datetime import datetime
121
+ import meerschaum as mrsm
122
+
123
+ pipe = mrsm.Pipe(
124
+ foo_conn, 'demo',
125
+ instance=sql_conn,
126
+ columns={'datetime': 'ts', 'id': 'id'},
127
+ tags=['production'],
128
+ )
129
+ pipe.sync(begin=datetime(2024, 1, 1))
130
+ df = pipe.get_data()
131
+ print(df)
132
+ # ts id vl
133
+ # 0 2024-01-01 1 97
134
+ # 1 2024-01-01 2 18
135
+ # 2 2024-01-01 3 96
91
136
  ```
92
137
 
93
- ## Plugins
138
+ #### Get Registered Pipes
94
139
 
95
- Check out the [Awesome Meerschaum list](https://github.com/bmeares/awesome-meerschaum) for a list of community plugins as well as the [public plugins repository](https://api.mrsm.io/dash/plugins).
140
+ ```python
141
+ import meerschaum as mrsm
96
142
 
97
- For details on installing, using, and writing plugins, check out the [plugins documentation](https://meerschaum.io/reference/plugins/types-of-plugins) at [meerschaum.io](https://meerschaum.io).
143
+ pipes = mrsm.get_pipes(
144
+ tags=['production'],
145
+ instance=sql_conn,
146
+ as_list=True,
147
+ )
148
+ print(pipes)
149
+ # [Pipe('foo:bar', 'demo', instance='sql:temp')]
150
+ ```
98
151
 
99
- #### Example Plugin
152
+ #### Access a Plugin's Module
100
153
 
101
154
  ```python
102
- # ~/.config/meerschaum/plugins/example.py
103
- __version__ = '0.0.1'
104
- required = []
105
-
106
- def register(pipe, **kw):
107
- return {
108
- 'columns': {
109
- 'datetime': 'dt',
110
- 'id': 'id',
111
- 'value': 'val',
112
- }
113
- }
114
-
115
- def fetch(pipe, **kw):
116
- import random
117
- from datetime import datetime
118
- docs = [
119
- {
120
- 'dt': datetime.now(),
121
- 'id': i,
122
- 'val': random.ranint(0, 200),
123
- }
124
- for i in range(random.randint(0, 100))
125
- ]
126
- return docs
155
+ import meerschaum as mrsm
156
+
157
+ plugin = mrsm.Plugin('noaa')
158
+ with mrsm.Venv(plugin):
159
+ noaa = plugin.module
160
+ print(noaa.get_station_info('KGMU'))
161
+ # {'name': 'Greenville Downtown Airport', 'geometry': {'type': 'Point', 'coordinates': [-82.35004, 34.84873]}}
127
162
  ```
128
163
 
129
- ## Support Meerschaum's Development
164
+ ## Submodules
165
+
166
+ <details>
167
+ <summary>
168
+ `meerschaum.actions`<br>
169
+ Access functions for actions and subactions.
170
+ </summary>
171
+
172
+ - `meerschaum.actions.actions`
173
+ - `meerschaum.actions.get_action()`
174
+ - `meerschaum.actions.get_completer()`
175
+ - `meerschaum.actions.get_main_action_name()`
176
+ - `meerschaum.actions.get_subactions()`
177
+
178
+ </details>
179
+
180
+ <details>
181
+ <summary>
182
+ `meerschaum.config`<br>
183
+ Read and write the Meerschaum configuration registry.
184
+ </summary>
185
+
186
+ - `meerschaum.config.get_config()`
187
+ - `meerschaum.config.get_plugin_config()`
188
+ - `meerschaum.config.write_config()`
189
+ - `meerschaum.config.write_plugin_config()`
190
+
191
+ </details>
192
+
193
+ <details>
194
+ <summary>
195
+ `meerschaum.connectors`<br>
196
+ Build connectors to interact with databases and fetch data.
197
+ </summary>
198
+
199
+ - `meerschaum.connectors.get_connector()`
200
+ - `meerschaum.connectors.make_connector()`
201
+ - `meerschaum.connectors.is_connected()`
202
+ - `meerschaum.connectors.poll.retry_connect()`
203
+ - `meerschaum.connectors.Connector`
204
+ - `meerschaum.connectors.SQLConnector`
205
+ - `meerschaum.connectors.APIConnector`
206
+
207
+ </details>
208
+
209
+ <details>
210
+ <summary>
211
+ `meerschaum.plugins`<br>
212
+ Access plugin modules and other API utilties.
213
+ </summary>
214
+
215
+ - `meerschaum.plugins.Plugin`
216
+ - `meerschaum.plugins.api_plugin()`
217
+ - `meerschaum.plugins.dash_plugin()`
218
+ - `meerschaum.plugins.import_plugins()`
219
+ - `meerschaum.plugins.reload_plugins()`
220
+ - `meerschaum.plugins.get_plugins()`
221
+ - `meerschaum.plugins.get_data_plugins()`
222
+ - `meerschaum.plugins.add_plugin_argument()`
223
+ - `meerschaum.plugins.pre_sync_hook()`
224
+ - `meerschaum.plugins.post_sync_hook()`
225
+
226
+ </details>
227
+
228
+ <details>
229
+ <summary><code>meerschaum.utils</code><br>
230
+ Utility functions are available in several submodules:<br>
231
+ </summary>
232
+
233
+ <ul>
234
+ <details>
235
+ <summary>
236
+ <code>meerschaum.utils.daemon</code><br>
237
+ Manage background jobs.<br>
238
+ </summary>
239
+ <p></p>
240
+ <ul>
241
+ <li><code>meerschaum.utils.daemon.daemon_entry()</code></li>
242
+ <li><code>meerschaum.utils.daemon.daemon_action()</code></li>
243
+ <li><code>meerschaum.utils.daemon.get_daemons()</code></li>
244
+ <li><code>meerschaum.utils.daemon.get_daemon_ids()</code></li>
245
+ <li><code>meerschaum.utils.daemon.get_running_daemons()</code></li>
246
+ <li><code>meerschaum.utils.daemon.get_paused_daemons()</code></li>
247
+ <li><code>meerschaum.utils.daemon.get_stopped_daemons()</code></li>
248
+ <li><code>meerschaum.utils.daemon.get_filtered_daemons()</code></li>
249
+ <li><code>meerschaum.utils.daemon.run_daemon()</code></li>
250
+ <li><code>meerschaum.utils.daemon.Daemon</code></li>
251
+ <li><code>meerschaum.utils.daemon.FileDescriptorInterceptor</code></li>
252
+ <li><code>meerschaum.utils.daemon.RotatingFile</code></li>
253
+ </ul>
254
+ </details>
255
+ </ul>
256
+
257
+ <ul>
258
+ <details>
259
+ <summary>
260
+ <code>meerschaum.utils.debug</code><br>
261
+ Debugging tools.<br>
262
+ </summary>
263
+ <p></p>
264
+ <ul>
265
+ <li><code>meerschaum.utils.debug.dprint()</code></li>
266
+ <li><code>meerschaum.utils.debug.trace()</code></li>
267
+ </ul>
268
+ </details>
269
+ </ul>
270
+
271
+ <ul>
272
+ <details>
273
+ <summary>
274
+ <code>meerschaum.utils.dataframe</code><br>
275
+ Manipulate dataframes.<br>
276
+ </summary>
277
+ <p></p>
278
+ <ul>
279
+ <li><code>meerschaum.utils.dataframe.add_missing_cols_to_df()</code></li>
280
+ <li><code>meerschaum.utils.dataframe.df_is_chunk_generator()</code></li>
281
+ <li><code>meerschaum.utils.dataframe.enforce_dtypes()</code></li>
282
+ <li><code>meerschaum.utils.dataframe.filter_unseen_df()</code></li>
283
+ <li><code>meerschaum.utils.dataframe.get_datetime_bound_from_df()</code></li>
284
+ <li><code>meerschaum.utils.dataframe.get_first_valid_dask_partition()</code></li>
285
+ <li><code>meerschaum.utils.dataframe.get_json_cols()</code></li>
286
+ <li><code>meerschaum.utils.dataframe.get_numeric_cols()</code></li>
287
+ <li><code>meerschaum.utils.dataframe.get_unhashable_cols()</code></li>
288
+ <li><code>meerschaum.utils.dataframe.parse_df_datetimes()</code></li>
289
+ <li><code>meerschaum.utils.dataframe.query_df()</code></li>
290
+ </ul>
291
+ </details>
292
+ </ul>
293
+
294
+ <ul>
295
+ <details>
296
+ <summary>
297
+ <code>meerschaum.utils.dtypes</code><br>
298
+ Work with data types.<br>
299
+ </summary>
300
+ <p></p>
301
+ <ul>
302
+ <li><code>meerschaum.utils.dtypes.are_dtypes_equal()</code></li>
303
+ <li><code>meerschaum.utils.dtypes.attempt_cast_to_numeric()</code></li>
304
+ <li><code>meerschaum.utils.dtypes.is_dtype_numeric()</code></li>
305
+ <li><code>meerschaum.utils.dtypes.none_if_null()</code></li>
306
+ <li><code>meerschaum.utils.dtypes.quantize_decimal()</code></li>
307
+ <li><code>meerschaum.utils.dtypes.to_pandas_dtype()</code></li>
308
+ <li><code>meerschaum.utils.dtypes.value_is_null()</code></li>
309
+ <li><code>meerschaum.utils.dtypes.sql.get_pd_type_from_db_type()</code></li>
310
+ <li><code>meerschaum.utils.dtypes.sql.get_db_type_from_pd_type()</code></li>
311
+ </ul>
312
+ </details>
313
+ </ul>
314
+
315
+ <ul>
316
+ <details>
317
+ <summary>
318
+ <code>meerschaum.utils.formatting</code><br>
319
+ Format output text.<br>
320
+ </summary>
321
+ <p></p>
322
+ <ul>
323
+ <li><code>meerschaum.utils.formatting.colored()</code></li>
324
+ <li><code>meerschaum.utils.formatting.extract_stats_from_message()</code></li>
325
+ <li><code>meerschaum.utils.formatting.fill_ansi()</code></li>
326
+ <li><code>meerschaum.utils.formatting.get_console()</code></li>
327
+ <li><code>meerschaum.utils.formatting.highlight_pipes()</code></li>
328
+ <li><code>meerschaum.utils.formatting.make_header()</code></li>
329
+ <li><code>meerschaum.utils.formatting.pipe_repr()</code></li>
330
+ <li><code>meerschaum.utils.formatting.pprint()</code></li>
331
+ <li><code>meerschaum.utils.formatting.pprint_pipes()</code></li>
332
+ <li><code>meerschaum.utils.formatting.print_options()</code></li>
333
+ <li><code>meerschaum.utils.formatting.print_pipes_results()</code></li>
334
+ <li><code>meerschaum.utils.formatting.print_tuple()</code></li>
335
+ <li><code>meerschaum.utils.formatting.translate_rich_to_termcolor()</code></li>
336
+ </ul>
337
+ </details>
338
+ </ul>
339
+
340
+ <ul>
341
+ <details>
342
+ <summary>
343
+ <code>meerschaum.utils.misc</code><br>
344
+ Miscellaneous utility functions.<br>
345
+ </summary>
346
+ <p></p>
347
+ <ul>
348
+ <li><code>meerschaum.utils.misc.items_str()</code></li>
349
+ <li><code>meerschaum.utils.misc.round_time()</code></li>
350
+ <li><code>meerschaum.utils.misc.is_int()</code></li>
351
+ <li><code>meerschaum.utils.misc.interval_str()</code></li>
352
+ <li><code>meerschaum.utils.misc.filter_keywords()</code></li>
353
+ <li><code>meerschaum.utils.misc.generate_password()</code></li>
354
+ <li><code>meerschaum.utils.misc.string_to_dict()</code></li>
355
+ <li><code>meerschaum.utils.misc.iterate_chunks()</code></li>
356
+ <li><code>meerschaum.utils.misc.timed_input()</code></li>
357
+ <li><code>meerschaum.utils.misc.replace_pipes_in_dict()</code></li>
358
+ <li><code>meerschaum.utils.misc.is_valid_email()</code></li>
359
+ <li><code>meerschaum.utils.misc.string_width()</code></li>
360
+ <li><code>meerschaum.utils.misc.replace_password()</code></li>
361
+ <li><code>meerschaum.utils.misc.parse_config_substitution()</code></li>
362
+ <li><code>meerschaum.utils.misc.edit_file()</code></li>
363
+ <li><code>meerschaum.utils.misc.get_in_ex_params()</code></li>
364
+ <li><code>meerschaum.utils.misc.separate_negation_values()</code></li>
365
+ <li><code>meerschaum.utils.misc.flatten_list()</code></li>
366
+ <li><code>meerschaum.utils.misc.make_symlink()</code></li>
367
+ <li><code>meerschaum.utils.misc.is_symlink()</code></li>
368
+ <li><code>meerschaum.utils.misc.wget()</code></li>
369
+ <li><code>meerschaum.utils.misc.add_method_to_class()</code></li>
370
+ <li><code>meerschaum.utils.misc.is_pipe_registered()</code></li>
371
+ <li><code>meerschaum.utils.misc.get_cols_lines()</code></li>
372
+ <li><code>meerschaum.utils.misc.sorted_dict()</code></li>
373
+ <li><code>meerschaum.utils.misc.flatten_pipes_dict()</code></li>
374
+ <li><code>meerschaum.utils.misc.dict_from_od()</code></li>
375
+ <li><code>meerschaum.utils.misc.remove_ansi()</code></li>
376
+ <li><code>meerschaum.utils.misc.get_connector_labels()</code></li>
377
+ <li><code>meerschaum.utils.misc.json_serialize_datetime()</code></li>
378
+ <li><code>meerschaum.utils.misc.async_wrap()</code></li>
379
+ <li><code>meerschaum.utils.misc.is_docker_available()</code></li>
380
+ <li><code>meerschaum.utils.misc.is_android()</code></li>
381
+ <li><code>meerschaum.utils.misc.is_bcp_available()</code></li>
382
+ <li><code>meerschaum.utils.misc.truncate_string_sections()</code></li>
383
+ <li><code>meerschaum.utils.misc.safely_extract_tar()</code></li>
384
+ </ul>
385
+ </details>
386
+ </ul>
387
+
388
+ <ul>
389
+ <details>
390
+ <summary>
391
+ <code>meerschaum.utils.packages</code><br>
392
+ Manage Python packages.
393
+ <br>
394
+ </summary>
395
+ <p></p>
396
+ <ul>
397
+ <li><code>meerschaum.utils.packages.attempt_import()</code></li>
398
+ <li><code>meerschaum.utils.packages.get_module_path()</code></li>
399
+ <li><code>meerschaum.utils.packages.manually_import_module()</code></li>
400
+ <li><code>meerschaum.utils.packages.get_install_no_version()</code></li>
401
+ <li><code>meerschaum.utils.packages.determine_version()</code></li>
402
+ <li><code>meerschaum.utils.packages.need_update()</code></li>
403
+ <li><code>meerschaum.utils.packages.get_pip()</code></li>
404
+ <li><code>meerschaum.utils.packages.pip_install()</code></li>
405
+ <li><code>meerschaum.utils.packages.pip_uninstall()</code></li>
406
+ <li><code>meerschaum.utils.packages.completely_uninstall_package()</code></li>
407
+ <li><code>meerschaum.utils.packages.run_python_package()</code></li>
408
+ <li><code>meerschaum.utils.packages.lazy_import()</code></li>
409
+ <li><code>meerschaum.utils.packages.pandas_name()</code></li>
410
+ <li><code>meerschaum.utils.packages.import_pandas()</code></li>
411
+ <li><code>meerschaum.utils.packages.import_rich()</code></li>
412
+ <li><code>meerschaum.utils.packages.import_dcc()</code></li>
413
+ <li><code>meerschaum.utils.packages.import_html()</code></li>
414
+ <li><code>meerschaum.utils.packages.get_modules_from_package()</code></li>
415
+ <li><code>meerschaum.utils.packages.import_children()</code></li>
416
+ <li><code>meerschaum.utils.packages.reload_package()</code></li>
417
+ <li><code>meerschaum.utils.packages.reload_meerschaum()</code></li>
418
+ <li><code>meerschaum.utils.packages.is_installed()</code></li>
419
+ <li><code>meerschaum.utils.packages.venv_contains_package()</code></li>
420
+ <li><code>meerschaum.utils.packages.package_venv()</code></li>
421
+ <li><code>meerschaum.utils.packages.ensure_readline()</code></li>
422
+ <li><code>meerschaum.utils.packages.get_prerelease_dependencies()</code></li>
423
+ </ul>
424
+ </details>
425
+ </ul>
426
+
427
+ <ul>
428
+ <details>
429
+ <summary>
430
+ <code>meerschaum.utils.prompt</code><br>
431
+ Read input from the user.
432
+ <br>
433
+ </summary>
434
+ <p></p>
435
+ <ul>
436
+ <li><code>meerschaum.utils.prompt.prompt()</code></li>
437
+ <li><code>meerschaum.utils.prompt.yes_no()</code></li>
438
+ <li><code>meerschaum.utils.prompt.choose()</code></li>
439
+ <li><code>meerschaum.utils.prompt.get_password()</code></li>
440
+ <li><code>meerschaum.utils.prompt.get_email()</code></li>
441
+ </ul>
442
+ </details>
443
+ </ul>
444
+
445
+ <ul>
446
+ <details>
447
+ <summary>
448
+ <code>meerschaum.utils.schedule</code><br>
449
+ Schedule processes and threads.
450
+ <br>
451
+ </summary>
452
+ <p></p>
453
+ <ul>
454
+ <li><code>meerschaum.utils.schedule.schedule_function()</code></li>
455
+ <li><code>meerschaum.utils.schedule.parse_schedule()</code></li>
456
+ <li><code>meerschaum.utils.schedule.parse_start_time()</code></li>
457
+ </ul>
458
+ </details>
459
+ </ul>
460
+
461
+ <ul>
462
+ <details>
463
+ <summary>
464
+ <code>meerschaum.utils.sql</code><br>
465
+ Build SQL queries.
466
+ <br>
467
+ </summary>
468
+ <p></p>
469
+ <ul>
470
+ <li><code>meerschaum.utils.sql.build_where()</code></li>
471
+ <li><code>meerschaum.utils.sql.clean()</code></li>
472
+ <li><code>meerschaum.utils.sql.dateadd_str()</code></li>
473
+ <li><code>meerschaum.utils.sql.test_connection()</code></li>
474
+ <li><code>meerschaum.utils.sql.get_distinct_col_count()</code></li>
475
+ <li><code>meerschaum.utils.sql.sql_item_name()</code></li>
476
+ <li><code>meerschaum.utils.sql.pg_capital()</code></li>
477
+ <li><code>meerschaum.utils.sql.oracle_capital()</code></li>
478
+ <li><code>meerschaum.utils.sql.truncate_item_name()</code></li>
479
+ <li><code>meerschaum.utils.sql.table_exists()</code></li>
480
+ <li><code>meerschaum.utils.sql.get_table_cols_types()</code></li>
481
+ <li><code>meerschaum.utils.sql.get_update_queries()</code></li>
482
+ <li><code>meerschaum.utils.sql.get_null_replacement()</code></li>
483
+ <li><code>meerschaum.utils.sql.get_db_version()</code></li>
484
+ <li><code>meerschaum.utils.sql.get_rename_table_queries()</code></li>
485
+ <li><code>meerschaum.utils.sql.get_create_table_query()</code></li>
486
+ <li><code>meerschaum.utils.sql.format_cte_subquery()</code></li>
487
+ <li><code>meerschaum.utils.sql.session_execute()</code></li>
488
+ </ul>
489
+ </details>
490
+ </ul>
491
+
492
+ <ul>
493
+ <details>
494
+ <summary>
495
+ <code>meerschaum.utils.venv</code><br>
496
+ Manage virtual environments.
497
+ <br>
498
+ </summary>
499
+ <p></p>
500
+ <ul>
501
+ <li><code>meerschaum.utils.venv.Venv</code></li>
502
+ <li><code>meerschaum.utils.venv.activate_venv()</code></li>
503
+ <li><code>meerschaum.utils.venv.deactivate_venv()</code></li>
504
+ <li><code>meerschaum.utils.venv.get_module_venv()</code></li>
505
+ <li><code>meerschaum.utils.venv.get_venvs()</code></li>
506
+ <li><code>meerschaum.utils.venv.init_venv()</code></li>
507
+ <li><code>meerschaum.utils.venv.inside_venv()</code></li>
508
+ <li><code>meerschaum.utils.venv.is_venv_active()</code></li>
509
+ <li><code>meerschaum.utils.venv.venv_exec()</code></li>
510
+ <li><code>meerschaum.utils.venv.venv_executable()</code></li>
511
+ <li><code>meerschaum.utils.venv.venv_exists()</code></li>
512
+ <li><code>meerschaum.utils.venv.venv_target_path()</code></li>
513
+ <li><code>meerschaum.utils.venv.verify_venv()</code></li>
514
+ </ul>
515
+ </details>
516
+ </ul>
517
+
518
+ <ul>
519
+ <details>
520
+ <summary>
521
+ <code>meerschaum.utils.warnings</code><br>
522
+ Print warnings, errors, info, and debug messages.
523
+ <br>
524
+ </summary>
525
+ <p></p>
526
+ <ul>
527
+ <li><code>meerschaum.utils.warnings.dprint()</code></li>
528
+ <li><code>meerschaum.utils.warnings.error()</code></li>
529
+ <li><code>meerschaum.utils.warnings.info()</code></li>
530
+ <li><code>meerschaum.utils.warnings.warn()</code></li>
531
+ </ul>
532
+ </details>
533
+ </ul>
130
534
 
131
- For consulting services and to support Meerschaum's development, please considering sponsoring me on [GitHub sponsors](https://github.com/sponsors/bmeares).
535
+ </details>
132
536
 
133
- Additionally, you can always [buy me a coffee☕](https://www.buymeacoffee.com/bmeares)!
134
537
  """
@@ -22,7 +22,7 @@ tornado, tornado_ioloop, terminado = attempt_import(
22
22
 
23
23
  def get_webterm_app_and_manager() -> Tuple[
24
24
  tornado.web.Application,
25
- terminado.UniqueTermManager,
25
+ terminado.UniqueTermManager,
26
26
  ]:
27
27
  """
28
28
  Construct the Tornado web app and term manager from the provided sysargs.
@@ -47,7 +47,7 @@ def get_webterm_app_and_manager() -> Tuple[
47
47
  {'term_manager': term_manager}
48
48
  ),
49
49
  (
50
- r"/",
50
+ r"/",
51
51
  TermPageHandler
52
52
  ),
53
53
  ]