Coverage for cc_modules/cc_all_models.py: 100%

48 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-08 23:14 +0000

1#!/usr/bin/env python 

2 

3""" 

4camcops_server/cc_modules/cc_all_models.py 

5 

6=============================================================================== 

7 

8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry. 

9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk). 

10 

11 This file is part of CamCOPS. 

12 

13 CamCOPS is free software: you can redistribute it and/or modify 

14 it under the terms of the GNU General Public License as published by 

15 the Free Software Foundation, either version 3 of the License, or 

16 (at your option) any later version. 

17 

18 CamCOPS is distributed in the hope that it will be useful, 

19 but WITHOUT ANY WARRANTY; without even the implied warranty of 

20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

21 GNU General Public License for more details. 

22 

23 You should have received a copy of the GNU General Public License 

24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>. 

25 

26=============================================================================== 

27 

28**The point of this is to import everything that's an SQLAlchemy model, so 

29they're registered (and also Task knows about all its subclasses).** 

30 

31""" 

32 

33# ============================================================================= 

34# Imports 

35# ============================================================================= 

36 

37# ----------------------------------------------------------------------------- 

38# Simple 

39# ----------------------------------------------------------------------------- 

40 

41import logging 

42from typing import Dict, List, Type 

43 

44from cardinal_pythonlib.logs import BraceStyleAdapter 

45from cardinal_pythonlib.sqlalchemy.orm_inspect import gen_orm_classes_from_base 

46from sqlalchemy.orm import configure_mappers 

47from sqlalchemy.sql.schema import Table 

48 

49from camcops_server.cc_modules.cc_baseconstants import ALEMBIC_VERSION_TABLE 

50from camcops_server.cc_modules.cc_db import GenericTabletRecordMixin 

51from camcops_server.cc_modules.cc_sqlalchemy import Base 

52 

53# ----------------------------------------------------------------------------- 

54# Non-task model imports representing client-side tables 

55# ----------------------------------------------------------------------------- 

56# How to suppress "Unused import statement"? 

57# https://stackoverflow.com/questions/21139329/false-unused-import-statement-in-pycharm # noqa 

58# http://codeoptimism.com/blog/pycharm-suppress-inspections-list/ 

59 

60# noinspection PyUnresolvedReferences 

61from camcops_server.cc_modules.cc_blob import Blob # noqa: F401 

62 

63# noinspection PyUnresolvedReferences 

64from camcops_server.cc_modules.cc_patientidnum import ( # noqa: F401 

65 PatientIdNum, 

66) 

67 

68# noinspection PyUnresolvedReferences 

69from camcops_server.cc_modules.cc_patient import Patient # noqa: F401 

70 

71# ----------------------------------------------------------------------------- 

72# Other non-task model imports 

73# ----------------------------------------------------------------------------- 

74 

75from camcops_server.cc_modules.cc_audit import AuditEntry 

76from camcops_server.cc_modules.cc_device import Device 

77from camcops_server.cc_modules.cc_dirtytables import DirtyTable 

78from camcops_server.cc_modules.cc_email import Email 

79from camcops_server.cc_modules.cc_group import Group, group_group_table 

80from camcops_server.cc_modules.cc_exportmodels import ( 

81 ExportedTaskEmail, 

82 ExportedTask, 

83 ExportedTaskFileGroup, 

84 ExportedTaskHL7Message, 

85) 

86from camcops_server.cc_modules.cc_exportrecipient import ExportRecipient 

87from camcops_server.cc_modules.cc_idnumdef import IdNumDefinition 

88from camcops_server.cc_modules.cc_membership import UserGroupMembership 

89from camcops_server.cc_modules.cc_session import CamcopsSession 

90from camcops_server.cc_modules.cc_specialnote import SpecialNote 

91from camcops_server.cc_modules.cc_serversettings import ServerSettings 

92 

93# noinspection PyUnresolvedReferences 

94from camcops_server.cc_modules.cc_task import Task 

95from camcops_server.cc_modules.cc_taskfilter import TaskFilter 

96from camcops_server.cc_modules.cc_taskschedule import ( 

97 TaskSchedule, 

98 TaskScheduleItem, 

99) 

100 

101# noinspection PyUnresolvedReferences 

102from camcops_server.cc_modules.cc_taskindex import ( 

103 PatientIdNumIndexEntry, 

104 TaskIndexEntry, 

105) 

