ipython_genutils-0.1.0/0000755000076500000000000000000012516471377015367 5ustar minrkwheel00000000000000ipython_genutils-0.1.0/CONTRIBUTING.md0000644000076500000000000000017412516471343017613 0ustar minrkwheel00000000000000# Contributing We follow the [IPython Contributing Guide](https://github.com/ipython/ipython/blob/master/CONTRIBUTING.md). ipython_genutils-0.1.0/COPYING.md0000644000076500000000000000542412516471343017017 0ustar minrkwheel00000000000000# Licensing terms This project is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD), as follows: - Copyright (c) 2001-, IPython Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the IPython Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## About the IPython Development Team The IPython Development Team is the set of all contributors to the IPython project. This includes all of the IPython subprojects. The core team that coordinates development on GitHub can be found here: https://github.com/jupyter/. ## Our Copyright Policy IPython uses a shared copyright model. Each contributor maintains copyright over their contributions to IPython. But, it is important to note that these contributions are typically only changes to the repositories. Thus, the IPython source code, in its entirety is not the copyright of any single person or institution. Instead, it is the collective copyright of the entire IPython Development Team. If individual contributors want to maintain a record of what changes/contributions they have specific copyright on, they should indicate their copyright in the commit message of the change, when they commit the change to one of the IPython repositories. With this in mind, the following banner should be used in any source code file to indicate the copyright and license terms: # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. ipython_genutils-0.1.0/ipython_genutils/0000755000076500000000000000000012516471377020773 5ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils/__init__.py0000644000076500000000000000006012516471343023071 0ustar minrkwheel00000000000000from ._version import __version__, version_info ipython_genutils-0.1.0/ipython_genutils/_version.py0000644000076500000000000000011012516471343023152 0ustar minrkwheel00000000000000version_info = (0, 1, 0) __version__ = '.'.join(map(str, version_info)) ipython_genutils-0.1.0/ipython_genutils/encoding.py0000644000076500000000000000546512516471343023136 0ustar minrkwheel00000000000000# coding: utf-8 """ Utilities for dealing with text encodings """ #----------------------------------------------------------------------------- # Copyright (C) 2008-2012 The IPython Development Team # # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- import sys import locale import warnings # to deal with the possibility of sys.std* not being a stream at all def get_stream_enc(stream, default=None): """Return the given stream's encoding or a default. There are cases where ``sys.std*`` might not actually be a stream, so check for the encoding attribute prior to returning it, and return a default if it doesn't exist or evaluates as False. ``default`` is None if not provided. """ if not hasattr(stream, 'encoding') or not stream.encoding: return default else: return stream.encoding # Less conservative replacement for sys.getdefaultencoding, that will try # to match the environment. # Defined here as central function, so if we find better choices, we # won't need to make changes all over IPython. def getdefaultencoding(prefer_stream=True): """Return IPython's guess for the default encoding for bytes as text. If prefer_stream is True (default), asks for stdin.encoding first, to match the calling Terminal, but that is often None for subprocesses. Then fall back on locale.getpreferredencoding(), which should be a sensible platform default (that respects LANG environment), and finally to sys.getdefaultencoding() which is the most conservative option, and usually ASCII on Python 2 or UTF8 on Python 3. """ enc = None if prefer_stream: enc = get_stream_enc(sys.stdin) if not enc or enc=='ascii': try: # There are reports of getpreferredencoding raising errors # in some cases, which may well be fixed, but let's be conservative here. enc = locale.getpreferredencoding() except Exception: pass enc = enc or sys.getdefaultencoding() # On windows `cp0` can be returned to indicate that there is no code page. # Since cp0 is an invalid encoding return instead cp1252 which is the # Western European default. if enc == 'cp0': warnings.warn( "Invalid code page cp0 detected - using cp1252 instead." "If cp1252 is incorrect please ensure a valid code page " "is defined for the process.", RuntimeWarning) return 'cp1252' return enc DEFAULT_ENCODING = getdefaultencoding() ipython_genutils-0.1.0/ipython_genutils/importstring.py0000644000076500000000000000201312516471343024073 0ustar minrkwheel00000000000000# encoding: utf-8 """ A simple utility to import something by its string name. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. def import_item(name): """Import and return ``bar`` given the string ``foo.bar``. Calling ``bar = import_item("foo.bar")`` is the functional equivalent of executing the code ``from foo import bar``. Parameters ---------- name : string The fully qualified name of the module/package being imported. Returns ------- mod : module object The module that was imported. """ parts = name.rsplit('.', 1) if len(parts) == 2: # called with 'foo.bar....' package, obj = parts module = __import__(package, fromlist=[obj]) try: pak = getattr(module, obj) except AttributeError: raise ImportError('No module named %s' % obj) return pak else: # called with un-dotted string return __import__(parts[0]) ipython_genutils-0.1.0/ipython_genutils/ipstruct.py0000644000076500000000000002577212516471343023230 0ustar minrkwheel00000000000000# encoding: utf-8 """A dict subclass that supports attribute style access. Can probably be replaced by types.SimpleNamespace from Python 3.3 """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. __all__ = ['Struct'] class Struct(dict): """A dict subclass with attribute style access. This dict subclass has a a few extra features: * Attribute style access. * Protection of class members (like keys, items) when using attribute style access. * The ability to restrict assignment to only existing keys. * Intelligent merging. * Overloaded operators. """ _allownew = True def __init__(self, *args, **kw): """Initialize with a dictionary, another Struct, or data. Parameters ---------- args : dict, Struct Initialize with one dict or Struct kw : dict Initialize with key, value pairs. Examples -------- >>> s = Struct(a=10,b=30) >>> s.a 10 >>> s.b 30 >>> s2 = Struct(s,c=30) >>> sorted(s2.keys()) ['a', 'b', 'c'] """ object.__setattr__(self, '_allownew', True) dict.__init__(self, *args, **kw) def __setitem__(self, key, value): """Set an item with check for allownew. Examples -------- >>> s = Struct() >>> s['a'] = 10 >>> s.allow_new_attr(False) >>> s['a'] = 10 >>> s['a'] 10 >>> try: ... s['b'] = 20 ... except KeyError: ... print('this is not allowed') ... this is not allowed """ if not self._allownew and key not in self: raise KeyError( "can't create new attribute %s when allow_new_attr(False)" % key) dict.__setitem__(self, key, value) def __setattr__(self, key, value): """Set an attr with protection of class members. This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to :exc:`AttributeError`. Examples -------- >>> s = Struct() >>> s.a = 10 >>> s.a 10 >>> try: ... s.get = 10 ... except AttributeError: ... print("you can't set a class member") ... you can't set a class member """ # If key is an str it might be a class member or instance var if isinstance(key, str): # I can't simply call hasattr here because it calls getattr, which # calls self.__getattr__, which returns True for keys in # self._data. But I only want keys in the class and in # self.__dict__ if key in self.__dict__ or hasattr(Struct, key): raise AttributeError( 'attr %s is a protected member of class Struct.' % key ) try: self.__setitem__(key, value) except KeyError as e: raise AttributeError(e) def __getattr__(self, key): """Get an attr by calling :meth:`dict.__getitem__`. Like :meth:`__setattr__`, this method converts :exc:`KeyError` to :exc:`AttributeError`. Examples -------- >>> s = Struct(a=10) >>> s.a 10 >>> type(s.get) <... 'builtin_function_or_method'> >>> try: ... s.b ... except AttributeError: ... print("I don't have that key") ... I don't have that key """ try: result = self[key] except KeyError: raise AttributeError(key) else: return result def __iadd__(self, other): """s += s2 is a shorthand for s.merge(s2). Examples -------- >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s += s2 >>> sorted(s.keys()) ['a', 'b', 'c'] """ self.merge(other) return self def __add__(self,other): """s + s2 -> New Struct made from s.merge(s2). Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s = s1 + s2 >>> sorted(s.keys()) ['a', 'b', 'c'] """ sout = self.copy() sout.merge(other) return sout def __sub__(self,other): """s1 - s2 -> remove keys in s2 from s1. Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=40) >>> s = s1 - s2 >>> s {'b': 30} """ sout = self.copy() sout -= other return sout def __isub__(self,other): """Inplace remove keys from self that are in other. Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=40) >>> s1 -= s2 >>> s1 {'b': 30} """ for k in other.keys(): if k in self: del self[k] return self def __dict_invert(self, data): """Helper function for merge. Takes a dictionary whose values are lists and returns a dict with the elements of each list as keys and the original keys as values. """ outdict = {} for k,lst in data.items(): if isinstance(lst, str): lst = lst.split() for entry in lst: outdict[entry] = k return outdict def dict(self): return self def copy(self): """Return a copy as a Struct. Examples -------- >>> s = Struct(a=10,b=30) >>> s2 = s.copy() >>> type(s2) is Struct True """ return Struct(dict.copy(self)) def hasattr(self, key): """hasattr function available as a method. Implemented like has_key. Examples -------- >>> s = Struct(a=10) >>> s.hasattr('a') True >>> s.hasattr('b') False >>> s.hasattr('get') False """ return key in self def allow_new_attr(self, allow = True): """Set whether new attributes can be created in this Struct. This can be used to catch typos by verifying that the attribute user tries to change already exists in this Struct. """ object.__setattr__(self, '_allownew', allow) def merge(self, __loc_data__=None, __conflict_solve=None, **kw): """Merge two Structs with customizable conflict resolution. This is similar to :meth:`update`, but much more flexible. First, a dict is made from data+key=value pairs. When merging this dict with the Struct S, the optional dictionary 'conflict' is used to decide what to do. If conflict is not given, the default behavior is to preserve any keys with their current value (the opposite of the :meth:`update` method's behavior). Parameters ---------- __loc_data : dict, Struct The data to merge into self __conflict_solve : dict The conflict policy dict. The keys are binary functions used to resolve the conflict and the values are lists of strings naming the keys the conflict resolution function applies to. Instead of a list of strings a space separated string can be used, like 'a b c'. kw : dict Additional key, value pairs to merge in Notes ----- The `__conflict_solve` dict is a dictionary of binary functions which will be used to solve key conflicts. Here is an example:: __conflict_solve = dict( func1=['a','b','c'], func2=['d','e'] ) In this case, the function :func:`func1` will be used to resolve keys 'a', 'b' and 'c' and the function :func:`func2` will be used for keys 'd' and 'e'. This could also be written as:: __conflict_solve = dict(func1='a b c',func2='d e') These functions will be called for each key they apply to with the form:: func1(self['a'], other['a']) The return value is used as the final merged value. As a convenience, merge() provides five (the most commonly needed) pre-defined policies: preserve, update, add, add_flip and add_s. The easiest explanation is their implementation:: preserve = lambda old,new: old update = lambda old,new: new add = lambda old,new: old + new add_flip = lambda old,new: new + old # note change of order! add_s = lambda old,new: old + ' ' + new # only for str! You can use those four words (as strings) as keys instead of defining them as functions, and the merge method will substitute the appropriate functions for you. For more complicated conflict resolution policies, you still need to construct your own functions. Examples -------- This show the default policy: >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s.merge(s2) >>> sorted(s.items()) [('a', 10), ('b', 30), ('c', 40)] Now, show how to specify a conflict dict: >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,b=40) >>> conflict = {'update':'a','add':'b'} >>> s.merge(s2,conflict) >>> sorted(s.items()) [('a', 20), ('b', 70)] """ data_dict = dict(__loc_data__,**kw) # policies for conflict resolution: two argument functions which return # the value that will go in the new struct preserve = lambda old,new: old update = lambda old,new: new add = lambda old,new: old + new add_flip = lambda old,new: new + old # note change of order! add_s = lambda old,new: old + ' ' + new # default policy is to keep current keys when there's a conflict conflict_solve = dict.fromkeys(self, preserve) # the conflict_solve dictionary is given by the user 'inverted': we # need a name-function mapping, it comes as a function -> names # dict. Make a local copy (b/c we'll make changes), replace user # strings for the three builtin policies and invert it. if __conflict_solve: inv_conflict_solve_user = __conflict_solve.copy() for name, func in [('preserve',preserve), ('update',update), ('add',add), ('add_flip',add_flip), ('add_s',add_s)]: if name in inv_conflict_solve_user.keys(): inv_conflict_solve_user[func] = inv_conflict_solve_user[name] del inv_conflict_solve_user[name] conflict_solve.update(self.__dict_invert(inv_conflict_solve_user)) for key in data_dict: if key not in self: self[key] = data_dict[key] else: self[key] = conflict_solve[key](self[key],data_dict[key]) ipython_genutils-0.1.0/ipython_genutils/path.py0000644000076500000000000001241212516471343022272 0ustar minrkwheel00000000000000# encoding: utf-8 """ Utilities for path handling. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import os import sys import errno import shutil import random from . import py3compat fs_encoding = sys.getfilesystemencoding() def filefind(filename, path_dirs=None): """Find a file by looking through a sequence of paths. This iterates through a sequence of paths looking for a file and returns the full, absolute path of the first occurence of the file. If no set of path dirs is given, the filename is tested as is, after running through :func:`expandvars` and :func:`expanduser`. Thus a simple call:: filefind('myfile.txt') will find the file in the current working dir, but:: filefind('~/myfile.txt') Will find the file in the users home directory. This function does not automatically try any paths, such as the cwd or the user's home directory. Parameters ---------- filename : str The filename to look for. path_dirs : str, None or sequence of str The sequence of paths to look for the file in. If None, the filename need to be absolute or be in the cwd. If a string, the string is put into a sequence and the searched. If a sequence, walk through each element and join with ``filename``, calling :func:`expandvars` and :func:`expanduser` before testing for existence. Returns ------- Raises :exc:`IOError` or returns absolute path to file. """ # If paths are quoted, abspath gets confused, strip them... filename = filename.strip('"').strip("'") # If the input is an absolute path, just check it exists if os.path.isabs(filename) and os.path.isfile(filename): return filename if path_dirs is None: path_dirs = ("",) elif isinstance(path_dirs, py3compat.string_types): path_dirs = (path_dirs,) for path in path_dirs: if path == '.': path = py3compat.getcwd() testname = expand_path(os.path.join(path, filename)) if os.path.isfile(testname): return os.path.abspath(testname) raise IOError("File %r does not exist in any of the search paths: %r" % (filename, path_dirs) ) def expand_path(s): """Expand $VARS and ~names in a string, like a shell :Examples: In [2]: os.environ['FOO']='test' In [3]: expand_path('variable FOO is $FOO') Out[3]: 'variable FOO is test' """ # This is a pretty subtle hack. When expand user is given a UNC path # on Windows (\\server\share$\%username%), os.path.expandvars, removes # the $ to get (\\server\share\%username%). I think it considered $ # alone an empty var. But, we need the $ to remains there (it indicates # a hidden share). if os.name=='nt': s = s.replace('$\\', 'IPYTHON_TEMP') s = os.path.expandvars(os.path.expanduser(s)) if os.name=='nt': s = s.replace('IPYTHON_TEMP', '$\\') return s try: ENOLINK = errno.ENOLINK except AttributeError: ENOLINK = 1998 def link(src, dst): """Hard links ``src`` to ``dst``, returning 0 or errno. Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't supported by the operating system. """ if not hasattr(os, "link"): return ENOLINK link_errno = 0 try: os.link(src, dst) except OSError as e: link_errno = e.errno return link_errno def link_or_copy(src, dst): """Attempts to hardlink ``src`` to ``dst``, copying if the link fails. Attempts to maintain the semantics of ``shutil.copy``. Because ``os.link`` does not overwrite files, a unique temporary file will be used if the target already exists, then that file will be moved into place. """ if os.path.isdir(dst): dst = os.path.join(dst, os.path.basename(src)) link_errno = link(src, dst) if link_errno == errno.EEXIST: if os.stat(src).st_ino == os.stat(dst).st_ino: # dst is already a hard link to the correct file, so we don't need # to do anything else. If we try to link and rename the file # anyway, we get duplicate files - see http://bugs.python.org/issue21876 return new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), ) try: link_or_copy(src, new_dst) except: try: os.remove(new_dst) except OSError: pass raise os.rename(new_dst, dst) elif link_errno != 0: # Either link isn't supported, or the filesystem doesn't support # linking, or 'src' and 'dst' are on different filesystems. shutil.copy(src, dst) def ensure_dir_exists(path, mode=0o755): """ensure that a directory exists If it doesn't exist, try to create it and protect against a race condition if another process is doing the same. The default permissions are 755, which differ from os.makedirs default of 777. """ if not os.path.exists(path): try: os.makedirs(path, mode=mode) except OSError as e: if e.errno != errno.EEXIST: raise elif not os.path.isdir(path): raise IOError("%r exists but is not a directory" % path) ipython_genutils-0.1.0/ipython_genutils/py3compat.py0000644000076500000000000002473012516471343023263 0ustar minrkwheel00000000000000# coding: utf-8 """Compatibility tricks for Python 3. Mainly to do with unicode.""" import functools import os import sys import re import shutil import types from .encoding import DEFAULT_ENCODING def no_code(x, encoding=None): return x def decode(s, encoding=None): encoding = encoding or DEFAULT_ENCODING return s.decode(encoding, "replace") def encode(u, encoding=None): encoding = encoding or DEFAULT_ENCODING return u.encode(encoding, "replace") def cast_unicode(s, encoding=None): if isinstance(s, bytes): return decode(s, encoding) return s def cast_bytes(s, encoding=None): if not isinstance(s, bytes): return encode(s, encoding) return s def buffer_to_bytes(buf): """Cast a buffer or memoryview object to bytes""" if isinstance(buf, memoryview): return buf.tobytes() if not isinstance(buf, bytes): return bytes(buf) return buf def _modify_str_or_docstring(str_change_func): @functools.wraps(str_change_func) def wrapper(func_or_str): if isinstance(func_or_str, string_types): func = None doc = func_or_str else: func = func_or_str doc = func.__doc__ doc = str_change_func(doc) if func: func.__doc__ = doc return func return doc return wrapper def safe_unicode(e): """unicode(e) with various fallbacks. Used for exceptions, which may not be safe to call unicode() on. """ try: return unicode_type(e) except UnicodeError: pass try: return str_to_unicode(str(e)) except UnicodeError: pass try: return str_to_unicode(repr(e)) except UnicodeError: pass return u'Unrecoverably corrupt evalue' # shutil.which from Python 3.4 def _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None): """Given a command, mode, and a PATH string, return the path which conforms to the given mode on the PATH, or None if there is no such file. `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result of os.environ.get("PATH"), or can be overridden with a custom search path. This is a backport of shutil.which from Python 3.4 """ # Check that a given file can be accessed with the correct mode. # Additionally check that `file` is not a directory, as on Windows # directories pass the os.access check. def _access_check(fn, mode): return (os.path.exists(fn) and os.access(fn, mode) and not os.path.isdir(fn)) # If we're given a path with a directory part, look it up directly rather # than referring to PATH directories. This includes checking relative to the # current directory, e.g. ./script if os.path.dirname(cmd): if _access_check(cmd, mode): return cmd return None if path is None: path = os.environ.get("PATH", os.defpath) if not path: return None path = path.split(os.pathsep) if sys.platform == "win32": # The current directory takes precedence on Windows. if not os.curdir in path: path.insert(0, os.curdir) # PATHEXT is necessary to check on Windows. pathext = os.environ.get("PATHEXT", "").split(os.pathsep) # See if the given file matches any of the expected path extensions. # This will allow us to short circuit when given "python.exe". # If it does match, only test that one, otherwise we have to try # others. if any(cmd.lower().endswith(ext.lower()) for ext in pathext): files = [cmd] else: files = [cmd + ext for ext in pathext] else: # On other platforms you don't have things like PATHEXT to tell you # what file suffixes are executable, so just pass on cmd as-is. files = [cmd] seen = set() for dir in path: normdir = os.path.normcase(dir) if not normdir in seen: seen.add(normdir) for thefile in files: name = os.path.join(dir, thefile) if _access_check(name, mode): return name return None if sys.version_info[0] >= 3: PY3 = True # keep reference to builtin_mod because the kernel overrides that value # to forward requests to a frontend. def input(prompt=''): return builtin_mod.input(prompt) builtin_mod_name = "builtins" import builtins as builtin_mod str_to_unicode = no_code unicode_to_str = no_code str_to_bytes = encode bytes_to_str = decode cast_bytes_py2 = no_code cast_unicode_py2 = no_code buffer_to_bytes_py2 = no_code string_types = (str,) unicode_type = str which = shutil.which def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return s.isidentifier() xrange = range def iteritems(d): return iter(d.items()) def itervalues(d): return iter(d.values()) getcwd = os.getcwd MethodType = types.MethodType def execfile(fname, glob, loc=None, compiler=None): loc = loc if (loc is not None) else glob with open(fname, 'rb') as f: compiler = compiler or compile exec(compiler(f.read(), fname, 'exec'), glob, loc) # Refactor print statements in doctests. _print_statement_re = re.compile(r"\bprint (?P.*)$", re.MULTILINE) def _print_statement_sub(match): expr = match.groups('expr') return "print(%s)" % expr @_modify_str_or_docstring def doctest_refactor_print(doc): """Refactor 'print x' statements in a doctest to print(x) style. 2to3 unfortunately doesn't pick up on our doctests. Can accept a string or a function, so it can be used as a decorator.""" return _print_statement_re.sub(_print_statement_sub, doc) # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "'abc'" (Python 3) Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='') def get_closure(f): """Get a function's closure attribute""" return f.__closure__ else: PY3 = False # keep reference to builtin_mod because the kernel overrides that value # to forward requests to a frontend. def input(prompt=''): return builtin_mod.raw_input(prompt) builtin_mod_name = "__builtin__" import __builtin__ as builtin_mod str_to_unicode = decode unicode_to_str = encode str_to_bytes = no_code bytes_to_str = no_code cast_bytes_py2 = cast_bytes cast_unicode_py2 = cast_unicode buffer_to_bytes_py2 = buffer_to_bytes string_types = (str, unicode) unicode_type = unicode import re _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return bool(_name_re.match(s)) xrange = xrange def iteritems(d): return d.iteritems() def itervalues(d): return d.itervalues() getcwd = os.getcwdu def MethodType(func, instance): return types.MethodType(func, instance, type(instance)) def doctest_refactor_print(func_or_str): return func_or_str def get_closure(f): """Get a function's closure attribute""" return f.func_closure which = _shutil_which # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "u'abc'" (Python 2) Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='u') if sys.platform == 'win32': def execfile(fname, glob=None, loc=None, compiler=None): loc = loc if (loc is not None) else glob scripttext = builtin_mod.open(fname).read()+ '\n' # compile converts unicode filename to str assuming # ascii. Let's do the conversion before calling compile if isinstance(fname, unicode): filename = unicode_to_str(fname) else: filename = fname compiler = compiler or compile exec(compiler(scripttext, filename, 'exec'), glob, loc) else: def execfile(fname, glob=None, loc=None, compiler=None): if isinstance(fname, unicode): filename = fname.encode(sys.getfilesystemencoding()) else: filename = fname where = [ns for ns in [glob, loc] if ns is not None] if compiler is None: builtin_mod.execfile(filename, *where) else: scripttext = builtin_mod.open(fname).read().rstrip() + '\n' exec(compiler(scripttext, filename, 'exec'), glob, loc) def annotate(**kwargs): """Python 3 compatible function annotation for Python 2.""" if not kwargs: raise ValueError('annotations must be provided as keyword arguments') def dec(f): if hasattr(f, '__annotations__'): for k, v in kwargs.items(): f.__annotations__[k] = v else: f.__annotations__ = kwargs return f return dec # Parts below taken from six: # Copyright (c) 2010-2013 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("_NewBase", bases, {}) ipython_genutils-0.1.0/ipython_genutils/tempdir.py0000644000076500000000000001150112516471343023000 0ustar minrkwheel00000000000000"""TemporaryDirectory class, copied from Python 3 This is copied from the stdlib and will be standard in Python 3.2 and onwards. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. from __future__ import print_function import os as _os import warnings as _warnings import sys as _sys # This code should only be used in Python versions < 3.2, since after that we # can rely on the stdlib itself. try: from tempfile import TemporaryDirectory except ImportError: from tempfile import mkdtemp, template class TemporaryDirectory(object): """Create and return a temporary directory. This has the same behavior as mkdtemp but can be used as a context manager. For example: with TemporaryDirectory() as tmpdir: ... Upon exiting the context, the directory and everthing contained in it are removed. """ def __init__(self, suffix="", prefix=template, dir=None): self.name = mkdtemp(suffix, prefix, dir) self._closed = False def __enter__(self): return self.name def cleanup(self, _warn=False): if self.name and not self._closed: try: self._rmtree(self.name) except (TypeError, AttributeError) as ex: # Issue #10188: Emit a warning on stderr # if the directory could not be cleaned # up due to missing globals if "None" not in str(ex): raise print("ERROR: {!r} while cleaning up {!r}".format(ex, self,), file=_sys.stderr) return self._closed = True if _warn: self._warn("Implicitly cleaning up {!r}".format(self), Warning) def __exit__(self, exc, value, tb): self.cleanup() def __del__(self): # Issue a ResourceWarning if implicit cleanup needed self.cleanup(_warn=True) # XXX (ncoghlan): The following code attempts to make # this class tolerant of the module nulling out process # that happens during CPython interpreter shutdown # Alas, it doesn't actually manage it. See issue #10188 _listdir = staticmethod(_os.listdir) _path_join = staticmethod(_os.path.join) _isdir = staticmethod(_os.path.isdir) _remove = staticmethod(_os.remove) _rmdir = staticmethod(_os.rmdir) _os_error = _os.error _warn = _warnings.warn def _rmtree(self, path): # Essentially a stripped down version of shutil.rmtree. We can't # use globals because they may be None'ed out at shutdown. for name in self._listdir(path): fullname = self._path_join(path, name) try: isdir = self._isdir(fullname) except self._os_error: isdir = False if isdir: self._rmtree(fullname) else: try: self._remove(fullname) except self._os_error: pass try: self._rmdir(path) except self._os_error: pass # extra temp-dir-related context managers class NamedFileInTemporaryDirectory(object): def __init__(self, filename, mode='w+b', bufsize=-1, **kwds): """ Open a file named `filename` in a temporary directory. This context manager is preferred over `NamedTemporaryFile` in stdlib `tempfile` when one needs to reopen the file. Arguments `mode` and `bufsize` are passed to `open`. Rest of the arguments are passed to `TemporaryDirectory`. """ self._tmpdir = TemporaryDirectory(**kwds) path = _os.path.join(self._tmpdir.name, filename) self.file = open(path, mode, bufsize) def cleanup(self): self.file.close() self._tmpdir.cleanup() __del__ = cleanup def __enter__(self): return self.file def __exit__(self, type, value, traceback): self.cleanup() class TemporaryWorkingDirectory(TemporaryDirectory): """ Creates a temporary directory and sets the cwd to that directory. Automatically reverts to previous cwd upon cleanup. Usage example: with TemporaryWorkingDirectory() as tmpdir: ... """ def __enter__(self): self.old_wd = _os.getcwd() _os.chdir(self.name) return super(TemporaryWorkingDirectory, self).__enter__() def __exit__(self, exc, value, tb): _os.chdir(self.old_wd) return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb) ipython_genutils-0.1.0/ipython_genutils/testing/0000755000076500000000000000000012516471377022450 5ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils/testing/__init__.py0000644000076500000000000000000012516471343024540 0ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils/testing/decorators.py0000644000076500000000000002524112516471343025164 0ustar minrkwheel00000000000000# -*- coding: utf-8 -*- """Decorators for labeling test objects. Decorators that merely return a modified version of the original function object are straightforward. Decorators that return a new function object need to use nose.tools.make_decorator(original_function)(decorator) in returning the decorator, in order to preserve metadata such as function name, setup and teardown functions and so on - see nose.tools for more information. This module provides a set of useful decorators meant to be ready to use in your own tests. See the bottom of the file for the ready-made ones, and if you find yourself writing a new one that may be of generic use, add it here. Included decorators: Lightweight testing that remains unittest-compatible. - An @as_unittest decorator can be used to tag any normal parameter-less function as a unittest TestCase. Then, both nose and normal unittest will recognize it as such. This will make it easier to migrate away from Nose if we ever need/want to while maintaining very lightweight tests. NOTE: This file contains IPython-specific decorators. Using the machinery in IPython.external.decorators, we import either numpy.testing.decorators if numpy is available, OR use equivalent code in IPython.external._decorators, which we've copied verbatim from numpy. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import sys import os import tempfile import unittest # For onlyif_cmd_exists decorator from ..py3compat import string_types, which #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- # Simple example of the basic idea def as_unittest(func): """Decorator to make a simple function into a normal test via unittest.""" class Tester(unittest.TestCase): def test(self): func() Tester.__name__ = func.__name__ return Tester # Utility functions def make_label_dec(label,ds=None): """Factory function to create a decorator that applies one or more labels. Parameters ---------- label : string or sequence One or more labels that will be applied by the decorator to the functions it decorates. Labels are attributes of the decorated function with their value set to True. ds : string An optional docstring for the resulting decorator. If not given, a default docstring is auto-generated. Returns ------- A decorator. Examples -------- A simple labeling decorator: >>> slow = make_label_dec('slow') >>> slow.__doc__ "Labels a test as 'slow'." And one that uses multiple labels and a custom docstring: >>> rare = make_label_dec(['slow','hard'], ... "Mix labels 'slow' and 'hard' for rare tests.") >>> rare.__doc__ "Mix labels 'slow' and 'hard' for rare tests." Now, let's test using this one: >>> @rare ... def f(): pass ... >>> >>> f.slow True >>> f.hard True """ if isinstance(label, string_types): labels = [label] else: labels = label # Validate that the given label(s) are OK for use in setattr() by doing a # dry run on a dummy function. tmp = lambda : None for label in labels: setattr(tmp,label,True) # This is the actual decorator we'll return def decor(f): for label in labels: setattr(f,label,True) return f # Apply the user's docstring, or autogenerate a basic one if ds is None: ds = "Labels a test as %r." % label decor.__doc__ = ds return decor # Inspired by numpy's skipif, but uses the full apply_wrapper utility to # preserve function metadata better and allows the skip condition to be a # callable. def skipif(skip_condition, msg=None): ''' Make function raise SkipTest exception if skip_condition is true Parameters ---------- skip_condition : bool or callable Flag to determine whether to skip test. If the condition is a callable, it is used at runtime to dynamically make the decision. This is useful for tests that may require costly imports, to delay the cost until the test suite is actually executed. msg : string Message to give on raising a SkipTest exception. Returns ------- decorator : function Decorator, which, when applied to a function, causes SkipTest to be raised when the skip_condition was True, and the function to be called normally otherwise. Notes ----- You will see from the code that we had to further decorate the decorator with the nose.tools.make_decorator function in order to transmit function name, and various other metadata. ''' def skip_decorator(f): # Local import to avoid a hard nose dependency and only incur the # import time overhead at actual test-time. import nose # Allow for both boolean or callable skip conditions. if callable(skip_condition): skip_val = skip_condition else: skip_val = lambda : skip_condition def get_msg(func,msg=None): """Skip message with information about function being skipped.""" if msg is None: out = 'Test skipped due to test condition.' else: out = msg return "Skipping test: %s. %s" % (func.__name__,out) # We need to define *two* skippers because Python doesn't allow both # return with value and yield inside the same function. def skipper_func(*args, **kwargs): """Skipper for normal test functions.""" if skip_val(): raise nose.SkipTest(get_msg(f,msg)) else: return f(*args, **kwargs) def skipper_gen(*args, **kwargs): """Skipper for test generators.""" if skip_val(): raise nose.SkipTest(get_msg(f,msg)) else: for x in f(*args, **kwargs): yield x # Choose the right skipper to use when building the actual generator. if nose.util.isgenerator(f): skipper = skipper_gen else: skipper = skipper_func return nose.tools.make_decorator(f)(skipper) return skip_decorator # A version with the condition set to true, common case just to attach a message # to a skip decorator def skip(msg=None): """Decorator factory - mark a test function for skipping from test suite. Parameters ---------- msg : string Optional message to be added. Returns ------- decorator : function Decorator, which, when applied to a function, causes SkipTest to be raised, with the optional message added. """ return skipif(True,msg) def onlyif(condition, msg): """The reverse from skipif, see skipif for details.""" if callable(condition): skip_condition = lambda : not condition() else: skip_condition = lambda : not condition return skipif(skip_condition, msg) #----------------------------------------------------------------------------- # Utility functions for decorators def module_not_available(module): """Can module be imported? Returns true if module does NOT import. This is used to make a decorator to skip tests that require module to be available, but delay the 'import numpy' to test execution time. """ def condition(): try: mod = __import__(module) return False except ImportError: return True return condition def decorated_dummy(dec, name): """Return a dummy function decorated with dec, with the given name. Examples -------- import IPython.testing.decorators as dec setup = dec.decorated_dummy(dec.skip_if_no_x11, __name__) """ dummy = lambda: None dummy.__name__ = name return dec(dummy) #----------------------------------------------------------------------------- # Decorators for public use # Decorators to skip certain tests on specific platforms. skip_win32 = skipif(sys.platform == 'win32', "This test does not run under Windows") skip_linux = skipif(sys.platform.startswith('linux'), "This test does not run under Linux") skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X") # Decorators to skip tests if not on specific platforms. skip_if_not_win32 = skipif(sys.platform != 'win32', "This test only runs under Windows") skip_if_not_linux = skipif(not sys.platform.startswith('linux'), "This test only runs under Linux") skip_if_not_osx = skipif(sys.platform != 'darwin', "This test only runs under OSX") _x11_skip_cond = (sys.platform not in ('darwin', 'win32') and os.environ.get('DISPLAY', '') == '') _x11_skip_msg = "Skipped under *nix when X11/XOrg not available" skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg) # not a decorator itself, returns a dummy function to be used as setup def skip_file_no_x11(name): return decorated_dummy(skip_if_no_x11, name) if _x11_skip_cond else None # Other skip decorators # generic skip without module skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod) skipif_not_numpy = skip_without('numpy') skipif_not_matplotlib = skip_without('matplotlib') skipif_not_sympy = skip_without('sympy') # A null 'decorator', useful to make more readable code that needs to pick # between different decorators based on OS or other conditions null_deco = lambda f: f # Some tests only run where we can use unicode paths. Note that we can't just # check os.path.supports_unicode_filenames, which is always False on Linux. try: f = tempfile.NamedTemporaryFile(prefix=u"tmp€") except UnicodeEncodeError: unicode_paths = False else: unicode_paths = True f.close() onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable " "where we can use unicode in filenames.")) def onlyif_cmds_exist(*commands): """ Decorator to skip test when at least one of `commands` is not found. """ for cmd in commands: if not which(cmd): return skip("This test runs only if command '{0}' " "is installed".format(cmd)) return null_deco def onlyif_any_cmd_exists(*commands): """ Decorator to skip test unless at least one of `commands` is found. """ for cmd in commands: if which(cmd): return null_deco return skip("This test runs only if one of the commands {0} " "is installed".format(commands)) ipython_genutils-0.1.0/ipython_genutils/tests/0000755000076500000000000000000012516471377022135 5ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils/tests/__init__.py0000644000076500000000000000000012516471343024225 0ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils/tests/test_importstring.py0000644000076500000000000000121612516471343026300 0ustar minrkwheel00000000000000"""Tests for IPython.utils.importstring.""" # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import nose.tools as nt from ..importstring import import_item def test_import_plain(): "Test simple imports" import os os2 = import_item('os') nt.assert_true(os is os2) def test_import_nested(): "Test nested imports from the stdlib" from os import path path2 = import_item('os.path') nt.assert_true(path is path2) def test_import_raises(): "Test that failing imports raise the right exception" nt.assert_raises(ImportError, import_item, 'IPython.foobar') ipython_genutils-0.1.0/ipython_genutils/tests/test_path.py0000644000076500000000000000635612516471343024505 0ustar minrkwheel00000000000000# encoding: utf-8 """Tests for genutils.path""" # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import os import sys import tempfile import nose.tools as nt from ..testing.decorators import skip_if_not_win32, skip_win32 from .. import path from .. import py3compat from ..tempdir import TemporaryDirectory def test_filefind(): f = tempfile.NamedTemporaryFile() t = path.filefind(f.name, '.') def test_ensure_dir_exists(): with TemporaryDirectory() as td: d = os.path.join(td, u'∂ir') path.ensure_dir_exists(d) # create it assert os.path.isdir(d) path.ensure_dir_exists(d) # no-op f = os.path.join(td, u'ƒile') open(f, 'w').close() # touch with nt.assert_raises(IOError): path.ensure_dir_exists(f) class TestLinkOrCopy(object): def setUp(self): self.tempdir = TemporaryDirectory() self.src = self.dst("src") with open(self.src, "w") as f: f.write("Hello, world!") def tearDown(self): self.tempdir.cleanup() def dst(self, *args): return os.path.join(self.tempdir.name, *args) def assert_inode_not_equal(self, a, b): nt.assert_not_equals(os.stat(a).st_ino, os.stat(b).st_ino, "%r and %r do reference the same indoes" %(a, b)) def assert_inode_equal(self, a, b): nt.assert_equals(os.stat(a).st_ino, os.stat(b).st_ino, "%r and %r do not reference the same indoes" %(a, b)) def assert_content_equal(self, a, b): with open(a) as a_f: with open(b) as b_f: nt.assert_equals(a_f.read(), b_f.read()) @skip_win32 def test_link_successful(self): dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst) @skip_win32 def test_link_into_dir(self): dst = self.dst("some_dir") os.mkdir(dst) path.link_or_copy(self.src, dst) expected_dst = self.dst("some_dir", os.path.basename(self.src)) self.assert_inode_equal(self.src, expected_dst) @skip_win32 def test_target_exists(self): dst = self.dst("target") open(dst, "w").close() path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst) @skip_win32 def test_no_link(self): real_link = os.link try: del os.link dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_content_equal(self.src, dst) self.assert_inode_not_equal(self.src, dst) finally: os.link = real_link @skip_if_not_win32 def test_windows(self): dst = self.dst("target") path.link_or_copy(self.src, dst) self.assert_content_equal(self.src, dst) def test_link_twice(self): # Linking the same file twice shouldn't leave duplicates around. # See https://github.com/ipython/ipython/issues/6450 dst = self.dst('target') path.link_or_copy(self.src, dst) path.link_or_copy(self.src, dst) self.assert_inode_equal(self.src, dst) nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target']) ipython_genutils-0.1.0/ipython_genutils/tests/test_tempdir.py0000644000076500000000000000123412516471343025203 0ustar minrkwheel00000000000000 import os from ..tempdir import NamedFileInTemporaryDirectory from ..tempdir import TemporaryWorkingDirectory def test_named_file_in_temporary_directory(): with NamedFileInTemporaryDirectory('filename') as file: name = file.name assert not file.closed assert os.path.exists(name) file.write(b'test') assert file.closed assert not os.path.exists(name) def test_temporary_working_directory(): with TemporaryWorkingDirectory() as dir: assert os.path.exists(dir) assert os.path.realpath(os.curdir) == os.path.realpath(dir) assert not os.path.exists(dir) assert os.path.abspath(os.curdir) != dir ipython_genutils-0.1.0/ipython_genutils/tests/test_text.py0000644000076500000000000000377312516471343024535 0ustar minrkwheel00000000000000# encoding: utf-8 """Tests for IPython.utils.text""" from __future__ import print_function # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. import os import math import random import sys import nose.tools as nt from .. import text def test_columnize(): """Basic columnize tests.""" size = 5 items = [l*size for l in 'abc'] out = text.columnize(items, displaywidth=80) nt.assert_equal(out, 'aaaaa bbbbb ccccc\n') out = text.columnize(items, displaywidth=12) nt.assert_equal(out, 'aaaaa ccccc\nbbbbb\n') out = text.columnize(items, displaywidth=10) nt.assert_equal(out, 'aaaaa\nbbbbb\nccccc\n') def test_columnize_random(): """Test with random input to hopfully catch edge case """ for nitems in [random.randint(2,70) for i in range(2,20)]: displaywidth = random.randint(20,200) rand_len = [random.randint(2,displaywidth) for i in range(nitems)] items = ['x'*l for l in rand_len] out = text.columnize(items, displaywidth=displaywidth) longer_line = max([len(x) for x in out.split('\n')]) longer_element = max(rand_len) if longer_line > displaywidth: print("Columnize displayed something lager than displaywidth : %s " % longer_line) print("longer element : %s " % longer_element) print("displaywidth : %s " % displaywidth) print("number of element : %s " % nitems) print("size of each element :\n %s" % rand_len) assert False def test_columnize_medium(): """Test with inputs than shouldn't be wider tahn 80 """ size = 40 items = [l*size for l in 'abc'] out = text.columnize(items, displaywidth=80) nt.assert_equal(out, '\n'.join(items+[''])) def test_columnize_long(): """Test columnize with inputs longer than the display window""" size = 11 items = [l*size for l in 'abc'] out = text.columnize(items, displaywidth=size-1) nt.assert_equal(out, '\n'.join(items+[''])) ipython_genutils-0.1.0/ipython_genutils/text.py0000644000076500000000000001542112516471343022325 0ustar minrkwheel00000000000000# encoding: utf-8 """ Utilities for working with strings and text. Inheritance diagram: .. inheritance-diagram:: IPython.utils.text :parts: 3 """ import os import re import sys import textwrap from string import Formatter # datetime.strftime date format for ipython if sys.platform == 'win32': date_format = "%B %d, %Y" else: date_format = "%B %-d, %Y" def indent(instr,nspaces=4, ntabs=0, flatten=False): """Indent a string a given number of spaces or tabstops. indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces. Parameters ---------- instr : basestring The string to be indented. nspaces : int (default: 4) The number of spaces to be indented. ntabs : int (default: 0) The number of tabs to be indented. flatten : bool (default: False) Whether to scrub existing indentation. If True, all lines will be aligned to the same indentation. If False, existing indentation will be strictly increased. Returns ------- str|unicode : string indented by ntabs and nspaces. """ if instr is None: return ind = '\t'*ntabs+' '*nspaces if flatten: pat = re.compile(r'^\s*', re.MULTILINE) else: pat = re.compile(r'^', re.MULTILINE) outstr = re.sub(pat, ind, instr) if outstr.endswith(os.linesep+ind): return outstr[:-len(ind)] else: return outstr def dedent(text): """Equivalent of textwrap.dedent that ignores unindented first line. This means it will still dedent strings like: '''foo is a bar ''' For use in wrap_paragraphs. """ if text.startswith('\n'): # text starts with blank line, don't ignore the first line return textwrap.dedent(text) # split first line splits = text.split('\n',1) if len(splits) == 1: # only one line return textwrap.dedent(text) first, rest = splits # dedent everything but the first line rest = textwrap.dedent(rest) return '\n'.join([first, rest]) def wrap_paragraphs(text, ncols=80): """Wrap multiple paragraphs to fit a specified width. This is equivalent to textwrap.wrap, but with support for multiple paragraphs, as separated by empty lines. Returns ------- list of complete paragraphs, wrapped to fill `ncols` columns. """ paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE) text = dedent(text).strip() paragraphs = paragraph_re.split(text)[::2] # every other entry is space out_ps = [] indent_re = re.compile(r'\n\s+', re.MULTILINE) for p in paragraphs: # presume indentation that survives dedent is meaningful formatting, # so don't fill unless text is flush. if indent_re.search(p) is None: # wrap paragraph p = textwrap.fill(p, ncols) out_ps.append(p) return out_ps def strip_ansi(source): """ Remove ansi escape codes from text. Parameters ---------- source : str Source to remove the ansi from """ return re.sub(r'\033\[(\d|;)+?m', '', source) #----------------------------------------------------------------------------- # Utils to columnize a list of string #----------------------------------------------------------------------------- def _chunks(l, n): """Yield successive n-sized chunks from l.""" for i in range(0, len(l), n): yield l[i:i+n] def _find_optimal(rlist , separator_size=2 , displaywidth=80): """Calculate optimal info to columnize a list of string""" for nrow in range(1, len(rlist)+1) : chk = list(map(max,_chunks(rlist, nrow))) sumlength = sum(chk) ncols = len(chk) if sumlength+separator_size*(ncols-1) <= displaywidth : break; return {'columns_numbers' : ncols, 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0, 'rows_numbers' : nrow, 'columns_width' : chk } def _get_or_default(mylist, i, default=None): """return list item number, or default if don't exist""" if i >= len(mylist): return default else : return mylist[i] def compute_item_matrix(items, empty=None, *args, **kwargs) : """Returns a nested list, and info to columnize items Parameters ---------- items list of strings to columize empty : (default None) default value to fill list if needed separator_size : int (default=2) How much caracters will be used as a separation between each columns. displaywidth : int (default=80) The width of the area onto wich the columns should enter Returns ------- strings_matrix nested list of string, the outer most list contains as many list as rows, the innermost lists have each as many element as colums. If the total number of elements in `items` does not equal the product of rows*columns, the last element of some lists are filled with `None`. dict_info some info to make columnize easier: columns_numbers number of columns rows_numbers number of rows columns_width list of with of each columns optimal_separator_width best separator width between columns Examples -------- :: In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l'] ...: compute_item_matrix(l,displaywidth=12) Out[1]: ([['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]], {'columns_numbers': 3, 'columns_width': [5, 1, 1], 'optimal_separator_width': 2, 'rows_numbers': 5}) """ info = _find_optimal(list(map(len, items)), *args, **kwargs) nrow, ncol = info['rows_numbers'], info['columns_numbers'] return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info) def columnize(items, separator=' ', displaywidth=80): """ Transform a list of strings into a single string with columns. Parameters ---------- items : sequence of strings The strings to process. separator : str, optional [default is two spaces] The string that separates columns. displaywidth : int, optional [default is 80] Width of the display in number of characters. Returns ------- The formatted string. """ if not items : return '\n' matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth) fmatrix = [filter(None, x) for x in matrix] sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])]) return '\n'.join(map(sjoin, fmatrix))+'\n' ipython_genutils-0.1.0/ipython_genutils.egg-info/0000755000076500000000000000000012516471377022465 5ustar minrkwheel00000000000000ipython_genutils-0.1.0/ipython_genutils.egg-info/dependency_links.txt0000644000076500000000000000000112516471377026533 0ustar minrkwheel00000000000000 ipython_genutils-0.1.0/ipython_genutils.egg-info/pbr.json0000644000076500000000000000005612516471377024144 0ustar minrkwheel00000000000000{"is_release": true, "git_version": "a21d401"}ipython_genutils-0.1.0/ipython_genutils.egg-info/PKG-INFO0000644000076500000000000000137512516471377023570 0ustar minrkwheel00000000000000Metadata-Version: 1.1 Name: ipython-genutils Version: 0.1.0 Summary: Vestigial utilities from IPython Home-page: http://ipython.org Author: IPython Development Team Author-email: ipython-dev@scipy.org License: BSD Description: Pretend this doesn't exist. Nobody should use it. Keywords: Interactive,Interpreter,Shell,Web Platform: Linux Platform: Mac OS X Platform: Windows Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: Intended Audience :: Science/Research Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 ipython_genutils-0.1.0/ipython_genutils.egg-info/SOURCES.txt0000644000076500000000000000142112516471377024347 0ustar minrkwheel00000000000000CONTRIBUTING.md COPYING.md MANIFEST.in README.md setup.cfg setup.py ipython_genutils/__init__.py ipython_genutils/_version.py ipython_genutils/encoding.py ipython_genutils/importstring.py ipython_genutils/ipstruct.py ipython_genutils/path.py ipython_genutils/py3compat.py ipython_genutils/tempdir.py ipython_genutils/text.py ipython_genutils.egg-info/PKG-INFO ipython_genutils.egg-info/SOURCES.txt ipython_genutils.egg-info/dependency_links.txt ipython_genutils.egg-info/pbr.json ipython_genutils.egg-info/top_level.txt ipython_genutils/testing/__init__.py ipython_genutils/testing/decorators.py ipython_genutils/tests/__init__.py ipython_genutils/tests/test_importstring.py ipython_genutils/tests/test_path.py ipython_genutils/tests/test_tempdir.py ipython_genutils/tests/test_text.pyipython_genutils-0.1.0/ipython_genutils.egg-info/top_level.txt0000644000076500000000000000002112516471377025210 0ustar minrkwheel00000000000000ipython_genutils ipython_genutils-0.1.0/MANIFEST.in0000644000076500000000000000056612516471343017125 0ustar minrkwheel00000000000000include COPYING.md include CONTRIBUTING.md include README.md # Documentation graft docs exclude docs/\#* # Examples graft examples # docs subdirs we want to skip prune docs/build prune docs/gh-pages prune docs/dist # Patterns to exclude from any directory global-exclude *~ global-exclude *.pyc global-exclude *.pyo global-exclude .git global-exclude .ipynb_checkpoints ipython_genutils-0.1.0/PKG-INFO0000644000076500000000000000137512516471377016472 0ustar minrkwheel00000000000000Metadata-Version: 1.1 Name: ipython_genutils Version: 0.1.0 Summary: Vestigial utilities from IPython Home-page: http://ipython.org Author: IPython Development Team Author-email: ipython-dev@scipy.org License: BSD Description: Pretend this doesn't exist. Nobody should use it. Keywords: Interactive,Interpreter,Shell,Web Platform: Linux Platform: Mac OS X Platform: Windows Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: Intended Audience :: Science/Research Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 ipython_genutils-0.1.0/README.md0000644000076500000000000000057012516471343016641 0ustar minrkwheel00000000000000# IPython vestigial utilities This package shouldn't exist. It contains some common utilities shared by Jupyter and IPython projects during The Big Split™. As soon as possible, those packages will remove their dependency on this, and this repo will go away. No functionality should be added to this repository, and no packages outside IPython/Jupyter should depend on it. ipython_genutils-0.1.0/setup.cfg0000644000076500000000000000013012516471377017202 0ustar minrkwheel00000000000000[bdist_wheel] universal = 1 [egg_info] tag_date = 0 tag_build = tag_svn_revision = 0 ipython_genutils-0.1.0/setup.py0000644000076500000000000000516612516471343017102 0ustar minrkwheel00000000000000#!/usr/bin/env python # coding: utf-8 # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. from __future__ import print_function # the name of the project name = 'ipython_genutils' #----------------------------------------------------------------------------- # Minimal Python version sanity check #----------------------------------------------------------------------------- import sys v = sys.version_info if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)): error = "ERROR: %s requires Python version 2.7 or 3.3 or above." % name print(error, file=sys.stderr) sys.exit(1) PY3 = (sys.version_info[0] >= 3) #----------------------------------------------------------------------------- # get on with it #----------------------------------------------------------------------------- import os from glob import glob from distutils.core import setup pjoin = os.path.join here = os.path.abspath(os.path.dirname(__file__)) pkg_root = pjoin(here, name) packages = [] for d, _, _ in os.walk(pjoin(here, name)): if os.path.exists(pjoin(d, '__init__.py')): packages.append(d[len(here)+1:].replace(os.path.sep, '.')) version_ns = {} with open(pjoin(here, name, '_version.py')) as f: exec(f.read(), {}, version_ns) setup_args = dict( name = name, version = version_ns['__version__'], scripts = glob(pjoin('scripts', '*')), packages = packages, description = "Vestigial utilities from IPython", long_description= "Pretend this doesn't exist. Nobody should use it.", author = 'IPython Development Team', author_email = 'ipython-dev@scipy.org', url = 'http://ipython.org', license = 'BSD', platforms = "Linux, Mac OS X, Windows", keywords = ['Interactive', 'Interpreter', 'Shell', 'Web'], classifiers = [ 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'Intended Audience :: Science/Research', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', ], ) if 'develop' in sys.argv or any(a.startswith('bdist') for a in sys.argv): import setuptools setuptools_args = {} install_requires = setuptools_args['install_requires'] = [ ] extras_require = setuptools_args['extras_require'] = { } if 'setuptools' in sys.modules: setup_args.update(setuptools_args) if __name__ == '__main__': setup(**setup_args)