Ejemplo n.º 1
0
    def replace(self):
        """Promote the selected version, log the action, and show the form."""

        if not self.session.can_do("MODIFY DOCUMENT", self.doc.doctype.name):
            self.bail("Not authorized")
        if not self.version:
            self.bail("No version specified")
        comment = f"Replacing CWD with version {self.version:d}"
        doc = Doc(self.session, id=self.doc.id, version=self.version)
        doc.check_out(comment=comment)
        pub_ver = self.make_version_publishable
        if self.comment:
            comment = f"{comment}: {self.comment}"
        opts = dict(
            version=self.create_version,
            publishable=pub_ver,
            val_types=("schema", "links") if pub_ver else None,
            comment=comment,
            reason=comment,
            unlock=True,
        )
        doc.save(**opts)
        path = f"{self.session.tier.logdir}/CWDReplacements.log"
        try:
            with open(path, "a", encoding="utf-8") as fp:
                fp.write(f"{self.message}\n")
        except IOError as e:
            self.bail(f"Error writing to {path}: {e}")
        self.show_form()
Ejemplo n.º 2
0
    def doc(self):
        """Prepare a `cdrapi.Doc` object for saving in the CDR"""

        # We may have already done the work and cached the object.
        if not hasattr(self, "_doc"):

            # If we're updating an existing Citation doc, fetch and modify it.
            if self.control.cdrid:
                cdrid = self.control.cdrid
                doc = Doc(self.control.session, id=cdrid)
                doc.check_out()
                root = doc.root
                old_node = root.find("PubmedArticle")
                if old_node is None:
                    raise Exception(f"{cdrid} is not a PubMed article")
                root.replace(old_node, self.pubmed_article)
                doc.xml = etree.tostring(root)

            # Otherwise, build up a new document and insert NLM's info.
            else:
                pmid = self.control.pmid
                cdrid = self.lookup(pmid)
                if cdrid:
                    raise Exception(f"PMID {pmid} already imported as {cdrid}")
                root = etree.Element("Citation")
                details = etree.SubElement(root, "VerificationDetails")
                etree.SubElement(details, "Verified").text = "Yes"
                etree.SubElement(details, "VerifiedIn").text = "PubMed"
                root.append(self.pubmed_article)
                opts = dict(xml=etree.tostring(root), doctype="Citation")
                doc = Doc(self.control.session, **opts)
            self._doc = doc
        return self._doc
Ejemplo n.º 3
0
    def expire(self):
        """
        Update data partner's CDR document to reflect deactivation.
        """

        doc = Doc(self.control.session, id=self.org_id)
        root = doc.root
        node = root.find("LicenseeInformation/LicenseeStatus")
        if node.text == "Test-inactive":
            self.logger.warning("CDR%s already deactivated", self.org_id)
            return
        self.logger.info("Marking CDR%s as expired", self.org_id)
        node.text = "Test-inactive"
        today = str(datetime.date.today())
        node = root.find("DateLastModified")
        if node is None:
            node = etree.SubElement(root, "DateLastModified")
        node.text = today
        node = root.find("LicenseeInformation/LicenseeStatusDates")
        if node is None:
            message = "CDR%s missing LicenseeStatusDates"
            self.logger.warning(message, self.org_id)
        else:
            child = node.find("TestInactivation")
            if child is None:
                child = etree.Element("TestInactivation")
                sibling = node.find("TestActivation")
                if sibling is not None:
                    sibling.addnext(child)
                else:
                    node.insert(0, child)
            if child.text is None or not child.text.strip():
                child.text = today
        if not self.control.test:
            comment = "Marking account as inactive"
            doc.check_out(force=True, comment=comment)
            opts = dict(
                version=True,
                reason=comment,
                comment=comment,
                unlock=True,
            )
            doc.save(**opts)
Ejemplo n.º 4
0
                    help="make version publishable",
                    action="store_true")
parser.add_argument("--force",
                    "-f",
                    help="force checkout",
                    action="store_true")
opts = parser.parse_args()
if opts.session:
    session = Session(opts.session, tier=opts.tier)
else:
    session = Session.create_session(opts.user, tier=opts.tier)
print(session)
with open(opts.xml, "rb") as fp:
    xml = fp.read()
doc = Doc(session, id=opts.id, doctype=opts.doctype, xml=xml)
if opts.id:
    doc.check_out(force=opts.force)
version = opts.version or opts.publishable
val_types = ["schema", "links"] if opts.publishable else None
save_opts = dict(
    version=version,
    publishable=opts.publishable,
    val_types=val_types,
    comment=opts.comment,
    unlock=True,
)
doc.save(**save_opts)
print(f"saved {doc.cdr_id} ({doc.title})")
if not opts.session:
    session.logout()
