def __itemNameToDictList(self, itemNameList): rL = [] for itemName in list(OrderedDict.fromkeys(itemNameList)): atName = CifName.attributePart(itemName) catName = CifName.categoryPart(itemName) rL.append({"CATEGORY": catName, "ATTRIBUTE": atName}) return rL
def testGetUcode(self): """Test case - Get all data items of type ucode """ print("\n") try: myIo = IoAdapter(raiseExceptions=True) self.__containerList = myIo.readFile( inputFilePath=self.__pathPdbxDictionary) dApi = DictionaryApi(containerList=self.__containerList, consolidate=True, verbose=self.__verbose) logger.debug( "+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n") catNameList = dApi.getCategoryList() for catName in catNameList: itemNameList = dApi.getItemNameList(catName) for itemName in itemNameList: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) code = dApi.getTypeCode(categoryName, attributeName) if (code == "ucode"): print("Table: ", categoryName, "\tColumn: ", attributeName, "\tType: ", code) except Exception as e: logger.exception("Failing with %s", str(e)) self.fail()
def __assignItemIconType(self, itemNameList): iconTypeList = [] # categoryName = CifName.categoryPart(itemNameList[0]) keyItemNameList = self.__dApi.getCategoryKeyList(categoryName) for itemName in itemNameList: tType = "none" attributeName = CifName.attributePart(itemName) aMan = self.__dApi.getMandatoryCode(categoryName, attributeName) in ["yes", "y"] dMan = self.__dApi.getMandatoryCodeAlt(categoryName, attributeName, fallBack=False) in ["yes", "y"] inArchive = self.__getItemCount(itemName, deliveryType="archive") > 0 inChemDict = self.__getItemCount(itemName, deliveryType="cc") > 0 inBirdDict = self.__getItemCount(itemName, deliveryType="prd") > 0 or self.__getItemCount(itemName, deliveryType="family") > 0 isKey = itemName in keyItemNameList if isKey: tType = "key" elif aMan and dMan: tType = "all-mandatory" elif aMan: tType = "mandatory" elif dMan: tType = "deposit-mandatory" if inArchive: tType += "+database" if inChemDict: tType += "+chem-dict" if inBirdDict: tType += "+bird-dict" iconTypeList.append(tType) return iconTypeList
def testConsolidateDictionary(self): """Test case - dump methods for dictionary metadata""" try: myIo = IoAdapter(raiseExceptions=True) self.__containerList = myIo.readFile(inputFilePath=self.__pathPdbxDictionary) dApi = DictionaryApi(containerList=self.__containerList, consolidate=True, expandItemLinked=False, verbose=self.__verbose) for itemName in [ "_entity.id", "_entity_poly_seq.num", "_atom_site.label_asym_id", "_struct_asym.id", "_chem_comp.id", "chem_comp_atom.comp_id", "chem_comp_bond.comp_id", ]: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) logger.debug("Full parent list for %s : %s\n", itemName, dApi.getFullParentList(categoryName, attributeName)) logger.debug("Full child list for %s : %s\n", itemName, dApi.getFullChildList(categoryName, attributeName)) logger.debug("Ultimate parent for %s : %s\n", itemName, dApi.getUltimateParent(categoryName, attributeName)) logger.debug("Type code for %s : %s\n", itemName, dApi.getTypeCode(categoryName, attributeName)) self.assertIsNotNone(dApi.getTypeCode(categoryName, attributeName)) except Exception as e: logger.exception("Failing with %s", str(e)) self.fail()
def test_consolidate_dictionary(self, api_paths): myIo = IoAdapter(raiseExceptions=True) containerList = myIo.readFile( inputFilePath=str(api_paths['pathPdbxDictionary'])) dApi = DictionaryApi(containerList=containerList, consolidate=True) for itemName in [ '_entity.id', '_entity_poly_seq.num', '_atom_site.label_asym_id', '_struct_asym.id', '_chem_comp.id', 'chem_comp_atom.comp_id', 'chem_comp_bond.comp_id' ]: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) print("Full parent list for %s : %s\n" % (itemName, dApi.getFullParentList(categoryName, attributeName))) print( "Full child list for %s : %s\n" % (itemName, dApi.getFullChildList(categoryName, attributeName))) print("Ultimate parent for %s : %s\n" % (itemName, dApi.getUltimateParent(categoryName, attributeName))) print("Type code for %s : %s\n" % (itemName, dApi.getTypeCode(categoryName, attributeName))) assert dApi.getTypeCode(categoryName, attributeName) is not None
def __getParentCategories(self, itemNameList): parentCategories = set() for itemName in itemNameList: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) parentItemList = self.__dApi.getFullParentList(categoryName, attributeName) for parentItem in parentItemList: parentCategoryName = CifName.categoryPart(parentItem) parentCategories.add(parentCategoryName) return list(parentCategories)
def __getChildCategories(self, itemNameList): childCategories = set() for itemName in itemNameList: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) childItemList = self.__dApi.getFullChildList(categoryName, attributeName) for childItem in childItemList: childCategoryName = CifName.categoryPart(childItem) childCategories.add(childCategoryName) return list(childCategories)
def __substituteItemPrefix(self, itemName, curPrefix, newPrefix): atName = CifName.attributePart(itemName) atName = atName.replace( curPrefix, newPrefix, 1) if atName and atName.startswith(curPrefix) else atName catName = CifName.categoryPart(itemName) catName = catName.replace( curPrefix, newPrefix, 1) if atName and catName.startswith(curPrefix) else catName return CifName.itemName(catName, atName)
def __getRelativesAdjacent(self, itemNameList): aR = {} for itemName in itemNameList: categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) tD = {} tD["parentItems"] = self.__dApi.getFullParentList(categoryName, attributeName) tD["childItems"] = self.__dApi.getFullChildList(categoryName, attributeName) aR[itemName] = tD # if (self.__verbose): # for k,v in aR.items(): # logger.debug("Item %s\n parents: %s\n children %s\n\n" % (k,v['parentItems'],v['childItems'])) return aR
def __getSliceChildren(self, sliceParentD): """Internal method to build data structure containing the parent-child relationships for the input slice parent construction. """ retD = OrderedDict() for sliceName, sliceParents in sliceParentD.items(): sD = OrderedDict() for pD in sliceParents: parentCategoryName = pD["CATEGORY_NAME"] parentAttributeName = pD["ATTRIBUTE_NAME"] # sD[parentCategoryName] = [{ "PARENT_CATEGORY_NAME": parentCategoryName, "PARENT_ATTRIBUTE_NAME": parentAttributeName, "CHILD_ATTRIBUTE_NAME": parentAttributeName }] # # childItems = self.__dApi.getFullChildList(parentCategoryName, parentAttributeName) childItems = self.__dApi.getFullDescendentList( parentCategoryName, parentAttributeName) # logger.info("Slice parent %s %s %r" % (parentCategoryName, parentAttributeName, childItems)) for childItem in childItems: atName = CifName.attributePart(childItem) catName = CifName.categoryPart(childItem) # Ignore children in the parent category if catName == parentCategoryName: continue if catName not in sD: sD[catName] = [] sD[catName].append({ "PARENT_CATEGORY_NAME": parentCategoryName, "PARENT_ATTRIBUTE_NAME": parentAttributeName, "CHILD_ATTRIBUTE_NAME": atName }) # Sort the list of dictionaries for each category for catName in sD: sD[catName] = sorted( sD[catName], key=lambda k: (k["PARENT_CATEGORY_NAME"], k["PARENT_ATTRIBUTE_NAME"], k["CHILD_ATTRIBUTE_NAME"])) retD[sliceName] = sD return retD
def __getCategoryFeatures(self, catName, unitCardinalityList, subCategoryD): cD = {"KEY_ATTRIBUTES": []} # cD['KEY_ATTRIBUTES'] = [CifName.attributePart(keyItem) for keyItem in self.__dApi.getCategoryKeyList(catName)] cD["KEY_ATTRIBUTES"] = [ CifName.attributePart(keyItem) for keyItem in self.__getCategoryKeysWithReplacement(catName) ] cD["UNIT_CARDINALITY"] = catName in unitCardinalityList cD["CONTENT_CLASSES"] = self.__getContentClasses(catName) cD["IS_MANDATORY"] = True if str( self.__dApi.getCategoryMandatoryCode( catName)).lower() == "yes" else False cD["SUB_CATEGORIES"] = subCategoryD[ catName] if catName in subCategoryD else [] # return cD
def __renameCategory(self, container, newCategoryName): if not container and not container.isCategory() or not newCategoryName: return container # catNameCur = container.getName() if catNameCur == newCategoryName: return container try: for item in self.__categoryIdRelatives: catName = CifName.categoryPart(item) if container.exists(catName): cObj = container.getObj(catName) atName = CifName.attributePart(item) if cObj.hasAttribute(atName): for iRow in range(cObj.getRowCount()): testVal = cObj.getValue(atName, iRow) if testVal == catNameCur: cObj.setValue(newCategoryName, atName, iRow) except Exception as e: logger.exception("Failing with %s", str(e)) return container
def __getCategoryFeatures(self, catName, unitCardinalityList, subCategoryD): cD = {"KEY_ATTRIBUTES": []} # cD['KEY_ATTRIBUTES'] = [CifName.attributePart(keyItem) for keyItem in self.__dApi.getCategoryKeyList(catName)] cD["KEY_ATTRIBUTES"] = [ CifName.attributePart(keyItem) for keyItem in self.__getCategoryKeysWithReplacement(catName) ] cD["UNIT_CARDINALITY"] = catName in unitCardinalityList cD["CONTENT_CLASSES"] = self.__getContentClasses(catName) # # Exclude all categories beginning with "ma_" from being mandatory # (temporarily hardcoded here until new configuration file section added to achieve same effect) cD["IS_MANDATORY"] = True if str( self.__dApi.getCategoryMandatoryCode(catName)).lower( ) == "yes" and not catName.startswith("ma_") else False # cD["IS_MANDATORY"] = True if str(self.__dApi.getCategoryMandatoryCode(catName)).lower() == "yes" else False # cD["SUB_CATEGORIES"] = subCategoryD[ catName] if catName in subCategoryD else [] # return cD
def __getAttributeFeatures(self, catName, iterableD, embeddedIterableD, itemTransformD, methodD): """ Args: catName (string): Category name iterableD (tuple, optional): iterable dictionary type codes iQueryStrings (list, optional): search strings applied to item descriptions to identify iterable candidates itemTransformD (dict): dictionary of data transform filters itd[(catName,atName)] = [f1,f2,...] Returns: dict: attribute features cL = self.getCategoryContextList(catName) """ aD = {} # # keyAtNames = [CifName.attributePart(kyItem) for kyItem in self.__dApi.getCategoryKeyList(catName)] keyAtNames = [ CifName.attributePart(kyItem) for kyItem in self.__getCategoryKeysWithReplacement(catName) ] for atName in self.__categorySchema[catName]: itemName = CifName.itemName(catName, atName) fD = { "CATEGORY_NAME": catName, "ATTRIBUTE_NAME": atName, "TYPE_CODE": None, "TYPE_CODE_ALT": None, "IS_MANDATORY": False, "CHILD_ITEMS": [], "CHILDREN": [], "ROOT_PARENT_ITEM": None, "ROOT_PARENT": None, "PARENT": None, "DESCRIPTION": None, "DESCRIPTION_ANNOTATED": [], "IS_KEY": False, "ITERABLE_DELIMITER": None, "EMBEDDED_ITERABLE_DELIMITER": None, "FILTER_TYPES": [], "IS_CHAR_TYPE": False, "METHODS": [], "CONTENT_CLASSES": [], "UNITS": None, "ENUMS": None, "ENUMS_ANNOTATED": None, "SEARCH_CONTEXTS": None, } fD["TYPE_CODE"] = self.__dApi.getTypeCode(catName, atName) fD["TYPE_CODE_ALT"] = self.__dApi.getTypeCodeAlt(catName, atName) fD["IS_MANDATORY"] = True if str( self.__dApi.getMandatoryCode( catName, atName)).lower() in ["y", "yes"] else False fD["DESCRIPTION"] = textwrap.dedent( self.__dApi.getDescription(catName, atName)).lstrip().rstrip() # fD["DESCRIPTION_ANNOTATED"] = [{ "text": fD["DESCRIPTION"], "context": "dictionary" }] tS = self.__dApi.getDescriptionPdbx(catName, atName) if tS: fD["DESCRIPTION_ANNOTATED"].append({ "text": textwrap.dedent(tS).lstrip().rstrip(), "context": "deposition" }) # fD["UNITS"] = self.__dApi.getUnits(catName, atName) # fD["CHILD_ITEMS"] = self.__dApi.getFullChildList(catName, atName) fD["CHILDREN"] = self.__itemNameToDictList( self.__dApi.getFullChildList(catName, atName)) # pItemName = self.__dApi.getUltimateParent(catName, atName) pName = pItemName if pItemName != itemName else None fD["ROOT_PARENT_ITEM"] = pName fD["ROOT_PARENT"] = self.__itemNameToDictList( [pName])[0] if pName else None # pL = self.__dApi.getFullParentList(catName, atName, stripSelfParent=True) if pL: rL = self.__itemNameToDictList(pL) fD["PARENT"] = rL[0] if rL else None if len(rL) > 1: logger.warning( "Unexpected multiple parent definition for %s %s : %r", catName, atName, rL) # # logger.debug("catName %s atName %s : parent %r root_parent %r", catName, atName, fD['PARENT'], fD['ROOT_PARENT']) # fD["IS_KEY"] = atName in keyAtNames pType = self.__dApi.getTypePrimitive(catName, atName) fD["IS_CHAR_TYPE"] = str(pType).lower() in ["char", "uchar"] # fD["ITERABLE_DELIMITER"] = iterableD[(catName, atName)] if ( catName, atName) in iterableD else None fD["EMBEDDED_ITERABLE_DELIMITER"] = embeddedIterableD[( catName, atName)] if (catName, atName) in embeddedIterableD else None # fD["FILTER_TYPES"] = itemTransformD[(catName, "__all__")] if ( catName, "__all__") in itemTransformD else [] fD["FILTER_TYPES"] = itemTransformD[(catName, atName)] if ( catName, atName) in itemTransformD else fD["FILTER_TYPES"] # fD["METHODS"] = methodD[(catName, atName)] if (catName, atName) in methodD else [] fD["CONTENT_CLASSES"] = self.__getContentClasses(catName, atName) if (catName, atName) in self.__intEnumD: fD["ENUMS"] = sorted( self.__assignEnumTypes( self.__dApi.getEnumListPdbx(catName, atName), pType)) logger.debug("Using internal enums for %s %s %d", catName, atName, len(fD["ENUMS"])) enumTupList = self.__dApi.getEnumListAltWithFullDetails( catName, atName) else: fD["ENUMS"] = sorted( self.__assignEnumTypes( self.__dApi.getEnumList(catName, atName), pType)) enumTupList = self.__dApi.getEnumListWithFullDetails( catName, atName) # if self.__hasEnumDetails(enumTupList): # fD["ENUMS_ANNOTATED"] = [] for eTup in self.__assignEnumTupTypes(enumTupList, pType): teD = {"value": eTup[0]} if eTup[1]: teD["detail"] = eTup[1] if eTup[2]: teD["name"] = eTup[2] if eTup[3]: teD["units"] = eTup[3] fD["ENUMS_ANNOTATED"].append(teD) # ----- fD["EXAMPLES"] = self.__assignExampleTupTypes( catName, atName, self.__dApi.getExampleListPdbx(catName, atName), pType) fD["EXAMPLES"].extend( self.__assignExampleTupTypes( catName, atName, self.__dApi.getExampleList(catName, atName), pType)) # ----- scL = [] for scTup in self.__dApi.getItemSubCategoryList(catName, atName): if scTup[1] is not None: qD = {"id": scTup[0], "label": scTup[1]} else: qD = {"id": scTup[0]} scL.append(qD) fD["SUB_CATEGORIES"] = scL if len(scL) > 1: logger.debug("Multiple subcategories for %r %r %r", catName, atName, scL) # # bList = self.__dApi.getBoundaryListAlt(catName, atName, fallBack=True) bdList = self.__dApi.getBoundaryList(catName, atName) if bdList: minD = {} maxD = {} for (minV, maxV) in bdList: if minV == maxV: continue if minV not in [".", "?"]: minD[minV] = False if maxV not in [".", "?"]: maxD[maxV] = False for (minV, maxV) in bdList: if minV == maxV and minV in minD: minD[minV] = True if minV == maxV and maxV in maxD: maxD[maxV] = True for ky in minD: if "." in ky: kyV = float(ky) else: kyV = int(ky) if minD[ky]: fD["MIN_VALUE"] = kyV else: fD["MIN_VALUE_EXCLUSIVE"] = kyV for ky in maxD: if "." in ky: kyV = float(ky) else: kyV = int(ky) if maxD[ky]: fD["MAX_VALUE"] = kyV else: fD["MAX_VALUE_EXCLUSIVE"] = kyV # aD[atName] = fD # return aD
def getItemRelatedList(self, itemName): categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) return self._dApi.getItemRelatedList(categoryName, attributeName)
def getCategoryPdbxItemEnum(self, itemName): """Returns any DepUI enum list""" categoryName = CifName.categoryPart(itemName) attributeName = CifName.attributePart(itemName) return self._dApi.getEnumListAlt(categoryName, attributeName)
def makeSchemaDef(self): sD = {} for tableName in self.__tableNameList: if tableName in [ "rcsb_columninfo", "columninfo", "tableinfo", "rcsb_tableinfo" ]: continue dD = {} tableAbbrev = self.__getTableAbbrev(tableName) tU = tableAbbrev.upper() dD["SCHEMA_ID"] = tU dD["SCHEMA_NAME"] = tableAbbrev dD["SCHEMA_TYPE"] = "transactional" dD["ATTRIBUTES"] = {} dD["ATTRIBUTE_INFO"] = {} dD["ATTRIBUTE_MAP"] = {} # # create a sub list for this table - infoL = [] for atD in self.__atDefList: if atD["table_name"] == tableName: infoL.append(atD) # mapD = {} for atD in self.__atMapList: if atD["target_table_name"] == tableName: attributeName = atD["target_attribute_name"] attributeAbbrev = self.__getAttributeAbbrev( tableName, attributeName) atU = attributeAbbrev.upper() itN = atD["source_item_name"] if atD[ "source_item_name"] not in ["?", "."] else None if itN is not None: catNameM = CifName.categoryPart(itN) attNameM = CifName.attributePart(itN) else: catNameM = None attNameM = None # cId = atD['condition_id'] if atD['condition_id'] not in ['?', '.'] else None fId = atD["function_id"] if atD["function_id"] not in [ "?", "." ] else None if fId is not None and catNameM is None: mapD[atU] = (catNameM, attNameM, fId, None) else: mapD[atU] = (catNameM, attNameM, fId, None) # try: indexList = [] for (ii, atD) in enumerate(infoL): attributeName = atD["attribute_name"] attributeAbbrev = self.__getAttributeAbbrev( tableName, attributeName) atU = attributeAbbrev.upper() # td = {} # 'data_type','index_flag','null_flag','width','precision','populated' td["APP_TYPE"] = self.__convertDataType(atD["data_type"], aWidth=int( atD["width"])) td["WIDTH"] = int(atD["width"]) td["PRECISION"] = int(atD["precision"]) td["NULLABLE"] = not self.__toBool(atD["null_flag"]) td["PRIMARY_KEY"] = self.__toBool(atD["index_flag"]) td["ORDER"] = ii + 1 if td["PRIMARY_KEY"]: indexList.append(atU) dD["ATTRIBUTES"][atU] = attributeAbbrev dD["ATTRIBUTE_INFO"][atU] = td dD["ATTRIBUTE_MAP"][atU] = mapD[atU] except Exception as e: logger.error("Failing for table %r attribute %r", tableName, attributeName) logger.exception("Failing with %s", str(e)) # if self.__verbose and len(indexList) > 16: logger.debug( "+WARNING - %s index list exceeds MySQL max length %d", tableName, len(indexList)) mergeDict = {} deleteAttributeList = [] for atU in indexList: tN = dD["ATTRIBUTE_MAP"][atU][0] aN = dD["ATTRIBUTE_MAP"][atU][1] fN = dD["ATTRIBUTE_MAP"][atU][2] if aN is not None: if tN not in mergeDict: mergeDict[tN] = [] mergeDict[tN].append(aN) # # Using RCSB convention of including one attribute in each table corresponding to the datablockId() # this attributeId is used a key pre-insert deletions. # if fN in ["datablockid()"]: deleteAttributeList.append(atU) # # Assign a merge index to this instance category # for k, v in mergeDict.items(): dD["MAP_MERGE_INDICES"] = { k: { "TYPE": "EQUI-JOIN", "ATTRIBUTES": tuple(v) } } if deleteAttributeList: dD["SCHEMA_DELETE_ATTRIBUTE"] = deleteAttributeList[0] dD["INDICES"] = { "p1": { "TYPE": "UNIQUE", "ATTRIBUTES": tuple(indexList) }, "s1": { "TYPE": "SEARCH", "ATTRIBUTES": tuple(deleteAttributeList) } } else: dD["INDICES"] = { "p1": { "TYPE": "UNIQUE", "ATTRIBUTES": tuple(indexList) } } logger.debug("+WARNING - No delete attribute for table %s", tableName) if not mergeDict: logger.debug("+WARNING - No merge index possible for table %s", tableName) sD[tU] = dD return sD
def test_markup_category_group(self, in_tmpdir, test_files, out_file_name, groupSelectList): oFile = out_file_name rL = [] myIo = IoAdapter() containerList = myIo.readFile( str(test_files / "mmcif_pdbx_v5_next.dic")) dApi = DictionaryApi(containerList=containerList, consolidate=True) # groupList = dApi.getCategoryGroups() print('groupList %s\n' % groupList) for groupName in groupList: if groupSelectList and groupName not in groupSelectList: continue # # Goup header details # rL.append("# Category Group %s" % groupName) rL.append("") rL.append("") rL.append("%s" % dApi.getCategoryGroupDescription(groupName)) rL.append("") rL.append("---") rL.append("") catNameList = dApi.getCategoryGroupCategories(groupName=groupName) # cList = self.__sortIgnoreCase(catNameList) for catName in cList: print('Group %s category %s\n' % (groupName, catName)) catDescription = dApi.getCategoryDescription(category=catName) catExTupList = dApi.getCategoryExampleList(category=catName) keyItemNameList = dApi.getCategoryKeyList(category=catName) keyAttNameList = [ CifName.attributePart(k) for k in keyItemNameList ] # # Category header details # rL.append("## Category %s" % catName) rL.append("") rL.append("") rL.append(" %s" % catDescription) rL.append("") rL.append("---") rL.append("") if catExTupList: rL.extend( self.__formatTupListInset(catExTupList, tab=' ')) # # summary table # rL.append("") rL.append("---") rL.append("") rL.append( "| Attribute | Key | Required | Type | Units | Enumerated | Bounded |" ) rL.append( "| --------- | --- | -------- | ---- | ----- | ---------- | ------- |" ) aList = self.__sortIgnoreCase( dApi.getAttributeNameList(category=catName)) for attName in aList: isKey = attName in keyAttNameList attDescription = dApi.getDescription(category=catName, attribute=attName) attUnits = dApi.getUnits(category=catName, attribute=attName) attMandatory = dApi.getMandatoryCode(category=catName, attribute=attName) attTypeCode = dApi.getTypeCode(category=catName, attribute=attName) enumTupList = dApi.getEnumListWithDetail(category=catName, attribute=attName) if len(enumTupList) > 0: isEnum = True else: isEnum = False bL = dApi.getBoundaryList(category=catName, attribute=attName) if len(bL) > 0: isBounded = True else: isBounded = False rL.append( '| %s | %s | %s | %s | %s | %s | %s |' % (attName, self.__trB(isKey), attMandatory, attTypeCode, attUnits, self.__trB(isEnum), self.__trB(isBounded))) # rL.append("") rL.append("---") rL.append("") # for attName in aList: isKey = attName in keyAttNameList attMandatory = dApi.getMandatoryCode(category=catName, attribute=attName) # tN = '_' + catName + '.' + attName if isKey: tN = tN + ' (key)' elif attMandatory.upper() in ['YES', 'Y']: tN = tN + ' (required)' # rL.append("#### %s\n" % tN) rL.append("") attDescription = dApi.getDescription(category=catName, attribute=attName) rL.append(" %s\n" % attDescription) rL.append("") attUnits = dApi.getUnits(category=catName, attribute=attName) attTypeCode = dApi.getTypeCode(category=catName, attribute=attName) enumTupList = dApi.getEnumListWithDetail(category=catName, attribute=attName) if len(enumTupList) > 0: rL.append("") rL.append("---") rL.append("") rL.append("| Allowed Values | Detail |") rL.append("| -------------- | ------ |") for tup in enumTupList: if tup[1] and len(tup[1]) > 0: rL.append("| %s | %s |" % (tup[0], tup[1])) else: rL.append("| %s | %s |" % (tup[0], ' ')) rL.append("") # bL = dApi.getBoundaryList(category=catName, attribute=attName) btL = self.__processbounds(bL) if len(btL) > 0: tup = btL[0] rL.append("") rL.append("---") rL.append("") rL.append("| %s | %s |" % (tup[0], tup[1])) # rL.append("| ------------- | ------ |") for tup in btL[1:]: rL.append("| %s | %s |" % (tup[0], tup[1])) rL.append("") rL.append("") with open(str(oFile), 'w') as ofh: ofh.write('\n'.join(rL))
def __renderCategory(self, categoryName, fkList=None, highLight="adjacent", maxItems=10, filterDelivery=False, deliveryType="archive"): """Create graphviz object with embedded tabular HTML represenation of the input data category * Add _ guard characters before graph name and port names -- _categoryName_1 [label=< <table border="0" cellborder="1" cellspacing="0" align="left"> <tr><td BGCOLOR="Lavender">categoryName_1</td></tr> <tr><td PORT="__attribute_1">attribute_1</td></tr> <tr><td PORT="__attribute_2">attribute_2</td></tr> <tr><td PORT="__attribute_3">attribute_3</td></tr> </table>>]; """ colorD = { "op1": 'BGCOLOR="#7fc97f"', "other": 'BGCOLOR="#beaed4"', "op2": 'BGCOLOR="#fdc086"', "key": 'BGCOLOR="#ffff99"', "op4": 'BGCOLOR="#386cb0"', "current": 'BGCOLOR="#f0027f"', "adjacent": 'BGCOLOR="#99c49b"', } oList = [] itemNameList, minItemCount = self.__getOrderedItemNameList(categoryName, fkList=fkList, filterDelivery=filterDelivery, deliveryType=deliveryType) itemsToRender = max(minItemCount, maxItems) # categoryUrl = os.path.join(self.__pI.getContentTypeObjUrl(contentObjName=categoryName, contentType="Categories")) logger.debug("Rendering %s categoryUrl %r itemNameList %r itemsToRender %r fkList %r", categoryName, categoryUrl, itemNameList, itemsToRender, fkList) if len(itemNameList) > 0: iconTypeList = self.__assignItemIconType(itemNameList) oList.append('_%s [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" ALIGN="LEFT">' % (categoryName)) tdText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__fontSizeCategory, self.__fontFace, categoryName.upper()) oList.append(' <tr><td %s CELLPADDING="4" HREF="%s" TARGET="_top">%s</td></tr>' % (colorD[highLight], categoryUrl, tdText)) for iconType, itemName in list(zip(iconTypeList, itemNameList))[:itemsToRender]: itemUrl = os.path.join(self.__pI.getContentTypeObjUrl(contentObjName=itemName, contentType="Items")) attributeName = CifName.attributePart(itemName) tdText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__fontSizeAttribute, self.__fontFace, attributeName) if "key" in iconType: oList.append('<tr><td %s PORT="__%s" CELLPADDING="4" HREF="%s" TARGET="_top" ALIGN="LEFT">%s</td></tr>' % (colorD["key"], attributeName, itemUrl, tdText)) else: oList.append('<tr><td PORT="__%s" CELLPADDING="4" HREF="%s" TARGET="_top" ALIGN="LEFT">%s</td></tr>' % (attributeName, itemUrl, tdText)) if len(itemNameList) > itemsToRender: tdText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__fontSizeAttribute, self.__fontFace, "... and others ...") oList.append("<tr><td>%s</td></tr>" % tdText) oList.append("</TABLE>>];") else: # Placeholder for missing category oList.append('_%s [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" ALIGN="LEFT">' % (categoryName)) tdText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__fontSizeCategory, self.__fontFace, categoryName.upper()) oList.append(' <tr><td %s CELLPADDING="4" TARGET="_top">%s</td></tr>' % (colorD[highLight], tdText)) for itemName in fkList: iconType = "none" itemUrl = os.path.join(self.__pI.getContentTypeObjUrl(contentObjName=itemName, contentType="Items")) attributeName = CifName.attributePart(itemName) tdText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__fontSizeAttribute, self.__fontFace, attributeName) if "key" in iconType: oList.append('<tr><td %s PORT="__%s" CELLPADDING="4" TARGET="_top" ALIGN="LEFT">%s</td></tr>' % (colorD["key"], attributeName, tdText)) else: oList.append('<tr><td PORT="__%s" CELLPADDING="4" TARGET="_top" ALIGN="LEFT">%s</td></tr>' % (attributeName, tdText)) oList.append("</TABLE>>];") # return oList
def __testMarkupCategoryGroup(self, oFile, groupSelectList=None): """Test case - extract the content to be rendered -""" startTime = time.time() logger.debug("\nStarting at %s\n", time.strftime("%Y %m %d %H:%M:%S", time.localtime())) try: rL = [] myIo = IoAdapter() containerList = myIo.readFile(self.__pathPdbxV50Dictionary) dApi = DictionaryApi(containerList=containerList, consolidate=True, verbose=self.__verbose) # groupList = dApi.getCategoryGroups() logger.debug("groupList %s\n", groupList) for groupName in groupList: if groupSelectList and groupName not in groupSelectList: continue # # Goup header details # rL.append("# Category Group %s" % groupName) rL.append("") rL.append("") rL.append("%s" % dApi.getCategoryGroupDescription(groupName)) rL.append("") rL.append("---") rL.append("") catNameList = dApi.getCategoryGroupCategories( groupName=groupName) # cList = self.__sortIgnoreCase(catNameList) for catName in cList: logger.debug("Group %s category %s\n", groupName, catName) catDescription = dApi.getCategoryDescription( category=catName) catExTupList = dApi.getCategoryExampleList( category=catName) keyItemNameList = dApi.getCategoryKeyList(category=catName) keyAttNameList = [ CifName.attributePart(k) for k in keyItemNameList ] # # Category header details # rL.append("## Category %s" % catName) rL.append("") rL.append("") rL.append(" %s" % catDescription) rL.append("") rL.append("---") rL.append("") if catExTupList: rL.extend( self.__formatTupListInset(catExTupList, tab=" ")) # # summary table # rL.append("") rL.append("---") rL.append("") rL.append( "| Attribute | Key | Required | Type | Units | Enumerated | Bounded |" ) rL.append( "| --------- | --- | -------- | ---- | ----- | ---------- | ------- |" ) aList = self.__sortIgnoreCase( dApi.getAttributeNameList(category=catName)) for attName in aList: isKey = attName in keyAttNameList attDescription = dApi.getDescription(category=catName, attribute=attName) attUnits = dApi.getUnits(category=catName, attribute=attName) attMandatory = dApi.getMandatoryCode(category=catName, attribute=attName) attTypeCode = dApi.getTypeCode(category=catName, attribute=attName) enumTupList = dApi.getEnumListWithDetail( category=catName, attribute=attName) if enumTupList: isEnum = True else: isEnum = False bL = dApi.getBoundaryList(category=catName, attribute=attName) if bL: isBounded = True else: isBounded = False rL.append("| %s | %s | %s | %s | %s | %s | %s |" % (attName, self.__trB(isKey), attMandatory, attTypeCode, attUnits, self.__trB(isEnum), self.__trB(isBounded))) # rL.append("") rL.append("---") rL.append("") # for attName in aList: isKey = attName in keyAttNameList attMandatory = dApi.getMandatoryCode(category=catName, attribute=attName) # tN = "_" + catName + "." + attName if isKey: tN = tN + " (key)" elif attMandatory.upper() in ["YES", "Y"]: tN = tN + " (required)" # rL.append("#### %s\n" % tN) rL.append("") attDescription = dApi.getDescription(category=catName, attribute=attName) rL.append(" %s\n" % attDescription) rL.append("") attUnits = dApi.getUnits(category=catName, attribute=attName) attTypeCode = dApi.getTypeCode(category=catName, attribute=attName) enumTupList = dApi.getEnumListWithDetail( category=catName, attribute=attName) if enumTupList: rL.append("") rL.append("---") rL.append("") rL.append("| Allowed Values | Detail |") rL.append("| -------------- | ------ |") for tup in enumTupList: if tup[1]: rL.append("| %s | %s |" % (tup[0], tup[1])) else: rL.append("| %s | %s |" % (tup[0], " ")) rL.append("") # bL = dApi.getBoundaryList(category=catName, attribute=attName) btL = self.__processbounds(bL) if btL: tup = btL[0] rL.append("") rL.append("---") rL.append("") rL.append("| %s | %s |" % (tup[0], tup[1])) # rL.append("| ------------- | ------ |") for tup in btL[1:]: rL.append("| %s | %s |" % (tup[0], tup[1])) rL.append("") rL.append("") with open(oFile, "w") as ofh: ofh.write("\n".join(rL)) except Exception as e: logger.exception("Failing with %s", str(e)) self.fail() endTime = time.time() logger.debug("\nCompleted at %s (%.2f seconds)", time.strftime("%Y %m %d %H:%M:%S", time.localtime()), endTime - startTime)
def __generateDotInstructions( self, categoryName, graphTitle=None, graphSubTitle=None, titleFormat="text", maxItems=20, filterDelivery=False, deliveryType="archive", neighborCategoryList=None, maxCategories=None, ): """Internal method producing GraphViz 'dot' instructions depicting data category relationships between the input category and either all of its adjacent neighbors or for selected 'neighborCategoryList'. Optionally apply filtering to categories in current use within the archive. maxItems controls target maximum number of attributes in any category object depiction. maxCategories limits the number of related category objects depicted. """ # # Skip cases where the principal category is not associated with the input delivery type - # if filterDelivery and not self.__isCategoryUsed(categoryName=categoryName, deliveryType=deliveryType): logger.debug("skipping category %r delivery %r", categoryName, deliveryType) return [], 0 # numCategoriesRendered = 0 itemNameList = self.__dApi.getItemNameList(categoryName) aR = self.__getRelativesAdjacent(itemNameList) # for k, v in aR.items(): logger.debug("%s relatives %s", k, v) # adjacentCategories = [] adjacentCategories.append(categoryName) if neighborCategoryList is None: adjacentCategories.extend(self.__getParentCategories(itemNameList)) adjacentCategories.extend(self.__getChildCategories(itemNameList)) else: adjacentCategories.extend(neighborCategoryList) # adjacentCategories = sorted(list(set(adjacentCategories))) if maxCategories is not None: adjacentCategories = adjacentCategories[:maxCategories] logger.debug("adjacent categories %s", adjacentCategories) # oL = [] oL.append("digraph %s {" % categoryName) # Some previous layout parameters --- jdw # oL.append('splines=true; overlap=portho; model=subset;') # oL.append('splines=ortho; overlap=compress; model=subset; ratio=1.0;') oL.append("splines=true; overlap=compress; ") # # Option graph title - if graphTitle is not None: if titleFormat == "text": # dot instructions do not recognize the font settings. # oL.append('graph [labelloc=b, labeljust=left, labelfontname=Helvetica, labelfontsize=18, label="%s"];' % (self.__titleFontFace, self.__titleFontSize, graphTitle)) oL.append('graph [labelloc=b, labeljust=left, labelfontname=%s, labelfontsize=%s, label="%s"];' % (self.__titleFontFace, self.__titleFontSize, graphTitle)) else: # Title is rendered with this font detail. titleText = '<FONT POINT-SIZE="%s" FACE="%s">%s</FONT>' % (self.__titleFontSize, self.__titleFontFace, graphTitle) if graphSubTitle is not None: titleText += '<FONT POINT-SIZE="%s" FACE="%s"> <br/> %s</FONT>' % (self.__subTitleFontSize, self.__titleFontFace, graphSubTitle) oL.append("graph [labelloc=b, label=<%s>];" % (titleText)) oL.append("node [shape=plaintext]") for catName in adjacentCategories: if filterDelivery and not self.__isCategoryUsed(categoryName=catName, deliveryType=deliveryType): continue if catName == categoryName: highLight = "current" else: highLight = "adjacent" relatedList = self.__getRelatedList(categoryName=catName, adjacentD=aR) oL.extend(self.__renderCategory(catName, fkList=relatedList, highLight=highLight, maxItems=maxItems, filterDelivery=filterDelivery, deliveryType=deliveryType)) numCategoriesRendered += 1 # -------- # JDW regenerate full item list - # itemNameList = [] for catName in adjacentCategories: itemNameList.extend(self.__dApi.getItemNameList(catName)) aR = {} aR = self.__getRelativesAdjacent(itemNameList) # # -------- lD = {} # for itemName in itemNameList: if filterDelivery and not self.__isItemUsed(itemName=itemName, deliveryType=deliveryType): continue tD = aR[itemName] for parentItemName in tD["parentItems"]: if filterDelivery and not self.__isItemUsed(itemName=parentItemName, deliveryType=deliveryType): continue catName = CifName.categoryPart(itemName) attName = CifName.attributePart(itemName) catParent = CifName.categoryPart(parentItemName) attParent = CifName.attributePart(parentItemName) # if (itemName, parentItemName) in lD: continue if catParent not in adjacentCategories: continue if catParent != catName: oL.append(" _%s:__%s:w -> _%s:__%s:w;" % (catName, attName, catParent, attParent)) else: oL.append(" _%s:__%s:e -> _%s:__%s:e;" % (catName, attName, catParent, attParent)) lD[(itemName, parentItemName)] = 1 lD[(parentItemName, itemName)] = 1 for childItemName in tD["childItems"]: if filterDelivery and not self.__isItemUsed(itemName=childItemName, deliveryType=deliveryType): continue catName = CifName.categoryPart(itemName) attName = CifName.attributePart(itemName) catChild = CifName.categoryPart(childItemName) attChild = CifName.attributePart(childItemName) # if (itemName, childItemName) in lD: continue if catChild not in adjacentCategories: continue if catChild != catName: oL.append(" _%s:__%s:w -> _%s:__%s:w;" % (catChild, attChild, catName, attName)) else: oL.append(" _%s:__%s:e -> _%s:__%s:e;" % (catChild, attChild, catName, attName)) lD[(itemName, childItemName)] = 1 lD[(childItemName, itemName)] = 1 oL.append("}") return oL, numCategoriesRendered