meerschaum 2.9.0rc2__py3-none-any.whl → 2.9.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.
- meerschaum/api/dash/callbacks/__init__.py +5 -2
- meerschaum/api/dash/callbacks/custom.py +17 -25
- meerschaum/api/dash/callbacks/dashboard.py +5 -21
- meerschaum/api/dash/callbacks/settings/__init__.py +8 -0
- meerschaum/api/dash/callbacks/settings/password_reset.py +76 -0
- meerschaum/api/dash/components.py +110 -7
- meerschaum/api/dash/pages/__init__.py +1 -0
- meerschaum/api/dash/pages/settings/__init__.py +8 -0
- meerschaum/api/dash/pages/settings/password_reset.py +63 -0
- meerschaum/api/resources/static/css/dash.css +7 -0
- meerschaum/api/routes/_pipes.py +76 -36
- meerschaum/config/_version.py +1 -1
- meerschaum/connectors/__init__.py +1 -0
- meerschaum/connectors/api/_pipes.py +79 -30
- meerschaum/connectors/sql/_pipes.py +38 -5
- meerschaum/connectors/valkey/_ValkeyConnector.py +2 -0
- meerschaum/connectors/valkey/_pipes.py +51 -39
- meerschaum/core/Pipe/__init__.py +1 -0
- meerschaum/core/Pipe/_sync.py +64 -4
- meerschaum/plugins/__init__.py +26 -4
- meerschaum/utils/dataframe.py +58 -3
- meerschaum/utils/dtypes/__init__.py +45 -17
- meerschaum/utils/dtypes/sql.py +182 -3
- meerschaum/utils/misc.py +1 -1
- meerschaum/utils/packages/_packages.py +6 -3
- meerschaum/utils/sql.py +122 -6
- meerschaum/utils/venv/__init__.py +4 -1
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/METADATA +14 -9
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/RECORD +35 -36
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/WHEEL +1 -1
- meerschaum/_internal/gui/__init__.py +0 -43
- meerschaum/_internal/gui/app/__init__.py +0 -50
- meerschaum/_internal/gui/app/_windows.py +0 -74
- meerschaum/_internal/gui/app/actions.py +0 -30
- meerschaum/_internal/gui/app/pipes.py +0 -47
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/LICENSE +0 -0
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/NOTICE +0 -0
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.9.0rc2.dist-info → meerschaum-2.9.1.dist-info}/zip-safe +0 -0
meerschaum/plugins/__init__.py
CHANGED
@@ -91,8 +91,8 @@ def make_action(
|
|
91
91
|
|
92
92
|
|
93
93
|
def pre_sync_hook(
|
94
|
-
|
95
|
-
|
94
|
+
function: Callable[[Any], Any],
|
95
|
+
) -> Callable[[Any], Any]:
|
96
96
|
"""
|
97
97
|
Register a function as a sync hook to be executed right before sync.
|
98
98
|
|
@@ -169,6 +169,7 @@ def web_page(
|
|
169
169
|
page: Union[str, None, Callable[[Any], Any]] = None,
|
170
170
|
login_required: bool = True,
|
171
171
|
skip_navbar: bool = False,
|
172
|
+
page_group: Optional[str] = None,
|
172
173
|
**kwargs
|
173
174
|
) -> Any:
|
174
175
|
"""
|
@@ -188,7 +189,7 @@ def web_page(
|
|
188
189
|
page_str = None
|
189
190
|
|
190
191
|
def _decorator(_func: Callable[[Any], Any]) -> Callable[[Any], Any]:
|
191
|
-
nonlocal page_str
|
192
|
+
nonlocal page_str, page_group
|
192
193
|
|
193
194
|
@functools.wraps(_func)
|
194
195
|
def wrapper(*_args, **_kwargs):
|
@@ -198,10 +199,31 @@ def web_page(
|
|
198
199
|
page_str = _func.__name__
|
199
200
|
|
200
201
|
page_str = page_str.lstrip('/').rstrip('/').strip()
|
201
|
-
|
202
|
+
page_key = (
|
203
|
+
' '.join(
|
204
|
+
[
|
205
|
+
word.capitalize()
|
206
|
+
for word in (
|
207
|
+
page_str.replace('/dash', '').lstrip('/').rstrip('/').strip()
|
208
|
+
.replace('-', ' ').replace('_', ' ').split(' ')
|
209
|
+
)
|
210
|
+
]
|
211
|
+
)
|
212
|
+
)
|
213
|
+
|
214
|
+
package_name = _func.__globals__['__name__']
|
215
|
+
plugin_name = (
|
216
|
+
package_name.split('.')[1]
|
217
|
+
if package_name.startswith('plugins.') else None
|
218
|
+
)
|
219
|
+
page_group = page_group or plugin_name
|
220
|
+
if page_group not in _plugin_endpoints_to_pages:
|
221
|
+
_plugin_endpoints_to_pages[page_group] = {}
|
222
|
+
_plugin_endpoints_to_pages[page_group][page_str] = {
|
202
223
|
'function': _func,
|
203
224
|
'login_required': login_required,
|
204
225
|
'skip_navbar': skip_navbar,
|
226
|
+
'page_key': page_key,
|
205
227
|
}
|
206
228
|
return wrapper
|
207
229
|
|
meerschaum/utils/dataframe.py
CHANGED
@@ -871,7 +871,10 @@ def get_bytes_cols(df: 'pd.DataFrame') -> List[str]:
|
|
871
871
|
]
|
872
872
|
|
873
873
|
|
874
|
-
def get_geometry_cols(
|
874
|
+
def get_geometry_cols(
|
875
|
+
df: 'pd.DataFrame',
|
876
|
+
with_types_srids: bool = False,
|
877
|
+
) -> Union[List[str], Dict[str, Any]]:
|
875
878
|
"""
|
876
879
|
Get the columns which contain shapely objects from a Pandas DataFrame.
|
877
880
|
|
@@ -880,9 +883,13 @@ def get_geometry_cols(df: 'pd.DataFrame') -> List[str]:
|
|
880
883
|
df: pd.DataFrame
|
881
884
|
The DataFrame which may contain bytes strings.
|
882
885
|
|
886
|
+
with_types_srids: bool, default False
|
887
|
+
If `True`, return a dictionary mapping columns to geometry types and SRIDs.
|
888
|
+
|
883
889
|
Returns
|
884
890
|
-------
|
885
891
|
A list of columns to treat as `geometry`.
|
892
|
+
If `with_types_srids`, return a dictionary mapping columns to tuples in the form (type, SRID).
|
886
893
|
"""
|
887
894
|
if df is None:
|
888
895
|
return []
|
@@ -898,7 +905,7 @@ def get_geometry_cols(df: 'pd.DataFrame') -> List[str]:
|
|
898
905
|
col: df[col].first_valid_index()
|
899
906
|
for col in df.columns
|
900
907
|
}
|
901
|
-
|
908
|
+
geo_cols = [
|
902
909
|
col
|
903
910
|
for col, ix in cols_indices.items()
|
904
911
|
if (
|
@@ -907,6 +914,38 @@ def get_geometry_cols(df: 'pd.DataFrame') -> List[str]:
|
|
907
914
|
'shapely' in str(type(df.loc[ix][col]))
|
908
915
|
)
|
909
916
|
]
|
917
|
+
if not with_types_srids:
|
918
|
+
return geo_cols
|
919
|
+
|
920
|
+
gpd = mrsm.attempt_import('geopandas', lazy=False)
|
921
|
+
geo_cols_types_srids = {}
|
922
|
+
for col in geo_cols:
|
923
|
+
try:
|
924
|
+
sample_geo_series = gpd.GeoSeries(df[col], crs=None)
|
925
|
+
geometry_types = {
|
926
|
+
geom.geom_type
|
927
|
+
for geom in sample_geo_series
|
928
|
+
if hasattr(geom, 'geom_type')
|
929
|
+
}
|
930
|
+
geometry_has_z = any(getattr(geom, 'has_z', False) for geom in sample_geo_series)
|
931
|
+
srid = (
|
932
|
+
(
|
933
|
+
sample_geo_series.crs.sub_crs_list[0].to_epsg()
|
934
|
+
if sample_geo_series.crs.is_compound
|
935
|
+
else sample_geo_series.crs.to_epsg()
|
936
|
+
)
|
937
|
+
if sample_geo_series.crs
|
938
|
+
else 0
|
939
|
+
)
|
940
|
+
geometry_type = list(geometry_types)[0] if len(geometry_types) == 1 else 'geometry'
|
941
|
+
if geometry_type != 'geometry' and geometry_has_z:
|
942
|
+
geometry_type = geometry_type + 'Z'
|
943
|
+
except Exception:
|
944
|
+
srid = 0
|
945
|
+
geometry_type = 'geometry'
|
946
|
+
geo_cols_types_srids[col] = (geometry_type, srid)
|
947
|
+
|
948
|
+
return geo_cols_types_srids
|
910
949
|
|
911
950
|
|
912
951
|
def enforce_dtypes(
|
@@ -1658,6 +1697,8 @@ def to_json(
|
|
1658
1697
|
orient: str = 'records',
|
1659
1698
|
date_format: str = 'iso',
|
1660
1699
|
date_unit: str = 'us',
|
1700
|
+
double_precision: int = 15,
|
1701
|
+
geometry_format: str = 'geojson',
|
1661
1702
|
**kwargs: Any
|
1662
1703
|
) -> str:
|
1663
1704
|
"""
|
@@ -1677,11 +1718,19 @@ def to_json(
|
|
1677
1718
|
date_unit: str, default 'us'
|
1678
1719
|
The precision of the timestamps.
|
1679
1720
|
|
1721
|
+
double_precision: int, default 15
|
1722
|
+
The number of decimal places to use when encoding floating point values (maximum 15).
|
1723
|
+
|
1724
|
+
geometry_format: str, default 'geojson'
|
1725
|
+
The serialization format for geometry data.
|
1726
|
+
Accepted values are `geojson`, `wkb_hex`, and `wkt`.
|
1727
|
+
|
1680
1728
|
Returns
|
1681
1729
|
-------
|
1682
1730
|
A JSON string.
|
1683
1731
|
"""
|
1684
1732
|
import warnings
|
1733
|
+
import functools
|
1685
1734
|
from meerschaum.utils.packages import import_pandas
|
1686
1735
|
from meerschaum.utils.dtypes import (
|
1687
1736
|
serialize_bytes,
|
@@ -1704,10 +1753,16 @@ def to_json(
|
|
1704
1753
|
with warnings.catch_warnings():
|
1705
1754
|
warnings.simplefilter("ignore")
|
1706
1755
|
for col in geometry_cols:
|
1707
|
-
df[col] = df[col].apply(
|
1756
|
+
df[col] = df[col].apply(
|
1757
|
+
functools.partial(
|
1758
|
+
serialize_geometry,
|
1759
|
+
geometry_format=geometry_format,
|
1760
|
+
)
|
1761
|
+
)
|
1708
1762
|
return df.infer_objects(copy=False).fillna(pd.NA).to_json(
|
1709
1763
|
date_format=date_format,
|
1710
1764
|
date_unit=date_unit,
|
1765
|
+
double_precision=double_precision,
|
1711
1766
|
orient=orient,
|
1712
1767
|
**kwargs
|
1713
1768
|
)
|
@@ -7,6 +7,7 @@ Utility functions for working with data types.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
import traceback
|
10
|
+
import json
|
10
11
|
import uuid
|
11
12
|
from datetime import timezone, datetime
|
12
13
|
from decimal import Decimal, Context, InvalidOperation, ROUND_HALF_UP
|
@@ -28,6 +29,7 @@ MRSM_ALIAS_DTYPES: Dict[str, str] = {
|
|
28
29
|
'guid': 'uuid',
|
29
30
|
'UUID': 'uuid',
|
30
31
|
'geom': 'geometry',
|
32
|
+
'geog': 'geography',
|
31
33
|
}
|
32
34
|
MRSM_PD_DTYPES: Dict[Union[str, None], str] = {
|
33
35
|
'json': 'object',
|
@@ -76,6 +78,7 @@ def to_pandas_dtype(dtype: str) -> str:
|
|
76
78
|
return get_pd_type_from_db_type(dtype)
|
77
79
|
|
78
80
|
from meerschaum.utils.packages import attempt_import
|
81
|
+
_ = attempt_import('pyarrow', lazy=False)
|
79
82
|
pandas = attempt_import('pandas', lazy=False)
|
80
83
|
|
81
84
|
try:
|
@@ -294,10 +297,21 @@ def attempt_cast_to_geometry(value: Any) -> Any:
|
|
294
297
|
"""
|
295
298
|
Given a value, attempt to coerce it into a `shapely` (`geometry`) object.
|
296
299
|
"""
|
297
|
-
shapely_wkt, shapely_wkb = mrsm.attempt_import(
|
300
|
+
shapely, shapely_wkt, shapely_wkb = mrsm.attempt_import(
|
301
|
+
'shapely',
|
302
|
+
'shapely.wkt',
|
303
|
+
'shapely.wkb',
|
304
|
+
lazy=False,
|
305
|
+
)
|
298
306
|
if 'shapely' in str(type(value)):
|
299
307
|
return value
|
300
308
|
|
309
|
+
if isinstance(value, (dict, list)):
|
310
|
+
try:
|
311
|
+
return shapely.from_geojson(json.dumps(value))
|
312
|
+
except Exception as e:
|
313
|
+
return value
|
314
|
+
|
301
315
|
value_is_wkt = geometry_is_wkt(value)
|
302
316
|
if value_is_wkt is None:
|
303
317
|
return value
|
@@ -327,6 +341,9 @@ def geometry_is_wkt(value: Union[str, bytes]) -> Union[bool, None]:
|
|
327
341
|
Return `None` if `value` should be parsed as neither.
|
328
342
|
"""
|
329
343
|
import re
|
344
|
+
if not isinstance(value, (str, bytes)):
|
345
|
+
return None
|
346
|
+
|
330
347
|
if isinstance(value, bytes):
|
331
348
|
return False
|
332
349
|
|
@@ -521,7 +538,11 @@ def serialize_bytes(data: bytes) -> str:
|
|
521
538
|
return base64.b64encode(data).decode('utf-8')
|
522
539
|
|
523
540
|
|
524
|
-
def serialize_geometry(
|
541
|
+
def serialize_geometry(
|
542
|
+
geom: Any,
|
543
|
+
geometry_format: str = 'wkb_hex',
|
544
|
+
as_wkt: bool = False,
|
545
|
+
) -> Union[str, Dict[str, Any]]:
|
525
546
|
"""
|
526
547
|
Serialize geometry data as a hex-encoded well-known-binary string.
|
527
548
|
|
@@ -530,16 +551,22 @@ def serialize_geometry(geom: Any, as_wkt: bool = False) -> str:
|
|
530
551
|
geom: Any
|
531
552
|
The potential geometry data to be serialized.
|
532
553
|
|
533
|
-
|
534
|
-
|
535
|
-
|
554
|
+
geometry_format: str, default 'wkb_hex'
|
555
|
+
The serialization format for geometry data.
|
556
|
+
Accepted formats are `wkb_hex` (well-known binary hex string),
|
557
|
+
`wkt` (well-known text), and `geojson`.
|
536
558
|
|
537
559
|
Returns
|
538
560
|
-------
|
539
561
|
A string containing the geometry data.
|
540
562
|
"""
|
563
|
+
shapely = mrsm.attempt_import('shapely', lazy=False)
|
564
|
+
if geometry_format == 'geojson':
|
565
|
+
geojson_str = shapely.to_geojson(geom)
|
566
|
+
return json.loads(geojson_str)
|
567
|
+
|
541
568
|
if hasattr(geom, 'wkb_hex'):
|
542
|
-
return geom.wkb_hex if
|
569
|
+
return geom.wkb_hex if geometry_format == 'wkb_hex' else geom.wkt
|
543
570
|
|
544
571
|
return str(geom)
|
545
572
|
|
@@ -711,24 +738,25 @@ def get_geometry_type_srid(
|
|
711
738
|
('Point', 4376)
|
712
739
|
"""
|
713
740
|
from meerschaum.utils.misc import is_int
|
741
|
+
### NOTE: PostGIS syntax must also be parsed.
|
742
|
+
dtype = dtype.replace('(', '[').replace(')', ']')
|
714
743
|
bare_dtype = dtype.split('[', maxsplit=1)[0]
|
715
744
|
modifier = dtype.split(bare_dtype, maxsplit=1)[-1].lstrip('[').rstrip(']')
|
716
745
|
if not modifier:
|
717
746
|
return default_type, default_srid
|
718
747
|
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
}
|
724
|
-
|
725
|
-
parts = [part.lower().replace('srid=', '').replace('type=', '').strip() for part in modifier.split(',')]
|
748
|
+
parts = [
|
749
|
+
part.split('=')[-1].strip()
|
750
|
+
for part in modifier.split(',')
|
751
|
+
]
|
726
752
|
parts_casted = [
|
727
753
|
(
|
728
754
|
int(part)
|
729
755
|
if is_int(part)
|
730
756
|
else part
|
731
|
-
)
|
757
|
+
)
|
758
|
+
for part in parts
|
759
|
+
]
|
732
760
|
|
733
761
|
srid = default_srid
|
734
762
|
geometry_type = default_type
|
@@ -738,9 +766,9 @@ def get_geometry_type_srid(
|
|
738
766
|
srid = part
|
739
767
|
break
|
740
768
|
|
741
|
-
for part in
|
742
|
-
if part
|
743
|
-
geometry_type =
|
769
|
+
for part in parts_casted:
|
770
|
+
if isinstance(part, str):
|
771
|
+
geometry_type = part
|
744
772
|
break
|
745
773
|
|
746
774
|
return geometry_type, srid
|
meerschaum/utils/dtypes/sql.py
CHANGED
@@ -74,10 +74,12 @@ DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
|
|
74
74
|
'DOUBLE': 'float64[pyarrow]',
|
75
75
|
'DECIMAL': 'numeric',
|
76
76
|
'BIGINT': 'int64[pyarrow]',
|
77
|
-
'INT': '
|
78
|
-
'INTEGER': '
|
77
|
+
'INT': 'int32[pyarrow]',
|
78
|
+
'INTEGER': 'int32[pyarrow]',
|
79
79
|
'NUMBER': 'numeric',
|
80
80
|
'NUMERIC': 'numeric',
|
81
|
+
'GEOMETRY': 'geometry',
|
82
|
+
'GEOMETRY(GEOMETRY)': 'geometry',
|
81
83
|
'TIMESTAMP': 'datetime64[ns]',
|
82
84
|
'TIMESTAMP WITHOUT TIMEZONE': 'datetime64[ns]',
|
83
85
|
'TIMESTAMP WITH TIMEZONE': 'datetime64[ns, UTC]',
|
@@ -120,6 +122,8 @@ DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
|
|
120
122
|
'BYTE': 'bytes',
|
121
123
|
'LOB': 'bytes',
|
122
124
|
'BINARY': 'bytes',
|
125
|
+
'GEOMETRY': 'geometry',
|
126
|
+
'GEOGRAPHY': 'geography',
|
123
127
|
},
|
124
128
|
'default': 'object',
|
125
129
|
}
|
@@ -139,6 +143,90 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
139
143
|
'cockroachdb': 'BIGINT',
|
140
144
|
'default': 'INT',
|
141
145
|
},
|
146
|
+
'uint': {
|
147
|
+
'timescaledb': 'BIGINT',
|
148
|
+
'postgresql': 'BIGINT',
|
149
|
+
'postgis': 'BIGINT',
|
150
|
+
'mariadb': 'BIGINT',
|
151
|
+
'mysql': 'BIGINT',
|
152
|
+
'mssql': 'BIGINT',
|
153
|
+
'oracle': 'INT',
|
154
|
+
'sqlite': 'BIGINT',
|
155
|
+
'duckdb': 'BIGINT',
|
156
|
+
'citus': 'BIGINT',
|
157
|
+
'cockroachdb': 'BIGINT',
|
158
|
+
'default': 'INT',
|
159
|
+
},
|
160
|
+
'int8': {
|
161
|
+
'timescaledb': 'SMALLINT',
|
162
|
+
'postgresql': 'SMALLINT',
|
163
|
+
'postgis': 'SMALLINT',
|
164
|
+
'mariadb': 'SMALLINT',
|
165
|
+
'mysql': 'SMALLINT',
|
166
|
+
'mssql': 'SMALLINT',
|
167
|
+
'oracle': 'INT',
|
168
|
+
'sqlite': 'INT',
|
169
|
+
'duckdb': 'SMALLINT',
|
170
|
+
'citus': 'SMALLINT',
|
171
|
+
'cockroachdb': 'SMALLINT',
|
172
|
+
'default': 'INT',
|
173
|
+
},
|
174
|
+
'uint8': {
|
175
|
+
'timescaledb': 'SMALLINT',
|
176
|
+
'postgresql': 'SMALLINT',
|
177
|
+
'postgis': 'SMALLINT',
|
178
|
+
'mariadb': 'SMALLINT',
|
179
|
+
'mysql': 'SMALLINT',
|
180
|
+
'mssql': 'SMALLINT',
|
181
|
+
'oracle': 'INT',
|
182
|
+
'sqlite': 'INT',
|
183
|
+
'duckdb': 'SMALLINT',
|
184
|
+
'citus': 'SMALLINT',
|
185
|
+
'cockroachdb': 'SMALLINT',
|
186
|
+
'default': 'INT',
|
187
|
+
},
|
188
|
+
'int16': {
|
189
|
+
'timescaledb': 'SMALLINT',
|
190
|
+
'postgresql': 'SMALLINT',
|
191
|
+
'postgis': 'SMALLINT',
|
192
|
+
'mariadb': 'SMALLINT',
|
193
|
+
'mysql': 'SMALLINT',
|
194
|
+
'mssql': 'SMALLINT',
|
195
|
+
'oracle': 'INT',
|
196
|
+
'sqlite': 'INT',
|
197
|
+
'duckdb': 'SMALLINT',
|
198
|
+
'citus': 'SMALLINT',
|
199
|
+
'cockroachdb': 'SMALLINT',
|
200
|
+
'default': 'INT',
|
201
|
+
},
|
202
|
+
'int32': {
|
203
|
+
'timescaledb': 'INT',
|
204
|
+
'postgresql': 'INT',
|
205
|
+
'postgis': 'INT',
|
206
|
+
'mariadb': 'INT',
|
207
|
+
'mysql': 'INT',
|
208
|
+
'mssql': 'INT',
|
209
|
+
'oracle': 'INT',
|
210
|
+
'sqlite': 'INT',
|
211
|
+
'duckdb': 'INT',
|
212
|
+
'citus': 'INT',
|
213
|
+
'cockroachdb': 'INT',
|
214
|
+
'default': 'INT',
|
215
|
+
},
|
216
|
+
'int64': {
|
217
|
+
'timescaledb': 'BIGINT',
|
218
|
+
'postgresql': 'BIGINT',
|
219
|
+
'postgis': 'BIGINT',
|
220
|
+
'mariadb': 'BIGINT',
|
221
|
+
'mysql': 'BIGINT',
|
222
|
+
'mssql': 'BIGINT',
|
223
|
+
'oracle': 'INT',
|
224
|
+
'sqlite': 'BIGINT',
|
225
|
+
'duckdb': 'BIGINT',
|
226
|
+
'citus': 'BIGINT',
|
227
|
+
'cockroachdb': 'BIGINT',
|
228
|
+
'default': 'INT',
|
229
|
+
},
|
142
230
|
'float': {
|
143
231
|
'timescaledb': 'DOUBLE PRECISION',
|
144
232
|
'postgresql': 'DOUBLE PRECISION',
|
@@ -380,6 +468,90 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
380
468
|
'cockroachdb': 'BigInteger',
|
381
469
|
'default': 'BigInteger',
|
382
470
|
},
|
471
|
+
'uint': {
|
472
|
+
'timescaledb': 'BigInteger',
|
473
|
+
'postgresql': 'BigInteger',
|
474
|
+
'postgis': 'BigInteger',
|
475
|
+
'mariadb': 'BigInteger',
|
476
|
+
'mysql': 'BigInteger',
|
477
|
+
'mssql': 'BigInteger',
|
478
|
+
'oracle': 'BigInteger',
|
479
|
+
'sqlite': 'BigInteger',
|
480
|
+
'duckdb': 'BigInteger',
|
481
|
+
'citus': 'BigInteger',
|
482
|
+
'cockroachdb': 'BigInteger',
|
483
|
+
'default': 'BigInteger',
|
484
|
+
},
|
485
|
+
'int8': {
|
486
|
+
'timescaledb': 'SmallInteger',
|
487
|
+
'postgresql': 'SmallInteger',
|
488
|
+
'postgis': 'SmallInteger',
|
489
|
+
'mariadb': 'SmallInteger',
|
490
|
+
'mysql': 'SmallInteger',
|
491
|
+
'mssql': 'SmallInteger',
|
492
|
+
'oracle': 'SmallInteger',
|
493
|
+
'sqlite': 'SmallInteger',
|
494
|
+
'duckdb': 'SmallInteger',
|
495
|
+
'citus': 'SmallInteger',
|
496
|
+
'cockroachdb': 'SmallInteger',
|
497
|
+
'default': 'SmallInteger',
|
498
|
+
},
|
499
|
+
'uint8': {
|
500
|
+
'timescaledb': 'SmallInteger',
|
501
|
+
'postgresql': 'SmallInteger',
|
502
|
+
'postgis': 'SmallInteger',
|
503
|
+
'mariadb': 'SmallInteger',
|
504
|
+
'mysql': 'SmallInteger',
|
505
|
+
'mssql': 'SmallInteger',
|
506
|
+
'oracle': 'SmallInteger',
|
507
|
+
'sqlite': 'SmallInteger',
|
508
|
+
'duckdb': 'SmallInteger',
|
509
|
+
'citus': 'SmallInteger',
|
510
|
+
'cockroachdb': 'SmallInteger',
|
511
|
+
'default': 'SmallInteger',
|
512
|
+
},
|
513
|
+
'int16': {
|
514
|
+
'timescaledb': 'SmallInteger',
|
515
|
+
'postgresql': 'SmallInteger',
|
516
|
+
'postgis': 'SmallInteger',
|
517
|
+
'mariadb': 'SmallInteger',
|
518
|
+
'mysql': 'SmallInteger',
|
519
|
+
'mssql': 'SmallInteger',
|
520
|
+
'oracle': 'SmallInteger',
|
521
|
+
'sqlite': 'SmallInteger',
|
522
|
+
'duckdb': 'SmallInteger',
|
523
|
+
'citus': 'SmallInteger',
|
524
|
+
'cockroachdb': 'SmallInteger',
|
525
|
+
'default': 'SmallInteger',
|
526
|
+
},
|
527
|
+
'int32': {
|
528
|
+
'timescaledb': 'Integer',
|
529
|
+
'postgresql': 'Integer',
|
530
|
+
'postgis': 'Integer',
|
531
|
+
'mariadb': 'Integer',
|
532
|
+
'mysql': 'Integer',
|
533
|
+
'mssql': 'Integer',
|
534
|
+
'oracle': 'Integer',
|
535
|
+
'sqlite': 'Integer',
|
536
|
+
'duckdb': 'Integer',
|
537
|
+
'citus': 'Integer',
|
538
|
+
'cockroachdb': 'Integer',
|
539
|
+
'default': 'Integer',
|
540
|
+
},
|
541
|
+
'int64': {
|
542
|
+
'timescaledb': 'BigInteger',
|
543
|
+
'postgresql': 'BigInteger',
|
544
|
+
'postgis': 'BigInteger',
|
545
|
+
'mariadb': 'BigInteger',
|
546
|
+
'mysql': 'BigInteger',
|
547
|
+
'mssql': 'BigInteger',
|
548
|
+
'oracle': 'BigInteger',
|
549
|
+
'sqlite': 'BigInteger',
|
550
|
+
'duckdb': 'BigInteger',
|
551
|
+
'citus': 'BigInteger',
|
552
|
+
'cockroachdb': 'BigInteger',
|
553
|
+
'default': 'BigInteger',
|
554
|
+
},
|
383
555
|
'float': {
|
384
556
|
'timescaledb': 'Float',
|
385
557
|
'postgresql': 'Float',
|
@@ -596,7 +768,7 @@ def get_pd_type_from_db_type(db_type: str, allow_custom_dtypes: bool = True) ->
|
|
596
768
|
-------
|
597
769
|
The equivalent datatype for a pandas DataFrame.
|
598
770
|
"""
|
599
|
-
from meerschaum.utils.dtypes import are_dtypes_equal
|
771
|
+
from meerschaum.utils.dtypes import are_dtypes_equal, get_geometry_type_srid
|
600
772
|
def parse_custom(_pd_type: str, _db_type: str) -> str:
|
601
773
|
if 'json' in _db_type.lower():
|
602
774
|
return 'json'
|
@@ -604,6 +776,13 @@ def get_pd_type_from_db_type(db_type: str, allow_custom_dtypes: bool = True) ->
|
|
604
776
|
precision, scale = get_numeric_precision_scale(None, dtype=_db_type.upper())
|
605
777
|
if precision and scale:
|
606
778
|
return f"numeric[{precision},{scale}]"
|
779
|
+
if are_dtypes_equal(_pd_type, 'geometry') and _pd_type != 'object':
|
780
|
+
geometry_type, srid = get_geometry_type_srid(_db_type.upper())
|
781
|
+
modifiers = [str(modifier) for modifier in (geometry_type, srid) if modifier]
|
782
|
+
typ = "geometry" if 'geography' not in _pd_type.lower() else 'geography'
|
783
|
+
if not modifiers:
|
784
|
+
return typ
|
785
|
+
return f"{typ}[{', '.join(modifiers)}]"
|
607
786
|
return _pd_type
|
608
787
|
|
609
788
|
pd_type = DB_TO_PD_DTYPES.get(db_type.upper().split('(', maxsplit=1)[0].strip(), None)
|
meerschaum/utils/misc.py
CHANGED
@@ -88,6 +88,11 @@ packages: Dict[str, Dict[str, str]] = {
|
|
88
88
|
'mssqlcli' : 'mssql-cli>=1.0.0',
|
89
89
|
'gadwall' : 'gadwall>=0.2.0',
|
90
90
|
},
|
91
|
+
'gis' : {
|
92
|
+
'pyproj' : 'pyproj>=3.7.1',
|
93
|
+
'geopandas' : 'geopandas>=1.0.1',
|
94
|
+
'shapely' : 'shapely>=2.0.7',
|
95
|
+
},
|
91
96
|
'stack': {
|
92
97
|
'compose' : 'docker-compose>=1.29.2',
|
93
98
|
},
|
@@ -120,7 +125,6 @@ packages: Dict[str, Dict[str, str]] = {
|
|
120
125
|
'jinja2' : 'jinja2==3.0.3',
|
121
126
|
},
|
122
127
|
'gui': {
|
123
|
-
'toga' : 'toga>=0.3.0-dev29',
|
124
128
|
'webview' : 'pywebview>=3.6.3',
|
125
129
|
'pycparser' : 'pycparser>=2.21.0',
|
126
130
|
},
|
@@ -135,8 +139,6 @@ packages: Dict[str, Dict[str, str]] = {
|
|
135
139
|
packages['sql'] = {
|
136
140
|
'numpy' : 'numpy>=1.18.5',
|
137
141
|
'pandas' : 'pandas[parquet]>=2.0.1',
|
138
|
-
'geopandas' : 'geopandas>=1.0.1',
|
139
|
-
'shapely' : 'shapely>=2.0.7',
|
140
142
|
'pyarrow' : 'pyarrow>=16.1.0',
|
141
143
|
'dask' : 'dask[complete]>=2024.12.1',
|
142
144
|
'partd' : 'partd>=1.4.2',
|
@@ -150,6 +152,7 @@ packages['sql'] = {
|
|
150
152
|
}
|
151
153
|
packages['sql'].update(packages['drivers'])
|
152
154
|
packages['sql'].update(packages['core'])
|
155
|
+
packages['sql'].update(packages['gis'])
|
153
156
|
packages['dash'] = {
|
154
157
|
'flask_compress' : 'Flask-Compress>=1.10.1',
|
155
158
|
'dash' : 'dash>=2.6.2',
|