meerschaum 2.8.4__py3-none-any.whl → 2.9.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.
Files changed (57) hide show
  1. meerschaum/api/_chunks.py +67 -0
  2. meerschaum/api/dash/callbacks/__init__.py +5 -2
  3. meerschaum/api/dash/callbacks/custom.py +21 -8
  4. meerschaum/api/dash/callbacks/dashboard.py +26 -4
  5. meerschaum/api/dash/callbacks/settings/__init__.py +8 -0
  6. meerschaum/api/dash/callbacks/settings/password_reset.py +76 -0
  7. meerschaum/api/dash/components.py +136 -25
  8. meerschaum/api/dash/pages/__init__.py +1 -0
  9. meerschaum/api/dash/pages/dashboard.py +11 -9
  10. meerschaum/api/dash/pages/plugins.py +31 -27
  11. meerschaum/api/dash/pages/settings/__init__.py +8 -0
  12. meerschaum/api/dash/pages/settings/password_reset.py +63 -0
  13. meerschaum/api/dash/webterm.py +6 -3
  14. meerschaum/api/resources/static/css/dash.css +8 -1
  15. meerschaum/api/resources/templates/termpage.html +4 -0
  16. meerschaum/api/routes/_pipes.py +232 -79
  17. meerschaum/config/_default.py +4 -0
  18. meerschaum/config/_version.py +1 -1
  19. meerschaum/connectors/__init__.py +1 -0
  20. meerschaum/connectors/api/_APIConnector.py +12 -1
  21. meerschaum/connectors/api/_pipes.py +106 -45
  22. meerschaum/connectors/api/_plugins.py +51 -45
  23. meerschaum/connectors/api/_request.py +1 -1
  24. meerschaum/connectors/parse.py +1 -2
  25. meerschaum/connectors/sql/_SQLConnector.py +3 -0
  26. meerschaum/connectors/sql/_cli.py +1 -0
  27. meerschaum/connectors/sql/_create_engine.py +51 -4
  28. meerschaum/connectors/sql/_pipes.py +38 -6
  29. meerschaum/connectors/sql/_sql.py +35 -4
  30. meerschaum/connectors/valkey/_ValkeyConnector.py +2 -0
  31. meerschaum/connectors/valkey/_pipes.py +51 -39
  32. meerschaum/core/Pipe/__init__.py +1 -0
  33. meerschaum/core/Pipe/_data.py +1 -2
  34. meerschaum/core/Pipe/_sync.py +64 -4
  35. meerschaum/plugins/_Plugin.py +21 -5
  36. meerschaum/plugins/__init__.py +32 -8
  37. meerschaum/utils/dataframe.py +139 -2
  38. meerschaum/utils/dtypes/__init__.py +211 -1
  39. meerschaum/utils/dtypes/sql.py +296 -5
  40. meerschaum/utils/formatting/_shell.py +1 -4
  41. meerschaum/utils/misc.py +1 -1
  42. meerschaum/utils/packages/_packages.py +7 -1
  43. meerschaum/utils/sql.py +139 -11
  44. meerschaum/utils/venv/__init__.py +6 -1
  45. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/METADATA +17 -3
  46. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/RECORD +52 -52
  47. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/WHEEL +1 -1
  48. meerschaum/_internal/gui/__init__.py +0 -43
  49. meerschaum/_internal/gui/app/__init__.py +0 -50
  50. meerschaum/_internal/gui/app/_windows.py +0 -74
  51. meerschaum/_internal/gui/app/actions.py +0 -30
  52. meerschaum/_internal/gui/app/pipes.py +0 -47
  53. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/LICENSE +0 -0
  54. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/NOTICE +0 -0
  55. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/entry_points.txt +0 -0
  56. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/top_level.txt +0 -0
  57. {meerschaum-2.8.4.dist-info → meerschaum-2.9.0.dist-info}/zip-safe +0 -0
@@ -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': 'int64[pyarrow]',
78
- 'INTEGER': 'int64[pyarrow]',
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
  }
