We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Why is there no asser_in in nose.tools on py2.7?
This makes me jump through hoops when writing tests.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `vispy/util/misc.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright (c) 2014, Vispy Development Team.
3 # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4 
5 """Miscellaneous functions
6 """
7 
8 import numpy as np
9 import tempfile
10 import atexit
11 from shutil import rmtree
12 import sys
13 import platform
14 import getopt
15 from os import path as op
16 import traceback
17 
18 from .six import string_types
19 from .event import EmitterGroup, EventEmitter, Event
20 from ._logging import logger, set_log_level, use_log_level
21 
22 
23 class _TempDir(str):
24 
25     """Class for creating and auto-destroying temp dir
26 
27     This is designed to be used with testing modules.
28 
29     We cannot simply use __del__() method for cleanup here because the rmtree
30     function may be cleaned up before this object, so we use the atexit module
31     instead.
32     """
33 
34     def __new__(self):
35         new = str.__new__(self, tempfile.mkdtemp())
36         return new
37 
38     def __init__(self):
39         self._path = self.__str__()
40         atexit.register(self.cleanup)
41 
42     def cleanup(self):
43         rmtree(self._path, ignore_errors=True)
44 
45 
46 def is_string(s):
47     return isinstance(s, string_types)
48 
49 
50 ###############################################################################
51 # These fast normal calculation routines are adapted from mne-python
52 
53 def _fast_cross_3d(x, y):
54     """Compute cross product between list of 3D vectors
55 
56     Much faster than np.cross() when the number of cross products
57     becomes large (>500). This is because np.cross() methods become
58     less memory efficient at this stage.
59 
60     Parameters
61     ----------
62     x : array
63         Input array 1.
64     y : array
65         Input array 2.
66 
67     Returns
68     -------
69     z : array
70         Cross product of x and y.
71 
72     Notes
73     -----
74     x and y must both be 2D row vectors. One must have length 1, or both
75     lengths must match.
76     """
77     assert x.ndim == 2
78     assert y.ndim == 2
79     assert x.shape[1] == 3
80     assert y.shape[1] == 3
81     assert (x.shape[0] == 1 or y.shape[0] == 1) or x.shape[0] == y.shape[0]
82     if max([x.shape[0], y.shape[0]]) >= 500:
83         return np.c_[x[:, 1] * y[:, 2] - x[:, 2] * y[:, 1],
84                      x[:, 2] * y[:, 0] - x[:, 0] * y[:, 2],
85                      x[:, 0] * y[:, 1] - x[:, 1] * y[:, 0]]
86     else:
87         return np.cross(x, y)
88 
89 
90 def _calculate_normals(rr, tris):
91     """Efficiently compute vertex normals for triangulated surface"""
92     # ensure highest precision for our summation/vectorization "trick"
93     rr = rr.astype(np.float64)
94     # first, compute triangle normals
95     r1 = rr[tris[:, 0], :]
96     r2 = rr[tris[:, 1], :]
97     r3 = rr[tris[:, 2], :]
98     tri_nn = _fast_cross_3d((r2 - r1), (r3 - r1))
99 
100     #   Triangle normals and areas
101     size = np.sqrt(np.sum(tri_nn * tri_nn, axis=1))
102     size[size == 0] = 1.0  # prevent ugly divide-by-zero
103     tri_nn /= size[:, np.newaxis]
104 
105     npts = len(rr)
106 
107     # the following code replaces this, but is faster (vectorized):
108     #
109     # for p, verts in enumerate(tris):
110     #     nn[verts, :] += tri_nn[p, :]
111     #
112     nn = np.zeros((npts, 3))
113     for verts in tris.T:  # note this only loops 3x (number of verts per tri)
114         for idx in range(3):  # x, y, z
115             nn[:, idx] += np.bincount(verts, tri_nn[:, idx], minlength=npts)
116     size = np.sqrt(np.sum(nn * nn, axis=1))
117     size[size == 0] = 1.0  # prevent ugly divide-by-zero
118     nn /= size[:, np.newaxis]
119     return nn
120 
121 
122 ###############################################################################
123 # CONFIG
124 
125 class ConfigEvent(Event):
126 
127     """ Event indicating a configuration change.
128 
129     This class has a 'changes' attribute which is a dict of all name:value
130     pairs that have changed in the configuration.
131     """
132 
133     def __init__(self, changes):
134         Event.__init__(self, type='config_change')
135         self.changes = changes
136 
137 
138 class Config(object):
139 
140     """ Container for global settings used application-wide in vispy.
141 
142     Events:
143     -------
144     Config.events.changed - Emits ConfigEvent whenever the configuration
145     changes.
146     """
147 
148     def __init__(self):
149         self.events = EmitterGroup(source=self)
150         self.events['changed'] = EventEmitter(
151             event_class=ConfigEvent,
152             source=self)
153         self._config = {}
154 
155     def __getitem__(self, item):
156         return self._config[item]
157 
158     def __setitem__(self, item, val):
159         self._config[item] = val
160         # inform any listeners that a configuration option has changed
161         self.events.changed(changes={item: val})
162 
163     def update(self, **kwds):
164         self._config.update(kwds)
165         self.events.changed(changes=kwds)
166 
167     def __repr__(self):
168         return repr(self._config)
169 
170 config = Config()
171 config.update(
172     default_backend='qt',
173     qt_lib='any',  # options are 'pyqt', 'pyside', or 'any'
174     show_warnings=False,
175     gl_debug=False,
176     logging_level='info',
177 )
178 
179 set_log_level(config['logging_level'])
180 
181 
182 def parse_command_line_arguments():
183     """ Transform vispy specific command line args to vispy config.
184     Put into a function so that any variables dont leak in the vispy namespace.
185     """
186     # Get command line args for vispy
187     argnames = ['vispy-backend', 'vispy-gl-debug']
188     try:
189         opts, args = getopt.getopt(sys.argv[1:], '', argnames)
190     except getopt.GetoptError:
191         opts = []
192     # Use them to set the config values
193     for o, a in opts:
194         if o.startswith('--vispy'):
195             if o == '--vispy-backend':
196                 config['default_backend'] = a
197                 logger.info('backend', a)
198             elif o == '--vispy-gl-debug':
199                 config['gl_debug'] = True
200             else:
201                 logger.warning("Unsupported vispy flag: %s" % o)
202 
203 
204 def sys_info(fname=None, overwrite=False):
205     """Get relevant system and debugging information
206 
207     Parameters
208     ----------
209     fname : str | None
210         Filename to dump info to. Use None to simply print.
211     overwrite : bool
212         If True, overwrite file (if it exists).
213 
214     Returns
215     -------
216     out : str
217         The system information as a string.
218     """
219     if fname is not None and op.isfile(fname) and not overwrite:
220         raise IOError('file exists, use overwrite=True to overwrite')
221 
222     out = ''
223     try:
224         # Nest all imports here to avoid any circular imports
225         from ..app import Application, Canvas, backends
226         from ..gloo import gl
227         # get default app
228         this_app = Application()
229         with use_log_level('warning'):
230             this_app.use()  # suppress unnecessary messages
231         out += 'Platform: %s\n' % platform.platform()
232         out += 'Python:   %s\n' % str(sys.version).replace('\n', ' ')
233         out += 'Backend:  %s\n' % this_app.backend_name
234         out += 'Qt:       %s\n' % backends.has_qt(return_which=True)[1]
235         out += 'Pyglet:   %s\n' % backends.has_pyglet(return_which=True)[1]
236         out += 'glfw:     %s\n' % backends.has_glfw(return_which=True)[1]
237         out += 'glut:     %s\n' % backends.has_glut(return_which=True)[1]
238         out += '\n'
239         # We need an OpenGL context to get GL info
240         if 'glut' in this_app.backend_name.lower():
241             # glut causes problems
242             out += 'OpenGL information omitted for glut backend\n'
243         else:
244             canvas = Canvas('Test', (10, 10), show=False, app=this_app)
245             canvas._backend._vispy_set_current()
246             out += 'GL version:  %s\n' % gl.glGetString(gl.GL_VERSION)
247             x_ = gl.GL_MAX_TEXTURE_SIZE
248             out += 'MAX_TEXTURE_SIZE: %d\n' % gl.glGetIntegerv(x_)
249             x_ = gl.ext.GL_MAX_3D_TEXTURE_SIZE
250             out += 'MAX_3D_TEXTURE_SIZE: %d\n\n' % gl.glGetIntegerv(x_)
251             out += 'Extensions: %s\n' % gl.glGetString(gl.GL_EXTENSIONS)
252             canvas.close()
253     except Exception:  # don't stop printing info
254         out += '\nInfo-gathering error:\n%s' % traceback.format_exc()
255         pass
256     if fname is not None:
257         with open(fname, 'w') as fid:
258             fid.write(out)
259     return out
260
```

