| 1 |
"""Auxillary methods for the UDD"""
|
| 2 |
|
| 3 |
import yaml
|
| 4 |
import sys
|
| 5 |
import psycopg2
|
| 6 |
from os import path
|
| 7 |
import fcntl
|
| 8 |
import re
|
| 9 |
from email.Utils import parseaddr
|
| 10 |
|
| 11 |
# If debug is something that evaluates to True, then print_debug actually prints something
|
| 12 |
debug = 0
|
| 13 |
|
| 14 |
def quote(s):
|
| 15 |
"Quote a string for SQL and encode it to UTF-8 if it is a unicode string"
|
| 16 |
if isinstance(s, unicode):
|
| 17 |
s = s.encode('utf-8')
|
| 18 |
return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'"
|
| 19 |
|
| 20 |
def null_or_quote(dict, key):
|
| 21 |
"If key is an element of dict, return it quoted. Return NULL otherwise"
|
| 22 |
if key in dict:
|
| 23 |
return quote(dict[key])
|
| 24 |
else:
|
| 25 |
return 'NULL'
|
| 26 |
|
| 27 |
class ConfigException(Exception):
|
| 28 |
def __init__(self, message):
|
| 29 |
Exception(self)
|
| 30 |
self.message = message
|
| 31 |
|
| 32 |
def __str__(self):
|
| 33 |
return "ConfigException: " + self.message
|
| 34 |
|
| 35 |
def open_connection(config):
|
| 36 |
"""Open the connection to the database and return it"""
|
| 37 |
if 'dbport' in config['general']:
|
| 38 |
p = " port=" + str(config['general']['dbport'])
|
| 39 |
else:
|
| 40 |
p = ""
|
| 41 |
c = psycopg2.connect("dbname=" + config['general']['dbname'] + p)
|
| 42 |
c.set_client_encoding("UTF8")
|
| 43 |
return c
|
| 44 |
|
| 45 |
__locks = {}
|
| 46 |
def lock(config, source):
|
| 47 |
lock_dir = config['general']['lock-dir']
|
| 48 |
lock_path = path.join(lock_dir, source)
|
| 49 |
f = file(lock_path, "w+")
|
| 50 |
__locks[lock_path] = f
|
| 51 |
try:
|
| 52 |
fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
| 53 |
except IOError:
|
| 54 |
print source+": lockfile found, exiting."
|
| 55 |
exit(1)
|
| 56 |
|
| 57 |
def unlock(config, source):
|
| 58 |
lock_dir = config['general']['lock-dir']
|
| 59 |
lock_path = path.join(lock_dir, source)
|
| 60 |
if lock_path in __locks:
|
| 61 |
f = file(lock_path)
|
| 62 |
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
|
| 63 |
del __locks[lock_path]
|
| 64 |
|
| 65 |
def load_config(str):
|
| 66 |
"""Load and check configuration from the string"""
|
| 67 |
config = yaml.load(str)
|
| 68 |
if not 'general' in config:
|
| 69 |
raise ConfigException('general section not specified')
|
| 70 |
|
| 71 |
general = config['general']
|
| 72 |
for k in ['dbname', 'archs', 'types', 'lock-dir']:
|
| 73 |
if not k in general:
|
| 74 |
raise ConfigException(k + ' not specified in node "general"')
|
| 75 |
if not 'debug' in general:
|
| 76 |
general['debug'] = 0
|
| 77 |
|
| 78 |
# Check that the source-entries are well-formed
|
| 79 |
for name in config:
|
| 80 |
if name == 'general':
|
| 81 |
continue
|
| 82 |
|
| 83 |
src = config[name]
|
| 84 |
if not 'type' in src:
|
| 85 |
raise ConfigException('type not specified for "%s"' % name)
|
| 86 |
if src['type'] not in general['types']:
|
| 87 |
raise ConfigException('Type of %s not specified in types' % name)
|
| 88 |
|
| 89 |
return config
|
| 90 |
|
| 91 |
def print_debug(*args):
|
| 92 |
"Print arguments to stdout if debug is set to something that evaluates to true"
|
| 93 |
if debug:
|
| 94 |
sys.stdout.write(*args)
|
| 95 |
sys.stdout.write("\n")
|
| 96 |
|
| 97 |
def parse_email(str):
|
| 98 |
"""Use email.Utils to parse name and email. Afterwards check whether it was successful and try harder to get a reasonable address"""
|
| 99 |
name, email = parseaddr(str)
|
| 100 |
# if no '@' is detected in email but string contains a '@' anyway try harder to get a reasonable Mail address
|
| 101 |
if email.find('@') == -1 and str.find('@') != -1:
|
| 102 |
email = re.sub('^[^<]+[<\(]([.\w]+@[.\w]+)[>\)].*', '\\1', str)
|
| 103 |
name = re.sub('^[^\w]*([^<]+[.\w\)\]]) *[<\(][.\w]+@[.\w]+[>\)].*', '\\1', str)
|
| 104 |
print_debug("parse_email: %s ---> %s <%s>" % (str, name, email))
|
| 105 |
return name, email
|
| 106 |
|
| 107 |
def validutf8(str):
|
| 108 |
try:
|
| 109 |
str.decode('utf-8')
|
| 110 |
return True
|
| 111 |
except UnicodeDecodeError:
|
| 112 |
return False
|