macrostrat.database 4.1.1__tar.gz → 4.2.1__tar.gz

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 (18) hide show
  1. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/PKG-INFO +1 -1
  2. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/__init__.py +1 -4
  3. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/query.py +36 -7
  4. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/utils.py +36 -30
  5. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/pyproject.toml +1 -1
  6. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/.DS_Store +0 -0
  7. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/compat.py +0 -0
  8. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/mapper/__init__.py +0 -0
  9. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/mapper/base.py +0 -0
  10. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/mapper/cache.py +0 -0
  11. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/mapper/utils.py +0 -0
  12. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/postgresql.py +0 -0
  13. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/__init__.py +0 -0
  14. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/dump_database.py +0 -0
  15. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/move_tables.py +0 -0
  16. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/restore_database.py +0 -0
  17. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/stream_utils.py +0 -0
  18. {macrostrat_database-4.1.1 → macrostrat_database-4.2.1}/macrostrat/database/transfer/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: macrostrat.database
3
- Version: 4.1.1
3
+ Version: 4.2.1
4
4
  Summary: A SQLAlchemy-based database toolkit.
5
5
  Author: Daven Quinn
6
6
  Author-email: Daven Quinn <dev@davenquinn.com>
@@ -12,9 +12,9 @@ from sqlalchemy.orm import Session, scoped_session, sessionmaker
12
12
  from sqlalchemy.sql.expression import Insert
13
13
 
14
14
  from macrostrat.utils import get_logger
15
-
16
15
  from .mapper import DatabaseMapper
17
16
  from .postgresql import on_conflict, prefix_inserts # noqa
