meerschaum 3.0.0rc1__py3-none-any.whl → 3.0.0rc2__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 (45) hide show
  1. meerschaum/_internal/arguments/_parser.py +2 -1
  2. meerschaum/_internal/docs/index.py +49 -2
  3. meerschaum/_internal/static.py +8 -24
  4. meerschaum/actions/verify.py +5 -8
  5. meerschaum/api/__init__.py +2 -1
  6. meerschaum/api/dash/__init__.py +0 -2
  7. meerschaum/api/dash/callbacks/dashboard.py +1 -1
  8. meerschaum/api/dash/tokens.py +2 -2
  9. meerschaum/api/routes/_pipes.py +47 -37
  10. meerschaum/config/_default.py +11 -1
  11. meerschaum/config/_version.py +1 -1
  12. meerschaum/config/stack/__init__.py +9 -8
  13. meerschaum/connectors/api/_pipes.py +2 -18
  14. meerschaum/connectors/api/_tokens.py +2 -2
  15. meerschaum/connectors/instance/_tokens.py +4 -4
  16. meerschaum/connectors/sql/_create_engine.py +3 -14
  17. meerschaum/connectors/sql/_pipes.py +118 -163
  18. meerschaum/connectors/sql/_sql.py +38 -20
  19. meerschaum/connectors/valkey/_pipes.py +44 -16
  20. meerschaum/core/Pipe/__init__.py +28 -5
  21. meerschaum/core/Pipe/_attributes.py +270 -46
  22. meerschaum/core/Pipe/_data.py +55 -17
  23. meerschaum/core/Pipe/_dtypes.py +19 -4
  24. meerschaum/core/Pipe/_edit.py +2 -0
  25. meerschaum/core/Pipe/_fetch.py +1 -1
  26. meerschaum/core/Pipe/_sync.py +90 -160
  27. meerschaum/core/Pipe/_verify.py +3 -3
  28. meerschaum/core/Token/_Token.py +3 -4
  29. meerschaum/utils/dataframe.py +379 -68
  30. meerschaum/utils/debug.py +15 -15
  31. meerschaum/utils/dtypes/__init__.py +388 -22
  32. meerschaum/utils/dtypes/sql.py +326 -30
  33. meerschaum/utils/misc.py +9 -68
  34. meerschaum/utils/packages/__init__.py +7 -21
  35. meerschaum/utils/packages/_packages.py +7 -2
  36. meerschaum/utils/schedule.py +1 -1
  37. meerschaum/utils/sql.py +7 -7
  38. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/METADATA +5 -17
  39. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/RECORD +45 -44
  40. meerschaum-3.0.0rc2.dist-info/licenses/NOTICE +2 -0
  41. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/WHEEL +0 -0
  42. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/entry_points.txt +0 -0
  43. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/licenses/LICENSE +0 -0
  44. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/top_level.txt +0 -0
  45. {meerschaum-3.0.0rc1.dist-info → meerschaum-3.0.0rc2.dist-info}/zip-safe +0 -0
@@ -8,6 +8,8 @@ Utility functions for working with SQL data types.
8
8
 
9
9
  from __future__ import annotations
10
10
  from meerschaum.utils.typing import Dict, Union, Tuple, Optional
11
+ from meerschaum._internal.static import STATIC_CONFIG as _STATIC_CONFIG
12
+ from meerschaum.utils.dtypes import MRSM_PRECISION_UNITS_ABBREVIATIONS as _MRSM_PRECISION_UNITS_ABBREVIATIONS
11
13
 
12
14
  NUMERIC_PRECISION_FLAVORS: Dict[str, Tuple[int, int]] = {
13
15
  'mariadb': (38, 20),
@@ -67,6 +69,9 @@ for _flavor, (_precision, _scale) in NUMERIC_PRECISION_FLAVORS.items():
67
69
  'DECIMAL': f"DECIMAL({_precision}, {_scale})",
68
70
  })
69
71
 
72
+ _default_precision_unit = _STATIC_CONFIG['dtypes']['datetime']['default_precision_unit']
73
+ _default_precision_abbreviation = _MRSM_PRECISION_UNITS_ABBREVIATIONS[_default_precision_unit]
74
+
70
75
  DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
71
76
  'FLOAT': 'float64[pyarrow]',
72
77
  'REAL': 'float64[pyarrow]',
@@ -80,15 +85,21 @@ DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
80
85
  'NUMERIC': 'numeric',
81
86
  'GEOMETRY': 'geometry',
82
87
  'GEOMETRY(GEOMETRY)': 'geometry',