Path: `vispy/util/__init__.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright (c) 2014, Vispy Development Team. All Rights Reserved.
3 # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4 
5 """ Utilities for Vispy. A collection of modules that are used in
6 one or more Vispy sub-packages.
7 """
8 
9 from .misc import (_TempDir, is_string, parse_command_line_arguments,  # noqa
10                    config, sys_info)  # noqa
11 from ._logging import logger, set_log_level, use_log_level  # noqa
12
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/vispy/util/__init__.py b/vispy/util/__init__.py
--- a/vispy/util/__init__.py
+++ b/vispy/util/__init__.py
@@ -7,5 +7,6 @@
 """
 
 from .misc import (_TempDir, is_string, parse_command_line_arguments,  # noqa
-                   config, sys_info)  # noqa
+                   config, sys_info, assert_in, assert_not_in,  # noqa
+                   assert_is)  # noqa
 from ._logging import logger, set_log_level, use_log_level  # noqa
diff --git a/vispy/util/misc.py b/vispy/util/misc.py
--- a/vispy/util/misc.py
+++ b/vispy/util/misc.py
@@ -257,3 +257,60 @@
         with open(fname, 'w') as fid:
             fid.write(out)
     return out
+
+
+# Adapted from Python's unittest2 (which is wrapped by nose)
+# http://docs.python.org/2/license.html
+def _safe_rep(obj, short=False):
+    """Helper for assert_* ports"""
+    try:
+        result = repr(obj)
+    except Exception:
+        result = object.__repr__(obj)
+    if not short or len(result) < 80:
+        return result
+    return result[:80] + ' [truncated]...'
+
+
+def _safe_str(obj):
+    """Helper for assert_* ports"""
+    try:
+        return str(obj)
+    except Exception:
+        return object.__str__(obj)
+
+
+def _format_msg(msg, std_msg):
+    """Helper for assert_* ports"""
+    if msg is None:
+        msg = std_msg
+    else:
+        try:
+            msg = '%s : %s' % (std_msg, msg)
+        except UnicodeDecodeError:
+            msg = '%s : %s' % (_safe_str(std_msg), _safe_str(msg))
+
+
+def assert_in(member, container, msg=None):
+    """Backport for old nose.tools"""
+    if member in container:
+        return
+    std_msg = '%s not found in %s' % (_safe_rep(member), _safe_rep(container))
+    msg = _format_msg(msg, std_msg)
+    raise AssertionError(msg)
+
+
+def assert_not_in(member, container, msg=None):
+    """Backport for old nose.tools"""
+    if member not in container:
+        return
+    std_msg = '%s found in %s' % (_safe_rep(member), _safe_rep(container))
+    msg = _format_msg(msg, std_msg)
+    raise AssertionError(msg)
+
+
+def assert_is(expr1, expr2, msg=None):
+    """Backport for old nose.tools"""
+    if expr1 is not expr2:
+        std_msg = '%s is not %s' % (_safe_rep(expr1), _safe_rep(expr2))
+        raise AssertionError(_format_msg(msg, std_msg))

{"golden_diff": "diff --git a/vispy/util/__init__.py b/vispy/util/__init__.py\n--- a/vispy/util/__init__.py\n+++ b/vispy/util/__init__.py\n@@ -7,5 +7,6 @@\n \"\"\"\n \n from .misc import (_TempDir, is_string, parse_command_line_arguments,  # noqa\n-                   config, sys_info)  # noqa\n+                   config, sys_info, assert_in, assert_not_in,  # noqa\n+                   assert_is)  # noqa\n from ._logging import logger, set_log_level, use_log_level  # noqa\ndiff --git a/vispy/util/misc.py b/vispy/util/misc.py\n--- a/vispy/util/misc.py\n+++ b/vispy/util/misc.py\n@@ -257,3 +257,60 @@\n         with open(fname, 'w') as fid:\n             fid.write(out)\n     return out\n+\n+\n+# Adapted from Python's unittest2 (which is wrapped by nose)\n+# http://docs.python.org/2/license.html\n+def _safe_rep(obj, short=False):\n+    \"\"\"Helper for assert_* ports\"\"\"\n+    try:\n+        result = repr(obj)\n+    except Exception:\n+        result = object.__repr__(obj)\n+    if not short or len(result) < 80:\n+        return result\n+    return result[:80] + ' [truncated]...'\n+\n+\n+def _safe_str(obj):\n+    \"\"\"Helper for assert_* ports\"\"\"\n+    try:\n+        return str(obj)\n+    except Exception:\n+        return object.__str__(obj)\n+\n+\n+def _format_msg(msg, std_msg):\n+    \"\"\"Helper for assert_* ports\"\"\"\n+    if msg is None:\n+        msg = std_msg\n+    else:\n+        try:\n+            msg = '%s : %s' % (std_msg, msg)\n+        except UnicodeDecodeError:\n+            msg = '%s : %s' % (_safe_str(std_msg), _safe_str(msg))\n+\n+\n+def assert_in(member, container, msg=None):\n+    \"\"\"Backport for old nose.tools\"\"\"\n+    if member in container:\n+        return\n+    std_msg = '%s not found in %s' % (_safe_rep(member), _safe_rep(container))\n+    msg = _format_msg(msg, std_msg)\n+    raise AssertionError(msg)\n+\n+\n+def assert_not_in(member, container, msg=None):\n+    \"\"\"Backport for old nose.tools\"\"\"\n+    if member not in container:\n+        return\n+    std_msg = '%s found in %s' % (_safe_rep(member), _safe_rep(container))\n+    msg = _format_msg(msg, std_msg)\n+    raise AssertionError(msg)\n+\n+\n+def assert_is(expr1, expr2, msg=None):\n+    \"\"\"Backport for old nose.tools\"\"\"\n+    if expr1 is not expr2:\n+        std_msg = '%s is not %s' % (_safe_rep(expr1), _safe_rep(expr2))\n+        raise AssertionError(_format_msg(msg, std_msg))\n", "issue": "Why is there no asser_in in nose.tools on py2.7?\nThis makes me jump through hoops when writing tests.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\n\"\"\"Miscellaneous functions\n\"\"\"\n\nimport numpy as np\nimport tempfile\nimport atexit\nfrom shutil import rmtree\nimport sys\nimport platform\nimport getopt\nfrom os import path as op\nimport traceback\n\nfrom .six import string_types\nfrom .event import EmitterGroup, EventEmitter, Event\nfrom ._logging import logger, set_log_level, use_log_level\n\n\nclass _TempDir(str):\n\n    \"\"\"Class for creating and auto-destroying temp dir\n\n    This is designed to be used with testing modules.\n\n    We cannot simply use __del__() method for cleanup here because the rmtree\n    function may be cleaned up before this object, so we use the atexit module\n    instead.\n    \"\"\"\n\n    def __new__(self):\n        new = str.__new__(self, tempfile.mkdtemp())\n        return new\n\n    def __init__(self):\n        self._path = self.__str__()\n        atexit.register(self.cleanup)\n\n    def cleanup(self):\n        rmtree(self._path, ignore_errors=True)\n\n\ndef is_string(s):\n    return isinstance(s, string_types)\n\n\n###############################################################################\n# These fast normal calculation routines are adapted from mne-python\n\ndef _fast_cross_3d(x, y):\n    \"\"\"Compute cross product between list of 3D vectors\n\n    Much faster than np.cross() when the number of cross products\n    becomes large (>500). This is because np.cross() methods become\n    less memory efficient at this stage.\n\n    Parameters\n    ----------\n    x : array\n        Input array 1.\n    y : array\n        Input array 2.\n\n    Returns\n    -------\n    z : array\n        Cross product of x and y.\n\n    Notes\n    -----\n    x and y must both be 2D row vectors. One must have length 1, or both\n    lengths must match.\n    \"\"\"\n    assert x.ndim == 2\n    assert y.ndim == 2\n    assert x.shape[1] == 3\n    assert y.shape[1] == 3\n    assert (x.shape[0] == 1 or y.shape[0] == 1) or x.shape[0] == y.shape[0]\n    if max([x.shape[0], y.shape[0]]) >= 500:\n        return np.c_[x[:, 1] * y[:, 2] - x[:, 2] * y[:, 1],\n                     x[:, 2] * y[:, 0] - x[:, 0] * y[:, 2],\n                     x[:, 0] * y[:, 1] - x[:, 1] * y[:, 0]]\n    else:\n        return np.cross(x, y)\n\n\ndef _calculate_normals(rr, tris):\n    \"\"\"Efficiently compute vertex normals for triangulated surface\"\"\"\n    # ensure highest precision for our summation/vectorization \"trick\"\n    rr = rr.astype(np.float64)\n    # first, compute triangle normals\n    r1 = rr[tris[:, 0], :]\n    r2 = rr[tris[:, 1], :]\n    r3 = rr[tris[:, 2], :]\n    tri_nn = _fast_cross_3d((r2 - r1), (r3 - r1))\n\n    #   Triangle normals and areas\n    size = np.sqrt(np.sum(tri_nn * tri_nn, axis=1))\n    size[size == 0] = 1.0  # prevent ugly divide-by-zero\n    tri_nn /= size[:, np.newaxis]\n\n    npts = len(rr)\n\n    # the following code replaces this, but is faster (vectorized):\n    #\n    # for p, verts in enumerate(tris):\n    #     nn[verts, :] += tri_nn[p, :]\n    #\n    nn = np.zeros((npts, 3))\n    for verts in tris.T:  # note this only loops 3x (number of verts per tri)\n        for idx in range(3):  # x, y, z\n            nn[:, idx] += np.bincount(verts, tri_nn[:, idx], minlength=npts)\n    size = np.sqrt(np.sum(nn * nn, axis=1))\n    size[size == 0] = 1.0  # prevent ugly divide-by-zero\n    nn /= size[:, np.newaxis]\n    return nn\n\n\n###############################################################################\n# CONFIG\n\nclass ConfigEvent(Event):\n\n    \"\"\" Event indicating a configuration change.\n\n    This class has a 'changes' attribute which is a dict of all name:value\n    pairs that have changed in the configuration.\n    \"\"\"\n\n    def __init__(self, changes):\n        Event.__init__(self, type='config_change')\n        self.changes = changes\n\n\nclass Config(object):\n\n    \"\"\" Container for global settings used application-wide in vispy.\n\n    Events:\n    -------\n    Config.events.changed - Emits ConfigEvent whenever the configuration\n    changes.\n    \"\"\"\n\n    def __init__(self):\n        self.events = EmitterGroup(source=self)\n        self.events['changed'] = EventEmitter(\n            event_class=ConfigEvent,\n            source=self)\n        self._config = {}\n\n    def __getitem__(self, item):\n        return self._config[item]\n\n    def __setitem__(self, item, val):\n        self._config[item] = val\n        # inform any listeners that a configuration option has changed\n        self.events.changed(changes={item: val})\n\n    def update(self, **kwds):\n        self._config.update(kwds)\n        self.events.changed(changes=kwds)\n\n    def __repr__(self):\n        return repr(self._config)\n\nconfig = Config()\nconfig.update(\n    default_backend='qt',\n    qt_lib='any',  # options are 'pyqt', 'pyside', or 'any'\n    show_warnings=False,\n    gl_debug=False,\n    logging_level='info',\n)\n\nset_log_level(config['logging_level'])\n\n\ndef parse_command_line_arguments():\n    \"\"\" Transform vispy specific command line args to vispy config.\n    Put into a function so that any variables dont leak in the vispy namespace.\n    \"\"\"\n    # Get command line args for vispy\n    argnames = ['vispy-backend', 'vispy-gl-debug']\n    try:\n        opts, args = getopt.getopt(sys.argv[1:], '', argnames)\n    except getopt.GetoptError:\n        opts = []\n    # Use them to set the config values\n    for o, a in opts:\n        if o.startswith('--vispy'):\n            if o == '--vispy-backend':\n                config['default_backend'] = a\n                logger.info('backend', a)\n            elif o == '--vispy-gl-debug':\n                config['gl_debug'] = True\n            else:\n                logger.warning(\"Unsupported vispy flag: %s\" % o)\n\n\ndef sys_info(fname=None, overwrite=False):\n    \"\"\"Get relevant system and debugging information\n\n    Parameters\n    ----------\n    fname : str | None\n        Filename to dump info to. Use None to simply print.\n    overwrite : bool\n        If True, overwrite file (if it exists).\n\n    Returns\n    -------\n    out : str\n        The system information as a string.\n    \"\"\"\n    if fname is not None and op.isfile(fname) and not overwrite:\n        raise IOError('file exists, use overwrite=True to overwrite')\n\n    out = ''\n    try:\n        # Nest all imports here to avoid any circular imports\n        from ..app import Application, Canvas, backends\n        from ..gloo import gl\n        # get default app\n        this_app = Application()\n        with use_log_level('warning'):\n            this_app.use()  # suppress unnecessary messages\n        out += 'Platform: %s\\n' % platform.platform()\n        out += 'Python:   %s\\n' % str(sys.version).replace('\\n', ' ')\n        out += 'Backend:  %s\\n' % this_app.backend_name\n        out += 'Qt:       %s\\n' % backends.has_qt(return_which=True)[1]\n        out += 'Pyglet:   %s\\n' % backends.has_pyglet(return_which=True)[1]\n        out += 'glfw:     %s\\n' % backends.has_glfw(return_which=True)[1]\n        out += 'glut:     %s\\n' % backends.has_glut(return_which=True)[1]\n        out += '\\n'\n        # We need an OpenGL context to get GL info\n        if 'glut' in this_app.backend_name.lower():\n            # glut causes problems\n            out += 'OpenGL information omitted for glut backend\\n'\n        else:\n            canvas = Canvas('Test', (10, 10), show=False, app=this_app)\n            canvas._backend._vispy_set_current()\n            out += 'GL version:  %s\\n' % gl.glGetString(gl.GL_VERSION)\n            x_ = gl.GL_MAX_TEXTURE_SIZE\n            out += 'MAX_TEXTURE_SIZE: %d\\n' % gl.glGetIntegerv(x_)\n            x_ = gl.ext.GL_MAX_3D_TEXTURE_SIZE\n            out += 'MAX_3D_TEXTURE_SIZE: %d\\n\\n' % gl.glGetIntegerv(x_)\n            out += 'Extensions: %s\\n' % gl.glGetString(gl.GL_EXTENSIONS)\n            canvas.close()\n    except Exception:  # don't stop printing info\n        out += '\\nInfo-gathering error:\\n%s' % traceback.format_exc()\n        pass\n    if fname is not None:\n        with open(fname, 'w') as fid:\n            fid.write(out)\n    return out\n", "path": "vispy/util/misc.py"}, {"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team. All Rights Reserved.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\n\"\"\" Utilities for Vispy. A collection of modules that are used in\none or more Vispy sub-packages.\n\"\"\"\n\nfrom .misc import (_TempDir, is_string, parse_command_line_arguments,  # noqa\n                   config, sys_info)  # noqa\nfrom ._logging import logger, set_log_level, use_log_level  # noqa\n", "path": "vispy/util/__init__.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\n\"\"\"Miscellaneous functions\n\"\"\"\n\nimport numpy as np\nimport tempfile\nimport atexit\nfrom shutil import rmtree\nimport sys\nimport platform\nimport getopt\nfrom os import path as op\nimport traceback\n\nfrom .six import string_types\nfrom .event import EmitterGroup, EventEmitter, Event\nfrom ._logging import logger, set_log_level, use_log_level\n\n\nclass _TempDir(str):\n\n    \"\"\"Class for creating and auto-destroying temp dir\n\n    This is designed to be used with testing modules.\n\n    We cannot simply use __del__() method for cleanup here because the rmtree\n    function may be cleaned up before this object, so we use the atexit module\n    instead.\n    \"\"\"\n\n    def __new__(self):\n        new = str.__new__(self, tempfile.mkdtemp())\n        return new\n\n    def __init__(self):\n        self._path = self.__str__()\n        atexit.register(self.cleanup)\n\n    def cleanup(self):\n        rmtree(self._path, ignore_errors=True)\n\n\ndef is_string(s):\n    return isinstance(s, string_types)\n\n\n###############################################################################\n# These fast normal calculation routines are adapted from mne-python\n\ndef _fast_cross_3d(x, y):\n    \"\"\"Compute cross product between list of 3D vectors\n\n    Much faster than np.cross() when the number of cross products\n    becomes large (>500). This is because np.cross() methods become\n    less memory efficient at this stage.\n\n    Parameters\n    ----------\n    x : array\n        Input array 1.\n    y : array\n        Input array 2.\n\n    Returns\n    -------\n    z : array\n        Cross product of x and y.\n\n    Notes\n    -----\n    x and y must both be 2D row vectors. One must have length 1, or both\n    lengths must match.\n    \"\"\"\n    assert x.ndim == 2\n    assert y.ndim == 2\n    assert x.shape[1] == 3\n    assert y.shape[1] == 3\n    assert (x.shape[0] == 1 or y.shape[0] == 1) or x.shape[0] == y.shape[0]\n    if max([x.shape[0], y.shape[0]]) >= 500:\n        return np.c_[x[:, 1] * y[:, 2] - x[:, 2] * y[:, 1],\n                     x[:, 2] * y[:, 0] - x[:, 0] * y[:, 2],\n                     x[:, 0] * y[:, 1] - x[:, 1] * y[:, 0]]\n    else:\n        return np.cross(x, y)\n\n\ndef _calculate_normals(rr, tris):\n    \"\"\"Efficiently compute vertex normals for triangulated surface\"\"\"\n    # ensure highest precision for our summation/vectorization \"trick\"\n    rr = rr.astype(np.float64)\n    # first, compute triangle normals\n    r1 = rr[tris[:, 0], :]\n    r2 = rr[tris[:, 1], :]\n    r3 = rr[tris[:, 2], :]\n    tri_nn = _fast_cross_3d((r2 - r1), (r3 - r1))\n\n    #   Triangle normals and areas\n    size = np.sqrt(np.sum(tri_nn * tri_nn, axis=1))\n    size[size == 0] = 1.0  # prevent ugly divide-by-zero\n    tri_nn /= size[:, np.newaxis]\n\n    npts = len(rr)\n\n    # the following code replaces this, but is faster (vectorized):\n    #\n    # for p, verts in enumerate(tris):\n    #     nn[verts, :] += tri_nn[p, :]\n    #\n    nn = np.zeros((npts, 3))\n    for verts in tris.T:  # note this only loops 3x (number of verts per tri)\n        for idx in range(3):  # x, y, z\n            nn[:, idx] += np.bincount(verts, tri_nn[:, idx], minlength=npts)\n    size = np.sqrt(np.sum(nn * nn, axis=1))\n    size[size == 0] = 1.0  # prevent ugly divide-by-zero\n    nn /= size[:, np.newaxis]\n    return nn\n\n\n###############################################################################\n# CONFIG\n\nclass ConfigEvent(Event):\n\n    \"\"\" Event indicating a configuration change.\n\n    This class has a 'changes' attribute which is a dict of all name:value\n    pairs that have changed in the configuration.\n    \"\"\"\n\n    def __init__(self, changes):\n        Event.__init__(self, type='config_change')\n        self.changes = changes\n\n\nclass Config(object):\n\n    \"\"\" Container for global settings used application-wide in vispy.\n\n    Events:\n    -------\n    Config.events.changed - Emits ConfigEvent whenever the configuration\n    changes.\n    \"\"\"\n\n    def __init__(self):\n        self.events = EmitterGroup(source=self)\n        self.events['changed'] = EventEmitter(\n            event_class=ConfigEvent,\n            source=self)\n        self._config = {}\n\n    def __getitem__(self, item):\n        return self._config[item]\n\n    def __setitem__(self, item, val):\n        self._config[item] = val\n        # inform any listeners that a configuration option has changed\n        self.events.changed(changes={item: val})\n\n    def update(self, **kwds):\n        self._config.update(kwds)\n        self.events.changed(changes=kwds)\n\n    def __repr__(self):\n        return repr(self._config)\n\nconfig = Config()\nconfig.update(\n    default_backend='qt',\n    qt_lib='any',  # options are 'pyqt', 'pyside', or 'any'\n    show_warnings=False,\n    gl_debug=False,\n    logging_level='info',\n)\n\nset_log_level(config['logging_level'])\n\n\ndef parse_command_line_arguments():\n    \"\"\" Transform vispy specific command line args to vispy config.\n    Put into a function so that any variables dont leak in the vispy namespace.\n    \"\"\"\n    # Get command line args for vispy\n    argnames = ['vispy-backend', 'vispy-gl-debug']\n    try:\n        opts, args = getopt.getopt(sys.argv[1:], '', argnames)\n    except getopt.GetoptError:\n        opts = []\n    # Use them to set the config values\n    for o, a in opts:\n        if o.startswith('--vispy'):\n            if o == '--vispy-backend':\n                config['default_backend'] = a\n                logger.info('backend', a)\n            elif o == '--vispy-gl-debug':\n                config['gl_debug'] = True\n            else:\n                logger.warning(\"Unsupported vispy flag: %s\" % o)\n\n\ndef sys_info(fname=None, overwrite=False):\n    \"\"\"Get relevant system and debugging information\n\n    Parameters\n    ----------\n    fname : str | None\n        Filename to dump info to. Use None to simply print.\n    overwrite : bool\n        If True, overwrite file (if it exists).\n\n    Returns\n    -------\n    out : str\n        The system information as a string.\n    \"\"\"\n    if fname is not None and op.isfile(fname) and not overwrite:\n        raise IOError('file exists, use overwrite=True to overwrite')\n\n    out = ''\n    try:\n        # Nest all imports here to avoid any circular imports\n        from ..app import Application, Canvas, backends\n        from ..gloo import gl\n        # get default app\n        this_app = Application()\n        with use_log_level('warning'):\n            this_app.use()  # suppress unnecessary messages\n        out += 'Platform: %s\\n' % platform.platform()\n        out += 'Python:   %s\\n' % str(sys.version).replace('\\n', ' ')\n        out += 'Backend:  %s\\n' % this_app.backend_name\n        out += 'Qt:       %s\\n' % backends.has_qt(return_which=True)[1]\n        out += 'Pyglet:   %s\\n' % backends.has_pyglet(return_which=True)[1]\n        out += 'glfw:     %s\\n' % backends.has_glfw(return_which=True)[1]\n        out += 'glut:     %s\\n' % backends.has_glut(return_which=True)[1]\n        out += '\\n'\n        # We need an OpenGL context to get GL info\n        if 'glut' in this_app.backend_name.lower():\n            # glut causes problems\n            out += 'OpenGL information omitted for glut backend\\n'\n        else:\n            canvas = Canvas('Test', (10, 10), show=False, app=this_app)\n            canvas._backend._vispy_set_current()\n            out += 'GL version:  %s\\n' % gl.glGetString(gl.GL_VERSION)\n            x_ = gl.GL_MAX_TEXTURE_SIZE\n            out += 'MAX_TEXTURE_SIZE: %d\\n' % gl.glGetIntegerv(x_)\n            x_ = gl.ext.GL_MAX_3D_TEXTURE_SIZE\n            out += 'MAX_3D_TEXTURE_SIZE: %d\\n\\n' % gl.glGetIntegerv(x_)\n            out += 'Extensions: %s\\n' % gl.glGetString(gl.GL_EXTENSIONS)\n            canvas.close()\n    except Exception:  # don't stop printing info\n        out += '\\nInfo-gathering error:\\n%s' % traceback.format_exc()\n        pass\n    if fname is not None:\n        with open(fname, 'w') as fid:\n            fid.write(out)\n    return out\n\n\n# Adapted from Python's unittest2 (which is wrapped by nose)\n# http://docs.python.org/2/license.html\ndef _safe_rep(obj, short=False):\n    \"\"\"Helper for assert_* ports\"\"\"\n    try:\n        result = repr(obj)\n    except Exception:\n        result = object.__repr__(obj)\n    if not short or len(result) < 80:\n        return result\n    return result[:80] + ' [truncated]...'\n\n\ndef _safe_str(obj):\n    \"\"\"Helper for assert_* ports\"\"\"\n    try:\n        return str(obj)\n    except Exception:\n        return object.__str__(obj)\n\n\ndef _format_msg(msg, std_msg):\n    \"\"\"Helper for assert_* ports\"\"\"\n    if msg is None:\n        msg = std_msg\n    else:\n        try:\n            msg = '%s : %s' % (std_msg, msg)\n        except UnicodeDecodeError:\n            msg = '%s : %s' % (_safe_str(std_msg), _safe_str(msg))\n\n\ndef assert_in(member, container, msg=None):\n    \"\"\"Backport for old nose.tools\"\"\"\n    if member in container:\n        return\n    std_msg = '%s not found in %s' % (_safe_rep(member), _safe_rep(container))\n    msg = _format_msg(msg, std_msg)\n    raise AssertionError(msg)\n\n\ndef assert_not_in(member, container, msg=None):\n    \"\"\"Backport for old nose.tools\"\"\"\n    if member not in container:\n        return\n    std_msg = '%s found in %s' % (_safe_rep(member), _safe_rep(container))\n    msg = _format_msg(msg, std_msg)\n    raise AssertionError(msg)\n\n\ndef assert_is(expr1, expr2, msg=None):\n    \"\"\"Backport for old nose.tools\"\"\"\n    if expr1 is not expr2:\n        std_msg = '%s is not %s' % (_safe_rep(expr1), _safe_rep(expr2))\n        raise AssertionError(_format_msg(msg, std_msg))\n", "path": "vispy/util/misc.py"}, {"content": "# -*- coding: utf-8 -*-\n# Copyright (c) 2014, Vispy Development Team. All Rights Reserved.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n\n\"\"\" Utilities for Vispy. A collection of modules that are used in\none or more Vispy sub-packages.\n\"\"\"\n\nfrom .misc import (_TempDir, is_string, parse_command_line_arguments,  # noqa\n                   config, sys_info, assert_in, assert_not_in,  # noqa\n                   assert_is)  # noqa\nfrom ._logging import logger, set_log_level, use_log_level  # noqa\n", "path": "vispy/util/__init__.py"}]}