15.3.39. crate_anon.crateweb.research.models¶
Copyright (C) 2015-2018 Rudolf Cardinal (rudolf@pobox.com).
This file is part of CRATE.
CRATE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CRATE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CRATE. If not, see <http://www.gnu.org/licenses/>.
-
class
crate_anon.crateweb.research.models.
Highlight
(*args, **kwargs)[source]¶ Represents the highlighting of a query.
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
exception
-
class
crate_anon.crateweb.research.models.
PatientExplorer
(*args, **kwargs)[source]¶ Class to explore the research database on a per-patient basis.
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
data_finder_excel
¶ Performs a SELECT COUNT(*) Returns (fieldnames, rows).
-
static
get_executed_cursor
(sql: str, args: List[Any] = None) → django.db.backends.utils.CursorWrapper[source]¶ Get cursor with a query executed
-
get_xlsx_binary
() → bytes[source]¶ Other notes:
- cell size: http://stackoverflow.com/questions/13197574/python-openpyxl-column-width-size-adjust … and the “auto_size” / “bestFit” options don’t really do the job, according to the interweb
-
exception
-
class
crate_anon.crateweb.research.models.
PatientExplorerAudit
(*args, **kwargs)[source]¶ Audit log for a PatientExplorer.
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
exception
-
class
crate_anon.crateweb.research.models.
PidLookup
(*args, **kwargs)[source]¶ Lookup class for secret RID-to-PID conversion. Used via one or other of the ‘secret’ database connections. Intended for READ-ONLY access to that table.
Since we have fixed the tablenames for the anonymiser, we remove the settings.SECRET_MAP option. See PatientInfo in crate_anon/anonymise/models.py. Moreover, we fix the maximum length, regardless of the specifics of the config used.
Use as e.g. Lookup(pid=XXX)
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
save
(*args, **kwargs) → None[source]¶ Save the current instance. Override this in a subclass if you want to control the saving process.
The ‘force_insert’ and ‘force_update’ parameters can be used to insist that the “save” must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set.
-
exception
-
class
crate_anon.crateweb.research.models.
Query
(*args, **kwargs)[source]¶ Class to query the research database.
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
get_executed_cursor
(sql_append_raw: str = None) → django.db.backends.utils.CursorWrapper[source]¶ Get cursor with a query executed
-
exception
-
class
crate_anon.crateweb.research.models.
QueryAudit
(*args, **kwargs)[source]¶ Audit log for a query.
-
exception
DoesNotExist
¶
-
exception
MultipleObjectsReturned
¶
-
exception
-
crate_anon.crateweb.research.models.
gen_excel_row_elements
(worksheet: openpyxl.worksheet.worksheet.Worksheet, row: Iterable) → Generator[[Any, NoneType], NoneType][source]¶ Given an Excel worksheet row, generate individual cell contents, cell by cell.
Reasons for this function:
- Need a tuple/list/generator, as openpyxl checks its types manually.
We want to have a Worksheet object from openpyxl, and say something like
ws.append(row)
where “row” has come from a database query.
However, openpyxl doesn’t believe in duck-typing; see
Worksheet.append()
inopenpyxl/worksheet/worksheet.py
. So sometimes the plain append works (e.g. from MySQL results), but sometimes it fails, e.g. when the row is of typepyodbc.Row
.So we must coerce it to a tuple, list, or generator.
A generator will be the most efficient.
If a string fails certain checks, openpyxl will raise an IllegalCharacterError exception. We need to work around that. We’ll use the “forgiveness, not permission” maxim. Specifically, it dislikes strings matching its ILLEGAL_CHARACTERS_RE, which contains unprintable low characters matching this:
r'[\000-\010]|[\013-\014]|[\016-\037]'
Note the use of octal;
\037
is decimal 31.openpyxl gets to its Cell.check_string() function for these types:
STRING_TYPES = (basestring, unicode, bytes)
In Python 3, this means (str, str, bytes). So we should check str and bytes. (For bytes, we’ll follow its method of converting to str in the encoding of the worksheet’s choice.)
-
crate_anon.crateweb.research.models.
hack_django_pyodbc_azure_cursorwrapper
() → None[source]¶ Monkey-patch part of the
sql_server.pyodbc
library fromdjango-pyodbc-azure
. It replaces thefetchone()
method with a version that doesn’t callcursor.nextset()
automatically.It looks like this becomes unnecessary in django-pyodbc-azure==2.0.6.1 or similar, because the call to ``cursor.nextset()`` is now only performed ``if not self.connection.supports_mars``.
Notes
- I thought I wanted to modify an instance, not a class (https://tryolabs.com/blog/2013/07/05/run-time-method-patching-python/).
- To modify a class, we do
SomeClass.method = newmethod
. - But to modify an instance, we use
instance.method = types.MethodType(newmethod, instance)
. - However, it turned out the instance was actually part of a long chain
of cursor wrappers, including the Django debug toolbar. Classes included
debug_toolbar.panels.sql.tracking.NormalCursorWrapper
;django.db.backends.utils.CursorDebugWrapper
. And in any case, modifying the class is a sensible thing.