Source code for pilot.user.atlas.nordugrid

#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Authors:
# - Paul Nilsson, paul.nilsson@cern.ch, 2018-2019

import re
import logging
from xml.dom import minidom
from xml.etree import ElementTree

logger = logging.getLogger(__name__)


[docs] class XMLDictionary(object): """ This is a helper class that is used to create the dictionary which is converted to the special XML files for Nordugrid pilots. Example dictionary: dictionary = { "outfiles": [ { "file": { "surl": "some_surl", "size": "123", "ad32": "aaaaaaa", "guid": "ababa22", "lfn": "some_lfn", "dataset": "some_dataset", "date": "11/11/11" } }, {}, {}, .. ] } Usage: xmldic = XMLDictionary() xmldic.add_to_list({"surl": "some_surl1", "size": "123", "ad32": "aaaaaaa", "guid": "ababa22", "lfn": "some_lfn", "dataset": "some_dataset", "date": "11/11/11"}) dictionary = xmldic.get_dictionary() """ _dictionary = None
[docs] def __init__(self, rootname="outfiles"): """ Standard init function. :param rootname: name of the root key. There is only one root key in the Nordugrid XML file ('outfiles'). """ self._dictionary = {} self._dictionary[rootname] = []
[docs] def add_to_list(self, dictionary, rootname="outfiles", itemname="file"): """ Add dictionary to itemname key. See example in class header. :param dictionary: dictionary to add to itemname key. :param rootname: name of the root key. There is only one root key in the Nordugrid XML file ('outfiles'). :param itemname: name of the item key. In the Nordugrid XML it should be called 'file'. :return: """ if isinstance(self._dictionary, dict): if isinstance(self._dictionary[rootname], list): _dic = {itemname: dictionary} self._dictionary[rootname].append(_dic) else: pass else: logger.info("not a dictionary: %s", str(self._dictionary))
[docs] def get_dictionary(self): """ Return the dictionary to be converted to XML. It should be populated with the dictionary added to it in add_to_list(). :return: dictionary """ return self._dictionary
[docs] def convert_to_xml(dictionary): """ Convert a dictionary to XML. The dictionary is expected to follow the Nordugrid format. See the XMLDictionary helper class. Example of XML (OutputFiles.xml): <?xml version="1.0" ?> <outfiles> <file> <ad32>aaaaaaa</ad32> <surl>some_surl1</surl> <lfn>some_lfn</lfn> <dataset>some_dataset</dataset> <date>11/11/11</date> <guid>ababa22</guid> <size>123</size> </file> </outfiles> :param dictionary: dictionary created with XMLDictionary. :return: xml (pretty printed for python >= 2.7 - for older python, use the convert_to_prettyprint() function). """ failed = False single_file_tag = list(dictionary.keys()) # Python 2/3 if len(single_file_tag) != 1: logger.warning("unexpected format - expected single entry, got %d entries", len(single_file_tag)) logger.warning('dictionary = %s', str(dictionary)) return None file_tag = single_file_tag[0] root = ElementTree.Element(file_tag) file_list = dictionary[file_tag] if isinstance(file_list, list): for file_entry in file_list: if isinstance(file_entry, dict) and len(file_entry) == 1: single_entry = list(file_entry.keys())[0] # Python 2/3 # add the 'file' element file_element = ElementTree.Element(single_entry) root.append(file_element) file_dictionary = file_entry[single_entry] if isinstance(file_dictionary, dict): for dictionary_entry in list(file_dictionary.keys()): # Python 2/3 # convert all entries to xml elements entry = ElementTree.SubElement(file_element, dictionary_entry) entry.text = file_dictionary[dictionary_entry] else: logger.warning("unexpected format - expected a dictionary, got %s", str(file_dictionary)) failed = True else: logger.warning("unexpected format - expected a length 1 dictionary, got %s", str(file_entry)) failed = True else: logger.warning("unexpected format - expected a list, got %s", str(file_list)) failed = True if failed: return None # generate pretty print return minidom.parseString(ElementTree.tostring(root)).toprettyxml(indent=" ")
[docs] def convert_to_prettyprint(xmlstr): """ Convert XML to pretty print for older python versions (< 2.7). :param xmlstr: input XML string :return: XML string (pretty printed) """ text_re = re.compile(r'>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) # Python 3 (added r) return text_re.sub(r'>\g<1></', xmlstr) # Python 3 (added r)