83
- 'TIMESTAMP': 'datetime64[ns]',
84
- 'TIMESTAMP WITHOUT TIMEZONE': 'datetime64[ns]',
85
- 'TIMESTAMP WITH TIMEZONE': 'datetime64[ns, UTC]',
86
- 'TIMESTAMP WITH TIME ZONE': 'datetime64[ns, UTC]',
87
- 'TIMESTAMPTZ': 'datetime64[ns, UTC]',
88
- 'DATE': 'datetime64[ns]',
89
- 'DATETIME': 'datetime64[ns]',
90
- 'DATETIME2': 'datetime64[ns]',
91
- 'DATETIMEOFFSET': 'datetime64[ns, UTC]',
88
+ 'TIMESTAMP': f'datetime64[{_default_precision_abbreviation}]',
89
+ 'TIMESTAMP WITHOUT TIMEZONE': f'datetime64[{_default_precision_abbreviation}]',
90
+ 'TIMESTAMP WITH TIMEZONE': f'datetime64[{_default_precision_abbreviation}, UTC]',
91
+ 'TIMESTAMP WITH TIME ZONE': f'datetime64[{_default_precision_abbreviation}, UTC]',
92
+ 'TIMESTAMPTZ': f'datetime64[{_default_precision_abbreviation}, UTC]',
93
+ 'DATE': 'date',
94
+ 'DATETIME': f'datetime64[{_default_precision_abbreviation}]',
95
+ 'DATETIME2': 'datetime64[us]',
96
+ 'DATETIME2(6)': 'datetime64[us]',
97
+ 'DATETIME2(3)': 'datetime64[ms]',
98
+ 'DATETIME2(0)': 'datetime64[s]',
99
+ 'DATETIMEOFFSET': 'datetime64[us, UTC]',
100
+ 'DATETIMEOFFSET(6)': 'datetime64[us, UTC]',
101
+ 'DATETIMEOFFSET(3)': 'datetime64[ms, UTC]',
102
+ 'DATETIMEOFFSET(0)': 'datetime64[s, UTC]',
92
103
  'TEXT': 'string[pyarrow]',
93
104
  'VARCHAR': 'string[pyarrow]',
94
105
  'CLOB': 'string[pyarrow]',
@@ -109,9 +120,9 @@ DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
109
120
  'VARBINARY(MAX)': 'bytes',
110
121
  'substrings': {
111
122
  'CHAR': 'string[pyarrow]',
112
- 'TIMESTAMP': 'datetime64[ns]',
113
- 'TIME': 'datetime64[ns]',
114
- 'DATE': 'datetime64[ns]',
123
+ 'TIMESTAMP': f'datetime64[{_default_precision_abbreviation}]',
124
+ 'TIME': f'datetime64[{_default_precision_abbreviation}]',
125
+ 'DATE': 'date',
115
126
  'DOUBLE': 'double[pyarrow]',
116
127
  'DECIMAL': 'numeric',
117
128
  'NUMERIC': 'numeric',
@@ -265,35 +276,125 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
265
276
  'default': 'DOUBLE',
266
277
  },
267
278
  'datetime64[ns]': {
268
- 'timescaledb': 'TIMESTAMP',
269
- 'timescaledb-ha': 'TIMESTAMP',
270
- 'postgresql': 'TIMESTAMP',
271
- 'postgis': 'TIMESTAMP',
279
+ 'timescaledb': 'TIMESTAMP(6)',
280
+ 'timescaledb-ha': 'TIMESTAMP(6)',
281
+ 'postgresql': 'TIMESTAMP(6)',
282
+ 'postgis': 'TIMESTAMP(6)',
272
283
  'mariadb': 'DATETIME',
273
284
  'mysql': 'DATETIME',
274
- 'mssql': 'DATETIME2',
285
+ 'mssql': 'DATETIME2(7)',
275
286
  'oracle': 'TIMESTAMP(9)',
276
287
  'sqlite': 'DATETIME',
277
- 'duckdb': 'TIMESTAMP',
278
- 'citus': 'TIMESTAMP',
279
- 'cockroachdb': 'TIMESTAMP',
288
+ 'duckdb': 'TIMESTAMP(6)',
289
+ 'citus': 'TIMESTAMP(6)',
290
+ 'cockroachdb': 'TIMESTAMP(6)',
280
291
  'default': 'DATETIME',
281
292
  },
