changeset 15:0b1292e920af

Variables: namespaces and filters
author Franz Glasner <f.glasner@feldmann-mg.com>
date Wed, 09 Mar 2016 15:35:46 +0100
parents 36fa039f7e11
children f85dc4677c01
files configmix/compat.py configmix/variables.py
diffstat 2 files changed, 126 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/configmix/compat.py	Wed Mar 09 12:06:46 2016 +0100
+++ b/configmix/compat.py	Wed Mar 09 15:35:46 2016 +0100
@@ -3,10 +3,39 @@
 
 """
 
+from __future__ import division, absolute_import, print_function
+
 import sys
+import locale
 
 
-__all__ = []
+__all__ = ["PY2",
+           "text_to_native_os_str",
+           "native_os_str_to_text"]
 
 
 PY2 = sys.version_info[0] <= 2
+
+
+if PY2:
+
+    _OS_ENCODING = locale.getpreferredencoding()
+
+    def text_to_native_os_str(s, encoding=None):
+        if isinstance(s, unicode):
+            return s.encode(encoding or _OS_ENCODING)
+        else:
+            return s
+
+
+    def native_os_str_to_text(s, encoding=None):
+        return s.decode(encoding or _OS_ENCODING)
+
+else:
+
+    def text_to_native_os_str(s, encoding=None):
+        return s
+
+
+    def native_os_str_to_text(s, encoding=None):
+        return s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configmix/variables.py	Wed Mar 09 15:35:46 2016 +0100
@@ -0,0 +1,96 @@
+# -*- 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
+
+
+__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
+
+
+_varns_registry = {"ENV": _envlookup}
+
+
+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)