106from camcops_server.cc_modules.cc_user import ( 

107 SecurityAccountLockout, 

108 SecurityLoginFailure, 

109 User, 

110) 

111 

112# ----------------------------------------------------------------------------- 

113# Task imports 

114# ----------------------------------------------------------------------------- 

115 

116# import_submodules("..tasks", __package__) 

117# 

118# ... NO LONGER SUFFICIENT as we are using SQLAlchemy relationship clauses that 

119# are EVALUATED and so require the class names to be in the relevant namespace 

120# at the time. So doing something equivalent to "import tasks.phq9" -- which is 

121# what we get from 'import_submodules("..tasks", __package__)' -- isn't enough. 

122# We need something equivalent to "from tasks.phq9 import Phq9". 

123 

124# noinspection PyUnresolvedReferences 

125from camcops_server.tasks import * # see tasks/__init__.py # noqa: F401,F403 

126 

127# ----------------------------------------------------------------------------- 

128# Other report imports 

129# ----------------------------------------------------------------------------- 

130 

131# noinspection PyUnresolvedReferences 

132from camcops_server.cc_modules.cc_taskreports import ( # noqa: F401 

133 TaskCountReport, 

134) 

135 

136# noinspection PyUnresolvedReferences 

137from camcops_server.cc_modules.cc_taskschedulereports import ( # noqa: F401 

138 TaskAssignmentReport, 

139) 

140 

141 

142# ============================================================================= 

143# Logging 

144# ============================================================================= 

145 

146log = BraceStyleAdapter(logging.getLogger(__name__)) 

147 

148# log.debug("Loading cc_all_models") 

149 

150 

151# ============================================================================= 

152# Ensure that anything with an AbstractConcreteBase gets its mappers 

153# registered (i.e. Task). 

154# ============================================================================= 

155 

156configure_mappers() 

157 

158 

159# ============================================================================= 

160# Tables (and fields) that clients can't touch 

161# ============================================================================= 

162 

163RESERVED_TABLE_NAMES = [ 

164 ALEMBIC_VERSION_TABLE, 

165 AuditEntry.__tablename__, 

166 CamcopsSession.__tablename__, 

167 Device.__tablename__, 

168 DirtyTable.__tablename__, 

169 Email.__tablename__, 

170 ExportedTask.__tablename__, 

171 ExportedTaskEmail.__tablename__, 

172 ExportedTaskFileGroup.__tablename__, 

173 ExportedTaskHL7Message.__tablename__, 

174 ExportRecipient.__tablename__, 

175 Group.__tablename__, 

176 group_group_table.name, 

177 IdNumDefinition.__tablename__, 

178 PatientIdNumIndexEntry.__tablename__, 

179 SecurityAccountLockout.__tablename__, 

180 SecurityLoginFailure.__tablename__, 

181 ServerSettings.__tablename__, 

182 SpecialNote.__tablename__, 

183 TaskFilter.__tablename__, 

184 TaskIndexEntry.__tablename__, 

185 TaskSchedule.__tablename__, 

186 TaskScheduleItem.__tablename__, 

187 User.__tablename__, 

188 UserGroupMembership.__tablename__, 

189] 

190 

191 

192# ============================================================================= 

193# Catalogue tables that clients use 

194# ============================================================================= 

195 

196CLIENT_TABLE_MAP = {} # type: Dict[str, Table] 

197NONTASK_CLIENT_TABLENAMES = [] # type: List[str] 

198 

199# Add all tables that clients may upload to (including ancillary tables). 

200for __orm_class in gen_orm_classes_from_base(Base): # type: Type[Base] 

201 # noinspection PyUnresolvedReferences 

202 if issubclass(__orm_class, GenericTabletRecordMixin): 

203 __tablename = __orm_class.__tablename__ 

204 if __tablename not in RESERVED_TABLE_NAMES: 

205 # Additional safety check: no client tables start with "_" and all 

206 # server tables do: 

207 if __tablename.startswith("_"): 

208 pass 

209 # noinspection PyUnresolvedReferences 

210 __table = __orm_class.__table__ # type: Table 

211 CLIENT_TABLE_MAP[__tablename] = __table 

212 if not issubclass(__orm_class, Task): 

213 NONTASK_CLIENT_TABLENAMES.append(__tablename) 

214NONTASK_CLIENT_TABLENAMES.sort() 

215# log.debug("NONTASK_CLIENT_TABLENAMES: {}", NONTASK_CLIENT_TABLENAMES)