def _mod_doc(self, doc_type, doc_title, doc_xml, doc_id): """ Add a new version for a document which was different on the two tiers. """ args = doc_type, doc_title, doc_id self._logger.info("updating %r document %r (CDR%d)", *args) # Lock the document, breaking any existing locks if necessary. doc = self._lock_doc(doc_id) if doc: # Plug in the preserved XML from PROD and create the new version. doc.xml = doc_xml.encode("utf-8") doc.ctrl["DocTitle"] = doc_title.encode("utf-8") response = cdr.repDoc(self._session, doc=str(doc), checkIn="Y", val="Y", ver="Y", reason=Job.COMMENT, comment=Job.COMMENT) err = cdr.checkErr(response) if err: args = cdr.normalize(doc_id), err self._logger.error("failure saving %s: %s", *args)
def getCipsContactAddress(self, id, withPersonTitle=TITLE_OMITTED): """ Constructs and returns a new Address object for the document. Parameters: id - Integer ID for CDR Person document. docType - 'Person' (default) or 'Organization' withPersonTitle - For Address constructor. Return value: Returns an Address object for the CIPS contact. """ # Make string version of id docId = cdr.normalize(id) # Find fragment ID for CIPS contact location in Person doc rows = cdr.getQueryTermValueForId( '/Person/PersonLocations/CIPSContact', id, self.__conn) if not rows: raise Exception("no CIPSContact for %s" % docId) fragId = rows[0] # Filter to create AddressElement XML filters = ["name:Person Address Fragment With Name"] result = cdr.filterDoc(self.__session, filters, docId, parm=(('fragId', fragId), )) # Expecting tuple of xml fragment, messages. Single string is error. if type(result) == type(""): raise Exception("failure extracting contact address " "for %s: %s" % (docId, result)) return Address(result[0], withPersonTitle)
def save_pair(self, doc_id, before, after, pair_type, errors=None): """ Write before and after XML to the file system Used in test mode to save everything to the file system for review, instead of writing to the repository. Pass: doc_id - integer identifying the document being processed before - serialized XML for the document before transformation after - serialzed XML for the document after transformation pair_type - string identifying what was transformed (cwd|pub|lastv) errors - optional sequence of validation error messages """ args = self.output_directory, cdr.normalize(doc_id), pair_type old_path = "{}/{}.{}old.xml".format(*args) new_path = "{}/{}.{}new.xml".format(*args) diff_path = "{}/{}.{}.diff".format(*args) errors_path = "{}/{}.{}.NEW_ERRORS.txt".format(*args) try: with open(old_path, "wb") as fp: fp.write(before) with open(new_path, "wb") as fp: fp.write(after) diff = cdr.diffXmlDocs(before, after) or b"-- No differences --" with open(diff_path, "wb") as fp: fp.write(diff) if errors: with open(errors_path, "wb") as fp: for error in errors: fp.write(error.encode("utf-8") + b"\n") except: self.logger.exception("Failure writing XML pair") raise
def show(self, page): "Add the summary to the HTML object" B = self.control.HTMLPage.B doc_id = B.BR() doc_id.tail = cdr.normalize(self.doc_id) page.append(B.H2(self.title, doc_id, B.CLASS("summary"))) page.append(self.changes)
def replace(self): """ Update an existing CDR document (if not testing). Return True, which is bubbled up to the main loop in `run()`. """ if self.control.opts.test: self.control.logger.info("%s is changed", self.name) return True cdr.checkOutDoc(self.control.session, self.id, force="Y") comment = "Updated by install-docset.py" ctrl = { "DocTitle": self.title } opts = { "type": self.doctype, "encoding": "utf-8", "ctrl": ctrl } opts["id"] = cdr.normalize(self.id) cdr_doc = cdr.Doc(self.xml, **opts) opts = dict(doc=str(cdr_doc), checkIn="Y", ver="Y", comment=comment) opts["publishable"] = self.control.PUBLISHABLE cdr_id = cdr.repDoc(self.control.session, **opts) error = cdr.checkErr(cdr_id) if error: self.control.logger.error(error) sys.exit(1) self.control.logger.info("replaced %s (%s)", self.name, cdr_id) return True
def _unlock_doc(self, doc_id): """ Release an existing lock on a CDR document. """ id_string = cdr.normalize(doc_id) response = cdr.unlock(self._session, id_string, Job.COMMENT) if response: self._logger.error("failure unlocking %s: %s", id_string, response) return False return True
def getBoardMemberAddress(self, personId, memberId): # Find fragment ID for CIPS contact location in BoardMemberInfo doc path = '/PDQBoardMemberInfo/BoardMemberContact/PersonContactID' rows = cdr.getQueryTermValueForId(path, memberId, self.__conn) # Filter to create AddressElement XML if rows: docId = cdr.normalize(personId) parms = (('fragId', rows[0]), ) filters = ["name:Person Address Fragment With Name"] else: docId = cdr.normalize(memberId) parms = () filters = ["name:Board Member Address Fragment With Name"] result = cdr.filterDoc(self.__session, filters, docId, parm=parms) if isinstance(result, (str, bytes)): raise Exception("failure extracting contact address " "for %s: %s" % (docId, result)) return Address(result[0])
def __init__(self, job, doc_id): self.job = job self.id = doc_id self.cdr_id = cdr.normalize(doc_id) self.versions = cdr.lastVersions("guest", doc_id, tier=job.tier) self.status = cdr.getDocStatus("guest", doc_id, tier=job.tier) self.saved = set() self.doc_objects = {} self.transformed_xml = {} self.errors = {} self.changed = set() self.load_versions()
def _lock_doc(self, doc_id): """ Check out an existing CDR document. """ # If someone else has the document locked, break the lock. locker = self._find_locker(doc_id) if locker and locker.lower() != self._uid.lower(): if not self._unlock_doc(doc_id): return None # Fetch the document with a lock. doc = cdr.getDoc(self._session, doc_id, checkout="Y", getObject=True) err = cdr.checkErr(doc) if not err: return doc args = cdr.normalize(doc_id), err self._logger.error("failure locking %s: %r", *args) return None
def addMailerTrackingDoc(self, doc, recipient, mailerType, remailerFor=None, protOrgId=None, email=None): """ Parameters: doc - Object of type Document, defined below recipient - Object of type Recipient, defined below mailerType - String containing a values matching the list of valid values for MailerType enumerated in the schema for Mailer docs. remailerFor - optional integer for the document ID of an earlier mailer that was sent out and never responded to, and for which this is a followup remailer. protOrgId - string or integer form of CDR ID for a protocol's lead organization (the one to which this mailer is being sent); used to distinguish between Status and Participant mailers for the same protocol in the same job. email - address used for electronic mailer. Return value: Integer ID for the newly inserted Mailer document. """ if remailerFor: remailerFor = "\n <RemailerFor cdr:ref='%s'/>" % \ cdr.normalize(remailerFor) else: remailerFor = "" if protOrgId: protOrg = "\n <ProtocolOrg cdr:ref='%s'/>" % \ cdr.normalize(protOrgId) else: protOrg = "" if email: mode = "Web-based" address = """\ <MailerAddress> <Email>%s</Email> </MailerAddress>""" % email else: mode = "Mail" address = recipient.getAddress().getXml() recipId = "CDR%010d" % recipient.getId() docId = "CDR%010d" % doc.getId() xml = """\ <CdrDoc Type="Mailer"> <CdrDocCtl> <DocTitle>Mailer for document %s sent to %s</DocTitle> </CdrDocCtl> <CdrDocXml><![CDATA[ <Mailer xmlns:cdr="cips.nci.nih.gov/cdr"> <Type Mode='%s'>%s</Type>%s <JobId>%d</JobId> <Recipient cdr:ref="%s">%s</Recipient>%s %s <Document cdr:ref="%s">%s</Document> <Sent>%s</Sent> <Deadline>%s</Deadline> </Mailer>]]> </CdrDocXml> </CdrDoc> """ % (docId, recipId, mode, mailerType, remailerFor, self.__id, recipId, recipient.getName(), protOrg, address, docId, doc.getTitle(), self.__now, self.getDeadline()) rsp = cdr.addDoc(self.__session, doc=xml.encode('utf-8'), checkIn="Y", ver="Y", val='Y') match = self.__ERR_PATTERN.search(rsp) if match: err = match.group(1) raise Exception("failure adding tracking document for %s: %s" % (docId, err)) self.__nMailers += 1 digits = re.sub("[^\d]", "", rsp) return int(digits)