Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/cardinal_pythonlib/sqlalchemy/table_identity.py : 41%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2# cardinal_pythonlib/sqlalchemy/table_identity.py
4"""
5===============================================================================
7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com).
9 This file is part of cardinal_pythonlib.
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
15 https://www.apache.org/licenses/LICENSE-2.0
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
23===============================================================================
25**Class to refer to database tables either by name or by SQLAlchemy Table
26object.**
28"""
30from sqlalchemy.sql.schema import MetaData, Table
32from cardinal_pythonlib.logs import get_brace_style_log_with_null_handler
34log = get_brace_style_log_with_null_handler(__name__)
37# =============================================================================
38# TableIdentity
39# =============================================================================
41class TableIdentity(object):
42 """
43 Convenient way of passing around SQLAlchemy :class:`Table` objects when you
44 might know either either its name or the :class:`Table` object itself.
45 """
46 def __init__(self,
47 tablename: str = None,
48 table: Table = None,
49 metadata: MetaData = None) -> None:
50 """
51 Initialize with either ``tablename`` or ``table``, not both.
53 Args:
54 tablename: string name of the table
55 table: SQLAlchemy :class:`Table` object
56 metadata: optional :class:`MetaData` object
57 """
58 assert table is not None or tablename, "No table information provided"
59 assert not (tablename and table is not None), (
60 "Specify either table or tablename, not both")
61 self._table = table
62 self._tablename = tablename
63 self._metadata = metadata
65 def __str__(self) -> str:
66 return self.tablename
68 def __repr__(self) -> str:
69 return (
70 f"TableIdentity(table={self._table!r}, "
71 f"tablename={self._tablename!r}, metadata={self._metadata!r}"
72 )
74 @property
75 def table(self) -> Table:
76 """
77 Returns a SQLAlchemy :class:`Table` object. This is either the
78 :class:`Table` object that was used for initialization, or one that
79 was constructed from the ``tablename`` plus the ``metadata``.
80 """
81 if self._table is not None:
82 return self._table
83 assert self._metadata, (
84 "Must specify metadata (in constructor or via set_metadata()/"
85 "set_metadata_if_none() before you can get a Table from a "
86 "tablename"
87 )
88 for table in self._metadata.tables.values(): # type: Table
89 if table.name == self._tablename:
90 return table
91 raise ValueError(
92 f"No table named {self._tablename!r} is present in the metadata")
94 @property
95 def tablename(self) -> str:
96 """
97 Returns the string name of the table.
98 """
99 if self._tablename:
100 return self._tablename
101 return self.table.name
103 def set_metadata(self, metadata: MetaData) -> None:
104 """
105 Sets the :class:`MetaData`.
106 """
107 self._metadata = metadata
109 def set_metadata_if_none(self, metadata: MetaData) -> None:
110 """
111 Sets the :class:`MetaData` unless it was set already.
112 """
113 if self._metadata is None:
114 self._metadata = metadata