17
+ from .query import run_fixtures, run_query, run_sql, execute # noqa
18
18
  from .utils import ( # noqa
19
19
  create_database,
20
20
  create_engine,
@@ -23,9 +23,6 @@ from .utils import ( # noqa
23
23
  get_dataframe,
24
24
  get_or_create,
25
25
  reflect_table,
26
- run_fixtures,
27
- run_query,
28
- run_sql,
29
26
  )
30
27
 
31
28
  metadata = MetaData()
@@ -10,10 +10,6 @@ from warnings import warn
10
10
 
11
11
  import psycopg2.sql as psql2
12
12
  from click import secho
13
- from macrostrat.database.compat import (
14
- update_legacy_identifier,
15
- )
16
- from macrostrat.utils import get_logger
17
13
  from psycopg.errors import QueryCanceled
18
14
  from psycopg.sql import SQL, Composable, Composed
19
15
  from rich.console import Console
@@ -29,6 +25,11 @@ from sqlalchemy.exc import (
29
25
  from sqlalchemy.sql.elements import TextClause
30
26
  from sqlparse import format, split
31
27
 
28
+ from macrostrat.database.compat import (
29
+ update_legacy_identifier,
30
+ )
31
+ from macrostrat.utils import get_logger
32
+
32
33
  log = get_logger(__name__)
33
34
 
34
35
 
@@ -398,13 +399,15 @@ def _execute_one(
398
399
 
399
400
  if result.label is not None:
400
401
  display_text = result.label
402
+ elif output_mode == OutputMode.NONE:
403
+ display_text = None
401
404
  elif output_mode != OutputMode.ALL:
402
405
  display_text = summarize_statement(str(query))
403
406
  else:
404
407
  display_text = str(query)
405
408
 
406
409
  if result.skip:
407
- if print_skipped:
410
+ if print_skipped and display_text is not None:
408
411
  secho(display_text, dim=True, strikethrough=True, file=output_file)
409
412
  return
410
413
 
@@ -430,7 +433,8 @@ def _execute_one(
430
433
  elif hasattr(connectable, "commit"):
431
434
  connectable.commit()
432
435
 
433
- secho(display_text, dim=True, file=output_file)
436
+ if display_text is not None:
437
+ secho(display_text, dim=True, file=output_file)
434
438
 
435
439
  except Exception as err:
436
440
  if trans is not None:
@@ -439,7 +443,8 @@ def _execute_one(
439
443
  connectable.rollback()
440
444
  if raise_errors or _should_raise_query_error(err):
441
445
  raise err
442
- _print_error(display_text, err, file=output_file)
446
+ if display_text is not None:
447
+ _print_error(display_text, err, file=output_file)
443
448
 
444
449
 
445
450
  def _should_raise_query_error(err):
@@ -595,3 +600,27 @@ def run_sql(*args, **kwargs):
595
600
  if kwargs.pop("yield_results", False):
596
601
  return res
597
602
  return list(res)
603
+
604
+
605
+ def execute(connectable, sql, params=None, stop_on_error=False, **kwargs):
606
+ output_file = kwargs.pop("output_file", None)
607
+ output_mode = kwargs.pop("output_mode", None)
608
+ sql = format(sql, strip_comments=True).strip()
609
+ if sql == "":
610
+ return
611
+ try:
612
+ connectable.begin()
613
+ res = connectable.execute(text(sql), params=params)
614
+ if hasattr(connectable, "commit"):
615
+ connectable.commit()
616
+ pretty_print(sql, dim=True, file=output_file, mode=output_mode)
617
+ return res
618
+ except (ProgrammingError, IntegrityError) as err:
619
+ if hasattr(connectable, "rollback"):
620
+ connectable.rollback()
621
+ _print_error(sql, dim=True, file=output_file, mode=output_mode)
622
+ if stop_on_error:
623
+ return
624
+ finally:
625
+ if hasattr(connectable, "close"):
626
+ connectable.close()
@@ -1,5 +1,7 @@
1
+ import warnings
1
2
  from contextlib import contextmanager
2
3
  from time import sleep
4
+ from uuid import uuid4
3
5
 
4
6
  from click import echo
5
7
  from sqlalchemy import MetaData
@@ -8,19 +10,16 @@ from sqlalchemy import text
8
10
  from sqlalchemy.engine import Engine
9
11
  from sqlalchemy.engine.url import make_url
10
12
  from sqlalchemy.exc import (
11
- IntegrityError,
12
13
  OperationalError,
13
- ProgrammingError,
14
14
  )
15
15
  from sqlalchemy.orm import sessionmaker
16
16
  from sqlalchemy.schema import Table
17
17
  from sqlalchemy.sql.elements import ClauseElement
18
18
  from sqlalchemy_utils import create_database as _create_database
19
19
  from sqlalchemy_utils import database_exists, drop_database
20
- from sqlparse import format
21
20
 
22
21
  from macrostrat.utils import cmd, get_logger
23
- from .query import get_sql_text
22
+ from .query import get_sql_text, execute # noqa
24
23
 
25
24
  log = get_logger(__name__)
26
25
 
@@ -46,30 +45,6 @@ def db_session(engine):
46
45
  return factory()
47
46
 
48
47
 
49
- def execute(connectable, sql, params=None, stop_on_error=False, **kwargs):
50
- output_file = kwargs.pop("output_file", None)
51
- output_mode = kwargs.pop("output_mode", None)
52
- sql = format(sql, strip_comments=True).strip()
53
- if sql == "":
54
- return
55
- try:
56
- connectable.begin()
57
- res = connectable.execute(text(sql), params=params)
58
- if hasattr(connectable, "commit"):
59
- connectable.commit()
60
- pretty_print(sql, dim=True, file=output_file, mode=output_mode)
61
- return res
62
- except (ProgrammingError, IntegrityError) as err:
63
- if hasattr(connectable, "rollback"):
64
- connectable.rollback()
65
- _print_error(sql, dim=True, file=output_file, mode=output_mode)
66
- if stop_on_error:
67
- return
68
- finally:
69
- if hasattr(connectable, "close"):
70
- connectable.close()
71
-
72
-
73
48
  def get_or_create(session, model, defaults=None, **kwargs):
74
49
  """
75
50
  Get an instance of a model, or create it if it doesn't
@@ -97,9 +72,13 @@ def get_db_model(db, model_name: str):
97
72
 
98
73
 
99
74
  @contextmanager
100
- def temp_database(conn_string, drop=True, ensure_empty=False):
75
+ def temporary_database(
76
+ conn_string, *, drop=True, ensure_empty=False, exists_ok=True, template=None
77
+ ):
101
78
  """Create a temporary database and tear it down after tests."""
102
- create_database(conn_string, exists_ok=True, replace=ensure_empty)
79
+ create_database(
80
+ conn_string, exists_ok=exists_ok, replace=ensure_empty, template=template
81
+ )
103
82
  try:
104
83
  engine = create_engine(conn_string)
105
84
  yield engine
@@ -109,6 +88,33 @@ def temp_database(conn_string, drop=True, ensure_empty=False):
109
88
  drop_database(conn_string)
110
89
 
111
90
 
91
+ @contextmanager
92
+ def temp_database(*args, **kwargs):
93
+ warnings.warn(
94
+ "temp_database is deprecated, use temporary_database instead",
95
+ DeprecationWarning,
96
+ )
97
+ with temporary_database(*args, **kwargs) as engine:
98
+ yield engine
99
+
100
+
101
+ @contextmanager
102
+ def template_database(engine: Engine, *, name: str = None):
103
+ """Create a temporary template database using an existing database as a template."""
104
+ db_name = engine.url.database
105
+ template_db_name = name
106
+ if name is None:
107
+ uid = str(uuid4())[:8]
108
+ template_db_name = db_name + "_template_" + uid
109
+ # Close connection to the database so we can create a new one based on the template
110
+ new_db_url = engine.url.set(database=template_db_name)
111
+ engine.dispose()
112
+ with temporary_database(
113
+ new_db_url, drop=True, exists_ok=False, template=db_name
114
+ ) as engine:
115
+ yield engine
116
+
117
+
112
118
  def create_database(url, **kwargs):
113
119
  """Create a database if it doesn't exist.
114
120
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "macrostrat.database"
3
- version = "4.1.1"
3
+ version = "4.2.1"
4
4
  description = "A SQLAlchemy-based database toolkit."
5
5
  authors = [{ name = "Daven Quinn", email = "dev@davenquinn.com" }]
6
6
  requires-python = ">=3.10,<4"