282
293
  'datetime64[ns, UTC]': {
283
- 'timescaledb': 'TIMESTAMPTZ',
284
- 'timescaledb-ha': 'TIMESTAMPTZ',
285
- 'postgresql': 'TIMESTAMPTZ',
286
- 'postgis': 'TIMESTAMPTZ',
294
+ 'timescaledb': 'TIMESTAMPTZ(6)',
295
+ 'timescaledb-ha': 'TIMESTAMPTZ(6)',
296
+ 'postgresql': 'TIMESTAMPTZ(9)',
297
+ 'postgis': 'TIMESTAMPTZ(6)',
287
298
  'mariadb': 'DATETIME',
288
299
  'mysql': 'DATETIME',
289
- 'mssql': 'DATETIMEOFFSET',
290
- 'oracle': 'TIMESTAMP(9)',
300
+ 'mssql': 'DATETIMEOFFSET(7)',
301
+ 'oracle': 'TIMESTAMP(9) WITH TIME ZONE',
291
302
  'sqlite': 'TIMESTAMP',
292
303
  'duckdb': 'TIMESTAMPTZ',
293
- 'citus': 'TIMESTAMPTZ',
294
- 'cockroachdb': 'TIMESTAMPTZ',
304
+ 'citus': 'TIMESTAMPTZ(6)',
305
+ 'cockroachdb': 'TIMESTAMPTZ(6)',
306
+ 'default': 'TIMESTAMPTZ',
307
+ },
308
+ 'datetime64[us]': {
309
+ 'timescaledb': 'TIMESTAMP(6)',
310
+ 'timescaledb-ha': 'TIMESTAMP(6)',
311
+ 'postgresql': 'TIMESTAMP(6)',
312
+ 'postgis': 'TIMESTAMP(6)',
313
+ 'mariadb': 'DATETIME',
314
+ 'mysql': 'DATETIME',
315
+ 'mssql': 'DATETIME2(6)',
316
+ 'oracle': 'TIMESTAMP(6)',
317
+ 'sqlite': 'DATETIME',
318
+ 'duckdb': 'TIMESTAMP(6)',
319
+ 'citus': 'TIMESTAMP(6)',
320
+ 'cockroachdb': 'TIMESTAMP',
321
+ 'default': 'DATETIME',
322
+ },
323
+ 'datetime64[us, UTC]': {
324
+ 'timescaledb': 'TIMESTAMPTZ(6)',
325
+ 'timescaledb-ha': 'TIMESTAMPTZ(6)',
326
+ 'postgresql': 'TIMESTAMPTZ(6)',
327
+ 'postgis': 'TIMESTAMPTZ(6)',
328
+ 'mariadb': 'DATETIME',
329
+ 'mysql': 'DATETIME',
330
+ 'mssql': 'DATETIMEOFFSET(6)',
331
+ 'oracle': 'TIMESTAMP(6) WITH TIME ZONE',
332
+ 'sqlite': 'TIMESTAMP',
333
+ 'duckdb': 'TIMESTAMPTZ',
334
+ 'citus': 'TIMESTAMPTZ(6)',
335
+ 'cockroachdb': 'TIMESTAMPTZ(6)',
295
336
  'default': 'TIMESTAMPTZ',
296
337
  },
