view configmix/variables.py @ 43:0e9f1f875ab0

A new PY variable namespace with some variables about the Python implementation and version
author Franz Glasner <f.glasner@feldmann-mg.com>
date Tue, 19 Apr 2016 12:22:15 +0200
parents 3ee21f868440
children b42e9936df2d
line wrap: on
line source

# -*- coding: utf-8 -*-
r"""Variable expansion: namespaces and filters

"""

from __future__ import division, absolute_import, print_function

import os
from functools import wraps

from .compat import PY2, text_to_native_os_str, native_os_str_to_text, u


__all__ = []


_MARKER = object()


def _envlookup(name, default=_MARKER):
    """Lookup an environment variable"""
    try:
        return native_os_str_to_text(os.environ[name])
    except KeyError:
        if default is _MARKER:
            raise
        else:
            return default


def _oslookup(name, default=_MARKER):
    """Lookup an environment variable"""
    if name == "cwd":
        return native_os_str_to_text(os.getcwd())
    raise KeyError("key %r not found in the namespace" % name)


def _pylookup(name, default=_MARKER):
    """Lookup a Python specific variable"""
    import platform
    if name == "version":
        return u(platform.python_version())
    elif name == "implementation":
        return  u(platform.python_implementation())
    elif name == "version_maj_min":
        t = platform.python_version_tuple()
        return u('.'.join(t[:2]))
    elif name == "version_maj":
        t = platform.python_version_tuple()
        return u(t[0])
    else:
        if default is _MARKER:
            raise KeyError("variable %r not found in namespace PY" % name)
        else:
            return default


_varns_registry = {
    "ENV": _envlookup,
    "OS": _oslookup,
    "PY": _pylookup
}


def lookup_varns(name):
    return _varns_registry[_normalized(name)]


_filter_registry = {}


def add_filter(name, fn):
    _filter_registry[_normalized(name)] = fn


def lookup_filter(name):
    return _filter_registry[_normalized(name)]


def filter(name):
    """Decorator for a filter function"""

    def _decorator(f):

        @wraps(f)
        def _f(appconfig, v):
            return f(appconfig, v)

        add_filter(name, _f)
        return _f

    return _decorator


def _normalized(name):
    return name.replace('-', '_')


#
# Some pre-defined filter functions
#
if PY2:

    @filter("urlquote")
    def urlquote(config, v):
        """Replace all special characters in string using the ``%xx`` escape"""
        from urllib import quote
        return quote(v.encode("utf-8"), safe=b"").decode("utf-8")

else:

    @filter("urlquote")
    def urlquote(config, v):
        """Replace all special characters in string using the ``%xx`` escape"""
        from urllib.parse import quote
        return quote(v, safe="")


@filter("saslprep")
def saslprep(config, v):
    """Do a `SASLprep` according to RFC4013 on `v`.

    This is a Stringprep Profile for usernames and passwords

    """
    import passlib.utils
    return passlib.utils.saslprep(v)


@filter("normpath")
def normpath_impl(config, v):
    return os.path.normpath(v)


@filter("abspath")
def abspath_impl(config, v):
    return os.path.abspath(v)


@filter("posixpath")
def posixpath_impl(config, v):
    return v.replace(u('\\'), u('/'))