meerschaum 2.4.13__py3-none-any.whl → 2.5.1__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.
@@ -77,15 +77,69 @@ def columns(self) -> Union[Dict[str, str], None]:
77
77
 
78
78
 
79
79
  @columns.setter
80
- def columns(self, columns: Dict[str, str]) -> None:
80
+ def columns(self, _columns: Union[Dict[str, str], List[str]]) -> None:
81
81
  """
82
82
  Override the columns dictionary of the in-memory pipe.
83
83
  Call `meerschaum.Pipe.edit()` to persist changes.
84
84
  """
85
+ if isinstance(_columns, (list, tuple)):
86
+ _columns = {col: col for col in _columns}
85
87
  if not isinstance(columns, dict):
86
- warn(f"{self}.columns must be a dictionary, received {type(columns)}")
88
+ warn(f"{self}.columns must be a dictionary, received {type(_columns)}.")
87
89
  return
88
- self.parameters['columns'] = columns
90
+ self.parameters['columns'] = _columns
91
+
92
+
93
+ @property
94
+ def indices(self) -> Union[Dict[str, Union[str, List[str]]], None]:
95
+ """
96
+ Return the `indices` dictionary defined in `meerschaum.Pipe.parameters`.
97
+ """
98
+ indices_key = (
99
+ 'indexes'
100
+ if 'indexes' in self.parameters
101
+ else 'indices'
102
+ )
103
+ if indices_key not in self.parameters:
104
+ self.parameters[indices_key] = {}
105
+ _indices = self.parameters[indices_key]
106
+ if not isinstance(_indices, dict):
107
+ _indices = {}
108
+ self.parameters[indices_key] = _indices
109
+ return {**self.columns, **_indices}
110
+
111
+
112
+ @property
113
+ def indexes(self) -> Union[Dict[str, Union[str, List[str]]], None]:
114
+ """
115
+ Alias for `meerschaum.Pipe.indices`.
116
+ """
117
+ return self.indices
118
+
119
+
120
+ @indices.setter
121
+ def indices(self, _indices: Union[Dict[str, Union[str, List[str]]], List[str]]) -> None:
122
+ """
123
+ Override the indices dictionary of the in-memory pipe.
124
+ Call `meerschaum.Pipe.edit()` to persist changes.
125
+ """
126
+ if not isinstance(_indices, dict):
127
+ warn(f"{self}.indices must be a dictionary, received {type(_indices)}.")
128
+ return
129
+ indices_key = (
130
+ 'indexes'
131
+ if 'indexes' in self.parameters
132
+ else 'indices'
133
+ )
134
+ self.parameters[indices_key] = _indices
135
+
136
+
137
+ @indexes.setter
138
+ def indexes(self, _indexes: Union[Dict[str, Union[str, List[str]]], List[str]]) -> None:
139
+ """
140
+ Alias for `meerschaum.Pipe.indices`.
141
+ """
142
+ self.indices = _indexes
89
143
 
90
144
 
91
145
  @property
@@ -415,27 +469,55 @@ def guess_datetime(self) -> Union[str, None]:
415
469
  """
416
470
  Try to determine a pipe's datetime column.
417
471
  """
418
- dtypes = self.dtypes
472
+ _dtypes = self.dtypes
419
473
 
420
474
  ### Abort if the user explictly disallows a datetime index.
421
- if 'datetime' in dtypes:
422
- if dtypes['datetime'] is None:
475
+ if 'datetime' in _dtypes:
476
+ if _dtypes['datetime'] is None:
423
477
  return None
424
478
 
479
+ from meerschaum.utils.dtypes import are_dtypes_equal
425
480
  dt_cols = [
426
- col for col, typ in self.dtypes.items()
427
- if str(typ).startswith('datetime')
481
+ col
482
+ for col, typ in _dtypes.items()
483
+ if are_dtypes_equal(typ, 'datetime')
428
484
  ]
429
485
  if not dt_cols:
430
486
  return None
431
- return dt_cols[0]
487
+ return dt_cols[0]
432
488
 
433
489
 
434
490
  def get_indices(self) -> Dict[str, str]:
