• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Licensed under the Apache License, Version 2.0 (the "License");
2# you may not use this file except in compliance with the License.
3# You may obtain a copy of the License at
4#
5#      http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS,
9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10# See the License for the specific language governing permissions and
11# limitations under the License.
12
13"""
14Provides patches for some commonly used modules that enable them to work
15with pyfakefs.
16"""
17import sys
18
19try:
20    import pandas.io.parsers as parsers
21except ImportError:
22    parsers = None
23
24try:
25    import xlrd
26except ImportError:
27    xlrd = None
28
29try:
30    from django.core.files import locks
31except ImportError:
32    locks = None
33
34
35def get_modules_to_patch():
36    modules_to_patch = {}
37    if xlrd is not None:
38        modules_to_patch['xlrd'] = XLRDModule
39    if locks is not None:
40        modules_to_patch['django.core.files.locks'] = FakeLocks
41    return modules_to_patch
42
43
44def get_classes_to_patch():
45    classes_to_patch = {}
46    if parsers is not None:
47        classes_to_patch[
48            'TextFileReader'
49        ] = 'pandas.io.parsers'
50    return classes_to_patch
51
52
53def get_fake_module_classes():
54    fake_module_classes = {}
55    if parsers is not None:
56        fake_module_classes[
57            'TextFileReader'
58        ] = FakeTextFileReader
59    return fake_module_classes
60
61
62if xlrd is not None:
63    class XLRDModule:
64        """Patches the xlrd module, which is used as the default Excel file
65        reader by pandas. Disables using memory mapped files, which are
66        implemented platform-specific on OS level."""
67
68        def __init__(self, _):
69            self._xlrd_module = xlrd
70
71        def open_workbook(self, filename=None,
72                          logfile=sys.stdout,
73                          verbosity=0,
74                          use_mmap=False,
75                          file_contents=None,
76                          encoding_override=None,
77                          formatting_info=False,
78                          on_demand=False,
79                          ragged_rows=False):
80            return self._xlrd_module.open_workbook(
81                filename, logfile, verbosity, False, file_contents,
82                encoding_override, formatting_info, on_demand, ragged_rows)
83
84        def __getattr__(self, name):
85            """Forwards any unfaked calls to the standard xlrd module."""
86            return getattr(self._xlrd_module, name)
87
88if parsers is not None:
89    # we currently need to add fake modules for both the parser module and
90    # the contained text reader - maybe this can be simplified
91
92    class FakeTextFileReader:
93        fake_parsers = None
94
95        def __init__(self, filesystem):
96            if self.fake_parsers is None:
97                self.__class__.fake_parsers = ParsersModule(filesystem)
98
99        def __call__(self, *args, **kwargs):
100            return self.fake_parsers.TextFileReader(*args, **kwargs)
101
102        def __getattr__(self, name):
103            return getattr(self.fake_parsers.TextFileReader, name)
104
105    class ParsersModule:
106        def __init__(self, _):
107            self._parsers_module = parsers
108
109        class TextFileReader(parsers.TextFileReader):
110            def __init__(self, *args, **kwargs):
111                kwargs['engine'] = 'python'
112                super().__init__(*args, **kwargs)
113
114        def __getattr__(self, name):
115            """Forwards any unfaked calls to the standard xlrd module."""
116            return getattr(self._parsers_module, name)
117
118if locks is not None:
119    class FakeLocks:
120        """django.core.files.locks uses low level OS functions, fake it."""
121        _locks_module = locks
122
123        def __init__(self, _):
124            pass
125
126        @staticmethod
127        def lock(f, flags):
128            return True
129
130        @staticmethod
131        def unlock(f):
132            return True
133
134        def __getattr__(self, name):
135            return getattr(self._locks_module, name)
136