338
+ 'datetime64[ms]': {
339
+ 'timescaledb': 'TIMESTAMP(3)',
340
+ 'timescaledb-ha': 'TIMESTAMP(3)',
341
+ 'postgresql': 'TIMESTAMP(3)',
342
+ 'postgis': 'TIMESTAMP(3)',
343
+ 'mariadb': 'DATETIME',
344
+ 'mysql': 'DATETIME',
345
+ 'mssql': 'DATETIME2(3)',
346
+ 'oracle': 'TIMESTAMP(3)',
347
+ 'sqlite': 'DATETIME',
348
+ 'duckdb': 'TIMESTAMP(3)',
349
+ 'citus': 'TIMESTAMP(3)',
350
+ 'cockroachdb': 'TIMESTAMP(3)',
351
+ 'default': 'DATETIME',
352
+ },
353
+ 'datetime64[ms, UTC]': {
354
+ 'timescaledb': 'TIMESTAMPTZ(3)',
355
+ 'timescaledb-ha': 'TIMESTAMPTZ(3)',
356
+ 'postgresql': 'TIMESTAMPTZ(3)',
357
+ 'postgis': 'TIMESTAMPTZ(3)',
358
+ 'mariadb': 'DATETIME',
359
+ 'mysql': 'DATETIME',
360
+ 'mssql': 'DATETIMEOFFSET(3)',
361
+ 'oracle': 'TIMESTAMP(3) WITH TIME ZONE',
362
+ 'sqlite': 'TIMESTAMP',
363
+ 'duckdb': 'TIMESTAMPTZ',
364
+ 'citus': 'TIMESTAMPTZ(3)',
365
+ 'cockroachdb': 'TIMESTAMPTZ(3)',
366
+ 'default': 'TIMESTAMPTZ',
367
+ },
368
+ 'datetime64[s]': {
369
+ 'timescaledb': 'TIMESTAMP(0)',
370
+ 'timescaledb-ha': 'TIMESTAMP(0)',
371
+ 'postgresql': 'TIMESTAMP(0)',
372
+ 'postgis': 'TIMESTAMP(0)',
373
+ 'mariadb': 'DATETIME',
374
+ 'mysql': 'DATETIME',
375
+ 'mssql': 'DATETIME2(0)',
376
+ 'oracle': 'TIMESTAMP(0)',
377
+ 'sqlite': 'DATETIME',
378
+ 'duckdb': 'TIMESTAMP(0)',
379
+ 'citus': 'TIMESTAMP(0)',
380
+ 'cockroachdb': 'TIMESTAMP(0)',
381
+ 'default': 'DATETIME',
382
+ },
383
+ 'datetime64[s, UTC]': {
384
+ 'timescaledb': 'TIMESTAMPTZ(0)',
385
+ 'timescaledb-ha': 'TIMESTAMPTZ(0)',
386
+ 'postgresql': 'TIMESTAMPTZ(0)',
387
+ 'postgis': 'TIMESTAMPTZ(0)',
388
+ 'mariadb': 'DATETIME',
389
+ 'mysql': 'DATETIME',
390
+ 'mssql': 'DATETIMEOFFSET(0)',
391
+ 'oracle': 'TIMESTAMP(0) WITH TIME ZONE',
392
+ 'sqlite': 'TIMESTAMP',
393
+ 'duckdb': 'TIMESTAMPTZ',
394
+ 'citus': 'TIMESTAMPTZ(0)',
395
+ 'cockroachdb': 'TIMESTAMPTZ(0)',
396
+ 'default': 'TIMESTAMPTZ(0)',
397
+ },
297
398
  'datetime': {
298
399
  'timescaledb': 'TIMESTAMPTZ',
299
400
  'timescaledb-ha': 'TIMESTAMPTZ',
@@ -302,7 +403,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
302
403
  'mariadb': 'DATETIME',
303
404
  'mysql': 'DATETIME',
304
405
  'mssql': 'DATETIMEOFFSET',
305
- 'oracle': 'TIMESTAMP(9)',
406
+ 'oracle': 'TIMESTAMP WITH TIME ZONE',
306
407
  'sqlite': 'TIMESTAMP',
307
408
  'duckdb': 'TIMESTAMPTZ',
308
409
  'citus': 'TIMESTAMPTZ',
@@ -317,13 +418,28 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
317
418
  'mariadb': 'DATETIME',
318
419
  'mysql': 'DATETIME',
319
420
  'mssql': 'DATETIMEOFFSET',
320
- 'oracle': 'TIMESTAMP(9)',
421
+ 'oracle': 'TIMESTAMP WITH TIME ZONE',
321
422
  'sqlite': 'TIMESTAMP',
322
423
  'duckdb': 'TIMESTAMPTZ',
323
424
  'citus': 'TIMESTAMPTZ',
324
425
  'cockroachdb': 'TIMESTAMPTZ',
325
426
  'default': 'TIMESTAMPTZ',
326
427
  },
428
+ 'date': {
429
+ 'timescaledb': 'DATE',
430
+ 'timescaledb-ha': 'DATE',
431
+ 'postgresql': 'DATE',
432
+ 'postgis': 'DATE',
433
+ 'mariadb': 'DATE',
434
+ 'mysql': 'DATE',
435
+ 'mssql': 'DATE',
436
+ 'oracle': 'DATE',
437
+ 'sqlite': 'DATE',
438
+ 'duckdb': 'DATE',
439
+ 'citus': 'DATE',
440
+ 'cockroachdb': 'DATE',
441
+ 'default': 'DATE',
442
+ },
327
443
  'bool': {
328
444
  'timescaledb': 'BOOLEAN',
329
445
  'timescaledb-ha': 'BOOLEAN',
@@ -339,6 +455,36 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
339
455
  'cockroachdb': 'BOOLEAN',
340
456
  'default': 'BOOLEAN',
341
457
  },
