meerschaum 2.7.4__py3-none-any.whl → 2.7.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.
- meerschaum/_internal/shell/Shell.py +4 -6
- meerschaum/_internal/shell/ShellCompleter.py +6 -5
- meerschaum/actions/clear.py +6 -3
- meerschaum/actions/copy.py +33 -27
- meerschaum/actions/sql.py +14 -4
- meerschaum/actions/sync.py +22 -18
- meerschaum/api/dash/pipes.py +2 -3
- meerschaum/config/_default.py +11 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/connectors/api/_misc.py +3 -2
- meerschaum/connectors/api/_pipes.py +8 -9
- meerschaum/connectors/sql/_SQLConnector.py +1 -0
- meerschaum/connectors/sql/_cli.py +18 -12
- meerschaum/connectors/sql/_create_engine.py +1 -0
- meerschaum/connectors/sql/_pipes.py +51 -14
- meerschaum/connectors/sql/_sql.py +109 -16
- meerschaum/jobs/_Job.py +1 -0
- meerschaum/plugins/__init__.py +7 -3
- meerschaum/utils/daemon/Daemon.py +11 -3
- meerschaum/utils/daemon/__init__.py +2 -2
- meerschaum/utils/misc.py +7 -6
- meerschaum/utils/packages/__init__.py +35 -28
- meerschaum/utils/packages/_packages.py +1 -1
- meerschaum/utils/prompt.py +54 -36
- meerschaum/utils/venv/_Venv.py +6 -1
- meerschaum/utils/venv/__init__.py +32 -16
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/METADATA +4 -4
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/RECORD +34 -34
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/WHEEL +1 -1
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/LICENSE +0 -0
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/NOTICE +0 -0
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/top_level.txt +0 -0
- {meerschaum-2.7.4.dist-info → meerschaum-2.7.6.dist-info}/zip-safe +0 -0
@@ -6,8 +6,10 @@ This module contains SQLConnector functions for executing SQL queries.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from __future__ import annotations
|
9
|
+
|
10
|
+
import meerschaum as mrsm
|
9
11
|
from meerschaum.utils.typing import (
|
10
|
-
Union,
|
12
|
+
Union, List, Dict, SuccessTuple, Optional, Any, Iterable, Callable,
|
11
13
|
Tuple, Hashable,
|
12
14
|
)
|
13
15
|
|
@@ -15,7 +17,7 @@ from meerschaum.utils.debug import dprint
|
|
15
17
|
from meerschaum.utils.warnings import warn
|
16
18
|
|
17
19
|
### database flavors that can use bulk insert
|
18
|
-
_bulk_flavors = {'postgresql', 'timescaledb', 'citus'}
|
20
|
+
_bulk_flavors = {'postgresql', 'timescaledb', 'citus', 'mssql'}
|
19
21
|
### flavors that do not support chunks
|
20
22
|
_disallow_chunks_flavors = ['duckdb']
|
21
23
|
_max_chunks_flavors = {'sqlite': 1000}
|
@@ -776,9 +778,11 @@ def to_sql(
|
|
776
778
|
import time
|
777
779
|
import json
|
778
780
|
from decimal import Decimal
|
781
|
+
from datetime import timedelta
|
779
782
|
from meerschaum.utils.warnings import error, warn
|
780
783
|
import warnings
|
781
784
|
import functools
|
785
|
+
|
782
786
|
if name is None:
|
783
787
|
error(f"Name must not be `None` to insert data into {self}.")
|
784
788
|
|
@@ -805,6 +809,7 @@ def to_sql(
|
|
805
809
|
quantize_decimal,
|
806
810
|
coerce_timezone,
|
807
811
|
encode_bytes_for_bytea,
|
812
|
+
serialize_bytes,
|
808
813
|
)
|
809
814
|
from meerschaum.utils.dtypes.sql import (
|
810
815
|
NUMERIC_PRECISION_FLAVORS,
|
@@ -812,6 +817,7 @@ def to_sql(
|
|
812
817
|
PD_TO_SQLALCHEMY_DTYPES_FLAVORS,
|
813
818
|
get_db_type_from_pd_type,
|
814
819
|
)
|
820
|
+
from meerschaum.utils.misc import interval_str
|
815
821
|
from meerschaum.connectors.sql._create_engine import flavor_configs
|
816
822
|
from meerschaum.utils.packages import attempt_import, import_pandas
|
817
823
|
sqlalchemy = attempt_import('sqlalchemy', debug=debug)
|
@@ -821,24 +827,36 @@ def to_sql(
|
|
821
827
|
bytes_cols = get_bytes_cols(df)
|
822
828
|
numeric_cols = get_numeric_cols(df)
|
823
829
|
|
824
|
-
|
830
|
+
enable_bulk_insert = mrsm.get_config(
|
831
|
+
'system', 'connectors', 'sql', 'bulk_insert'
|
832
|
+
).get(self.flavor, False)
|
833
|
+
stats = {'target': name}
|
825
834
|
### resort to defaults if None
|
826
835
|
copied = False
|
827
|
-
|
836
|
+
use_bulk_insert = False
|
828
837
|
if method == "":
|
829
|
-
if
|
830
|
-
method =
|
831
|
-
|
838
|
+
if enable_bulk_insert:
|
839
|
+
method = (
|
840
|
+
functools.partial(mssql_insert_json, debug=debug)
|
841
|
+
if self.flavor == 'mssql'
|
842
|
+
else functools.partial(psql_insert_copy, debug=debug)
|
843
|
+
)
|
844
|
+
use_bulk_insert = True
|
832
845
|
else:
|
833
846
|
### Should resolve to 'multi' or `None`.
|
834
847
|
method = flavor_configs.get(self.flavor, {}).get('to_sql', {}).get('method', 'multi')
|
835
848
|
|
836
|
-
if bytes_cols and (
|
849
|
+
if bytes_cols and (use_bulk_insert or self.flavor == 'oracle'):
|
837
850
|
if safe_copy and not copied:
|
838
851
|
df = df.copy()
|
839
852
|
copied = True
|
853
|
+
bytes_serializer = (
|
854
|
+
functools.partial(encode_bytes_for_bytea, with_prefix=(self.flavor != 'oracle'))
|
855
|
+
if self.flavor != 'mssql'
|
856
|
+
else serialize_bytes
|
857
|
+
)
|
840
858
|
for col in bytes_cols:
|
841
|
-
df[col] = df[col].apply(
|
859
|
+
df[col] = df[col].apply(bytes_serializer)
|
842
860
|
|
843
861
|
if self.flavor in NUMERIC_AS_TEXT_FLAVORS:
|
844
862
|
if safe_copy and not copied:
|
@@ -982,13 +1000,19 @@ def to_sql(
|
|
982
1000
|
|
983
1001
|
end = time.perf_counter()
|
984
1002
|
if success:
|
985
|
-
|
1003
|
+
num_rows = len(df)
|
1004
|
+
msg = (
|
1005
|
+
f"It took {interval_str(timedelta(seconds=(end - start)))} "
|
1006
|
+
+ f"to sync {num_rows:,} row"
|
1007
|
+
+ ('s' if num_rows != 1 else '')
|
1008
|
+
+ f" to {name}."
|
1009
|
+
)
|
986
1010
|
stats['start'] = start
|
987
1011
|
stats['end'] = end
|
988
1012
|
stats['duration'] = end - start
|
989
1013
|
|
990
1014
|
if debug:
|
991
|
-
print(
|
1015
|
+
print(" done.", flush=True)
|
992
1016
|
dprint(msg)
|
993
1017
|
|
994
1018
|
stats['success'] = success
|
@@ -1005,7 +1029,7 @@ def psql_insert_copy(
|
|
1005
1029
|
conn: Union[sqlalchemy.engine.Engine, sqlalchemy.engine.Connection],
|
1006
1030
|
keys: List[str],
|
1007
1031
|
data_iter: Iterable[Any],
|
1008
|
-
|
1032
|
+
debug: bool = False,
|
1009
1033
|
) -> None:
|
1010
1034
|
"""
|
1011
1035
|
Execute SQL statement inserting data for PostgreSQL.
|
@@ -1022,18 +1046,15 @@ def psql_insert_copy(
|
|
1022
1046
|
data_iter: Iterable[Any]
|
1023
1047
|
Iterable that iterates the values to be inserted
|
1024
1048
|
|
1025
|
-
schema: Optional[str], default None
|
1026
|
-
Optionally specify the schema of the table to be inserted into.
|
1027
|
-
|
1028
1049
|
Returns
|
1029
1050
|
-------
|
1030
1051
|
None
|
1031
1052
|
"""
|
1032
1053
|
import csv
|
1033
|
-
from io import StringIO
|
1034
1054
|
import json
|
1035
1055
|
|
1036
1056
|
from meerschaum.utils.sql import sql_item_name
|
1057
|
+
from meerschaum.utils.warnings import dprint
|
1037
1058
|
|
1038
1059
|
### NOTE: PostgreSQL doesn't support NUL chars in text, so they're removed from strings.
|
1039
1060
|
data_iter = (
|
@@ -1057,6 +1078,8 @@ def psql_insert_copy(
|
|
1057
1078
|
table_name = sql_item_name(table.name, 'postgresql', table.schema)
|
1058
1079
|
columns = ', '.join(f'"{k}"' for k in keys)
|
1059
1080
|
sql = f"COPY {table_name} ({columns}) FROM STDIN WITH CSV NULL '\\N'"
|
1081
|
+
if debug:
|
1082
|
+
dprint(sql)
|
1060
1083
|
|
1061
1084
|
dbapi_conn = conn.connection
|
1062
1085
|
with dbapi_conn.cursor() as cur:
|
@@ -1065,6 +1088,76 @@ def psql_insert_copy(
|
|
1065
1088
|
writer.writerows(data_iter)
|
1066
1089
|
|
1067
1090
|
|
1091
|
+
def mssql_insert_json(
|
1092
|
+
table: pandas.io.sql.SQLTable,
|
1093
|
+
conn: Union[sqlalchemy.engine.Engine, sqlalchemy.engine.Connection],
|
1094
|
+
keys: List[str],
|
1095
|
+
data_iter: Iterable[Any],
|
1096
|
+
cols_types: Optional[Dict[str, str]] = None,
|
1097
|
+
debug: bool = False,
|
1098
|
+
):
|
1099
|
+
"""
|
1100
|
+
Execute SQL statement inserting data via OPENJSON.
|
1101
|
+
|
1102
|
+
Adapted from this snippet:
|
1103
|
+
https://gist.github.com/gordthompson/1fb0f1c3f5edbf6192e596de8350f205
|
1104
|
+
|
1105
|
+
Parameters
|
1106
|
+
----------
|
1107
|
+
table: pandas.io.sql.SQLTable
|
1108
|
+
|
1109
|
+
conn: Union[sqlalchemy.engine.Engine, sqlalchemy.engine.Connection]
|
1110
|
+
|
1111
|
+
keys: List[str]
|
1112
|
+
Column names
|
1113
|
+
|
1114
|
+
data_iter: Iterable[Any]
|
1115
|
+
Iterable that iterates the values to be inserted
|
1116
|
+
|
1117
|
+
cols_types: Optional[Dict[str, str]], default None
|
1118
|
+
If provided, use these as the columns and types for the table.
|
1119
|
+
|
1120
|
+
Returns
|
1121
|
+
-------
|
1122
|
+
None
|
1123
|
+
"""
|
1124
|
+
import json
|
1125
|
+
from meerschaum.utils.sql import sql_item_name
|
1126
|
+
from meerschaum.utils.dtypes.sql import get_pd_type_from_db_type, get_db_type_from_pd_type
|
1127
|
+
from meerschaum.utils.warnings import dprint
|
1128
|
+
table_name = sql_item_name(table.name, 'mssql', table.schema)
|
1129
|
+
if not cols_types:
|
1130
|
+
pd_types = {
|
1131
|
+
str(column.name): get_pd_type_from_db_type(str(column.type))
|
1132
|
+
for column in table.table.columns
|
1133
|
+
}
|
1134
|
+
cols_types = {
|
1135
|
+
col: get_db_type_from_pd_type(typ, 'mssql')
|
1136
|
+
for col, typ in pd_types.items()
|
1137
|
+
}
|
1138
|
+
columns = ",\n ".join([f"[{k}]" for k in keys])
|
1139
|
+
json_data = [dict(zip(keys, row)) for row in data_iter]
|
1140
|
+
with_clause = ",\n ".join(
|
1141
|
+
[
|
1142
|
+
f"[{col_name}] {col_type} '$.\"{col_name}\"'"
|
1143
|
+
for col_name, col_type in cols_types.items()
|
1144
|
+
]
|
1145
|
+
)
|
1146
|
+
placeholder = "?" if conn.dialect.paramstyle == "qmark" else "%s"
|
1147
|
+
sql = (
|
1148
|
+
f"INSERT INTO {table_name} (\n {columns}\n)\n"
|
1149
|
+
f"SELECT\n {columns}\n"
|
1150
|
+
f"FROM OPENJSON({placeholder})\n"
|
1151
|
+
"WITH (\n"
|
1152
|
+
f" {with_clause}\n"
|
1153
|
+
");"
|
1154
|
+
)
|
1155
|
+
if debug:
|
1156
|
+
dprint(sql)
|
1157
|
+
|
1158
|
+
conn.exec_driver_sql(sql, (json.dumps(json_data, default=str),))
|
1159
|
+
|
1160
|
+
|
1068
1161
|
def format_sql_query_for_dask(query: str) -> 'sqlalchemy.sql.selectable.Select':
|
1069
1162
|
"""
|
1070
1163
|
Given a `SELECT` query, return a `sqlalchemy` query for Dask to use.
|
meerschaum/jobs/_Job.py
CHANGED
meerschaum/plugins/__init__.py
CHANGED
@@ -126,8 +126,8 @@ def pre_sync_hook(
|
|
126
126
|
|
127
127
|
|
128
128
|
def post_sync_hook(
|
129
|
-
|
130
|
-
|
129
|
+
function: Callable[[Any], Any],
|
130
|
+
) -> Callable[[Any], Any]:
|
131
131
|
"""
|
132
132
|
Register a function as a sync hook to be executed upon completion of a sync.
|
133
133
|
|
@@ -143,10 +143,14 @@ def post_sync_hook(
|
|
143
143
|
Examples
|
144
144
|
--------
|
145
145
|
>>> from meerschaum.plugins import post_sync_hook
|
146
|
+
>>> from meerschaum.utils.misc import interval_str
|
147
|
+
>>> from datetime import timedelta
|
146
148
|
>>>
|
147
149
|
>>> @post_sync_hook
|
148
150
|
... def log_sync(pipe, success_tuple, duration=None, **kwargs):
|
149
|
-
...
|
151
|
+
... duration_delta = timedelta(seconds=duration)
|
152
|
+
... duration_text = interval_str(duration_delta)
|
153
|
+
... print(f"It took {duration_text} to sync {pipe}.")
|
150
154
|
>>>
|
151
155
|
"""
|
152
156
|
with _locks['_post_sync_hooks']:
|
@@ -261,7 +261,10 @@ class Daemon:
|
|
261
261
|
-------
|
262
262
|
Nothing — this will exit the parent process.
|
263
263
|
"""
|
264
|
-
import platform
|
264
|
+
import platform
|
265
|
+
import sys
|
266
|
+
import os
|
267
|
+
import traceback
|
265
268
|
from meerschaum.utils.warnings import warn
|
266
269
|
from meerschaum.config import get_config
|
267
270
|
daemon = attempt_import('daemon')
|
@@ -1014,7 +1017,8 @@ class Daemon:
|
|
1014
1017
|
|
1015
1018
|
def read_pickle(self) -> Daemon:
|
1016
1019
|
"""Read a Daemon's pickle file and return the `Daemon`."""
|
1017
|
-
import pickle
|
1020
|
+
import pickle
|
1021
|
+
import traceback
|
1018
1022
|
if not self.pickle_path.exists():
|
1019
1023
|
error(f"Pickle file does not exist for daemon '{self.daemon_id}'.")
|
1020
1024
|
|
@@ -1050,6 +1054,9 @@ class Daemon:
|
|
1050
1054
|
if self._properties is None:
|
1051
1055
|
self._properties = {}
|
1052
1056
|
|
1057
|
+
if self._properties.get('result', None) is None:
|
1058
|
+
_ = self._properties.pop('result', None)
|
1059
|
+
|
1053
1060
|
if _file_properties is not None:
|
1054
1061
|
self._properties = apply_patch_to_config(
|
1055
1062
|
_file_properties,
|
@@ -1085,7 +1092,8 @@ class Daemon:
|
|
1085
1092
|
|
1086
1093
|
def write_pickle(self) -> SuccessTuple:
|
1087
1094
|
"""Write the pickle file for the daemon."""
|
1088
|
-
import pickle
|
1095
|
+
import pickle
|
1096
|
+
import traceback
|
1089
1097
|
try:
|
1090
1098
|
self.path.mkdir(parents=True, exist_ok=True)
|
1091
1099
|
with open(self.pickle_path, 'wb+') as pickle_file:
|
@@ -37,7 +37,7 @@ def daemon_entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
37
37
|
filtered_sysargs = [arg for arg in sysargs if arg not in ('-d', '--daemon')]
|
38
38
|
try:
|
39
39
|
label = shlex.join(filtered_sysargs) if sysargs else None
|
40
|
-
except Exception
|
40
|
+
except Exception:
|
41
41
|
label = ' '.join(filtered_sysargs) if sysargs else None
|
42
42
|
|
43
43
|
name = _args.get('name', None)
|
@@ -45,7 +45,7 @@ def daemon_entry(sysargs: Optional[List[str]] = None) -> SuccessTuple:
|
|
45
45
|
if name:
|
46
46
|
try:
|
47
47
|
daemon = Daemon(daemon_id=name)
|
48
|
-
except Exception
|
48
|
+
except Exception:
|
49
49
|
daemon = None
|
50
50
|
|
51
51
|
if daemon is not None:
|
meerschaum/utils/misc.py
CHANGED
@@ -90,20 +90,21 @@ def add_method_to_class(
|
|
90
90
|
|
91
91
|
|
92
92
|
def generate_password(length: int = 12) -> str:
|
93
|
-
"""
|
93
|
+
"""
|
94
|
+
Generate a secure password of given length.
|
94
95
|
|
95
96
|
Parameters
|
96
97
|
----------
|
97
|
-
length
|
98
|
+
length: int, default 12
|
98
99
|
The length of the password.
|
99
100
|
|
100
101
|
Returns
|
101
102
|
-------
|
102
103
|
A random password string.
|
103
|
-
|
104
104
|
"""
|
105
|
-
import secrets
|
106
|
-
|
105
|
+
import secrets
|
106
|
+
import string
|
107
|
+
return ''.join((secrets.choice(string.ascii_letters + string.digits) for i in range(length)))
|
107
108
|
|
108
109
|
def is_int(s : str) -> bool:
|
109
110
|
"""
|
@@ -121,7 +122,7 @@ def is_int(s : str) -> bool:
|
|
121
122
|
"""
|
122
123
|
try:
|
123
124
|
float(s)
|
124
|
-
except Exception
|
125
|
+
except Exception:
|
125
126
|
return False
|
126
127
|
|
127
128
|
return float(s).is_integer()
|
@@ -337,14 +337,14 @@ def get_install_no_version(install_name: str) -> str:
|
|
337
337
|
|
338
338
|
import_versions = {}
|
339
339
|
def determine_version(
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
340
|
+
path: pathlib.Path,
|
341
|
+
import_name: Optional[str] = None,
|
342
|
+
venv: Optional[str] = 'mrsm',
|
343
|
+
search_for_metadata: bool = True,
|
344
|
+
split: bool = True,
|
345
|
+
warn: bool = False,
|
346
|
+
debug: bool = False,
|
347
|
+
) -> Union[str, None]:
|
348
348
|
"""
|
349
349
|
Determine a module's `__version__` string from its filepath.
|
350
350
|
|
@@ -381,11 +381,8 @@ def determine_version(
|
|
381
381
|
with _locks['import_versions']:
|
382
382
|
if venv not in import_versions:
|
383
383
|
import_versions[venv] = {}
|
384
|
-
import
|
385
|
-
import re, os
|
384
|
+
import os
|
386
385
|
old_cwd = os.getcwd()
|
387
|
-
if debug:
|
388
|
-
from meerschaum.utils.debug import dprint
|
389
386
|
from meerschaum.utils.warnings import warn as warn_function
|
390
387
|
if import_name is None:
|
391
388
|
import_name = path.parent.stem if path.stem == '__init__' else path.stem
|
@@ -395,7 +392,10 @@ def determine_version(
|
|
395
392
|
_version = None
|
396
393
|
module_parent_dir = (
|
397
394
|
path.parent.parent if path.stem == '__init__' else path.parent
|
398
|
-
) if path is not None else venv_target_path(venv, debug=debug)
|
395
|
+
) if path is not None else venv_target_path(venv, allow_nonexistent=True, debug=debug)
|
396
|
+
|
397
|
+
if not module_parent_dir.exists():
|
398
|
+
return None
|
399
399
|
|
400
400
|
installed_dir_name = _import_to_dir_name(import_name)
|
401
401
|
clean_installed_dir_name = installed_dir_name.lower().replace('-', '_')
|
@@ -403,7 +403,11 @@ def determine_version(
|
|
403
403
|
### First, check if a dist-info directory exists.
|
404
404
|
_found_versions = []
|
405
405
|
if search_for_metadata:
|
406
|
-
|
406
|
+
try:
|
407
|
+
filenames = os.listdir(module_parent_dir)
|
408
|
+
except FileNotFoundError:
|
409
|
+
filenames = []
|
410
|
+
for filename in filenames:
|
407
411
|
if not filename.endswith('.dist-info'):
|
408
412
|
continue
|
409
413
|
filename_lower = filename.lower()
|
@@ -430,7 +434,7 @@ def determine_version(
|
|
430
434
|
try:
|
431
435
|
os.chdir(module_parent_dir)
|
432
436
|
_version = importlib_metadata.metadata(import_name)['Version']
|
433
|
-
except Exception
|
437
|
+
except Exception:
|
434
438
|
_version = None
|
435
439
|
finally:
|
436
440
|
os.chdir(old_cwd)
|
@@ -698,7 +702,7 @@ def need_update(
|
|
698
702
|
(not semver.Version.parse(version).match(required_version))
|
699
703
|
if required_version else False
|
700
704
|
)
|
701
|
-
except AttributeError
|
705
|
+
except AttributeError:
|
702
706
|
pip_install(_import_to_install_name('semver'), venv='mrsm', debug=debug)
|
703
707
|
semver = manually_import_module('semver', venv='mrsm', debug=debug)
|
704
708
|
return (
|
@@ -724,10 +728,10 @@ def need_update(
|
|
724
728
|
|
725
729
|
|
726
730
|
def get_pip(
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
+
venv: Optional[str] = 'mrsm',
|
732
|
+
color: bool = True,
|
733
|
+
debug: bool = False,
|
734
|
+
) -> bool:
|
731
735
|
"""
|
732
736
|
Download and run the get-pip.py script.
|
733
737
|
|
@@ -747,7 +751,8 @@ def get_pip(
|
|
747
751
|
A bool indicating success.
|
748
752
|
|
749
753
|
"""
|
750
|
-
import sys
|
754
|
+
import sys
|
755
|
+
import subprocess
|
751
756
|
from meerschaum.utils.misc import wget
|
752
757
|
from meerschaum.config._paths import CACHE_RESOURCES_PATH
|
753
758
|
from meerschaum.config.static import STATIC_CONFIG
|
@@ -755,7 +760,7 @@ def get_pip(
|
|
755
760
|
dest = CACHE_RESOURCES_PATH / 'get-pip.py'
|
756
761
|
try:
|
757
762
|
wget(url, dest, color=False, debug=debug)
|
758
|
-
except Exception
|
763
|
+
except Exception:
|
759
764
|
print(f"Failed to fetch pip from '{url}'. Please install pip and restart Meerschaum.")
|
760
765
|
sys.exit(1)
|
761
766
|
if venv is not None:
|
@@ -776,6 +781,7 @@ def pip_install(
|
|
776
781
|
_uninstall: bool = False,
|
777
782
|
_from_completely_uninstall: bool = False,
|
778
783
|
_install_uv_pip: bool = True,
|
784
|
+
_use_uv_pip: bool = True,
|
779
785
|
color: bool = True,
|
780
786
|
silent: bool = False,
|
781
787
|
debug: bool = False,
|
@@ -831,15 +837,11 @@ def pip_install(
|
|
831
837
|
|
832
838
|
"""
|
833
839
|
from meerschaum.config._paths import VIRTENV_RESOURCES_PATH
|
834
|
-
from meerschaum.config import get_config
|
835
840
|
from meerschaum.config.static import STATIC_CONFIG
|
836
841
|
from meerschaum.utils.warnings import warn
|
837
842
|
if args is None:
|
838
843
|
args = ['--upgrade'] if not _uninstall else []
|
839
|
-
if color
|
840
|
-
ANSI, UNICODE = True, True
|
841
|
-
else:
|
842
|
-
ANSI, UNICODE = False, False
|
844
|
+
ANSI = True if color else False
|
843
845
|
if check_wheel:
|
844
846
|
have_wheel = venv_contains_package('wheel', venv=venv, debug=debug)
|
845
847
|
|
@@ -878,7 +880,8 @@ def pip_install(
|
|
878
880
|
)
|
879
881
|
|
880
882
|
use_uv_pip = (
|
881
|
-
|
883
|
+
_use_uv_pip
|
884
|
+
and venv_contains_package('uv', venv=None, debug=debug)
|
882
885
|
and uv_bin is not None
|
883
886
|
and venv is not None
|
884
887
|
and is_uv_enabled()
|
@@ -966,6 +969,10 @@ def pip_install(
|
|
966
969
|
|
967
970
|
if '--target' not in _args and '-t' not in _args and not (not use_uv_pip and _uninstall):
|
968
971
|
if venv is not None:
|
972
|
+
vtp = venv_target_path(venv, allow_nonexistent=True, debug=debug)
|
973
|
+
if not vtp.exists():
|
974
|
+
if not init_venv(venv, force=True):
|
975
|
+
vtp.mkdir(parents=True, exist_ok=True)
|
969
976
|
_args += ['--target', venv_target_path(venv, debug=debug)]
|
970
977
|
elif (
|
971
978
|
'--target' not in _args
|
@@ -136,7 +136,7 @@ packages['sql'] = {
|
|
136
136
|
'numpy' : 'numpy>=1.18.5',
|
137
137
|
'pandas' : 'pandas[parquet]>=2.0.1',
|
138
138
|
'pyarrow' : 'pyarrow>=16.1.0',
|
139
|
-
'dask' : 'dask[complete]>=2024.
|
139
|
+
'dask' : 'dask[complete]>=2024.12.1',
|
140
140
|
'partd' : 'partd>=1.4.2',
|
141
141
|
'pytz' : 'pytz',
|
142
142
|
'joblib' : 'joblib>=0.17.0',
|