meerschaum 2.1.7__py3-none-any.whl → 2.2.0__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.
- meerschaum/__main__.py +1 -1
- meerschaum/_internal/arguments/_parser.py +3 -0
- meerschaum/_internal/entry.py +3 -2
- meerschaum/actions/install.py +7 -3
- meerschaum/actions/show.py +128 -42
- meerschaum/actions/sync.py +7 -3
- meerschaum/api/__init__.py +24 -14
- meerschaum/api/_oauth2.py +4 -4
- meerschaum/api/dash/callbacks/dashboard.py +93 -23
- meerschaum/api/dash/callbacks/jobs.py +55 -3
- meerschaum/api/dash/jobs.py +34 -8
- meerschaum/api/dash/keys.py +1 -1
- meerschaum/api/dash/pages/dashboard.py +14 -4
- meerschaum/api/dash/pipes.py +137 -26
- meerschaum/api/dash/plugins.py +25 -9
- meerschaum/api/resources/static/js/xterm.js +1 -1
- meerschaum/api/resources/templates/termpage.html +3 -0
- meerschaum/api/routes/_login.py +5 -4
- meerschaum/api/routes/_plugins.py +6 -3
- meerschaum/config/_dash.py +11 -0
- meerschaum/config/_default.py +3 -1
- meerschaum/config/_jobs.py +13 -4
- meerschaum/config/_paths.py +2 -0
- meerschaum/config/_sync.py +2 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +6 -7
- meerschaum/config/stack/grafana/__init__.py +1 -1
- meerschaum/config/static/__init__.py +4 -1
- meerschaum/connectors/__init__.py +2 -0
- meerschaum/connectors/api/_plugins.py +2 -1
- meerschaum/connectors/sql/SQLConnector.py +4 -2
- meerschaum/connectors/sql/_create_engine.py +9 -9
- meerschaum/connectors/sql/_instance.py +3 -1
- meerschaum/connectors/sql/_pipes.py +54 -38
- meerschaum/connectors/sql/_plugins.py +0 -2
- meerschaum/connectors/sql/_sql.py +7 -9
- meerschaum/core/User/_User.py +158 -16
- meerschaum/core/User/__init__.py +1 -1
- meerschaum/plugins/_Plugin.py +12 -3
- meerschaum/plugins/__init__.py +23 -1
- meerschaum/utils/daemon/Daemon.py +89 -36
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +140 -0
- meerschaum/utils/daemon/RotatingFile.py +130 -14
- meerschaum/utils/daemon/__init__.py +3 -0
- meerschaum/utils/dtypes/__init__.py +9 -5
- meerschaum/utils/packages/__init__.py +21 -5
- meerschaum/utils/packages/_packages.py +18 -20
- meerschaum/utils/process.py +13 -10
- meerschaum/utils/schedule.py +276 -30
- meerschaum/utils/threading.py +1 -0
- meerschaum/utils/typing.py +1 -1
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/METADATA +59 -62
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/RECORD +59 -57
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/WHEEL +1 -1
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/LICENSE +0 -0
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/NOTICE +0 -0
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.1.7.dist-info → meerschaum-2.2.0.dist-info}/zip-safe +0 -0
meerschaum/utils/schedule.py
CHANGED
@@ -7,11 +7,71 @@ Schedule processes and threads.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
|
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
|
11
14
|
|
15
|
+
STARTING_KEYWORD: str = 'starting'
|
16
|
+
INTERVAL_UNITS: List[str] = ['months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'years']
|
17
|
+
FREQUENCY_ALIASES: Dict[str, str] = {
|
18
|
+
'daily': 'every 1 day',
|
19
|
+
'hourly': 'every 1 hour',
|
20
|
+
'minutely': 'every 1 minute',
|
21
|
+
'weekly': 'every 1 week',
|
22
|
+
'monthly': 'every 1 month',
|
23
|
+
'secondly': 'every 1 second',
|
24
|
+
'yearly': 'every 1 year',
|
25
|
+
}
|
26
|
+
LOGIC_ALIASES: Dict[str, str] = {
|
27
|
+
'and': '&',
|
28
|
+
'or': '|',
|
29
|
+
' through ': '-',
|
30
|
+
' thru ': '-',
|
31
|
+
' - ': '-',
|
32
|
+
'beginning': STARTING_KEYWORD,
|
33
|
+
}
|
34
|
+
CRON_DAYS_OF_WEEK: List[str] = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
|
35
|
+
CRON_DAYS_OF_WEEK_ALIASES: Dict[str, str] = {
|
36
|
+
'monday': 'mon',
|
37
|
+
'tuesday': 'tue',
|
38
|
+
'tues': 'tue',
|
39
|
+
'wednesday': 'wed',
|
40
|
+
'thursday': 'thu',
|
41
|
+
'thurs': 'thu',
|
42
|
+
'friday': 'fri',
|
43
|
+
'saturday': 'sat',
|
44
|
+
'sunday': 'sun',
|
45
|
+
}
|
46
|
+
CRON_MONTHS: List[str] = [
|
47
|
+
'jan', 'feb', 'mar', 'apr', 'may', 'jun',
|
48
|
+
'jul', 'aug', 'sep', 'oct', 'nov', 'dec',
|
49
|
+
]
|
50
|
+
CRON_MONTHS_ALIASES: Dict[str, str] = {
|
51
|
+
'january': 'jan',
|
52
|
+
'february': 'feb',
|
53
|
+
'march': 'mar',
|
54
|
+
'april': 'apr',
|
55
|
+
'may': 'may',
|
56
|
+
'june': 'jun',
|
57
|
+
'july': 'jul',
|
58
|
+
'august': 'aug',
|
59
|
+
'september': 'sep',
|
60
|
+
'october': 'oct',
|
61
|
+
'november': 'nov',
|
62
|
+
'december': 'dec',
|
63
|
+
}
|
64
|
+
SCHEDULE_ALIASES: Dict[str, str] = {
|
65
|
+
**FREQUENCY_ALIASES,
|
66
|
+
**LOGIC_ALIASES,
|
67
|
+
**CRON_DAYS_OF_WEEK_ALIASES,
|
68
|
+
**CRON_MONTHS_ALIASES,
|
69
|
+
}
|
70
|
+
|
71
|
+
_scheduler = None
|
12
72
|
def schedule_function(
|
13
73
|
function: Callable[[Any], Any],
|
14
|
-
|
74
|
+
schedule: str,
|
15
75
|
*args,
|
16
76
|
debug: bool = False,
|
17
77
|
**kw
|
@@ -25,41 +85,227 @@ def schedule_function(
|
|
25
85
|
function: Callable[[Any], Any]
|
26
86
|
The function to execute.
|
27
87
|
|
28
|
-
|
29
|
-
The frequency at which `function` should be executed (e.g. `'daily'`).
|
88
|
+
schedule: str
|
89
|
+
The frequency schedule at which `function` should be executed (e.g. `'daily'`).
|
30
90
|
|
31
91
|
"""
|
32
|
-
import
|
92
|
+
import asyncio
|
33
93
|
from meerschaum.utils.warnings import warn
|
34
|
-
from meerschaum.utils.
|
35
|
-
|
36
|
-
from concurrent.futures._base import CancelledError
|
94
|
+
from meerschaum.utils.misc import filter_keywords, round_time
|
95
|
+
global _scheduler
|
37
96
|
kw['debug'] = debug
|
38
97
|
kw = filter_keywords(function, **kw)
|
39
98
|
|
40
|
-
|
41
|
-
|
99
|
+
apscheduler = mrsm.attempt_import('apscheduler', lazy=False)
|
100
|
+
now = round_time(datetime.now(timezone.utc), timedelta(minutes=1))
|
101
|
+
trigger = parse_schedule(schedule, now=now)
|
102
|
+
_scheduler = apscheduler.AsyncScheduler()
|
103
|
+
try:
|
104
|
+
loop = asyncio.get_running_loop()
|
105
|
+
except RuntimeError:
|
106
|
+
loop = asyncio.new_event_loop()
|
107
|
+
|
108
|
+
async def run_scheduler():
|
109
|
+
async with _scheduler:
|
110
|
+
job = await _scheduler.add_schedule(function, trigger, args=args, kwargs=kw)
|
111
|
+
try:
|
112
|
+
await _scheduler.run_until_stopped()
|
113
|
+
except (KeyboardInterrupt, SystemExit) as e:
|
114
|
+
await _stop_scheduler()
|
115
|
+
raise e
|
42
116
|
|
43
|
-
pydantic = attempt_import('pydantic', debug=debug, lazy=False)
|
44
|
-
rocketry = attempt_import('rocketry', debug=debug, lazy=False)
|
45
117
|
try:
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
118
|
+
loop.run_until_complete(run_scheduler())
|
119
|
+
except (KeyboardInterrupt, SystemExit) as e:
|
120
|
+
loop.run_until_complete(_stop_scheduler())
|
121
|
+
|
122
|
+
|
123
|
+
def parse_schedule(schedule: str, now: Optional[datetime] = None):
|
124
|
+
"""
|
125
|
+
Parse a schedule string (e.g. 'daily') into a Trigger object.
|
126
|
+
"""
|
127
|
+
from meerschaum.utils.warnings import error
|
128
|
+
from meerschaum.utils.misc import items_str, is_int
|
129
|
+
(
|
130
|
+
apscheduler_triggers_cron,
|
131
|
+
apscheduler_triggers_interval,
|
132
|
+
apscheduler_triggers_calendarinterval,
|
133
|
+
apscheduler_triggers_combining,
|
134
|
+
) = (
|
135
|
+
mrsm.attempt_import(
|
136
|
+
'apscheduler.triggers.cron',
|
137
|
+
'apscheduler.triggers.interval',
|
138
|
+
'apscheduler.triggers.calendarinterval',
|
139
|
+
'apscheduler.triggers.combining',
|
140
|
+
lazy = False,
|
64
141
|
)
|
142
|
+
)
|
143
|
+
|
144
|
+
starting_ts = parse_start_time(schedule, now=now)
|
145
|
+
schedule = schedule.split(STARTING_KEYWORD)[0].strip()
|
146
|
+
for alias_keyword, true_keyword in SCHEDULE_ALIASES.items():
|
147
|
+
schedule = schedule.replace(alias_keyword, true_keyword)
|
148
|
+
|
149
|
+
### TODO Allow for combining `and` + `or` logic.
|
150
|
+
if '&' in schedule and '|' in schedule:
|
151
|
+
raise ValueError(f"Cannot accept both 'and' + 'or' logic in the schedule frequency.")
|
152
|
+
|
153
|
+
join_str = '|' if '|' in schedule else '&'
|
154
|
+
join_trigger = (
|
155
|
+
apscheduler_triggers_combining.OrTrigger
|
156
|
+
if join_str == '|'
|
157
|
+
else apscheduler_triggers_combining.AndTrigger
|
158
|
+
)
|
159
|
+
join_kwargs = {
|
160
|
+
'max_iterations': 1_000_000,
|
161
|
+
'threshold': 0,
|
162
|
+
} if join_str == '&' else {}
|
163
|
+
|
164
|
+
schedule_parts = [part.strip() for part in schedule.split(join_str)]
|
165
|
+
triggers = []
|
166
|
+
|
167
|
+
has_seconds = 'second' in schedule
|
168
|
+
has_minutes = 'minute' in schedule
|
169
|
+
|
170
|
+
for schedule_part in schedule_parts:
|
171
|
+
|
172
|
+
### Intervals must begin with 'every' (after alias substitution).
|
173
|
+
if schedule_part.lower().startswith('every '):
|
174
|
+
schedule_num_str, schedule_unit = (
|
175
|
+
schedule_part[len('every '):].split(' ', maxsplit=1)
|
176
|
+
)
|
177
|
+
schedule_unit = schedule_unit.rstrip('s') + 's'
|
178
|
+
if schedule_unit not in INTERVAL_UNITS:
|
179
|
+
raise ValueError(
|
180
|
+
f"Invalid interval '{schedule_unit}'.\n"
|
181
|
+
+ f" Accepted values are {items_str(INTERVAL_UNITS)}."
|
182
|
+
)
|
183
|
+
|
184
|
+
schedule_num = (
|
185
|
+
int(schedule_num_str)
|
186
|
+
if is_int(schedule_num_str)
|
187
|
+
else float(schedule_num_str)
|
188
|
+
)
|
189
|
+
|
190
|
+
trigger = (
|
191
|
+
apscheduler_triggers_interval.IntervalTrigger(
|
192
|
+
**{
|
193
|
+
schedule_unit: schedule_num,
|
194
|
+
'start_time': starting_ts,
|
195
|
+
}
|
196
|
+
)
|
197
|
+
if schedule_unit not in ('months', 'years') else (
|
198
|
+
apscheduler_triggers_calendarinterval.CalendarIntervalTrigger(
|
199
|
+
**{
|
200
|
+
schedule_unit: schedule_num,
|
201
|
+
'start_date': starting_ts,
|
202
|
+
'timezone': starting_ts.tzinfo,
|
203
|
+
}
|
204
|
+
)
|
205
|
+
)
|
206
|
+
)
|
207
|
+
|
208
|
+
### Determine whether this is a pure cron string or a cron subset (e.g. 'may-aug')_.
|
209
|
+
else:
|
210
|
+
first_three_prefix = schedule_part[:3].lower()
|
211
|
+
first_four_prefix = schedule_part[:4].lower()
|
212
|
+
cron_kw = {}
|
213
|
+
if first_three_prefix in CRON_DAYS_OF_WEEK:
|
214
|
+
cron_kw['day_of_week'] = schedule_part
|
215
|
+
elif first_three_prefix in CRON_MONTHS:
|
216
|
+
cron_kw['month'] = schedule_part
|
217
|
+
elif is_int(first_four_prefix) and len(first_four_prefix) == 4:
|
218
|
+
cron_kw['year'] = int(first_four_prefix)
|
219
|
+
trigger = (
|
220
|
+
apscheduler_triggers_cron.CronTrigger(
|
221
|
+
**{
|
222
|
+
**cron_kw,
|
223
|
+
'hour': '*',
|
224
|
+
'minute': '*' if has_minutes else starting_ts.minute,
|
225
|
+
'second': '*' if has_seconds else starting_ts.second,
|
226
|
+
'start_time': starting_ts,
|
227
|
+
'timezone': starting_ts.tzinfo,
|
228
|
+
}
|
229
|
+
)
|
230
|
+
if cron_kw
|
231
|
+
else apscheduler_triggers_cron.CronTrigger.from_crontab(
|
232
|
+
schedule_part,
|
233
|
+
timezone = starting_ts.tzinfo,
|
234
|
+
)
|
235
|
+
)
|
236
|
+
### Explicitly set the `start_time` after building with `from_crontab`.
|
237
|
+
if trigger.start_time != starting_ts:
|
238
|
+
trigger.start_time = starting_ts
|
239
|
+
|
240
|
+
triggers.append(trigger)
|
241
|
+
|
242
|
+
return (
|
243
|
+
join_trigger(triggers, **join_kwargs)
|
244
|
+
if len(triggers) != 1
|
245
|
+
else triggers[0]
|
246
|
+
)
|
247
|
+
|
248
|
+
|
249
|
+
def parse_start_time(schedule: str, now: Optional[datetime] = None) -> datetime:
|
250
|
+
"""
|
251
|
+
Return the datetime to use for the given schedule string.
|
252
|
+
|
253
|
+
Parameters
|
254
|
+
----------
|
255
|
+
schedule: str
|
256
|
+
The schedule frequency to be parsed into a starting datetime.
|
257
|
+
|
258
|
+
now: Optional[datetime], default None
|
259
|
+
If provided, use this value as a default if no start time is explicitly stated.
|
260
|
+
|
261
|
+
Returns
|
262
|
+
-------
|
263
|
+
A `datetime` object, either `now` or the datetime embedded in the schedule string.
|
264
|
+
|
265
|
+
Examples
|
266
|
+
--------
|
267
|
+
>>> parse_start_time('daily starting 2024-01-01')
|
268
|
+
datetime.datetime(2024, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
|
269
|
+
>>> parse_start_time('monthly starting 1st')
|
270
|
+
datetime.datetime(2024, 5, 1, 0, 0, tzinfo=datetime.timezone.utc)
|
271
|
+
>>> parse_start_time('hourly starting 00:30')
|
272
|
+
datetime.datetime(2024, 5, 13, 0, 30, tzinfo=datetime.timezone.utc)
|
273
|
+
"""
|
274
|
+
from meerschaum.utils.misc import round_time
|
275
|
+
from meerschaum.utils.warnings import error, warn
|
276
|
+
dateutil_parser = mrsm.attempt_import('dateutil.parser')
|
277
|
+
starting_parts = schedule.split(STARTING_KEYWORD)
|
278
|
+
starting_str = ('now' if len(starting_parts) == 1 else starting_parts[-1]).strip()
|
279
|
+
now = now or round_time(datetime.now(timezone.utc), timedelta(minutes=1))
|
280
|
+
try:
|
281
|
+
if starting_str == 'now':
|
282
|
+
starting_ts = now
|
283
|
+
elif 'tomorrow' in starting_str or 'today' in starting_str:
|
284
|
+
today = round_time(now, timedelta(days=1))
|
285
|
+
tomorrow = today + timedelta(days=1)
|
286
|
+
is_tomorrow = 'tomorrow' in starting_str
|
287
|
+
time_str = starting_str.replace('tomorrow', '').replace('today', '').strip()
|
288
|
+
time_ts = dateutil_parser.parse(time_str) if time_str else today
|
289
|
+
starting_ts = (
|
290
|
+
(tomorrow if is_tomorrow else today)
|
291
|
+
+ timedelta(hours=time_ts.hour)
|
292
|
+
+ timedelta(minutes=time_ts.minute)
|
293
|
+
)
|
294
|
+
else:
|
295
|
+
starting_ts = dateutil_parser.parse(starting_str)
|
296
|
+
schedule_parse_error = None
|
297
|
+
except Exception as e:
|
298
|
+
warn(f"Unable to parse starting time from '{starting_str}'.", stack=False)
|
299
|
+
schedule_parse_error = str(e)
|
300
|
+
if schedule_parse_error:
|
301
|
+
error(schedule_parse_error, ValueError, stack=False)
|
302
|
+
if not starting_ts.tzinfo:
|
303
|
+
starting_ts = starting_ts.replace(tzinfo=timezone.utc)
|
304
|
+
return starting_ts
|
305
|
+
|
65
306
|
|
307
|
+
async def _stop_scheduler():
|
308
|
+
if _scheduler is None:
|
309
|
+
return
|
310
|
+
await _scheduler.stop()
|
311
|
+
await _scheduler.wait_until_stopped()
|
meerschaum/utils/threading.py
CHANGED
meerschaum/utils/typing.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: meerschaum
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.2.0
|
4
4
|
Summary: Sync Time-Series Pipes with Meerschaum
|
5
5
|
Home-page: https://meerschaum.io
|
6
6
|
Author: Bennett Meares
|
@@ -31,47 +31,19 @@ Requires-Python: >=3.8
|
|
31
31
|
Description-Content-Type: text/markdown
|
32
32
|
License-File: LICENSE
|
33
33
|
License-File: NOTICE
|
34
|
-
Provides-Extra: _drivers
|
35
|
-
Requires-Dist: pyodbc >=4.0.30 ; extra == '_drivers'
|
36
|
-
Requires-Dist: cx-Oracle >=8.3.0 ; extra == '_drivers'
|
37
|
-
Provides-Extra: _required
|
38
|
-
Requires-Dist: wheel >=0.34.2 ; extra == '_required'
|
39
|
-
Requires-Dist: setuptools >=63.3.0 ; extra == '_required'
|
40
|
-
Requires-Dist: PyYAML >=5.3.1 ; extra == '_required'
|
41
|
-
Requires-Dist: pip >=22.0.4 ; extra == '_required'
|
42
|
-
Requires-Dist: update-checker >=0.18.0 ; extra == '_required'
|
43
|
-
Requires-Dist: semver >=3.0.0 ; extra == '_required'
|
44
|
-
Requires-Dist: pathspec >=0.9.0 ; extra == '_required'
|
45
|
-
Requires-Dist: python-dateutil >=2.7.5 ; extra == '_required'
|
46
|
-
Requires-Dist: requests >=2.23.0 ; extra == '_required'
|
47
|
-
Requires-Dist: binaryornot >=0.4.4 ; extra == '_required'
|
48
|
-
Requires-Dist: pyvim >=3.0.2 ; extra == '_required'
|
49
|
-
Requires-Dist: aiofiles >=0.6.0 ; extra == '_required'
|
50
|
-
Requires-Dist: packaging >=21.3.0 ; extra == '_required'
|
51
|
-
Requires-Dist: prompt-toolkit >=3.0.39 ; extra == '_required'
|
52
|
-
Requires-Dist: more-itertools >=8.7.0 ; extra == '_required'
|
53
|
-
Requires-Dist: python-daemon >=0.2.3 ; extra == '_required'
|
54
|
-
Requires-Dist: fasteners >=0.18.0 ; extra == '_required'
|
55
|
-
Requires-Dist: psutil >=5.8.0 ; extra == '_required'
|
56
|
-
Requires-Dist: watchgod >=0.7.0 ; extra == '_required'
|
57
|
-
Requires-Dist: dill >=0.3.3 ; extra == '_required'
|
58
|
-
Requires-Dist: virtualenv >=20.1.0 ; extra == '_required'
|
59
|
-
Requires-Dist: rocketry >=2.5.1 ; extra == '_required'
|
60
34
|
Provides-Extra: api
|
61
|
-
Requires-Dist: uvicorn[standard] >=0.
|
62
|
-
Requires-Dist: gunicorn >=
|
35
|
+
Requires-Dist: uvicorn[standard] >=0.29.0 ; extra == 'api'
|
36
|
+
Requires-Dist: gunicorn >=22.0.0 ; extra == 'api'
|
63
37
|
Requires-Dist: python-dotenv >=0.20.0 ; extra == 'api'
|
64
38
|
Requires-Dist: websockets >=11.0.3 ; extra == 'api'
|
65
|
-
Requires-Dist: fastapi >=0.
|
66
|
-
Requires-Dist: passlib >=1.7.4 ; extra == 'api'
|
39
|
+
Requires-Dist: fastapi >=0.111.0 ; extra == 'api'
|
67
40
|
Requires-Dist: fastapi-login >=1.7.2 ; extra == 'api'
|
68
|
-
Requires-Dist: python-multipart >=0.0.
|
69
|
-
Requires-Dist: pydantic <2.0.0 ; extra == 'api'
|
41
|
+
Requires-Dist: python-multipart >=0.0.9 ; extra == 'api'
|
70
42
|
Requires-Dist: httpx >=0.24.1 ; extra == 'api'
|
71
43
|
Requires-Dist: numpy >=1.18.5 ; extra == 'api'
|
72
44
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'api'
|
73
|
-
Requires-Dist: pyarrow >=
|
74
|
-
Requires-Dist: dask >=
|
45
|
+
Requires-Dist: pyarrow >=16.1.0 ; extra == 'api'
|
46
|
+
Requires-Dist: dask[dataframe] >=2024.5.1 ; extra == 'api'
|
75
47
|
Requires-Dist: pytz ; extra == 'api'
|
76
48
|
Requires-Dist: joblib >=0.17.0 ; extra == 'api'
|
77
49
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'api'
|
@@ -79,11 +51,11 @@ Requires-Dist: databases >=0.4.0 ; extra == 'api'
|
|
79
51
|
Requires-Dist: aiosqlite >=0.16.0 ; extra == 'api'
|
80
52
|
Requires-Dist: asyncpg >=0.21.0 ; extra == 'api'
|
81
53
|
Requires-Dist: cryptography >=38.0.1 ; extra == 'api'
|
82
|
-
Requires-Dist:
|
54
|
+
Requires-Dist: psycopg[binary] >=3.1.18 ; extra == 'api'
|
83
55
|
Requires-Dist: PyMySQL >=0.9.0 ; extra == 'api'
|
84
56
|
Requires-Dist: aiomysql >=0.0.21 ; extra == 'api'
|
85
57
|
Requires-Dist: sqlalchemy-cockroachdb >=2.0.0 ; extra == 'api'
|
86
|
-
Requires-Dist: duckdb
|
58
|
+
Requires-Dist: duckdb <0.10.3 ; extra == 'api'
|
87
59
|
Requires-Dist: duckdb-engine >=0.9.2 ; extra == 'api'
|
88
60
|
Requires-Dist: wheel >=0.34.2 ; extra == 'api'
|
89
61
|
Requires-Dist: setuptools >=63.3.0 ; extra == 'api'
|
@@ -103,10 +75,10 @@ Requires-Dist: more-itertools >=8.7.0 ; extra == 'api'
|
|
103
75
|
Requires-Dist: python-daemon >=0.2.3 ; extra == 'api'
|
104
76
|
Requires-Dist: fasteners >=0.18.0 ; extra == 'api'
|
105
77
|
Requires-Dist: psutil >=5.8.0 ; extra == 'api'
|
106
|
-
Requires-Dist:
|
78
|
+
Requires-Dist: watchfiles >=0.21.0 ; extra == 'api'
|
107
79
|
Requires-Dist: dill >=0.3.3 ; extra == 'api'
|
108
80
|
Requires-Dist: virtualenv >=20.1.0 ; extra == 'api'
|
109
|
-
Requires-Dist:
|
81
|
+
Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'api'
|
110
82
|
Requires-Dist: pprintpp >=0.4.0 ; extra == 'api'
|
111
83
|
Requires-Dist: asciitree >=0.3.3 ; extra == 'api'
|
112
84
|
Requires-Dist: typing-extensions >=4.7.1 ; extra == 'api'
|
@@ -124,14 +96,37 @@ Requires-Dist: dash-daq >=0.5.0 ; extra == 'api'
|
|
124
96
|
Requires-Dist: terminado >=0.12.1 ; extra == 'api'
|
125
97
|
Requires-Dist: tornado >=6.1.0 ; extra == 'api'
|
126
98
|
Provides-Extra: build
|
127
|
-
Requires-Dist: cx-Freeze >=
|
128
|
-
Requires-Dist: pyinstaller
|
99
|
+
Requires-Dist: cx-Freeze >=7.0.0 ; extra == 'build'
|
100
|
+
Requires-Dist: pyinstaller >6.6.0 ; extra == 'build'
|
129
101
|
Provides-Extra: cli
|
130
102
|
Requires-Dist: pgcli >=3.1.0 ; extra == 'cli'
|
131
103
|
Requires-Dist: mycli >=1.23.2 ; extra == 'cli'
|
132
104
|
Requires-Dist: litecli >=1.5.0 ; extra == 'cli'
|
133
105
|
Requires-Dist: mssql-cli >=1.0.0 ; extra == 'cli'
|
134
106
|
Requires-Dist: gadwall >=0.2.0 ; extra == 'cli'
|
107
|
+
Provides-Extra: core
|
108
|
+
Requires-Dist: wheel >=0.34.2 ; extra == 'core'
|
109
|
+
Requires-Dist: setuptools >=63.3.0 ; extra == 'core'
|
110
|
+
Requires-Dist: PyYAML >=5.3.1 ; extra == 'core'
|
111
|
+
Requires-Dist: pip >=22.0.4 ; extra == 'core'
|
112
|
+
Requires-Dist: update-checker >=0.18.0 ; extra == 'core'
|
113
|
+
Requires-Dist: semver >=3.0.0 ; extra == 'core'
|
114
|
+
Requires-Dist: pathspec >=0.9.0 ; extra == 'core'
|
115
|
+
Requires-Dist: python-dateutil >=2.7.5 ; extra == 'core'
|
116
|
+
Requires-Dist: requests >=2.23.0 ; extra == 'core'
|
117
|
+
Requires-Dist: binaryornot >=0.4.4 ; extra == 'core'
|
118
|
+
Requires-Dist: pyvim >=3.0.2 ; extra == 'core'
|
119
|
+
Requires-Dist: aiofiles >=0.6.0 ; extra == 'core'
|
120
|
+
Requires-Dist: packaging >=21.3.0 ; extra == 'core'
|
121
|
+
Requires-Dist: prompt-toolkit >=3.0.39 ; extra == 'core'
|
122
|
+
Requires-Dist: more-itertools >=8.7.0 ; extra == 'core'
|
123
|
+
Requires-Dist: python-daemon >=0.2.3 ; extra == 'core'
|
124
|
+
Requires-Dist: fasteners >=0.18.0 ; extra == 'core'
|
125
|
+
Requires-Dist: psutil >=5.8.0 ; extra == 'core'
|
126
|
+
Requires-Dist: watchfiles >=0.21.0 ; extra == 'core'
|
127
|
+
Requires-Dist: dill >=0.3.3 ; extra == 'core'
|
128
|
+
Requires-Dist: virtualenv >=20.1.0 ; extra == 'core'
|
129
|
+
Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'core'
|
135
130
|
Provides-Extra: dash
|
136
131
|
Requires-Dist: Flask-Compress >=1.10.1 ; extra == 'dash'
|
137
132
|
Requires-Dist: dash >=2.6.2 ; extra == 'dash'
|
@@ -149,6 +144,7 @@ Requires-Dist: mypy >=0.812.0 ; extra == 'dev-tools'
|
|
149
144
|
Requires-Dist: pytest >=6.2.2 ; extra == 'dev-tools'
|
150
145
|
Requires-Dist: pytest-xdist >=3.2.1 ; extra == 'dev-tools'
|
151
146
|
Requires-Dist: heartrate >=0.2.1 ; extra == 'dev-tools'
|
147
|
+
Requires-Dist: build >=1.2.1 ; extra == 'dev-tools'
|
152
148
|
Provides-Extra: docs
|
153
149
|
Requires-Dist: mkdocs >=1.1.2 ; extra == 'docs'
|
154
150
|
Requires-Dist: mkdocs-material >=6.2.5 ; extra == 'docs'
|
@@ -161,12 +157,15 @@ Requires-Dist: mkdocs-redirects >=1.0.4 ; extra == 'docs'
|
|
161
157
|
Requires-Dist: jinja2 ==3.0.3 ; extra == 'docs'
|
162
158
|
Provides-Extra: drivers
|
163
159
|
Requires-Dist: cryptography >=38.0.1 ; extra == 'drivers'
|
164
|
-
Requires-Dist:
|
160
|
+
Requires-Dist: psycopg[binary] >=3.1.18 ; extra == 'drivers'
|
165
161
|
Requires-Dist: PyMySQL >=0.9.0 ; extra == 'drivers'
|
166
162
|
Requires-Dist: aiomysql >=0.0.21 ; extra == 'drivers'
|
167
163
|
Requires-Dist: sqlalchemy-cockroachdb >=2.0.0 ; extra == 'drivers'
|
168
|
-
Requires-Dist: duckdb
|
164
|
+
Requires-Dist: duckdb <0.10.3 ; extra == 'drivers'
|
169
165
|
Requires-Dist: duckdb-engine >=0.9.2 ; extra == 'drivers'
|
166
|
+
Provides-Extra: drivers-extras
|
167
|
+
Requires-Dist: pyodbc >=4.0.30 ; extra == 'drivers-extras'
|
168
|
+
Requires-Dist: cx-Oracle >=8.3.0 ; extra == 'drivers-extras'
|
170
169
|
Provides-Extra: extras
|
171
170
|
Requires-Dist: cmd2 >=1.4.0 ; extra == 'extras'
|
172
171
|
Requires-Dist: ruamel.yaml >=0.16.12 ; extra == 'extras'
|
@@ -209,24 +208,24 @@ Requires-Dist: more-itertools >=8.7.0 ; extra == 'full'
|
|
209
208
|
Requires-Dist: python-daemon >=0.2.3 ; extra == 'full'
|
210
209
|
Requires-Dist: fasteners >=0.18.0 ; extra == 'full'
|
211
210
|
Requires-Dist: psutil >=5.8.0 ; extra == 'full'
|
212
|
-
Requires-Dist:
|
211
|
+
Requires-Dist: watchfiles >=0.21.0 ; extra == 'full'
|
213
212
|
Requires-Dist: dill >=0.3.3 ; extra == 'full'
|
214
213
|
Requires-Dist: virtualenv >=20.1.0 ; extra == 'full'
|
215
|
-
Requires-Dist:
|
214
|
+
Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'full'
|
216
215
|
Requires-Dist: cryptography >=38.0.1 ; extra == 'full'
|
217
|
-
Requires-Dist:
|
216
|
+
Requires-Dist: psycopg[binary] >=3.1.18 ; extra == 'full'
|
218
217
|
Requires-Dist: PyMySQL >=0.9.0 ; extra == 'full'
|
219
218
|
Requires-Dist: aiomysql >=0.0.21 ; extra == 'full'
|
220
219
|
Requires-Dist: sqlalchemy-cockroachdb >=2.0.0 ; extra == 'full'
|
221
|
-
Requires-Dist: duckdb
|
220
|
+
Requires-Dist: duckdb <0.10.3 ; extra == 'full'
|
222
221
|
Requires-Dist: duckdb-engine >=0.9.2 ; extra == 'full'
|
223
222
|
Requires-Dist: toga >=0.3.0-dev29 ; extra == 'full'
|
224
223
|
Requires-Dist: pywebview >=3.6.3 ; extra == 'full'
|
225
224
|
Requires-Dist: pycparser >=2.21.0 ; extra == 'full'
|
226
225
|
Requires-Dist: numpy >=1.18.5 ; extra == 'full'
|
227
226
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'full'
|
228
|
-
Requires-Dist: pyarrow >=
|
229
|
-
Requires-Dist: dask >=
|
227
|
+
Requires-Dist: pyarrow >=16.1.0 ; extra == 'full'
|
228
|
+
Requires-Dist: dask[dataframe] >=2024.5.1 ; extra == 'full'
|
230
229
|
Requires-Dist: pytz ; extra == 'full'
|
231
230
|
Requires-Dist: joblib >=0.17.0 ; extra == 'full'
|
232
231
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'full'
|
@@ -241,15 +240,13 @@ Requires-Dist: dash-extensions >=1.0.4 ; extra == 'full'
|
|
241
240
|
Requires-Dist: dash-daq >=0.5.0 ; extra == 'full'
|
242
241
|
Requires-Dist: terminado >=0.12.1 ; extra == 'full'
|
243
242
|
Requires-Dist: tornado >=6.1.0 ; extra == 'full'
|
244
|
-
Requires-Dist: uvicorn[standard] >=0.
|
245
|
-
Requires-Dist: gunicorn >=
|
243
|
+
Requires-Dist: uvicorn[standard] >=0.29.0 ; extra == 'full'
|
244
|
+
Requires-Dist: gunicorn >=22.0.0 ; extra == 'full'
|
246
245
|
Requires-Dist: python-dotenv >=0.20.0 ; extra == 'full'
|
247
246
|
Requires-Dist: websockets >=11.0.3 ; extra == 'full'
|
248
|
-
Requires-Dist: fastapi >=0.
|
249
|
-
Requires-Dist: passlib >=1.7.4 ; extra == 'full'
|
247
|
+
Requires-Dist: fastapi >=0.111.0 ; extra == 'full'
|
250
248
|
Requires-Dist: fastapi-login >=1.7.2 ; extra == 'full'
|
251
|
-
Requires-Dist: python-multipart >=0.0.
|
252
|
-
Requires-Dist: pydantic <2.0.0 ; extra == 'full'
|
249
|
+
Requires-Dist: python-multipart >=0.0.9 ; extra == 'full'
|
253
250
|
Requires-Dist: httpx >=0.24.1 ; extra == 'full'
|
254
251
|
Provides-Extra: gui
|
255
252
|
Requires-Dist: toga >=0.3.0-dev29 ; extra == 'gui'
|
@@ -261,8 +258,8 @@ Provides-Extra: setup
|
|
261
258
|
Provides-Extra: sql
|
262
259
|
Requires-Dist: numpy >=1.18.5 ; extra == 'sql'
|
263
260
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'sql'
|
264
|
-
Requires-Dist: pyarrow >=
|
265
|
-
Requires-Dist: dask >=
|
261
|
+
Requires-Dist: pyarrow >=16.1.0 ; extra == 'sql'
|
262
|
+
Requires-Dist: dask[dataframe] >=2024.5.1 ; extra == 'sql'
|
266
263
|
Requires-Dist: pytz ; extra == 'sql'
|
267
264
|
Requires-Dist: joblib >=0.17.0 ; extra == 'sql'
|
268
265
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'sql'
|
@@ -270,11 +267,11 @@ Requires-Dist: databases >=0.4.0 ; extra == 'sql'
|
|
270
267
|
Requires-Dist: aiosqlite >=0.16.0 ; extra == 'sql'
|
271
268
|
Requires-Dist: asyncpg >=0.21.0 ; extra == 'sql'
|
272
269
|
Requires-Dist: cryptography >=38.0.1 ; extra == 'sql'
|
273
|
-
Requires-Dist:
|
270
|
+
Requires-Dist: psycopg[binary] >=3.1.18 ; extra == 'sql'
|
274
271
|
Requires-Dist: PyMySQL >=0.9.0 ; extra == 'sql'
|
275
272
|
Requires-Dist: aiomysql >=0.0.21 ; extra == 'sql'
|
276
273
|
Requires-Dist: sqlalchemy-cockroachdb >=2.0.0 ; extra == 'sql'
|
277
|
-
Requires-Dist: duckdb
|
274
|
+
Requires-Dist: duckdb <0.10.3 ; extra == 'sql'
|
278
275
|
Requires-Dist: duckdb-engine >=0.9.2 ; extra == 'sql'
|
279
276
|
Requires-Dist: wheel >=0.34.2 ; extra == 'sql'
|
280
277
|
Requires-Dist: setuptools >=63.3.0 ; extra == 'sql'
|
@@ -294,12 +291,12 @@ Requires-Dist: more-itertools >=8.7.0 ; extra == 'sql'
|
|
294
291
|
Requires-Dist: python-daemon >=0.2.3 ; extra == 'sql'
|
295
292
|
Requires-Dist: fasteners >=0.18.0 ; extra == 'sql'
|
296
293
|
Requires-Dist: psutil >=5.8.0 ; extra == 'sql'
|
297
|
-
Requires-Dist:
|
294
|
+
Requires-Dist: watchfiles >=0.21.0 ; extra == 'sql'
|
298
295
|
Requires-Dist: dill >=0.3.3 ; extra == 'sql'
|
299
296
|
Requires-Dist: virtualenv >=20.1.0 ; extra == 'sql'
|
300
|
-
Requires-Dist:
|
297
|
+
Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'sql'
|
301
298
|
Provides-Extra: stack
|
302
|
-
Requires-Dist: docker-compose >=1.
|
299
|
+
Requires-Dist: docker-compose >=1.29.2 ; extra == 'stack'
|
303
300
|
|
304
301
|
<img src="https://meerschaum.io/assets/banner_1920x320.png" alt="Meerschaum banner" style="width: 100%"/>
|
305
302
|
|