@@ -128,6 +132,91 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
128
132
  'int': {
129
133
  'timescaledb': 'BIGINT',
130
134
  'postgresql': 'BIGINT',
135
+ 'postgis': 'BIGINT',
136
+ 'mariadb': 'BIGINT',
137
+ 'mysql': 'BIGINT',
138
+ 'mssql': 'BIGINT',
139
+ 'oracle': 'INT',
140
+ 'sqlite': 'BIGINT',
141
+ 'duckdb': 'BIGINT',
142
+ 'citus': 'BIGINT',
143
+ 'cockroachdb': 'BIGINT',
144
+ 'default': 'INT',
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',
131
220
  'mariadb': 'BIGINT',
132
221
  'mysql': 'BIGINT',
133
222
  'mssql': 'BIGINT',
@@ -141,6 +230,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
141
230
  'float': {
142
231
  'timescaledb': 'DOUBLE PRECISION',
143
232
  'postgresql': 'DOUBLE PRECISION',
233
+ 'postgis': 'DOUBLE PRECISION',
144
234
  'mariadb': 'DOUBLE PRECISION',
145
235
  'mysql': 'DOUBLE PRECISION',
146
236
  'mssql': 'FLOAT',
@@ -154,6 +244,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
154
244
  'double': {
155
245
  'timescaledb': 'DOUBLE PRECISION',
156
246
  'postgresql': 'DOUBLE PRECISION',
247
+ 'postgis': 'DOUBLE PRECISION',
157
248
  'mariadb': 'DOUBLE PRECISION',
158
249
  'mysql': 'DOUBLE PRECISION',
159
250
  'mssql': 'FLOAT',
@@ -167,6 +258,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
167
258
  'datetime64[ns]': {
168
259
  'timescaledb': 'TIMESTAMP',
169
260
  'postgresql': 'TIMESTAMP',
261
+ 'postgis': 'TIMESTAMP',
170
262
  'mariadb': 'DATETIME',
171
263
  'mysql': 'DATETIME',
172
264
  'mssql': 'DATETIME2',
@@ -180,6 +272,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
180
272
  'datetime64[ns, UTC]': {
181
273
  'timescaledb': 'TIMESTAMPTZ',
182
274
  'postgresql': 'TIMESTAMPTZ',
275
+ 'postgis': 'TIMESTAMPTZ',
183
276
  'mariadb': 'DATETIME',
184
277
  'mysql': 'DATETIME',
185
278
  'mssql': 'DATETIMEOFFSET',
@@ -193,6 +286,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
193
286
  'datetime': {
194
287
  'timescaledb': 'TIMESTAMPTZ',
195
288
  'postgresql': 'TIMESTAMPTZ',
289
+ 'postgis': 'TIMESTAMPTZ',
196
290
  'mariadb': 'DATETIME',
197
291
  'mysql': 'DATETIME',
198
292
  'mssql': 'DATETIMEOFFSET',
@@ -206,6 +300,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
206
300
  'datetimetz': {
207
301
  'timescaledb': 'TIMESTAMPTZ',
208
302
  'postgresql': 'TIMESTAMPTZ',
303
+ 'postgis': 'TIMESTAMPTZ',
209
304
  'mariadb': 'DATETIME',
210
305
  'mysql': 'DATETIME',
211
306
  'mssql': 'DATETIMEOFFSET',
@@ -219,6 +314,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
219
314
  'bool': {
220
315
  'timescaledb': 'BOOLEAN',
221
316
  'postgresql': 'BOOLEAN',
317
+ 'postgis': 'BOOLEAN',
222
318
  'mariadb': 'BOOLEAN',
223
319
  'mysql': 'BOOLEAN',
224
320
  'mssql': 'BIT',
@@ -232,6 +328,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
232
328
  'object': {
233
329
  'timescaledb': 'TEXT',
234
330
  'postgresql': 'TEXT',
331
+ 'postgis': 'TEXT',
235
332
  'mariadb': 'TEXT',
236
333
  'mysql': 'TEXT',
237
334
  'mssql': 'NVARCHAR(MAX)',
@@ -245,6 +342,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
245
342
  'string': {
246
343
  'timescaledb': 'TEXT',
247
344
  'postgresql': 'TEXT',
345
+ 'postgis': 'TEXT',
248
346
  'mariadb': 'TEXT',
249
347
  'mysql': 'TEXT',
250
348
  'mssql': 'NVARCHAR(MAX)',
@@ -258,6 +356,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
258
356
  'unicode': {
259
357
  'timescaledb': 'TEXT',
260
358
  'postgresql': 'TEXT',
359
+ 'postgis': 'TEXT',
261
360
  'mariadb': 'TEXT',
262
361
  'mysql': 'TEXT',
263
362
  'mssql': 'NVARCHAR(MAX)',
@@ -271,6 +370,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
271
370
  'json': {
272
371
  'timescaledb': 'JSONB',
273
372
  'postgresql': 'JSONB',
373
+ 'postgis': 'JSONB',
274
374
  'mariadb': 'TEXT',
275
375
  'mysql': 'TEXT',
276
376
  'mssql': 'NVARCHAR(MAX)',
@@ -284,6 +384,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
284
384
  'numeric': {
285
385
  'timescaledb': 'NUMERIC',
286
386
  'postgresql': 'NUMERIC',
387
+ 'postgis': 'NUMERIC',
287
388
  'mariadb': f'DECIMAL{NUMERIC_PRECISION_FLAVORS["mariadb"]}',
288
389
  'mysql': f'DECIMAL{NUMERIC_PRECISION_FLAVORS["mysql"]}',
289
390
  'mssql': f'NUMERIC{NUMERIC_PRECISION_FLAVORS["mssql"]}',
@@ -297,6 +398,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
297
398
  'uuid': {
298
399
  'timescaledb': 'UUID',
299
400
  'postgresql': 'UUID',
401
+ 'postgis': 'UUID',
300
402
  'mariadb': 'CHAR(36)',
301
403
  'mysql': 'CHAR(36)',
302
404
  'mssql': 'UNIQUEIDENTIFIER',
@@ -311,6 +413,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
311
413
  'bytes': {
312
414
  'timescaledb': 'BYTEA',
313
415
  'postgresql': 'BYTEA',
416
+ 'postgis': 'BYTEA',
314
417
  'mariadb': 'BLOB',
315
418
  'mysql': 'BLOB',
316
419
  'mssql': 'VARBINARY(MAX)',
@@ -321,11 +424,124 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
321
424
  'cockroachdb': 'BYTEA',
322
425
  'default': 'BLOB',
323
426
  },
427
+ 'geometry': {
428
+ 'timescaledb': 'TEXT',
429
+ 'postgresql': 'TEXT',
430
+ 'postgis': 'GEOMETRY',
431
+ 'mariadb': 'TEXT',
432
+ 'mysql': 'TEXT',
433
+ 'mssql': 'NVARCHAR(MAX)',
434
+ 'oracle': 'NVARCHAR2(2000)',
435
+ 'sqlite': 'TEXT',
436
+ 'duckdb': 'TEXT',
437
+ 'citus': 'TEXT',
438
+ 'cockroachdb': 'TEXT',
439
+ 'default': 'TEXT',
440
+ },
441
+ 'geography': {
442
+ 'timescaledb': 'TEXT',
443
+ 'postgresql': 'TEXT',
444
+ 'postgis': 'GEOGRAPHY',
445
+ 'mariadb': 'TEXT',
446
+ 'mysql': 'TEXT',
447
+ 'mssql': 'NVARCHAR(MAX)',
448
+ 'oracle': 'NVARCHAR2(2000)',
449
+ 'sqlite': 'TEXT',
450
+ 'duckdb': 'TEXT',
451
+ 'citus': 'TEXT',
452
+ 'cockroachdb': 'TEXT',
453
+ 'default': 'TEXT',
454
+ },
324
455
  }
325
456
  PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
326
457
  'int': {
327
458
  'timescaledb': 'BigInteger',
328
459
  'postgresql': 'BigInteger',
460
+ 'postgis': 'BigInteger',
461
+ 'mariadb': 'BigInteger',
462
+ 'mysql': 'BigInteger',
463
+ 'mssql': 'BigInteger',
464
+ 'oracle': 'BigInteger',
465
+ 'sqlite': 'BigInteger',
466
+ 'duckdb': 'BigInteger',
467
+ 'citus': 'BigInteger',
468
+ 'cockroachdb': 'BigInteger',
469
+ 'default': 'BigInteger',
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',
329
545
  'mariadb': 'BigInteger',
330
546
  'mysql': 'BigInteger',
331
547
  'mssql': 'BigInteger',
@@ -339,6 +555,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
339
555
  'float': {
340
556
  'timescaledb': 'Float',
341
557
  'postgresql': 'Float',
558
+ 'postgis': 'Float',
342
559
  'mariadb': 'Float',
343
560
  'mysql': 'Float',
344
561
  'mssql': 'Float',
@@ -352,6 +569,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
352
569
  'datetime': {
353
570
  'timescaledb': 'DateTime(timezone=True)',
354
571
  'postgresql': 'DateTime(timezone=True)',
572
+ 'postgis': 'DateTime(timezone=True)',
355
573
  'mariadb': 'DateTime(timezone=True)',
356
574
  'mysql': 'DateTime(timezone=True)',
357
575
  'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
@@ -365,6 +583,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
365
583
  'datetime64[ns]': {
366
584
  'timescaledb': 'DateTime',
367
585
  'postgresql': 'DateTime',
586
+ 'postgis': 'DateTime',
368
587
  'mariadb': 'DateTime',
369
588
  'mysql': 'DateTime',
370
589
  'mssql': 'sqlalchemy.dialects.mssql.DATETIME2',
@@ -378,6 +597,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
378
597
  'datetime64[ns, UTC]': {
379
598
  'timescaledb': 'DateTime(timezone=True)',
380
599
  'postgresql': 'DateTime(timezone=True)',
600
+ 'postgis': 'DateTime(timezone=True)',
381
601
  'mariadb': 'DateTime(timezone=True)',
382
602
  'mysql': 'DateTime(timezone=True)',
383
603
  'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
@@ -391,6 +611,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
391
611
  'bool': {
392
612
  'timescaledb': 'Boolean',
393
613
  'postgresql': 'Boolean',
614
+ 'postgis': 'Boolean',
394
615
  'mariadb': 'Integer',
395
616
  'mysql': 'Integer',
396
617
  'mssql': 'sqlalchemy.dialects.mssql.BIT',
@@ -404,6 +625,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
404
625
  'object': {
405
626
  'timescaledb': 'UnicodeText',
406
627
  'postgresql': 'UnicodeText',
628
+ 'postgis': 'UnicodeText',
407
629
  'mariadb': 'UnicodeText',
408
630
  'mysql': 'UnicodeText',
409
631
  'mssql': 'UnicodeText',
@@ -417,6 +639,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
417
639
  'string': {
418
640
  'timescaledb': 'UnicodeText',
419
641
  'postgresql': 'UnicodeText',
642
+ 'postgis': 'UnicodeText',
420
643
  'mariadb': 'UnicodeText',
421
644
  'mysql': 'UnicodeText',
422
645
  'mssql': 'UnicodeText',
@@ -430,6 +653,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
430
653
  'json': {
431
654
  'timescaledb': 'sqlalchemy.dialects.postgresql.JSONB',
432
655
  'postgresql': 'sqlalchemy.dialects.postgresql.JSONB',
656
+ 'postgis': 'sqlalchemy.dialects.postgresql.JSONB',
433
657
  'mariadb': 'UnicodeText',
434
658
  'mysql': 'UnicodeText',
435
659
  'mssql': 'UnicodeText',
@@ -443,6 +667,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
443
667
  'numeric': {
444
668
  'timescaledb': 'Numeric',
445
669
  'postgresql': 'Numeric',
670
+ 'postgis': 'Numeric',
446
671
  'mariadb': 'Numeric',
447
672
  'mysql': 'Numeric',
448
673
  'mssql': 'Numeric',
@@ -456,6 +681,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
456
681
  'uuid': {
457
682
  'timescaledb': 'Uuid',
458
683
  'postgresql': 'Uuid',
684
+ 'postgis': 'Uuid',
459
685
  'mariadb': 'sqlalchemy.dialects.mysql.CHAR(36)',
460
686
  'mysql': 'sqlalchemy.dialects.mysql.CHAR(36)',
461
687
  'mssql': 'Uuid',
@@ -469,6 +695,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
469
695
  'bytes': {
470
696
  'timescaledb': 'LargeBinary',
471
697
  'postgresql': 'LargeBinary',
698
+ 'postgis': 'LargeBinary',
472
699
  'mariadb': 'LargeBinary',
473
700
  'mysql': 'LargeBinary',
474
701
  'mssql': 'LargeBinary',
@@ -479,11 +706,40 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
479
706
  'cockroachdb': 'LargeBinary',
480
707
  'default': 'LargeBinary',
481
708
  },
709
+ 'geometry': {
710
+ 'timescaledb': 'UnicodeText',
711
+ 'postgresql': 'UnicodeText',
712
+ 'postgis': 'geoalchemy2.Geometry',
713
+ 'mariadb': 'UnicodeText',
714
+ 'mysql': 'UnicodeText',
715
+ 'mssql': 'UnicodeText',
716
+ 'oracle': 'UnicodeText',
717
+ 'sqlite': 'UnicodeText',
718
+ 'duckdb': 'UnicodeText',
719
+ 'citus': 'UnicodeText',
720
+ 'cockroachdb': 'UnicodeText',
721
+ 'default': 'UnicodeText',
722
+ },
723
+ 'geography': {
724
+ 'timescaledb': 'UnicodeText',
725
+ 'postgresql': 'UnicodeText',
726
+ 'postgis': 'geoalchemy2.Geography',
727
+ 'mariadb': 'UnicodeText',
728
+ 'mysql': 'UnicodeText',
729
+ 'mssql': 'UnicodeText',
730
+ 'oracle': 'UnicodeText',
731
+ 'sqlite': 'UnicodeText',
732
+ 'duckdb': 'UnicodeText',
733
+ 'citus': 'UnicodeText',
734
+ 'cockroachdb': 'UnicodeText',
735
+ 'default': 'UnicodeText',
736
+ },
482
737
  }
483
738
 
484
739
  AUTO_INCREMENT_COLUMN_FLAVORS: Dict[str, str] = {
485
740
  'timescaledb': 'GENERATED BY DEFAULT AS IDENTITY',
486
741
  'postgresql': 'GENERATED BY DEFAULT AS IDENTITY',
742
+ 'postgis': 'GENERATED BY DEFAULT AS IDENTITY',
487
743
  'mariadb': 'AUTO_INCREMENT',
488
744
  'mysql': 'AUTO_INCREMENT',
489
745
  'mssql': 'IDENTITY(1,1)',
@@ -512,7 +768,7 @@ def get_pd_type_from_db_type(db_type: str, allow_custom_dtypes: bool = True) ->
512
768
  -------
513
769
  The equivalent datatype for a pandas DataFrame.
514
770
  """
515
- from meerschaum.utils.dtypes import are_dtypes_equal
771
+ from meerschaum.utils.dtypes import are_dtypes_equal, get_geometry_type_srid
516
772
  def parse_custom(_pd_type: str, _db_type: str) -> str:
517
773
  if 'json' in _db_type.lower():
518
774
  return 'json'
@@ -520,6 +776,13 @@ def get_pd_type_from_db_type(db_type: str, allow_custom_dtypes: bool = True) ->
520
776
  precision, scale = get_numeric_precision_scale(None, dtype=_db_type.upper())
521
777
  if precision and scale:
522
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)}]"
523
786
  return _pd_type
524
787
 
525
788
  pd_type = DB_TO_PD_DTYPES.get(db_type.upper().split('(', maxsplit=1)[0].strip(), None)
@@ -565,7 +828,7 @@ def get_db_type_from_pd_type(
565
828
  """
566
829
  from meerschaum.utils.warnings import warn
567
830
  from meerschaum.utils.packages import attempt_import
568
- from meerschaum.utils.dtypes import are_dtypes_equal, MRSM_ALIAS_DTYPES
831
+ from meerschaum.utils.dtypes import are_dtypes_equal, MRSM_ALIAS_DTYPES, get_geometry_type_srid
569
832
  from meerschaum.utils.misc import parse_arguments_str
570
833
  sqlalchemy_types = attempt_import('sqlalchemy.types', lazy=False)
571
834
 
@@ -576,18 +839,30 @@ def get_db_type_from_pd_type(
576
839
  )
577
840
 
578
841
  precision, scale = None, None
842
+ geometry_type, geometry_srid = None, None
579
843
  og_pd_type = pd_type
580
844
  if pd_type in MRSM_ALIAS_DTYPES:
581
845
  pd_type = MRSM_ALIAS_DTYPES[pd_type]
582
846
 
583
847
  ### Check whether we are able to match this type (e.g. pyarrow support).
584
848
  found_db_type = False
585
- if pd_type not in types_registry and not pd_type.startswith('numeric['):
849
+ if (
850
+ pd_type not in types_registry
851
+ and not any(
852
+ pd_type.startswith(f'{typ}[')
853
+ for typ in ('numeric', 'geometry', 'geography')
854
+ )
855
+ ):
586
856
  for mapped_pd_type in types_registry:
587
857
  if are_dtypes_equal(mapped_pd_type, pd_type):
588
858
  pd_type = mapped_pd_type
589
859
  found_db_type = True
590
860
  break
861
+ elif (pd_type.startswith('geometry[') or pd_type.startswith('geography[')):
862
+ og_pd_type = pd_type
863
+ pd_type = 'geometry' if 'geometry' in pd_type else 'geography'
864
+ geometry_type, geometry_srid = get_geometry_type_srid(og_pd_type)
865
+ found_db_type = True
591
866
  elif pd_type.startswith('numeric['):
592
867
  og_pd_type = pd_type
593
868
  pd_type = 'numeric'
@@ -628,6 +903,11 @@ def get_db_type_from_pd_type(
628
903
  if precision is not None and scale is not None:
629
904
  db_type_bare = db_type.split('(', maxsplit=1)[0]
630
905
  return f"{db_type_bare}({precision},{scale})"
906
+ if geometry_type is not None and geometry_srid is not None:
907
+ if 'geometry' not in db_type.lower() and 'geography' not in db_type.lower():
908
+ return db_type
909
+ db_type_bare = db_type.split('(', maxsplit=1)[0]
910
+ return f"{db_type_bare}({geometry_type.upper()}, {geometry_srid})"
631
911
  return db_type
632
912
 
633
913
  if db_type.startswith('sqlalchemy.dialects'):
@@ -643,6 +923,17 @@ def get_db_type_from_pd_type(
643
923
  return cls
644
924
  return cls(*cls_args, **cls_kwargs)
645
925
 
926
+ if 'geometry' in db_type.lower() or 'geography' in db_type.lower():
927
+ geoalchemy2 = attempt_import('geoalchemy2', lazy=False)
928
+ geometry_class = (
929
+ geoalchemy2.Geometry
930
+ if 'geometry' in db_type.lower()
931
+ else geoalchemy2.Geography
932
+ )
933
+ if geometry_type is None or geometry_srid is None:
934
+ return geometry_class
935
+ return geometry_class(geometry_type=geometry_type, srid=geometry_srid)
936
+
646
937
  if 'numeric' in db_type.lower():
647
938
  if precision is None or scale is None:
648
939
  return sqlalchemy_types.Numeric
@@ -66,10 +66,7 @@ def clear_screen(debug: bool = False) -> bool:
66
66
  get_console().clear()
67
67
  print("", end="", flush=True)
68
68
  return True
69
- clear_string = (
70
- '\033c' if platform.system() != 'Windows'
71
- else '\033[2J'
72
- )
69
+ clear_string = '\033[2J'
73
70
  reset_string = '\033[0m'
74
71
  print(clear_string + reset_string, end="")
75
72
  print("", end="", flush=True)
meerschaum/utils/misc.py CHANGED
@@ -175,7 +175,7 @@ def string_to_dict(
175
175
  import ast
176
176
  params_dict = {}
177
177
  for param in params_string.split(","):
178
- _keys = param.split(":")
178
+ _keys = param.split(":", maxsplit=1)
179
179
  keys = _keys[:-1]
180
180
  try:
181
181
  val = ast.literal_eval(_keys[-1])
@@ -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
  },
@@ -141,12 +145,14 @@ packages['sql'] = {
141
145
  'pytz' : 'pytz',
142
146
  'joblib' : 'joblib>=0.17.0',
143
147
  'sqlalchemy' : 'SQLAlchemy>=2.0.5',
148
+ 'geoalchemy' : 'GeoAlchemy2>=0.17.1',
144
149
  'databases' : 'databases>=0.4.0',
145
150
  'aiosqlite' : 'aiosqlite>=0.16.0',
146
151
  'asyncpg' : 'asyncpg>=0.21.0',
147
152
  }
148
153
  packages['sql'].update(packages['drivers'])
149
154
  packages['sql'].update(packages['core'])
155
+ packages['sql'].update(packages['gis'])
150
156
  packages['dash'] = {
151
157
  'flask_compress' : 'Flask-Compress>=1.10.1',
152
158
  'dash' : 'dash>=2.6.2',