458
+ 'bool[pyarrow]': {
459
+ 'timescaledb': 'BOOLEAN',
460
+ 'timescaledb-ha': 'BOOLEAN',
461
+ 'postgresql': 'BOOLEAN',
462
+ 'postgis': 'BOOLEAN',
463
+ 'mariadb': 'BOOLEAN',
464
+ 'mysql': 'BOOLEAN',
465
+ 'mssql': 'BIT',
466
+ 'oracle': 'INTEGER',
467
+ 'sqlite': 'FLOAT',
468
+ 'duckdb': 'BOOLEAN',
469
+ 'citus': 'BOOLEAN',
470
+ 'cockroachdb': 'BOOLEAN',
471
+ 'default': 'BOOLEAN',
472
+ },
473
+ 'boolean': {
474
+ 'timescaledb': 'BOOLEAN',
475
+ 'timescaledb-ha': 'BOOLEAN',
476
+ 'postgresql': 'BOOLEAN',
477
+ 'postgis': 'BOOLEAN',
478
+ 'mariadb': 'BOOLEAN',
479
+ 'mysql': 'BOOLEAN',
480
+ 'mssql': 'BIT',
481
+ 'oracle': 'INTEGER',
482
+ 'sqlite': 'FLOAT',
483
+ 'duckdb': 'BOOLEAN',
484
+ 'citus': 'BOOLEAN',
485
+ 'cockroachdb': 'BOOLEAN',
486
+ 'default': 'BOOLEAN',
487
+ },
342
488
  'object': {
343
489
  'timescaledb': 'TEXT',
344
490
  'timescaledb-ha': 'TEXT',
@@ -642,6 +788,111 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
642
788
  'cockroachdb': 'DateTime(timezone=True)',
643
789
  'default': 'DateTime(timezone=True)',
644
790
  },
791
+ 'datetime64[us]': {
792
+ 'timescaledb': 'DateTime',
793
+ 'timescaledb-ha': 'DateTime',
794
+ 'postgresql': 'DateTime',
795
+ 'postgis': 'DateTime',
796
+ 'mariadb': 'DateTime',
797
+ 'mysql': 'DateTime',
798
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIME2',
799
+ 'oracle': 'DateTime',
800
+ 'sqlite': 'DateTime',
801
+ 'duckdb': 'DateTime',
802
+ 'citus': 'DateTime',
803
+ 'cockroachdb': 'DateTime',
804
+ 'default': 'DateTime',
805
+ },
806
+ 'datetime64[us, UTC]': {
807
+ 'timescaledb': 'DateTime(timezone=True)',
808
+ 'timescaledb-ha': 'DateTime(timezone=True)',
809
+ 'postgresql': 'DateTime(timezone=True)',
810
+ 'postgis': 'DateTime(timezone=True)',
811
+ 'mariadb': 'DateTime(timezone=True)',
812
+ 'mysql': 'DateTime(timezone=True)',
813
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
814
+ 'oracle': 'sqlalchemy.dialects.oracle.TIMESTAMP(timezone=True)',
815
+ 'sqlite': 'DateTime(timezone=True)',
816
+ 'duckdb': 'DateTime(timezone=True)',
817
+ 'citus': 'DateTime(timezone=True)',
818
+ 'cockroachdb': 'DateTime(timezone=True)',
819
+ 'default': 'DateTime(timezone=True)',
820
+ },
821
+ 'datetime64[ms]': {
822
+ 'timescaledb': 'DateTime',
823
+ 'timescaledb-ha': 'DateTime',
824
+ 'postgresql': 'DateTime',
825
+ 'postgis': 'DateTime',
826
+ 'mariadb': 'DateTime',
827
+ 'mysql': 'DateTime',
828
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIME2',
829
+ 'oracle': 'DateTime',
830
+ 'sqlite': 'DateTime',
831
+ 'duckdb': 'DateTime',
832
+ 'citus': 'DateTime',
833
+ 'cockroachdb': 'DateTime',
834
+ 'default': 'DateTime',
835
+ },
836
+ 'datetime64[ms, UTC]': {
837
+ 'timescaledb': 'DateTime(timezone=True)',
838
+ 'timescaledb-ha': 'DateTime(timezone=True)',
839
+ 'postgresql': 'DateTime(timezone=True)',
840
+ 'postgis': 'DateTime(timezone=True)',
841
+ 'mariadb': 'DateTime(timezone=True)',
842
+ 'mysql': 'DateTime(timezone=True)',
843
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
844
+ 'oracle': 'sqlalchemy.dialects.oracle.TIMESTAMP(timezone=True)',
845
+ 'sqlite': 'DateTime(timezone=True)',
846
+ 'duckdb': 'DateTime(timezone=True)',
847
+ 'citus': 'DateTime(timezone=True)',
848
+ 'cockroachdb': 'DateTime(timezone=True)',
849
+ 'default': 'DateTime(timezone=True)',
850
+ },
851
+ 'datetime64[s]': {
852
+ 'timescaledb': 'DateTime',
853
+ 'timescaledb-ha': 'DateTime',
854
+ 'postgresql': 'DateTime',
855
+ 'postgis': 'DateTime',
856
+ 'mariadb': 'DateTime',
857
+ 'mysql': 'DateTime',
858
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIME2',
859
+ 'oracle': 'DateTime',
860
+ 'sqlite': 'DateTime',
861
+ 'duckdb': 'DateTime',
862
+ 'citus': 'DateTime',
863
+ 'cockroachdb': 'DateTime',
864
+ 'default': 'DateTime',
865
+ },
866
+ 'datetime64[s, UTC]': {
867
+ 'timescaledb': 'DateTime(timezone=True)',
868
+ 'timescaledb-ha': 'DateTime(timezone=True)',
869
+ 'postgresql': 'DateTime(timezone=True)',
870
+ 'postgis': 'DateTime(timezone=True)',
871
+ 'mariadb': 'DateTime(timezone=True)',
872
+ 'mysql': 'DateTime(timezone=True)',
873
+ 'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
874
+ 'oracle': 'sqlalchemy.dialects.oracle.TIMESTAMP(timezone=True)',
875
+ 'sqlite': 'DateTime(timezone=True)',
876
+ 'duckdb': 'DateTime(timezone=True)',
877
+ 'citus': 'DateTime(timezone=True)',
878
+ 'cockroachdb': 'DateTime(timezone=True)',
879
+ 'default': 'DateTime(timezone=True)',
880
+ },
881
+ 'date': {
882
+ 'timescaledb': 'Date',
883
+ 'timescaledb-ha': 'Date',
884
+ 'postgresql': 'Date',
885
+ 'postgis': 'Date',
886
+ 'mariadb': 'Date',
887
+ 'mysql': 'Date',
888
+ 'mssql': 'Date',
889
+ 'oracle': 'Date',
890
+ 'sqlite': 'Date',
891
+ 'duckdb': 'Date',
892
+ 'citus': 'Date',
893
+ 'cockroachdb': 'Date',
894
+ 'default': 'Date',
895
+ },
645
896
  'bool': {
646
897
  'timescaledb': 'Boolean',
647
898
  'timescaledb-ha': 'Boolean',
@@ -657,6 +908,36 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
657
908
  'cockroachdb': 'Boolean',
658
909
  'default': 'Boolean',
659
910
  },
