13.2.30. camcops_server.cc_modules.cc_convert

camcops_server/cc_modules/cc_convert.py


Copyright (C) 2012-2019 Rudolf Cardinal (rudolf@pobox.com).

This file is part of CamCOPS.

CamCOPS 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.

CamCOPS 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 CamCOPS. If not, see <http://www.gnu.org/licenses/>.


Miscellaneous conversion functions.

camcops_server.cc_modules.cc_convert.br_html(text: str) → str[source]

Filter that escapes text safely whilst also converting n to <br>.

camcops_server.cc_modules.cc_convert.decode_single_value(v: str) → Any[source]

Takes a string representing an SQL value. Returns the value. Value types/examples:

int 35, -12
float 7.23
str 'hello, here''s an apostrophe' (starts and ends with a quote)
NULL NULL (case-insensitive)
BLOB X'4D7953514C' (hex-encoded; matches MySQL method; http://dev.mysql.com/doc/refman/5.0/en/hexadecimal-literals.html)
BLOB 64'TXlTUUw=' (base-64-encoded; this notation is my invention)

But

  • we use ISO-8601 text for dates/times

In the old Titanium client, the client-side counterpart to this function was SQLite’s QUOTE() function (see getRecordByPK_lowmem() in lib/dbsqlite.js), except in the case of BLOBs (when it was getEncodedBlob() in table/Blob.js); see lib/dbupload.js.

In the newer C++ client, the client-side counterpart is toSqlLiteral() in lib/convert.cpp.

camcops_server.cc_modules.cc_convert.decode_values(valuelist: str) → List[Any][source]

Takes a SQL CSV value list and returns the corresponding list of decoded values.

camcops_server.cc_modules.cc_convert.encode_single_value(v: Any, is_blob=False) → str[source]

Encodes a value for incorporation into an SQL CSV value string.

Note that this also escapes newlines. That is not necessary when receiving data from tablets, because those data arrive in CGI forms, but necessary for the return journey to the tablet/webclient, because those data get sent in a one-record-one-line format.

In the old Titanium client, the client-side counterpart to this function was decode_single_sql_literal() in lib/conversion.js.

In the newer C++ client, the client-side counterpart is fromSqlLiteral() in lib/convert.cpp.

camcops_server.cc_modules.cc_convert.tsv_from_query(rows: Iterable[Iterable[Any]], descriptions: Iterable[str], dialect: str = 'excel-tab') → str[source]

Converts rows from an SQL query result to TSV format.

For the dialect, see https://docs.python.org/3/library/csv.html#csv.excel_tab.

For CSV files, see RGC 4180: https://tools.ietf.org/html/rfc4180.

For TSV files, see https://www.iana.org/assignments/media-types/text/tab-separated-values.

Test code:

import io
import csv
from typing import List

def test(row: List[str], dialect: str = "excel-tab") -> str:
    f = io.StringIO()
    writer = csv.writer(f, dialect=dialect)
    writer.writerow(row)
    return f.getvalue()

test(["hello", "world"])
test(["hello\ttab", "world"])  # actual tab within double quotes
test(["hello\nnewline", "world"])  # actual newline within double quotes
test(['hello"doublequote', "world"])  # doubled double quote within double quotes