Ejemplo n.º 5
0
class Control(Controller):
    """Access to the current CDR login session and page-building tools."""

    SUBTITLE = "Post CDR Schema"
    LOGNAME = "post-schema"
    ACTIONS = (
        ("add", "Add New Schema"),
        ("replace", "Replace Existing Schema"),
    )

    def populate_form(self, page):
        """Prompt for the file and an optional comment.

        Checking for processing logs triggers the schema save
        if a schema file has been posted, and in that case the
        logs are displayed below the form.

        Pass:
            page - HTMLPage on which we place the fields
        """

        fieldset = page.fieldset("Schema")
        fieldset.append(page.file_field("file", label="Schema File"))
        fieldset.append(page.text_field("comment"))
        page.form.append(fieldset)
        fieldset = page.fieldset("Action")
        checked = False
        for value, label in self.ACTIONS:
            opts = dict(value=value, label=label, checked=checked)
            fieldset.append(page.radio_button("action", **opts))
            checked = True
        page.form.append(fieldset)
        if self.logs is not None:
            fieldset = page.fieldset("Processing Logs")
            fieldset.append(self.logs)
            page.form.append(fieldset)
            page.add_css("fieldset { width: 600px } #comment { width: 450px }")
            page.add_css("pre { color: green }")
        page.form.set("enctype", "multipart/form-data")

    def show_report(self):
        """Cycle back to the form."""
        self.show_form()

    @property
    def action(self):
        """Are we replacing an existing schema or adding a new one?"""
        return self.fields.getvalue("action")

    @property
    def buttons(self):
        """Customize the action buttons on the banner bar."""
        return self.SUBMIT, self.DEVMENU, self.ADMINMENU, self.LOG_OUT

    @property
    def comment(self):
        """Override the default comment as appropriate."""

        if not hasattr(self, "_comment"):
            self._comment = self.fields.getvalue("comment")
            if not self._comment:
                verb = "Replacing" if self.document.id else "Adding"
                self._comment = f"{verb} schema using admin interface"
        return self._comment

    @property
    def document(self):
        """Uploaded schema document to be posted."""

        if not hasattr(self, "_document"):
            self._document = None
            if self.schema_title and self.file_bytes:
                title = self.schema_title
                xml = self.file_bytes
                opts = dict(xml=xml, doctype="schema")
                query = self.Query("document d", "d.id")
                query.join("doc_type t", "t.id = d.doc_type")
                query.where("t.name = 'schema'")
                query.where(query.Condition("d.title", title))
                rows = query.execute(self.cursor).fetchall()
                if rows:
                    if self.action == "add":
                        raise Exception(f"Schema {title} already exists")
                    if len(rows) > 1:
                        raise Exception(f"Multiple schemas match {title}")
                    opts["id"] = rows[0].id
                else:
                    if self.action != "add":
                        raise Exception(f"Schema document {title} not found")
                self._document = Doc(self.session, **opts)
                if rows:
                    self._document.check_out(comment="locking for update")
        return self._document

    @property
    def file_bytes(self):
        """UTF-8 serialization of the document to be posted."""

        if not hasattr(self, "_file_bytes"):
            self._file_bytes = None
            if self.file_field is not None:
                if self.file_field.file:
                    segments = []
                    while True:
                        more_bytes = self.file_field.file.read()
                        if not more_bytes:
                            break
                        segments.append(more_bytes)
                else:
                    segments = [self.file_field.value]
                self._file_bytes = b"".join(segments)
        return self._file_bytes

    @property
    def file_field(self):
        """CGI field for the uploaded file, if any."""

        if not hasattr(self, "_file_field"):
            self._file_field = None
            if "file" in list(self.fields.keys()):
                self._file_field = self.fields["file"]
        return self._file_field

    @property
    def logs(self):
        """Log output describing the outcome of a post action."""

        if not hasattr(self, "_logs"):
            self._logs = None
            if self.document:
                if not self.session.can_do("MODIFY DOCUMENT", "schema"):
                    error = "Account not authorized for posting schemas."
                    self.bail(error)
                self.document.save(**self.opts)
                message = "\n\n".join([
                    f"Saved {self.document.cdr_id}.",
                    self.__check_dtds().strip(),
                    self.__refresh_manifest().strip(),
                    "Schema posted successfully.",
                    f"Elapsed: {self.elapsed}",
                ])
                self._logs = self.HTMLPage.B.PRE(message)
        return self._logs

    @property
    def opts(self):
        """Options passed to the `Doc.save()` method."""

        if not hasattr(self, "_opts"):
            self._opts = dict(
                version=True,
                unlock=True,
                comment=self.comment,
                reason=self.comment,
                title=self.schema_title,
            )
        return self._opts

    @property
    def schema_title(self):
        """Name of the uploaded file without the full path."""

        if not hasattr(self, "_filename"):
            self._title = None
            if self.file_field is not None:
                self._title = basename(self.file_field.filename)
                self.logger.info("filename for schema is %r", self._title)
        return self._title

    def __check_dtds(self):
        """Regenerate the DTDs to reflect the new/updated schema.

        Return:
            string to append to the processing log display
        """

        cmd = r"python d:\cdr\build\CheckDtds.py"
        result = run_command(cmd, merge_output=True)
        if result.returncode:
            raise Exception(f"DTD check failure: {result.stdout}")
        self.logger.info("DTDs updated")
        return "Running CheckDtds.py ...\n" + result.stdout

    def __refresh_manifest(self):
        """Rebuild the client manifest file.

        Return:
            string to append to the processing log display
        """

        cmd = r"python d:\cdr\build\RefreshManifest.py"
        result = run_command(cmd, merge_output=True)
        if result.returncode:
            output = result.stdout
            raise Exception(f"Manifest refresh failure: {output}")
        self.logger.info("Manifest updated")
        return "Running RefreshManifest.py ...\n" + result.stdout