Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

177 lines (135 sloc) 4.34 kb
import sys
import re
import os, os.path as op
import shlex
import imp
import json
from subprocess import Popen, PIPE
from configparser import ConfigParser, ExtendedInterpolation
from termcolor import cprint
if sys.version_info[0] == 3:
shell_split = shlex.split
else:
def shell_split(cmd):
return shlex.split(cmd.encode('utf-8'))
NUM_RE = re.compile('(\d+)')
class NomadError(Exception):
pass
class NomadIniNotFound(Exception):
pass
def cachedproperty(f):
"""Returns a cached property that is calculated by function f
"""
def get(self):
try:
return self._property_cache[f]
except AttributeError:
self._property_cache = {}
except KeyError:
pass
x = self._property_cache[f] = f(self)
return x
return property(get)
def abort(msg, code=1):
cprint('Error: %s' % msg, 'red', file=sys.stderr)
sys.exit(code)
def shsplit(s):
if not isinstance(s, str):
s = s.encode('utf-8')
return shlex.split(s)
def humankey(fn):
'''Turn a string into a list of substrings and numbers.
This can be used as a key function for ``sorted``::
>>> s = lambda *x: list(sorted(x, key=humankey))
>>> print s('up-1', 'up-5', 'up-15', 'up-50')
['up-1', 'up-5', 'up-15', 'up-50']
>>> print s('up-1.sql', 'up.sql', 'up1.sql')
['up.sql', 'up1.sql', 'up-1.sql']
>>> print s('up.rb', 'up.py') # check extension sorting
['up.py', 'up.rb']
'''
fn, ext = os.path.splitext(fn)
return [int(s) if s.isdigit() else s for s in NUM_RE.split(fn)], ext
def loadpath(path):
modname = 'nomad_url_%s' % path.replace('/', '_').replace('.', '_')
path = op.expanduser(op.expandvars(path))
if op.isdir(path):
# path/__init__.py
d, f = op.split(path.rstrip('/'))
fd, fpath, desc = imp.find_module(f, [d])
return imp.load_module(modname, fd, fpath, desc)
else:
return imp.load_source(modname, path)
def clean_sql(sql):
return '\n'.join(x for x in sql.split('\n')
if not x.strip().startswith('--'))
### URL retrievers
def get_python(path):
pypath, attr = path.split(':')
if '/' in pypath or pypath.endswith('.py'):
# load from file
mod = loadpath(pypath)
else:
# load from sys.path
mod = __import__(pypath, {}, {}, [''])
try:
return reduce(lambda x, y: getattr(x, y), attr.split('.'), mod)
except AttributeError:
raise AttributeError("No attr '%s' in module %s" % (attr, pypath))
def get_file(path):
return open(path).read().strip()
def get_command(cmd):
p1 = Popen(shell_split(cmd), stdout=PIPE)
return p1.communicate()[0].strip().decode('utf-8')
def get_json(path):
fn, path = path.split(':')
obj = json.load(open(fn))
path = map(lambda x: int(x) if x.isdigit() else x, path.split('.'))
return reduce(lambda x, y: x[y], path, obj)
def get_ini(path):
fn, path = path.split(':')
section, key = path.split('.')
cfg = ConfigParser(interpolation=ExtendedInterpolation())
cfg.read([fn])
try:
return cfg[section][key]
except KeyError:
raise KeyError('%s not found in %s' % (path, fn))
def get_yaml(path):
try:
import yaml
except ImportError:
abort('Please, install PyYAML to parse YAML config.')
fn, path = path.split(':')
obj = yaml.load(open(fn))
path = map(lambda x: int(x) if x.isdigit() else x, path.split('.'))
return reduce(lambda x, y: x[y], path, obj)
def get_env(key):
return os.environ[key]
URLTYPES = {
'python': get_python,
'py': get_python,
'file': get_file,
'command': get_command,
'cmd': get_command,
'json': get_json,
'ini': get_ini,
'yaml': get_yaml,
'env': get_env,
}
def geturl(urlspec):
for url in shsplit(urlspec):
bits = url.split(':', 1)
if len(bits) > 1 and bits[0] in URLTYPES:
try:
url = URLTYPES[bits[0]](bits[1])
if url:
return url
except (IOError, OSError, KeyError):
pass
else:
return url
abort("could not read database url from spec '%s'" % urlspec)
if __name__ == '__main__':
import doctest
doctest.testmod()
Jump to Line
Something went wrong with that request. Please try again.