1# -*- coding: utf-8 -*-
2#
3# (c) 2018, Toshio Kuratomi <a.badger@gmail.com>
4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5#
6# Note that the original author of this, Toshio Kuratomi, is trying to submit this to six.  If
7# successful, the code in six will be available under six's more liberal license:
8# https://mail.python.org/pipermail/python-porting/2018-July/000539.html
9
10# Make coding more python3-ish
11from __future__ import (absolute_import, division, print_function)
12__metaclass__ = type
13
14import os
15import sys
16
17from ansible.module_utils.six import PY3
18from ansible.module_utils._text import to_bytes, to_text
19from ansible.module_utils.common._collections_compat import MutableMapping
20
21__all__ = ('environ',)
22
23
24class _TextEnviron(MutableMapping):
25    """
26    Utility class to return text strings from the environment instead of byte strings
27
28    Mimics the behaviour of os.environ on Python3
29    """
30    def __init__(self, env=None, encoding=None):
31        if env is None:
32            env = os.environ
33        self._raw_environ = env
34        self._value_cache = {}
35        # Since we're trying to mimic Python3's os.environ, use sys.getfilesystemencoding()
36        # instead of utf-8
37        if encoding is None:
38            # Since we're trying to mimic Python3's os.environ, use sys.getfilesystemencoding()
39            # instead of utf-8
40            self.encoding = sys.getfilesystemencoding()
41        else:
42            self.encoding = encoding
43
44    def __delitem__(self, key):
45        del self._raw_environ[key]
46
47    def __getitem__(self, key):
48        value = self._raw_environ[key]
49        if PY3:
50            return value
51        # Cache keys off of the undecoded values to handle any environment variables which change
52        # during a run
53        if value not in self._value_cache:
54            self._value_cache[value] = to_text(value, encoding=self.encoding,
55                                               nonstring='passthru', errors='surrogate_or_strict')
56        return self._value_cache[value]
57
58    def __setitem__(self, key, value):
59        self._raw_environ[key] = to_bytes(value, encoding=self.encoding, nonstring='strict',
60                                          errors='surrogate_or_strict')
61
62    def __iter__(self):
63        return self._raw_environ.__iter__()
64
65    def __len__(self):
66        return len(self._raw_environ)
67
68
69environ = _TextEnviron(encoding='utf-8')
70