911
+ 'bool[pyarrow]': {
912
+ 'timescaledb': 'Boolean',
913
+ 'timescaledb-ha': 'Boolean',
914
+ 'postgresql': 'Boolean',
915
+ 'postgis': 'Boolean',
916
+ 'mariadb': 'Integer',
917
+ 'mysql': 'Integer',
918
+ 'mssql': 'sqlalchemy.dialects.mssql.BIT',
919
+ 'oracle': 'Integer',
920
+ 'sqlite': 'Float',
921
+ 'duckdb': 'Boolean',
922
+ 'citus': 'Boolean',
923
+ 'cockroachdb': 'Boolean',
924
+ 'default': 'Boolean',
925
+ },
926
+ 'boolean': {
927
+ 'timescaledb': 'Boolean',
928
+ 'timescaledb-ha': 'Boolean',
929
+ 'postgresql': 'Boolean',
930
+ 'postgis': 'Boolean',
931
+ 'mariadb': 'Integer',
932
+ 'mysql': 'Integer',
933
+ 'mssql': 'sqlalchemy.dialects.mssql.BIT',
934
+ 'oracle': 'Integer',
935
+ 'sqlite': 'Float',
936
+ 'duckdb': 'Boolean',
937
+ 'citus': 'Boolean',
938
+ 'cockroachdb': 'Boolean',
939
+ 'default': 'Boolean',
940
+ },
660
941
  'object': {
661
942
  'timescaledb': 'UnicodeText',
662
943
  'timescaledb-ha': 'UnicodeText',
@@ -732,6 +1013,21 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
732
1013
  'cockroachdb': 'Uuid',
733
1014
  'default': 'Uuid',
734
1015
  },
