1# Licensed under a 3-clause BSD style license - see LICENSE.rst
2"""
3Simple utility functions and bug fixes for compatibility with all supported
4versions of Python.  This module should generally not be used directly, as
5everything in `__all__` will be imported into `astropy.utils.compat` and can
6be accessed from there.
7"""
8
9import sys
10import functools
11from contextlib import suppress
12
13
14__all__ = ['override__dir__', 'suppress',
15           'possible_filename', 'namedtuple_asdict']
16
17
18def possible_filename(filename):
19    """
20    Determine if the ``filename`` argument is an allowable type for a filename.
21
22    In Python 3.3 use of non-unicode filenames on system calls such as
23    `os.stat` and others that accept a filename argument was deprecated (and
24    may be removed outright in the future).
25
26    Therefore this returns `True` in all cases except for `bytes` strings in
27    Windows.
28    """
29
30    if isinstance(filename, str):
31        return True
32    elif isinstance(filename, bytes):
33        return not (sys.platform == 'win32')
34
35    return False
36
37
38def override__dir__(f):
39    """
40    When overriding a __dir__ method on an object, you often want to
41    include the "standard" members on the object as well.  This
42    decorator takes care of that automatically, and all the wrapped
43    function needs to do is return a list of the "special" members
44    that wouldn't be found by the normal Python means.
45
46    Example
47    -------
48
49    Your class could define __dir__ as follows::
50
51        @override__dir__
52        def __dir__(self):
53            return ['special_method1', 'special_method2']
54    """
55    # http://bugs.python.org/issue12166
56
57    @functools.wraps(f)
58    def override__dir__wrapper(self):
59        members = set(object.__dir__(self))
60        members.update(f(self))
61        return sorted(members)
62
63    return override__dir__wrapper
64
65
66def namedtuple_asdict(namedtuple):
67    """
68    The same as ``namedtuple._adict()``.
69
70    Parameters
71    ----------
72    namedtuple : collections.namedtuple
73    The named tuple to get the dict of
74    """
75    return namedtuple._asdict()
76