435
491
  """
436
- Return a dictionary in the form of `pipe.columns` but map to index names.
437
- """
438
- return {
439
- ix: (self.target + '_' + col + '_index')
440
- for ix, col in self.columns.items() if col
492
+ Return a dictionary mapping index keys to their names on the database.
493
+
494
+ Returns
495
+ -------
496
+ A dictionary of index keys to column names.
497
+ """
498
+ _parameters = self.parameters
499
+ _index_template = _parameters.get('index_template', "IX_{target}_{column_names}")
500
+ _indices = self.indices
501
+ _target = self.target
502
+ _column_names = {
503
+ ix: (
504
+ '_'.join(cols)
505
+ if isinstance(cols, (list, tuple))
506
+ else str(cols)
507
+ )
508
+ for ix, cols in _indices.items()
509
+ if cols
510
+ }
511
+ _index_names = {
512
+ ix: (
513
+ _index_template.format(
514
+ target=_target,
515
+ column_names=column_names,
516
+ connector_keys=self.connector_keys,
517
+ metric_key=self.connector_key,
518
+ location_key=self.location_key,
519
+ )
520
+ )
521
+ for ix, column_names in _column_names.items()
441
522
  }
523
+ return _index_names
@@ -413,6 +413,7 @@ def parse_df_datetimes(
413
413
  from meerschaum.utils.packages import import_pandas, attempt_import
414
414
  from meerschaum.utils.debug import dprint
415
415
  from meerschaum.utils.warnings import warn
416
+ from meerschaum.utils.misc import items_str
416
417
  import traceback
417
418
  pd = import_pandas()
418
419
  pandas = attempt_import('pandas')
@@ -503,14 +504,14 @@ def parse_df_datetimes(
503
504
  else:
504
505
  df[datetime_cols] = df[datetime_cols].apply(
505
506
  pd.to_datetime,
506
- utc = True,
507
- axis = 1,
508
- meta = {
507
+ utc=True,
508
+ axis=1,
509
+ meta={
509
510
  col: 'datetime64[ns]'
510
511
  for col in datetime_cols
511
512
  }
512
513
  )
513
- except Exception as e:
514
+ except Exception:
514
515
  warn(
515
516
  f"Unable to apply `pd.to_datetime` to {items_str(datetime_cols)}:\n"
516
517
  + f"{traceback.format_exc()}"
@@ -519,7 +520,7 @@ def parse_df_datetimes(
519
520
  for dt in datetime_cols:
520
521
  try:
521
522
  df[dt] = df[dt].dt.tz_localize(None)
522
- except Exception as e:
523
+ except Exception:
523
524
  warn(f"Unable to convert column '{dt}' to naive datetime:\n{traceback.format_exc()}")
524
525
 
525
526
  return df
@@ -567,6 +568,9 @@ def get_json_cols(df: 'pd.DataFrame') -> List[str]:
567
568
  -------
568
569
  A list of columns to be encoded as JSON.
569
570
  """
571
+ if df is None:
572
+ return []
573
+
570
574
  is_dask = 'dask' in df.__module__ if hasattr(df, '__module__') else False
571
575
  if is_dask:
572
576
  df = get_first_valid_dask_partition(df)
@@ -602,6 +606,8 @@ def get_numeric_cols(df: 'pd.DataFrame') -> List[str]:
602
606
  -------
603
607
  A list of columns to treat as numerics.
604
608
  """
609
+ if df is None:
610
+ return []
605
611
  from decimal import Decimal
606
612
  is_dask = 'dask' in df.__module__
607
613
  if is_dask:
@@ -638,6 +644,8 @@ def get_uuid_cols(df: 'pd.DataFrame') -> List[str]:
638
644
  -------
639
645
  A list of columns to treat as numerics.
640
646
  """
647
+ if df is None:
648
+ return []
641
649
  from uuid import UUID
642
650
  is_dask = 'dask' in df.__module__
643
651
  if is_dask:
@@ -883,6 +891,8 @@ def get_datetime_bound_from_df(
883
891
  -------
884
892
  The minimum or maximum datetime value in the dataframe, or `None`.
885
893
  """
894
+ if df is None:
895
+ return None
886
896
  if not datetime_column:
887
897
  return None
888
898
 
@@ -955,6 +965,8 @@ def get_unique_index_values(
955
965
  -------
956
966
  A dictionary mapping indices to unique values.
957
967
  """
968
+ if df is None:
969
+ return {}
958
970
  if 'dataframe' in str(type(df)).lower():
959
971
  pandas = mrsm.attempt_import('pandas')
960
972
  return {
@@ -1182,9 +1194,9 @@ def query_df(
1182
1194
  dtypes = {col: str(typ) for col, typ in df.dtypes.items()}
1183
1195
 
1184
1196
  if inplace:
1185
- df.infer_objects(copy=False).fillna(NA, inplace=True)
1197
+ df.fillna(NA, inplace=True)
1186
1198
  else:
1187
- df = df.infer_objects(copy=False).fillna(NA)
1199
+ df = df.infer_objects().fillna(NA)
1188
1200
 
1189
1201
  if isinstance(begin, str):
1190
1202
  begin = dateutil_parser.parse(begin)
@@ -11,7 +11,12 @@ from __future__ import annotations
11
11
  import importlib.util, os, pathlib, re
12
12
  from meerschaum.utils.typing import Any, List, SuccessTuple, Optional, Union, Tuple, Dict, Iterable
13
13
  from meerschaum.utils.threading import Lock, RLock
14
- from meerschaum.utils.packages._packages import packages, all_packages, get_install_names
14
+ from meerschaum.utils.packages._packages import (
15
+ packages,
16
+ all_packages,
17
+ get_install_names,
18
+ _MRSM_PACKAGE_ARCHIVES_PREFIX,
19
+ )
15
20
  from meerschaum.utils.venv import (
16
21
  activate_venv,
17
22
  deactivate_venv,
@@ -35,14 +40,14 @@ _locks = {
35
40
  }
36
41
  _checked_for_updates = set()
37
42
  _is_installed_first_check: Dict[str, bool] = {}
38
- _MRSM_PACKAGE_ARCHIVES_PREFIX: str = "https://meerschaum.io/files/archives/"
43
+
39
44
 
40
45
  def get_module_path(
41
- import_name: str,
42
- venv: Optional[str] = 'mrsm',
43
- debug: bool = False,
44
- _try_install_name_on_fail: bool = True,
45
- ) -> Union[pathlib.Path, None]:
46
+ import_name: str,
47
+ venv: Optional[str] = 'mrsm',
48
+ debug: bool = False,
49
+ _try_install_name_on_fail: bool = True,
50
+ ) -> Union[pathlib.Path, None]:
46
51
  """
47
52
  Get a module's path without importing.
48
53
  """
@@ -232,10 +237,10 @@ def manually_import_module(
232
237
  if check_update:
233
238
  if need_update(
234
239
  None,
235
- import_name = root_name,
236
- version = _version,
237
- check_pypi = check_pypi,
238
- debug = debug,
240
+ import_name=root_name,
241
+ version=_version,
242
+ check_pypi=check_pypi,
243
+ debug=debug,
239
244
  ):
240
245
  if install:
241
246
  if not pip_install(
@@ -491,6 +496,8 @@ def _get_package_metadata(import_name: str, venv: Optional[str]) -> Dict[str, st
491
496
  import re
492
497
  from meerschaum.config._paths import VIRTENV_RESOURCES_PATH
493
498
  install_name = _import_to_install_name(import_name)
499
+ if install_name.startswith(_MRSM_PACKAGE_ARCHIVES_PREFIX):
500
+ return {}
494
501
  _args = ['pip', 'show', install_name]
495
502
  if venv is not None:
496
503
  cache_dir_path = VIRTENV_RESOURCES_PATH / venv / 'cache'
@@ -586,7 +593,10 @@ def need_update(
586
593
  _checked_for_updates.add(install_name)
587
594
 
588
595
  _install_no_version = get_install_no_version(install_name)
589
- required_version = install_name.replace(_install_no_version, '')
596
+ required_version = (
597
+ install_name
598
+ .replace(_install_no_version, '')
599
+ )
590
600
  if ']' in required_version:
591
601
  required_version = required_version.split(']')[1]
592
602
 
@@ -681,8 +691,8 @@ def need_update(
681
691
  )
682
692
 
683
693
  if 'a' in required_version:
684
- required_version = required_version.replace('a', '-dev').replace('+mrsm', '')
685
- version = version.replace('a', '-dev').replace('+mrsm', '')
694
+ required_version = required_version.replace('a', '-pre.').replace('+mrsm', '')
695
+ version = version.replace('a', '-pre.').replace('+mrsm', '')
686
696
  try:
687
697
  return (
688
698
  (not semver.Version.parse(version).match(required_version))
@@ -780,7 +790,7 @@ def pip_install(
780
790
  This includes version restrictions.
781
791
  Use `_import_to_install_name()` to get the predefined `install_name` for a package
782
792
  from its import name.
783
-
793
+
784
794
  args: Optional[List[str]], default None
785
795
  A list of command line arguments to pass to `pip`.
786
796
  If not provided, default to `['--upgrade']` if `_uninstall` is `False`, else `[]`.
@@ -975,7 +985,11 @@ def pip_install(
975
985
  pass
976
986
 
977
987
  _packages = [
978
- (install_name if not _uninstall else get_install_no_version(install_name))
988
+ (
989
+ get_install_no_version(install_name)
990
+ if _uninstall or install_name.startswith(_MRSM_PACKAGE_ARCHIVES_PREFIX)
991
+ else install_name
992
+ )
979
993
  for install_name in install_names
980
994
  ]
981
995
  msg = "Installing packages:" if not _uninstall else "Uninstalling packages:"
@@ -1774,13 +1788,17 @@ def is_installed(
1774
1788
 
1775
1789
  found = (
1776
1790
  not need_update(
1777
- None, import_name = root_name,
1778
- _run_determine_version = False,
1779
- check_pypi = False,
1780
- version = determine_version(
1781
- spec_path, venv=venv, debug=debug, import_name=root_name
1791
+ None,
1792
+ import_name=root_name,
1793
+ _run_determine_version=False,
1794
+ check_pypi=False,
1795
+ version=determine_version(
1796
+ spec_path,
1797
+ venv=venv,
1798
+ debug=debug,
1799
+ import_name=root_name,
1782
1800
  ),
1783
- debug = debug,
1801
+ debug=debug,
1784
1802
  )
1785
1803
  ) if spec_path is not None else False
1786
1804
 
@@ -16,9 +16,10 @@ packages dictionary is structured in the following schema:
16
16
  from __future__ import annotations
17
17
  from meerschaum.utils.typing import Dict
18
18
 
19
+ _MRSM_PACKAGE_ARCHIVES_PREFIX: str = "https://meerschaum.io/files/archives/wheels/"
20
+
19
21
  packages: Dict[str, Dict[str, str]] = {
20
- 'required': {
21
- },
22
+ 'required': {},
22
23
  'minimal': {},
23
24
  'formatting': {
24
25
  'pprintpp' : 'pprintpp>=0.4.0',
@@ -36,7 +37,7 @@ packages: Dict[str, Dict[str, str]] = {
36
37
  'yaml' : 'PyYAML>=5.3.1',
37
38
  'pip' : 'pip>=22.0.4',
38
39
  'update_checker' : 'update-checker>=0.18.0',
39
- 'semver' : 'semver>=3.0.0',
40
+ 'semver' : 'semver>=3.0.2',
40
41
  'pathspec' : 'pathspec>=0.9.0',
41
42
  'dateutil' : 'python-dateutil>=2.7.5',
42
43
  'requests' : 'requests>=2.32.3',
@@ -51,10 +52,15 @@ packages: Dict[str, Dict[str, str]] = {
51
52
  'more_itertools' : 'more-itertools>=8.7.0',
52
53
  'fasteners' : 'fasteners>=0.19.0',
53
54
  'virtualenv' : 'virtualenv>=20.1.0',
54
- 'attrs' : 'attrs<24.2.0',
55
- 'apscheduler' : 'APScheduler>=4.0.0a5',
55
+ 'attrs' : 'attrs>=24.2.0',
56
56
  'uv' : 'uv>=0.2.11',
57
57
  },
58
+ '_internal' : {
59
+ 'apscheduler' : (
60
+ f"{_MRSM_PACKAGE_ARCHIVES_PREFIX}"
61
+ "APScheduler-4.0.0a5.post75+mrsm-py3-none-any.whl>=4.0.0a5"
62
+ ),
63
+ },
58
64
  'jobs': {
59
65
  'dill' : 'dill>=0.3.3',
60
66
  'daemon' : 'python-daemon>=0.2.3',
@@ -157,7 +163,8 @@ packages['api'] = {
157
163
  'fastapi' : 'fastapi>=0.111.0',
158
164
  'fastapi_login' : 'fastapi-login>=1.7.2',
159
165
  'multipart' : 'python-multipart>=0.0.9',
160
- 'httpx' : 'httpx>=0.24.1',
166
+ 'httpx' : 'httpx>=0.27.2',
167
+ 'httpcore' : 'httpcore>=1.0.6',
161
168
  'valkey' : 'valkey>=6.0.0',
162
169
  }
163
170
  packages['api'].update(packages['sql'])
@@ -179,15 +186,25 @@ def get_install_names():
179
186
  install_names[get_install_no_version(_install_name)] = _import_name
180
187
  return install_names
181
188
 
182
- skip_groups = {'docs', 'build', 'cli', 'dev-tools', 'portable', 'extras', 'stack', 'drivers-extras'}
189
+
190
+ skip_groups = {
191
+ 'docs',
192
+ 'build',
193
+ 'cli',
194
+ 'dev-tools',
195
+ 'portable',
196
+ 'extras',
197
+ 'stack',
198
+ 'drivers-extras',
199
+ '_internal',
200
+ }
183
201
  full = []
184
202
  _full = {}
185
203
  for group, import_names in packages.items():
186
204
  ### omit 'cli' and 'docs' from 'full'
187
- if group in skip_groups:
205
+ if group in skip_groups or group.startswith('_'):
188
206
  continue
189
207
  full += [ install_name for import_name, install_name in import_names.items() ]
190
208
  for import_name, install_name in import_names.items():
191
209
  _full[import_name] = install_name
192
210
  packages['full'] = _full
193
-
@@ -111,16 +111,18 @@ def schedule_function(
111
111
  except RuntimeError:
112
112
  loop = asyncio.new_event_loop()
113
113
 
114
-
115
114
  async def run_scheduler():
116
115
  async with _scheduler:
117
116
  job = await _scheduler.add_schedule(
118
117
  function,
119
118
  trigger,
120
- args=args,
121
- kwargs=kw,
122
- max_running_jobs=1,
123
- conflict_policy=apscheduler.ConflictPolicy.replace,
119
+ **filter_keywords(
120
+ _scheduler.add_schedule,
121
+ args=args,
122
+ kwargs=kw,
123
+ max_running_jobs=1,
124
+ conflict_policy=apscheduler.ConflictPolicy.replace,
125
+ )
124
126
  )
125
127
  try:
126
128
  await _scheduler.run_until_stopped()
@@ -140,7 +142,7 @@ def parse_schedule(schedule: str, now: Optional[datetime] = None):
140
142
  """
141
143
  Parse a schedule string (e.g. 'daily') into a Trigger object.
142
144
  """
143
- from meerschaum.utils.misc import items_str, is_int
145
+ from meerschaum.utils.misc import items_str, is_int, filter_keywords
144
146
  (
145
147
  apscheduler_triggers_cron,
146
148
  apscheduler_triggers_interval,
@@ -204,10 +206,14 @@ def parse_schedule(schedule: str, now: Optional[datetime] = None):
204
206
 
205
207
  trigger = (
206
208
  apscheduler_triggers_interval.IntervalTrigger(
207
- **{
208
- schedule_unit: schedule_num,
209
- 'start_time': starting_ts,
210
- }
209
+ **filter_keywords(
210
+ apscheduler_triggers_interval.IntervalTrigger.__init__,
211
+ **{
212
+ schedule_unit: schedule_num,
213
+ 'start_time': starting_ts,
214
+ 'start_date': starting_ts,
215
+ }
216
+ )
211
217
  )
212
218
  if schedule_unit not in ('months', 'years') else (
213
219
  apscheduler_triggers_calendarinterval.CalendarIntervalTrigger(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: meerschaum
3
- Version: 2.4.13
3
+ Version: 2.5.1
4
4
  Summary: Sync Time-Series Pipes with Meerschaum
5
5
  Home-page: https://meerschaum.io
6
6
  Author: Bennett Meares
@@ -39,7 +39,8 @@ Requires-Dist: websockets >=11.0.3 ; extra == 'api'
39
39
  Requires-Dist: fastapi >=0.111.0 ; extra == 'api'
40
40
  Requires-Dist: fastapi-login >=1.7.2 ; extra == 'api'
41
41
  Requires-Dist: python-multipart >=0.0.9 ; extra == 'api'
42
- Requires-Dist: httpx >=0.24.1 ; extra == 'api'
42
+ Requires-Dist: httpx >=0.27.2 ; extra == 'api'
43
+ Requires-Dist: httpcore >=1.0.6 ; extra == 'api'
43
44
  Requires-Dist: valkey >=6.0.0 ; extra == 'api'
44
45
  Requires-Dist: numpy >=1.18.5 ; extra == 'api'
45
46
  Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'api'
@@ -64,7 +65,7 @@ Requires-Dist: setuptools >=63.3.0 ; extra == 'api'
64
65
  Requires-Dist: PyYAML >=5.3.1 ; extra == 'api'
65
66
  Requires-Dist: pip >=22.0.4 ; extra == 'api'
66
67
  Requires-Dist: update-checker >=0.18.0 ; extra == 'api'
67
- Requires-Dist: semver >=3.0.0 ; extra == 'api'
68
+ Requires-Dist: semver >=3.0.2 ; extra == 'api'
68
69
  Requires-Dist: pathspec >=0.9.0 ; extra == 'api'
69
70
  Requires-Dist: python-dateutil >=2.7.5 ; extra == 'api'
70
71
  Requires-Dist: requests >=2.32.3 ; extra == 'api'
@@ -79,8 +80,7 @@ Requires-Dist: prompt-toolkit >=3.0.39 ; extra == 'api'
79
80
  Requires-Dist: more-itertools >=8.7.0 ; extra == 'api'
80
81
  Requires-Dist: fasteners >=0.19.0 ; extra == 'api'
81
82
  Requires-Dist: virtualenv >=20.1.0 ; extra == 'api'
82
- Requires-Dist: attrs <24.2.0 ; extra == 'api'
83
- Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'api'
83
+ Requires-Dist: attrs >=24.2.0 ; extra == 'api'
84
84
  Requires-Dist: uv >=0.2.11 ; extra == 'api'
85
85
  Requires-Dist: pprintpp >=0.4.0 ; extra == 'api'
86
86
  Requires-Dist: asciitree >=0.3.3 ; extra == 'api'
@@ -117,7 +117,7 @@ Requires-Dist: setuptools >=63.3.0 ; extra == 'core'
117
117
  Requires-Dist: PyYAML >=5.3.1 ; extra == 'core'
118
118
  Requires-Dist: pip >=22.0.4 ; extra == 'core'
119
119
  Requires-Dist: update-checker >=0.18.0 ; extra == 'core'
120
- Requires-Dist: semver >=3.0.0 ; extra == 'core'
120
+ Requires-Dist: semver >=3.0.2 ; extra == 'core'
121
121
  Requires-Dist: pathspec >=0.9.0 ; extra == 'core'
122
122
  Requires-Dist: python-dateutil >=2.7.5 ; extra == 'core'
123
123
  Requires-Dist: requests >=2.32.3 ; extra == 'core'
@@ -132,8 +132,7 @@ Requires-Dist: prompt-toolkit >=3.0.39 ; extra == 'core'
132
132
  Requires-Dist: more-itertools >=8.7.0 ; extra == 'core'
133
133
  Requires-Dist: fasteners >=0.19.0 ; extra == 'core'
134
134
  Requires-Dist: virtualenv >=20.1.0 ; extra == 'core'
135
- Requires-Dist: attrs <24.2.0 ; extra == 'core'
136
- Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'core'
135
+ Requires-Dist: attrs >=24.2.0 ; extra == 'core'
137
136
  Requires-Dist: uv >=0.2.11 ; extra == 'core'
138
137
  Provides-Extra: dash
139
138
  Requires-Dist: Flask-Compress >=1.10.1 ; extra == 'dash'
@@ -203,7 +202,7 @@ Requires-Dist: setuptools >=63.3.0 ; extra == 'full'
203
202
  Requires-Dist: PyYAML >=5.3.1 ; extra == 'full'
204
203
  Requires-Dist: pip >=22.0.4 ; extra == 'full'
205
204
  Requires-Dist: update-checker >=0.18.0 ; extra == 'full'
206
- Requires-Dist: semver >=3.0.0 ; extra == 'full'
205
+ Requires-Dist: semver >=3.0.2 ; extra == 'full'
207
206
  Requires-Dist: pathspec >=0.9.0 ; extra == 'full'
208
207
  Requires-Dist: python-dateutil >=2.7.5 ; extra == 'full'
209
208
  Requires-Dist: requests >=2.32.3 ; extra == 'full'
@@ -218,8 +217,7 @@ Requires-Dist: prompt-toolkit >=3.0.39 ; extra == 'full'
218
217
  Requires-Dist: more-itertools >=8.7.0 ; extra == 'full'
219
218
  Requires-Dist: fasteners >=0.19.0 ; extra == 'full'
220
219
  Requires-Dist: virtualenv >=20.1.0 ; extra == 'full'
221
- Requires-Dist: attrs <24.2.0 ; extra == 'full'
222
- Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'full'
220
+ Requires-Dist: attrs >=24.2.0 ; extra == 'full'
223
221
  Requires-Dist: uv >=0.2.11 ; extra == 'full'
224
222
  Requires-Dist: dill >=0.3.3 ; extra == 'full'
225
223
  Requires-Dist: python-daemon >=0.2.3 ; extra == 'full'
@@ -261,7 +259,8 @@ Requires-Dist: websockets >=11.0.3 ; extra == 'full'
261
259
  Requires-Dist: fastapi >=0.111.0 ; extra == 'full'
262
260
  Requires-Dist: fastapi-login >=1.7.2 ; extra == 'full'
263
261
  Requires-Dist: python-multipart >=0.0.9 ; extra == 'full'
264
- Requires-Dist: httpx >=0.24.1 ; extra == 'full'
262
+ Requires-Dist: httpx >=0.27.2 ; extra == 'full'
263
+ Requires-Dist: httpcore >=1.0.6 ; extra == 'full'
265
264
  Requires-Dist: valkey >=6.0.0 ; extra == 'full'
266
265
  Provides-Extra: gui
267
266
  Requires-Dist: toga >=0.3.0-dev29 ; extra == 'gui'
@@ -299,7 +298,7 @@ Requires-Dist: setuptools >=63.3.0 ; extra == 'sql'
299
298
  Requires-Dist: PyYAML >=5.3.1 ; extra == 'sql'
300
299
  Requires-Dist: pip >=22.0.4 ; extra == 'sql'
301
300
  Requires-Dist: update-checker >=0.18.0 ; extra == 'sql'
302
- Requires-Dist: semver >=3.0.0 ; extra == 'sql'
301
+ Requires-Dist: semver >=3.0.2 ; extra == 'sql'
303
302
  Requires-Dist: pathspec >=0.9.0 ; extra == 'sql'
304
303
  Requires-Dist: python-dateutil >=2.7.5 ; extra == 'sql'
305
304
  Requires-Dist: requests >=2.32.3 ; extra == 'sql'
@@ -314,8 +313,7 @@ Requires-Dist: prompt-toolkit >=3.0.39 ; extra == 'sql'
314
313
  Requires-Dist: more-itertools >=8.7.0 ; extra == 'sql'
315
314
  Requires-Dist: fasteners >=0.19.0 ; extra == 'sql'
316
315
  Requires-Dist: virtualenv >=20.1.0 ; extra == 'sql'
317
- Requires-Dist: attrs <24.2.0 ; extra == 'sql'
318
- Requires-Dist: APScheduler >=4.0.0a5 ; extra == 'sql'
316
+ Requires-Dist: attrs >=24.2.0 ; extra == 'sql'
319
317
  Requires-Dist: uv >=0.2.11 ; extra == 'sql'
320
318
  Provides-Extra: stack
321
319
  Requires-Dist: docker-compose >=1.29.2 ; extra == 'stack'