1016
+ 'binary[pyarrow]': {
1017
+ 'timescaledb': 'LargeBinary',
1018
+ 'timescaledb-ha': 'LargeBinary',
1019
+ 'postgresql': 'LargeBinary',
1020
+ 'postgis': 'LargeBinary',
1021
+ 'mariadb': 'LargeBinary',
1022
+ 'mysql': 'LargeBinary',
1023
+ 'mssql': 'LargeBinary',
1024
+ 'oracle': 'LargeBinary',
1025
+ 'sqlite': 'LargeBinary',
1026
+ 'duckdb': 'LargeBinary',
1027
+ 'citus': 'LargeBinary',
1028
+ 'cockroachdb': 'LargeBinary',
1029
+ 'default': 'LargeBinary',
1030
+ },
735
1031
  'bytes': {
736
1032
  'timescaledb': 'LargeBinary',
737
1033
  'timescaledb-ha': 'LargeBinary',
meerschaum/utils/misc.py CHANGED
@@ -479,74 +479,6 @@ def flatten_pipes_dict(pipes_dict: PipesDict) -> List[Pipe]:
479
479
  return pipes_list
480
480
 
481
481
 
482
- def round_time(
483
- dt: Optional[datetime] = None,
484
- date_delta: Optional[timedelta] = None,
485
- to: 'str' = 'down'
486
- ) -> datetime:
487
- """
488
- Round a datetime object to a multiple of a timedelta.
489
- http://stackoverflow.com/questions/3463930/how-to-round-the-minute-of-a-datetime-object-python
490
-
491
- NOTE: This function strips timezone information!
492
-
493
- Parameters
494
- ----------
495
- dt: Optional[datetime], default None
496
- If `None`, grab the current UTC datetime.
497
-
498
- date_delta: Optional[timedelta], default None
499
- If `None`, use a delta of 1 minute.
500
-
501
- to: 'str', default 'down'
502
- Available options are `'up'`, `'down'`, and `'closest'`.
503
-
504
- Returns
505
- -------
506
- A rounded `datetime` object.
507
-
508
- Examples
509
- --------
510
- >>> round_time(datetime(2022, 1, 1, 12, 15, 57, 200))
511
- datetime.datetime(2022, 1, 1, 12, 15)
512
- >>> round_time(datetime(2022, 1, 1, 12, 15, 57, 200), to='up')
513
- datetime.datetime(2022, 1, 1, 12, 16)
514
- >>> round_time(datetime(2022, 1, 1, 12, 15, 57, 200), timedelta(hours=1))
515
- datetime.datetime(2022, 1, 1, 12, 0)
516
- >>> round_time(
517
- ... datetime(2022, 1, 1, 12, 15, 57, 200),
518
- ... timedelta(hours=1),
519
- ... to = 'closest'
520
- ... )
521
- datetime.datetime(2022, 1, 1, 12, 0)
522
- >>> round_time(
523
- ... datetime(2022, 1, 1, 12, 45, 57, 200),
524
- ... datetime.timedelta(hours=1),
525
- ... to = 'closest'
526
- ... )
527
- datetime.datetime(2022, 1, 1, 13, 0)
528
-
529
- """
530
- if date_delta is None:
531
- date_delta = timedelta(minutes=1)
532
- round_to = date_delta.total_seconds()
533
- if dt is None:
534
- dt = datetime.now(timezone.utc).replace(tzinfo=None)
535
- seconds = (dt.replace(tzinfo=None) - dt.min.replace(tzinfo=None)).seconds
536
-
537
- if seconds % round_to == 0 and dt.microsecond == 0:
538
- rounding = (seconds + round_to / 2) // round_to * round_to
539
- else:
540
- if to == 'up':
541
- rounding = (seconds + dt.microsecond/1000000 + round_to) // round_to * round_to
542
- elif to == 'down':
543
- rounding = seconds // round_to * round_to
544
- else:
545
- rounding = (seconds + round_to / 2) // round_to * round_to
546
-
547
- return dt + timedelta(0, rounding - seconds, - dt.microsecond)
548
-
549
-
550
482
  def timed_input(
551
483
  seconds: int = 10,
552
484
  timeout_message: str = "",
@@ -1912,6 +1844,15 @@ def replace_pipes_in_dict(*args, **kwargs):
1912
1844
  return replace_pipes_in_dict(*args, **kwargs)
1913
1845
 
1914
1846
 
1847
+ def round_time(*args, **kwargs):
1848
+ """
1849
+ Placeholder function to prevent breaking legacy behavior.
1850
+ See `meerschaum.utils.dtypes.round_time`.
1851
+ """
1852
+ from meerschaum.utils.dtypes import round_time
1853
+ return round_time(*args, **kwargs)
1854
+
1855
+
1915
1856
  _current_module = sys.modules[__name__]
1916
1857
  __all__ = tuple(
1917
1858
  name
@@ -75,7 +75,9 @@ def get_module_path(
75
75
 
76
76
  venv_target_candidate_paths = [vtp]
77
77
  if venv is None:
78
- site_user_packages_dirs = [pathlib.Path(site.getusersitepackages())]
78
+ site_user_packages_dirs = [
79
+ pathlib.Path(site.getusersitepackages())
80
+ ] if not inside_venv() else []
79
81
  site_packages_dirs = [pathlib.Path(path) for path in site.getsitepackages()]
80
82
 
81
83
  paths_to_add = [
@@ -1770,6 +1772,10 @@ def is_installed(
1770
1772
  allow_outside_venv: bool, default True
1771
1773
  If `True`, search outside of the specified virtual environment
1772
1774
  if the package cannot be found.
1775
+
1776
+ Returns
1777
+ -------
1778
+ A bool indicating whether a package may be imported.
1773
1779
  """
1774
1780
  if debug:
1775
1781
  from meerschaum.utils.debug import dprint
@@ -1861,26 +1867,6 @@ def ensure_readline() -> 'ModuleType':
1861
1867
  sys.modules['readline'] = readline
1862
1868
  return readline
1863
1869
 
1864
- _pkg_resources_get_distribution = None
1865
- _custom_distributions = {}
1866
- def _monkey_patch_get_distribution(_dist: str, _version: str) -> None:
1867
- """
1868
- Monkey patch `pkg_resources.get_distribution` to allow for importing `flask_compress`.
1869
- """
1870
- import pkg_resources
1871
- from collections import namedtuple
1872
- global _pkg_resources_get_distribution
1873
- with _locks['_pkg_resources_get_distribution']:
1874
- _pkg_resources_get_distribution = pkg_resources.get_distribution
1875
- _custom_distributions[_dist] = _version
1876
- _Dist = namedtuple('_Dist', ['version'])
1877
- def _get_distribution(dist):
1878
- """Hack for flask-compress."""
1879
- if dist in _custom_distributions:
1880
- return _Dist(_custom_distributions[dist])
1881
- return _pkg_resources_get_distribution(dist)
1882
- pkg_resources.get_distribution = _get_distribution
1883
-
1884
1870
 
1885
1871
  def _get_pip_os_env(color: bool = True):
1886
1872
  """
@@ -13,8 +13,7 @@ packages dictionary is structured in the following schema:
13
13
  }
14
14
  """
15
15
 
16
- from __future__ import annotations
17
- from meerschaum.utils.typing import Dict
16
+ from typing import Dict
18
17
 
19
18
  _MRSM_PACKAGE_ARCHIVES_PREFIX: str = "https://meerschaum.io/files/archives/wheels/"
20
19
 
@@ -218,3 +217,9 @@ for group, import_names in packages.items():
218
217
  for import_name, install_name in import_names.items():
219
218
  _full[import_name] = install_name
220
219
  packages['full'] = _full
220
+
221
+ extras = {
222
+ group: list(import_names_install_names_map.values())
223
+ for group, import_names_install_names_map in packages.items()
224
+ if not group.startswith('_')
225
+ }
@@ -293,7 +293,7 @@ def parse_start_time(schedule: str, now: Optional[datetime] = None) -> datetime:
293
293
  >>> parse_start_time('hourly starting 00:30')
294
294
  datetime.datetime(2024, 5, 13, 0, 30, tzinfo=datetime.timezone.utc)
295
295
  """
296
- from meerschaum.utils.misc import round_time
296
+ from meerschaum.utils.dtypes import round_time
297
297
  dateutil_parser = mrsm.attempt_import('dateutil.parser')
298
298
  starting_parts = schedule.split(STARTING_KEYWORD)
299
299
  starting_str = ('now' if len(starting_parts) == 1 else starting_parts[-1]).strip()
meerschaum/utils/sql.py CHANGED
@@ -259,7 +259,7 @@ columns_types_queries = {
259
259
  DATA_TYPE AS [type],
260
260
  NUMERIC_PRECISION AS [numeric_precision],
261
261
  NUMERIC_SCALE AS [numeric_scale]
262
- FROM {db_prefix}INFORMATION_SCHEMA.COLUMNS
262
+ FROM {db_prefix}INFORMATION_SCHEMA.COLUMNS WITH (NOLOCK)
263
263
  WHERE TABLE_NAME IN (
264
264
  '{table}',
265
265
  '{table_trunc}'
@@ -404,18 +404,18 @@ columns_indices_queries = {
404
404
  ELSE CAST(0 AS BIT)
405
405
  END AS [clustered]
406
406
  FROM
407
- sys.schemas s
408
- INNER JOIN sys.tables t
407
+ sys.schemas s WITH (NOLOCK)
408
+ INNER JOIN sys.tables t WITH (NOLOCK)
409
409
  ON s.schema_id = t.schema_id
410
- INNER JOIN sys.indexes i
410
+ INNER JOIN sys.indexes i WITH (NOLOCK)
411
411
  ON t.object_id = i.object_id
412
- INNER JOIN sys.index_columns ic
412
+ INNER JOIN sys.index_columns ic WITH (NOLOCK)
413
413
  ON i.object_id = ic.object_id
414
414
  AND i.index_id = ic.index_id
415
- INNER JOIN sys.columns c
415
+ INNER JOIN sys.columns c WITH (NOLOCK)
416
416
  ON ic.object_id = c.object_id
417
417
  AND ic.column_id = c.column_id
418
- LEFT JOIN sys.key_constraints kc
418
+ LEFT JOIN sys.key_constraints kc WITH (NOLOCK)
419
419
  ON kc.parent_object_id = i.object_id
420
420
  AND kc.type = 'PK'
421
421
  AND kc.name = i.name