1"""Miscellaneous utility functions and classes.
2
3This module is used internally by Tornado.  It is not necessarily expected
4that the functions and classes defined here will be useful to other
5applications, but they are documented here in case they are.
6
7The one public-facing part of this module is the `Configurable` class
8and its `~Configurable.configure` method, which becomes a part of the
9interface of its subclasses, including `.AsyncHTTPClient`, `.IOLoop`,
10and `.Resolver`.
11"""
12
13from __future__ import absolute_import, division, print_function, with_statement
14
15import sys
16
17
18def import_object(name):
19    """Imports an object by name.
20
21    import_object('x') is equivalent to 'import x'.
22    import_object('x.y.z') is equivalent to 'from x.y import z'.
23
24    >>> import tornado.escape
25    >>> import_object('tornado.escape') is tornado.escape
26    True
27    >>> import_object('tornado.escape.utf8') is tornado.escape.utf8
28    True
29    >>> import_object('tornado') is tornado
30    True
31    >>> import_object('tornado.missing_module')
32    Traceback (most recent call last):
33        ...
34    ImportError: No module named missing_module
35    """
36    if name.count('.') == 0:
37        return __import__(name, None, None)
38
39    parts = name.split('.')
40    obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
41    try:
42        return getattr(obj, parts[-1])
43    except AttributeError:
44        raise ImportError("No module named %s" % parts[-1])
45
46
47# Fake unicode literal support:  Python 3.2 doesn't have the u'' marker for
48# literal strings, and alternative solutions like "from __future__ import
49# unicode_literals" have other problems (see PEP 414).  u() can be applied
50# to ascii strings that include \u escapes (but they must not contain
51# literal non-ascii characters).
52if type('') is not type(b''):
53    def u(s):
54        return s
55    bytes_type = bytes
56    unicode_type = str
57    basestring_type = str
58else:
59    def u(s):
60        return s.decode('unicode_escape')
61    bytes_type = str
62    unicode_type = unicode
63    basestring_type = basestring
64
65
66if sys.version_info > (3,):
67    exec("""
68def raise_exc_info(exc_info):
69    raise exc_info[1].with_traceback(exc_info[2])
70
71def exec_in(code, glob, loc=None):
72    if isinstance(code, str):
73        code = compile(code, '<string>', 'exec', dont_inherit=True)
74    exec(code, glob, loc)
75""")
76else:
77    exec("""
78def raise_exc_info(exc_info):
79    raise exc_info[0], exc_info[1], exc_info[2]
80
81def exec_in(code, glob, loc=None):
82    if isinstance(code, basestring):
83        # exec(string) inherits the caller's future imports; compile
84        # the string first to prevent that.
85        code = compile(code, '<string>', 'exec', dont_inherit=True)
86    exec code in glob, loc
87""")
88
89
90class Configurable(object):
91    """Base class for configurable interfaces.
92
93    A configurable interface is an (abstract) class whose constructor
94    acts as a factory function for one of its implementation subclasses.
95    The implementation subclass as well as optional keyword arguments to
96    its initializer can be set globally at runtime with `configure`.
97
98    By using the constructor as the factory method, the interface
99    looks like a normal class, `isinstance` works as usual, etc.  This
100    pattern is most useful when the choice of implementation is likely
101    to be a global decision (e.g. when `~select.epoll` is available,
102    always use it instead of `~select.select`), or when a
103    previously-monolithic class has been split into specialized
104    subclasses.
105
106    Configurable subclasses must define the class methods
107    `configurable_base` and `configurable_default`, and use the instance
108    method `initialize` instead of ``__init__``.
109    """
110    __impl_class = None
111    __impl_kwargs = None
112
113    def __new__(cls, **kwargs):
114        base = cls.configurable_base()
115        args = {}
116        if cls is base:
117            impl = cls.configured_class()
118            if base.__impl_kwargs:
119                args.update(base.__impl_kwargs)
120        else:
121            impl = cls
122        args.update(kwargs)
123        instance = super(Configurable, cls).__new__(impl)
124        # initialize vs __init__ chosen for compatiblity with AsyncHTTPClient
125        # singleton magic.  If we get rid of that we can switch to __init__
126        # here too.
127        instance.initialize(**args)
128        return instance
129
130    @classmethod
131    def configurable_base(cls):
132        """Returns the base class of a configurable hierarchy.
133
134        This will normally return the class in which it is defined.
135        (which is *not* necessarily the same as the cls classmethod parameter).
136        """
137        raise NotImplementedError()
138
139    @classmethod
140    def configurable_default(cls):
141        """Returns the implementation class to be used if none is configured."""
142        raise NotImplementedError()
143
144    def initialize(self):
145        """Initialize a `Configurable` subclass instance.
146
147        Configurable classes should use `initialize` instead of ``__init__``.
148        """
149
150    @classmethod
151    def configure(cls, impl, **kwargs):
152        """Sets the class to use when the base class is instantiated.
153
154        Keyword arguments will be saved and added to the arguments passed
155        to the constructor.  This can be used to set global defaults for
156        some parameters.
157        """
158        base = cls.configurable_base()
159        if isinstance(impl, (unicode_type, bytes_type)):
160            impl = import_object(impl)
161        if impl is not None and not issubclass(impl, cls):
162            raise ValueError("Invalid subclass of %s" % cls)
163        base.__impl_class = impl
164        base.__impl_kwargs = kwargs
165
166    @classmethod
167    def configured_class(cls):
168        """Returns the currently configured class."""
169        base = cls.configurable_base()
170        if cls.__impl_class is None:
171            base.__impl_class = cls.configurable_default()
172        return base.__impl_class
173
174    @classmethod
175    def _save_configuration(cls):
176        base = cls.configurable_base()
177        return (base.__impl_class, base.__impl_kwargs)
178
179    @classmethod
180    def _restore_configuration(cls, saved):
181        base = cls.configurable_base()
182        base.__impl_class = saved[0]
183        base.__impl_kwargs = saved[1]
184
185