Exemple #1
0
    def as_r(self) -> str:
        """
        Returns data as an R script.

        This could be more sophisticated, e.g. creating factors with
        appropriate levels (etc.).
        """
        now = format_datetime(
            get_now_localtz_pendulum(),
            DateFormat.ISO8601_HUMANIZED_TO_SECONDS_TZ,
        )
        table_definition_str = "\n\n".join(page.r_data_table_definition()
                                           for page in self.pages)
        script = f"""#!/usr/bin/env Rscript

# R script generated by CamCOPS at {now}

# =============================================================================
# Libraries
# =============================================================================

library(data.table)

# =============================================================================
# Data
# =============================================================================

{table_definition_str}

"""
        return script
Exemple #2
0
def nlprp_datetime_now(as_local: bool = True) -> str:
    """
    Returns the time now, as a string suitable for use with NLPRP.

    Args:
        as_local: use local timezone? (Otherwise, use UTC.)
    """
    now = get_now_localtz_pendulum() if as_local else get_now_utc_pendulum()
    return pendulum_to_nlprp_datetime(now)
def get_changelog() -> str:
    now = get_now_localtz_pendulum()
    return """camcops-server ({CAMCOPS_SERVER_VERSION_STRING}) all; urgency=low

  * Change date: {CAMCOPS_SERVER_CHANGEDATE}.
  * PLEASE SEE docs/source/changelog.rst FOR ALL CHANGES, or the online version
    at https://camcops.readthedocs.io/.
  * This file (changelog.Debian) has a very precise format:
    https://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog
  * Note that newer entries are at the top.

 -- Rudolf Cardinal <*****@*****.**>  {now}

    """.format(
        CAMCOPS_SERVER_VERSION_STRING=CAMCOPS_SERVER_VERSION_STRING,
        CAMCOPS_SERVER_CHANGEDATE=CAMCOPS_SERVER_CHANGEDATE,
        now=now.strftime(DEBIAN_DATETIME_FORMAT),
    )
Exemple #4
0
    def __init__(self,
                 from_addr: str,
                 date: str = None,
                 sender: str = "",
                 reply_to: str = "",
                 to: str = "",
                 cc: str = "",
                 bcc: str = "",
                 subject: str = "",
                 body: str = "",
                 content_type: str = "text/plain",
                 charset: str = "utf8",
                 attachment_filenames: Sequence[str] = None,
                 attachments_binary: Sequence[Tuple[str, bytes]] = None,
                 save_msg_string: bool = False) -> None:
        """
        Args:
            from_addr: name of the sender for the "From:" field
            date: e-mail date in RFC 2822 format, or ``None`` for "now"
            sender: name of the sender for the "Sender:" field
            reply_to: name of the sender for the "Reply-To:" field

            to: e-mail address(es) of the recipients for "To:" field, as a
                CSV list
            cc: e-mail address(es) of the recipients for "Cc:" field, as a
                CSV list
            bcc: e-mail address(es) of the recipients for "Bcc:" field, as a
                CSV list

            subject: e-mail subject
            body: e-mail body
            content_type: MIME type for body content, default ``text/plain``
            charset: character set for body; default ``utf8``
            charset:

            attachment_filenames: filenames of attachments to add
            attachments_binary: binary attachments to add, as a list of
                ``filename, bytes`` tuples

            save_msg_string: save the encoded message string? (May take
                significant space in the database).
        """

        # ---------------------------------------------------------------------
        # Timestamp
        # ---------------------------------------------------------------------
        now_local = get_now_localtz_pendulum()
        self.created_at_utc = convert_datetime_to_utc(now_local)

        # -------------------------------------------------------------------------
        # Arguments
        # -------------------------------------------------------------------------
        if not date:
            date = email.utils.format_datetime(now_local)
        attachment_filenames = attachment_filenames or []  # type: List[str]
        attachments_binary = attachments_binary or [
        ]  # type: List[Tuple[str, bytes]]  # noqa
        attachment_binary_filenames, attachment_binaries = zip(
            *attachments_binary)  # noqa
        # ... https://stackoverflow.com/questions/13635032/what-is-the-inverse-function-of-zip-in-python  # noqa
        # Other checks performed by our e-mail function below

        # ---------------------------------------------------------------------
        # Transient fields
        # ---------------------------------------------------------------------
        self.password = None
        self.msg = make_email(
            from_addr=from_addr,
            date=date,
            sender=sender,
            reply_to=reply_to,
            to=to,
            cc=cc,
            bcc=bcc,
            subject=subject,
            body=body,
            content_type=content_type,
            attachment_filenames=attachment_filenames,
            attachment_binaries=attachment_binaries,
            attachment_binary_filenames=attachment_binary_filenames,
        )

        # ---------------------------------------------------------------------
        # Database fields
        # ---------------------------------------------------------------------
        self.date = date
        self.from_addr = from_addr
        self.sender = sender
        self.reply_to = reply_to
        self.to = to
        self.cc = cc
        self.bcc = bcc
        self.subject = subject
        self.body = body
        self.content_type = content_type
        self.charset = charset
        if save_msg_string:
            self.msg_string = self.msg.as_string()
