Coverage for cc_modules/cc_dataclasses.py: 62%
32 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-15 14:23 +0100
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-15 14:23 +0100
1"""
2camcops_server/cc_modules/cc_dataclasses.py
4===============================================================================
6 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
7 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
9 This file is part of CamCOPS.
11 CamCOPS is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 CamCOPS is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
24===============================================================================
26**Dataclasses.**
28"""
30from dataclasses import dataclass
31from typing import Dict, TYPE_CHECKING
33if TYPE_CHECKING:
34 from sqlalchemy.sql.schema import Column
35 from camcops_server.cc_modules.cc_summaryelement import SummaryElement
38# =============================================================================
39# SummarySchemaInfo
40# =============================================================================
43@dataclass(eq=True, frozen=True, order=True) # hashable, sortable
44class SummarySchemaInfo:
45 """
46 Information to be given to the user about the schema for spreadsheet-style
47 downloads, including database and summary columns.
48 """
50 # Summary schema values:
51 SSV_DB = "database"
52 SSV_SUMMARY = "summary"
53 VALID_SOURCES = {SSV_DB, SSV_SUMMARY}
55 table_name: str
56 source: str
57 column_name: str
58 data_type: str
59 comment: str
61 def __post_init__(self) -> None:
62 assert (
63 self.source in self.VALID_SOURCES
64 ), f"Bad source: {self.source!r}"
66 @property
67 def as_dict(self) -> Dict[str, str]:
68 """
69 Used to create spreadsheet rows. Maps spreadsheet headings to values.
70 """
71 return {
72 "table_name": self.table_name,
73 "source": self.source,
74 "column_name": self.column_name,
75 "data_type": self.data_type,
76 "comment": self.comment,
77 }
79 @classmethod
80 def from_column(
81 cls,
82 column: "Column",
83 table_name: str = "",
84 source: str = "",
85 column_name_prefix: str = "",
86 ) -> "SummarySchemaInfo":
87 """
88 Create from an SQLAlchemy column.
89 """
90 if not table_name:
91 if column.table is not None:
92 table_name = column.table.name
93 else:
94 raise ValueError(
95 f"table_name not specified and column not "
96 f"attached to a table: {column!r}"
97 )
98 source = source or cls.SSV_DB
99 return cls(
100 table_name=table_name,
101 source=source,
102 column_name=column_name_prefix + column.name,
103 data_type=str(column.type),
104 comment=column.comment,
105 )
107 @classmethod
108 def from_summary_element(
109 cls,
110 table_name: str,
111 element: "SummaryElement",
112 source: str = "",
113 column_name_prefix: str = "",
114 ) -> "SummarySchemaInfo":
115 """
116 Create from a
117 :class:`camcops_server.cc_modules.cc_summaryelement.SummarySchemaInfo`.
118 """
119 source = source or cls.SSV_SUMMARY
120 return cls(
121 table_name=table_name,
122 source=source,
123 column_name=column_name_prefix + element.name,
124 data_type=str(element.coltype),
125 comment=element.decorated_comment,
126 )