# -*- coding: utf-8 -*- ''' feedgen.util ~~~~~~~~~~~~ This file contains helper functions for the feed generator module. :copyright: 2013, Lars Kiesow :license: FreeBSD and LGPL, see license.* for more details. ''' import locale import sys import lxml # nosec - we configure a safe parser below # Configure a safe parser which does not allow XML entity expansion parser = lxml.etree.XMLParser( attribute_defaults=False, dtd_validation=False, load_dtd=False, no_network=True, recover=False, remove_pis=True, resolve_entities=False, huge_tree=False) def xml_fromstring(xmlstring): return lxml.etree.fromstring(xmlstring, parser) # nosec - safe parser def xml_elem(name, parent=None, **kwargs): if parent is not None: return lxml.etree.SubElement(parent, name, **kwargs) return lxml.etree.Element(name, **kwargs) def ensure_format(val, allowed, required, allowed_values=None, defaults=None): '''Takes a dictionary or a list of dictionaries and check if all keys are in the set of allowed keys, if all required keys are present and if the values of a specific key are ok. :param val: Dictionaries to check. :param allowed: Set of allowed keys. :param required: Set of required keys. :param allowed_values: Dictionary with keys and sets of their allowed values. :param defaults: Dictionary with default values. :returns: List of checked dictionaries. ''' if not val: return [] if allowed_values is None: allowed_values = {} if defaults is None: defaults = {} # Make shure that we have a list of dicts. Even if there is only one. if not isinstance(val, list): val = [val] for elem in val: if not isinstance(elem, dict): raise ValueError('Invalid data (value is no dictionary)') # Set default values version = sys.version_info[0] if version == 2: items = defaults.iteritems() else: items = defaults.items() for k, v in items: elem[k] = elem.get(k, v) if not set(elem.keys()) <= allowed: raise ValueError('Data contains invalid keys') if not set(elem.keys()) >= required: raise ValueError('Data contains not all required keys') if version == 2: values = allowed_values.iteritems() else: values = allowed_values.items() for k, v in values: if elem.get(k) and not elem[k] in v: raise ValueError('Invalid value for %s' % k) return val def formatRFC2822(date): '''Make sure the locale setting do not interfere with the time format. ''' old = locale.setlocale(locale.LC_ALL) locale.setlocale(locale.LC_ALL, 'C') date = date.strftime('%a, %d %b %Y %H:%M:%S %z') locale.setlocale(locale.LC_ALL, old) return date