Exemple #5
0
def get_export_filename(
    req: "CamcopsRequest",
    patient_spec_if_anonymous: str,
    patient_spec: str,
    filename_spec: str,
    filetype: str,
    is_anonymous: bool = False,
    surname: str = None,
    forename: str = None,
    dob: Date = None,
    sex: str = None,
    idnum_objects: List["PatientIdNum"] = None,
    creation_datetime: Pendulum = None,
    basetable: str = None,
    serverpk: int = None,
    skip_conversion_to_safe_filename: bool = False,
) -> str:
    """
    Get filename, for file exports/transfers.
    Also used for e-mail headers and bodies.

    Args:
        req: :class:`camcops_server.cc_modules.cc_request.CamcopsRequest`
        patient_spec_if_anonymous:
            patient specification to be used for anonymous tasks
        patient_spec:
            patient specification to be used for patient-identifiable tasks
        filename_spec:
            specification to use to create the filename (may include
            patient information from the patient specification)
        filetype:
            task output format and therefore file type (e.g. HTML, PDF, XML)
        is_anonymous: is it an anonymous task?
        surname: patient's surname
        forename: patient's forename
        dob: patient's date of birth
        sex: patient's sex
        idnum_objects: list of :class:`PatientIdNum` objects for the patient
        creation_datetime: date/time the task was created
        basetable: name of the task's base table
        serverpk: server PK of the task
        skip_conversion_to_safe_filename: don't bother converting the result
            to a safe filename (because it'll be used for something else, like
            an e-mail subject)

    Returns:
        the generated filename

    """
    idnum_objects = idnum_objects or []  # type: List['PatientIdNum']
    pse = PatientSpecElementForFilename
    fse = FilenameSpecElement
    d = {
        pse.SURNAME:
        surname or "",
        pse.FORENAME:
        forename or "",
        pse.DOB: (format_datetime(dob, DateFormat.FILENAME_DATE_ONLY, "")
                  if dob else ""),
        pse.SEX:
        sex or "",
    }
    all_id_components = []
    for idobj in idnum_objects:
        if idobj.which_idnum is not None:
            nstr = str(idobj.which_idnum)
            has_num = idobj.idnum_value is not None
            d[pse.IDNUM_PREFIX +
              nstr] = (str(idobj.idnum_value) if has_num else "")
            d[pse.IDSHORTDESC_PREFIX + nstr] = (idobj.short_description(req)
                                                or "")
            if has_num and idobj.short_description(req):
                all_id_components.append(idobj.get_filename_component(req))
    d[pse.ALLIDNUMS] = "_".join(all_id_components)
    if is_anonymous:
        patient = patient_spec_if_anonymous
    else:
        try:
            patient = str(patient_spec).format(**d)
        except STR_FORMAT_EXCEPTIONS:
            log.warning("Bad patient_spec: {!r}; dictionary was {!r}",
                        patient_spec, d)
            patient = "invalid_patient_spec"
    d.update({
        fse.PATIENT:
        patient,
        fse.CREATED:
        format_datetime(creation_datetime, DateFormat.FILENAME, ""),
        fse.NOW:
        format_datetime(get_now_localtz_pendulum(), DateFormat.FILENAME),
        fse.TASKTYPE:
        str(basetable or ""),
        fse.SERVERPK:
        str(serverpk or ""),
        fse.FILETYPE:
        filetype.lower(),
        fse.ANONYMOUS:
        patient_spec_if_anonymous if is_anonymous else "",
    })
    try:
        formatted = str(filename_spec).format(**d)
    except STR_FORMAT_EXCEPTIONS:
        log.warning("Bad filename_spec: {!r}", filename_spec)
        formatted = "invalid_filename_spec"
    if skip_conversion_to_safe_filename:
        return formatted
    return convert_string_for_filename(formatted, allow_paths=True)