From a3c4e796e658ac3fbe557be3456c24ea07092f90 2013-02-05 16:14:17 From: Bussonnier Matthias <bussonniermatthias@gmail.com> Date: 2013-02-05 16:14:17 Subject: [PATCH] Merge pull request #2882 from takluyver/utils-cleanup Utils cleanup. This removes various unused code that was sitting in IPython.utils. I checked that we don't use these functions and modules at present, but we may want to leave some of them for future use or for extension authors. For the first pass, I've been deliberately quite aggressive about removing things. --- diff --git a/IPython/core/magics/code.py b/IPython/core/magics/code.py index 5826539..1c7a66a 100644 --- a/IPython/core/magics/code.py +++ b/IPython/core/magics/code.py @@ -27,7 +27,6 @@ from IPython.core.oinspect import find_file, find_source_lines from IPython.testing.skipdoctest import skip_doctest from IPython.utils import py3compat from IPython.utils.contexts import preserve_keys -from IPython.utils.io import file_read from IPython.utils.path import get_py_filename, unquote_filename from IPython.utils.warn import warn @@ -531,7 +530,8 @@ class CodeMagics(Magics): # XXX TODO: should this be generalized for all string vars? # For now, this is special-cased to blocks created by cpaste if args.strip() == 'pasted_block': - self.shell.user_ns['pasted_block'] = file_read(filename) + with open(filename, 'r') as f: + self.shell.user_ns['pasted_block'] = f.read() if 'x' in opts: # -x prevents actual execution print @@ -541,8 +541,9 @@ class CodeMagics(Magics): if not is_temp: self.shell.user_ns['__file__'] = filename if 'r' in opts: # Untranslated IPython code - self.shell.run_cell(file_read(filename), - store_history=False) + with open(filename, 'r') as f: + source = f.read() + self.shell.run_cell(source, store_history=False) else: self.shell.safe_execfile(filename, self.shell.user_ns, self.shell.user_ns) diff --git a/IPython/core/magics/osm.py b/IPython/core/magics/osm.py index e7a0567..6c9da55 100644 --- a/IPython/core/magics/osm.py +++ b/IPython/core/magics/osm.py @@ -31,7 +31,6 @@ from IPython.core.magic import ( Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic ) from IPython.testing.skipdoctest import skip_doctest -from IPython.utils.io import nlprint from IPython.utils.openpy import source_to_unicode from IPython.utils.path import unquote_filename from IPython.utils.process import abbrev_cwd @@ -403,7 +402,7 @@ class OSMagics(Magics): %dhist -> print full history\\ %dhist n -> print last n entries only\\ - %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\ + %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\ This history is automatically maintained by the %cd command, and always available as the global list variable _dh. You can use %cd -<n> @@ -425,14 +424,15 @@ class OSMagics(Magics): ini,fin = max(len(dh)-(args[0]),0),len(dh) elif len(args) == 2: ini,fin = args + fin = min(fin, len(dh)) else: self.arg_err(self.dhist) return else: ini,fin = 0,len(dh) - nlprint(dh, - header = 'Directory history (kept in _dh)', - start=ini,stop=fin) + print 'Directory history (kept in _dh)' + for i in range(ini, fin): + print "%d: %s" % (i, dh[i]) @skip_doctest @line_magic diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py index 6413215..a0d787b 100644 --- a/IPython/core/ultratb.py +++ b/IPython/core/ultratb.py @@ -104,9 +104,9 @@ from IPython.core.display_trap import DisplayTrap from IPython.core.excolors import exception_colors from IPython.utils import PyColorize from IPython.utils import io +from IPython.utils import openpy from IPython.utils import path as util_path from IPython.utils import py3compat -from IPython.utils import pyfile from IPython.utils import ulinecache from IPython.utils.data import uniq_stable from IPython.utils.warn import info, error @@ -837,7 +837,7 @@ class VerboseTB(TBTools): continue elif file.endswith(('.pyc','.pyo')): # Look up the corresponding source file. - file = pyfile.source_from_cache(file) + file = openpy.source_from_cache(file) def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): line = getline(file, lnum[0]) diff --git a/IPython/extensions/autoreload.py b/IPython/extensions/autoreload.py index 947d4a1..f1cec38 100644 --- a/IPython/extensions/autoreload.py +++ b/IPython/extensions/autoreload.py @@ -119,7 +119,7 @@ try: except NameError: from imp import reload -from IPython.utils import pyfile +from IPython.utils import openpy from IPython.utils.py3compat import PY3 #------------------------------------------------------------------------------ @@ -207,12 +207,12 @@ class ModuleReloader(object): path, ext = os.path.splitext(filename) if ext.lower() == '.py': - pyc_filename = pyfile.cache_from_source(filename) + pyc_filename = openpy.cache_from_source(filename) py_filename = filename else: pyc_filename = filename try: - py_filename = pyfile.source_from_cache(filename) + py_filename = openpy.source_from_cache(filename) except ValueError: continue diff --git a/IPython/lib/demo.py b/IPython/lib/demo.py index a094c10..621e44a 100644 --- a/IPython/lib/demo.py +++ b/IPython/lib/demo.py @@ -184,7 +184,6 @@ import shlex import sys from IPython.utils import io -from IPython.utils.io import file_read from IPython.utils.text import marquee from IPython.utils import openpy __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] @@ -380,7 +379,8 @@ class Demo(object): filename = self.shell.mktempfile(self.src_blocks[index]) self.shell.hooks.editor(filename,1) - new_block = file_read(filename) + with open(filename, 'r') as f: + new_block = f.read() # update the source and colored block self.src_blocks[index] = new_block self.src_blocks_colored[index] = self.ip_colorize(new_block) diff --git a/IPython/parallel/tests/test_newserialized.py b/IPython/parallel/tests/test_newserialized.py deleted file mode 100644 index c7a6180..0000000 --- a/IPython/parallel/tests/test_newserialized.py +++ /dev/null @@ -1,117 +0,0 @@ -"""test serialization with newserialized - -Authors: - -* Min RK -""" - -#------------------------------------------------------------------------------- -# Copyright (C) 2011 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 - -from unittest import TestCase - -from IPython.testing.decorators import parametric -from IPython.utils import newserialized as ns -from IPython.utils.pickleutil import can, uncan, CannedObject, CannedFunction -from IPython.parallel.tests.clienttest import skip_without - -if sys.version_info[0] >= 3: - buffer = memoryview - -class CanningTestCase(TestCase): - def test_canning(self): - d = dict(a=5,b=6) - cd = can(d) - self.assertTrue(isinstance(cd, dict)) - - def test_canned_function(self): - f = lambda : 7 - cf = can(f) - self.assertTrue(isinstance(cf, CannedFunction)) - - @parametric - def test_can_roundtrip(cls): - objs = [ - dict(), - set(), - list(), - ['a',1,['a',1],u'e'], - ] - return map(cls.run_roundtrip, objs) - - @classmethod - def run_roundtrip(self, obj): - o = uncan(can(obj)) - assert o == obj, "failed assertion: %r == %r"%(o,obj) - - def test_serialized_interfaces(self): - - us = {'a':10, 'b':range(10)} - s = ns.serialize(us) - uus = ns.unserialize(s) - self.assertTrue(isinstance(s, ns.SerializeIt)) - self.assertEqual(uus, us) - - def test_pickle_serialized(self): - obj = {'a':1.45345, 'b':'asdfsdf', 'c':10000L} - original = ns.UnSerialized(obj) - originalSer = ns.SerializeIt(original) - firstData = originalSer.getData() - firstTD = originalSer.getTypeDescriptor() - firstMD = originalSer.getMetadata() - self.assertEqual(firstTD, 'pickle') - self.assertEqual(firstMD, {}) - unSerialized = ns.UnSerializeIt(originalSer) - secondObj = unSerialized.getObject() - for k, v in secondObj.iteritems(): - self.assertEqual(obj[k], v) - secondSer = ns.SerializeIt(ns.UnSerialized(secondObj)) - self.assertEqual(firstData, secondSer.getData()) - self.assertEqual(firstTD, secondSer.getTypeDescriptor() ) - self.assertEqual(firstMD, secondSer.getMetadata()) - - @skip_without('numpy') - def test_ndarray_serialized(self): - import numpy - a = numpy.linspace(0.0, 1.0, 1000) - unSer1 = ns.UnSerialized(a) - ser1 = ns.SerializeIt(unSer1) - td = ser1.getTypeDescriptor() - self.assertEqual(td, 'ndarray') - md = ser1.getMetadata() - self.assertEqual(md['shape'], a.shape) - self.assertEqual(md['dtype'], a.dtype) - buff = ser1.getData() - self.assertEqual(buff, buffer(a)) - s = ns.Serialized(buff, td, md) - final = ns.unserialize(s) - self.assertEqual(buffer(a), buffer(final)) - self.assertTrue((a==final).all()) - self.assertEqual(a.dtype, final.dtype) - self.assertEqual(a.shape, final.shape) - # test non-copying: - a[2] = 1e9 - self.assertTrue((a==final).all()) - - def test_uncan_function_globals(self): - """test that uncanning a module function restores it into its module""" - from re import search - cf = can(search) - csearch = uncan(cf) - self.assertEqual(csearch.__module__, search.__module__) - self.assertNotEqual(csearch('asd', 'asdf'), None) - csearch = uncan(cf, dict(a=5)) - self.assertEqual(csearch.__module__, search.__module__) - self.assertNotEqual(csearch('asd', 'asdf'), None) - - \ No newline at end of file diff --git a/IPython/utils/_process_posix.py b/IPython/utils/_process_posix.py index dae2f42..baf7c24 100644 --- a/IPython/utils/_process_posix.py +++ b/IPython/utils/_process_posix.py @@ -22,7 +22,6 @@ import sys from IPython.external import pexpect # Our own -from .autoattr import auto_attr from ._process_common import getoutput, arg_split from IPython.utils import py3compat from IPython.utils.encoding import DEFAULT_ENCODING @@ -55,14 +54,16 @@ class ProcessHandler(object): logfile = None # Shell to call for subprocesses to execute - sh = None + _sh = None - @auto_attr + @property def sh(self): - sh = pexpect.which('sh') - if sh is None: - raise OSError('"sh" shell not found') - return sh + if self._sh is None: + self._sh = pexpect.which('sh') + if self._sh is None: + raise OSError('"sh" shell not found') + + return self._sh def __init__(self, logfile=None, read_timeout=None, terminate_timeout=None): """Arguments are used for pexpect calls.""" diff --git a/IPython/utils/autoattr.py b/IPython/utils/autoattr.py deleted file mode 100644 index f8cb63a..0000000 --- a/IPython/utils/autoattr.py +++ /dev/null @@ -1,164 +0,0 @@ -"""Descriptor utilities. - -Utilities to support special Python descriptors [1,2], in particular the use of -a useful pattern for properties we call 'one time properties'. These are -object attributes which are declared as properties, but become regular -attributes once they've been read the first time. They can thus be evaluated -later in the object's life cycle, but once evaluated they become normal, static -attributes with no function call overhead on access or any other constraints. - -A special ResetMixin class is provided to add a .reset() method to users who -may want to have their objects capable of resetting these computed properties -to their 'untriggered' state. - -References ----------- -[1] How-To Guide for Descriptors, Raymond -Hettinger. http://users.rcn.com/python/download/Descriptor.htm - -[2] Python data model, http://docs.python.org/reference/datamodel.html - -Notes ------ -This module is taken from the NiPy project -(http://nipy.sourceforge.net/nipy/stable/index.html), and is BSD licensed. - -Authors -------- -- Fernando Perez. -""" - -#----------------------------------------------------------------------------- -# Classes and Functions -#----------------------------------------------------------------------------- - -class ResetMixin(object): - """A Mixin class to add a .reset() method to users of OneTimeProperty. - - By default, auto attributes once computed, become static. If they happen to - depend on other parts of an object and those parts change, their values may - now be invalid. - - This class offers a .reset() method that users can call *explicitly* when - they know the state of their objects may have changed and they want to - ensure that *all* their special attributes should be invalidated. Once - reset() is called, all their auto attributes are reset to their - OneTimeProperty descriptors, and their accessor functions will be triggered - again. - - Example - ------- - - >>> class A(ResetMixin): - ... def __init__(self,x=1.0): - ... self.x = x - ... - ... @auto_attr - ... def y(self): - ... print '*** y computation executed ***' - ... return self.x / 2.0 - ... - - >>> a = A(10) - - About to access y twice, the second time no computation is done: - >>> a.y - *** y computation executed *** - 5.0 - >>> a.y - 5.0 - - Changing x - >>> a.x = 20 - - a.y doesn't change to 10, since it is a static attribute: - >>> a.y - 5.0 - - We now reset a, and this will then force all auto attributes to recompute - the next time we access them: - >>> a.reset() - - About to access y twice again after reset(): - >>> a.y - *** y computation executed *** - 10.0 - >>> a.y - 10.0 - """ - - def reset(self): - """Reset all OneTimeProperty attributes that may have fired already.""" - instdict = self.__dict__ - classdict = self.__class__.__dict__ - # To reset them, we simply remove them from the instance dict. At that - # point, it's as if they had never been computed. On the next access, - # the accessor function from the parent class will be called, simply - # because that's how the python descriptor protocol works. - for mname, mval in classdict.items(): - if mname in instdict and isinstance(mval, OneTimeProperty): - delattr(self, mname) - - -class OneTimeProperty(object): - """A descriptor to make special properties that become normal attributes. - - This is meant to be used mostly by the auto_attr decorator in this module. - """ - def __init__(self,func): - """Create a OneTimeProperty instance. - - Parameters - ---------- - func : method - - The method that will be called the first time to compute a value. - Afterwards, the method's name will be a standard attribute holding - the value of this computation. - """ - self.getter = func - self.name = func.func_name - - def __get__(self,obj,type=None): - """This will be called on attribute access on the class or instance. """ - - if obj is None: - # Being called on the class, return the original function. This way, - # introspection works on the class. - #return func - return self.getter - - val = self.getter(obj) - #print "** auto_attr - loading '%s'" % self.name # dbg - setattr(obj, self.name, val) - return val - - -def auto_attr(func): - """Decorator to create OneTimeProperty attributes. - - Parameters - ---------- - func : method - The method that will be called the first time to compute a value. - Afterwards, the method's name will be a standard attribute holding the - value of this computation. - - Examples - -------- - >>> class MagicProp(object): - ... @auto_attr - ... def a(self): - ... return 99 - ... - >>> x = MagicProp() - >>> 'a' in x.__dict__ - False - >>> x.a - 99 - >>> 'a' in x.__dict__ - True - """ - return OneTimeProperty(func) - - diff --git a/IPython/utils/data.py b/IPython/utils/data.py index 69811d9..1ce7aa3 100644 --- a/IPython/utils/data.py +++ b/IPython/utils/data.py @@ -9,16 +9,6 @@ # the file COPYING, distributed as part of this software. #----------------------------------------------------------------------------- -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -import types - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - def uniq_stable(elems): """uniq_stable(elems) -> list @@ -32,65 +22,14 @@ def uniq_stable(elems): return [x for x in elems if x not in seen and not seen.add(x)] -def sort_compare(lst1, lst2, inplace=1): - """Sort and compare two lists. - - By default it does it in place, thus modifying the lists. Use inplace = 0 - to avoid that (at the cost of temporary copy creation).""" - if not inplace: - lst1 = lst1[:] - lst2 = lst2[:] - lst1.sort(); lst2.sort() - return lst1 == lst2 - - -def list2dict(lst): - """Takes a list of (key,value) pairs and turns it into a dict.""" - - dic = {} - for k,v in lst: dic[k] = v - return dic - - -def list2dict2(lst, default=''): - """Takes a list and turns it into a dict. - Much slower than list2dict, but more versatile. This version can take - lists with sublists of arbitrary length (including sclars).""" - - dic = {} - for elem in lst: - if type(elem) in (types.ListType,types.TupleType): - size = len(elem) - if size == 0: - pass - elif size == 1: - dic[elem] = default - else: - k,v = elem[0], elem[1:] - if len(v) == 1: v = v[0] - dic[k] = v - else: - dic[elem] = default - return dic - - def flatten(seq): """Flatten a list of lists (NOT recursive, only works for 2d lists).""" return [x for subseq in seq for x in subseq] - - -def get_slice(seq, start=0, stop=None, step=1): - """Get a slice of a sequence with variable step. Specify start,stop,step.""" - if stop == None: - stop = len(seq) - item = lambda i: seq[i] - return map(item,xrange(start,stop,step)) - + def chop(seq, size): """Chop a sequence into chunks of the given size.""" - chunk = lambda i: seq[i:i+size] - return map(chunk,xrange(0,len(seq),size)) + return [seq[i:i+size] for i in xrange(0,len(seq),size)] diff --git a/IPython/utils/growl.py b/IPython/utils/growl.py deleted file mode 100644 index db1279b..0000000 --- a/IPython/utils/growl.py +++ /dev/null @@ -1,65 +0,0 @@ -# encoding: utf-8 -""" -Utilities using Growl on OS X for notifications. -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 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 -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - -class IPythonGrowlError(Exception): - pass - -class Notifier(object): - - def __init__(self, app_name): - try: - import Growl - except ImportError: - self.g_notifier = None - else: - self.g_notifier = Growl.GrowlNotifier(app_name, ['kernel', 'core']) - self.g_notifier.register() - - def _notify(self, title, msg): - if self.g_notifier is not None: - self.g_notifier.notify('core', title, msg) - - def notify(self, title, msg): - self._notify(title, msg) - - def notify_deferred(self, r, msg): - title = "Deferred Result" - msg = msg + '\n' + repr(r) - self._notify(title, msg) - return r - -_notifier = None - -def notify(title, msg): - pass - -def notify_deferred(r, msg): - return r - -def start(app_name): - global _notifier, notify, notify_deferred - if _notifier is not None: - raise IPythonGrowlError("this process is already registered with Growl") - else: - _notifier = Notifier(app_name) - notify = _notifier.notify - notify_deferred = _notifier.notify_deferred - - diff --git a/IPython/utils/io.py b/IPython/utils/io.py index ec00a29..e5be667 100644 --- a/IPython/utils/io.py +++ b/IPython/utils/io.py @@ -154,64 +154,6 @@ class Tee(object): self.close() -def file_read(filename): - """Read a file and close it. Returns the file source.""" - fobj = open(filename,'r'); - source = fobj.read(); - fobj.close() - return source - - -def file_readlines(filename): - """Read a file and close it. Returns the file source using readlines().""" - fobj = open(filename,'r'); - lines = fobj.readlines(); - fobj.close() - return lines - - -def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'): - """Take multiple lines of input. - - A list with each line of input as a separate element is returned when a - termination string is entered (defaults to a single '.'). Input can also - terminate via EOF (^D in Unix, ^Z-RET in Windows). - - Lines of input which end in \\ are joined into single entries (and a - secondary continuation prompt is issued as long as the user terminates - lines with \\). This allows entering very long strings which are still - meant to be treated as single entities. - """ - - try: - if header: - header += '\n' - lines = [raw_input(header + ps1)] - except EOFError: - return [] - terminate = [terminate_str] - try: - while lines[-1:] != terminate: - new_line = raw_input(ps1) - while new_line.endswith('\\'): - new_line = new_line[:-1] + raw_input(ps2) - lines.append(new_line) - - return lines[:-1] # don't return the termination command - except EOFError: - print() - return lines - - -def raw_input_ext(prompt='', ps2='... '): - """Similar to raw_input(), but accepts extended lines if input ends with \\.""" - - line = raw_input(prompt) - while line.endswith('\\'): - line = line[:-1] + raw_input(ps2) - return line - - def ask_yes_no(prompt,default=None): """Asks a question and returns a boolean (y/n) answer. @@ -242,44 +184,6 @@ def ask_yes_no(prompt,default=None): return answers[ans] -class NLprinter: - """Print an arbitrarily nested list, indicating index numbers. - - An instance of this class called nlprint is available and callable as a - function. - - nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent' - and using 'sep' to separate the index from the value. """ - - def __init__(self): - self.depth = 0 - - def __call__(self,lst,pos='',**kw): - """Prints the nested list numbering levels.""" - kw.setdefault('indent',' ') - kw.setdefault('sep',': ') - kw.setdefault('start',0) - kw.setdefault('stop',len(lst)) - # we need to remove start and stop from kw so they don't propagate - # into a recursive call for a nested list. - start = kw['start']; del kw['start'] - stop = kw['stop']; del kw['stop'] - if self.depth == 0 and 'header' in kw.keys(): - print(kw['header']) - - for idx in range(start,stop): - elem = lst[idx] - newpos = pos + str(idx) - if type(elem)==type([]): - self.depth += 1 - self.__call__(elem, newpos+",", **kw) - self.depth -= 1 - else: - print(kw['indent']*self.depth + newpos + kw["sep"] + repr(elem)) - -nlprint = NLprinter() - - def temp_pyfile(src, ext='.py'): """Make a temporary python file, return filename and filehandle. diff --git a/IPython/utils/ipstruct.py b/IPython/utils/ipstruct.py index ca53e2e..809c7ac 100644 --- a/IPython/utils/ipstruct.py +++ b/IPython/utils/ipstruct.py @@ -18,8 +18,6 @@ Authors: # Imports #----------------------------------------------------------------------------- -from IPython.utils.data import list2dict2 - __all__ = ['Struct'] #----------------------------------------------------------------------------- @@ -370,7 +368,7 @@ class Struct(dict): add_s = lambda old,new: old + ' ' + new # default policy is to keep current keys when there's a conflict - conflict_solve = list2dict2(self.keys(), default = preserve) + 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 diff --git a/IPython/utils/newserialized.py b/IPython/utils/newserialized.py deleted file mode 100644 index c3336c7..0000000 --- a/IPython/utils/newserialized.py +++ /dev/null @@ -1,177 +0,0 @@ -# encoding: utf-8 -# -*- test-case-name: IPython.kernel.test.test_newserialized -*- - -"""Refactored serialization classes and interfaces.""" - -__docformat__ = "restructuredtext en" - -# Tell nose to skip this module -__test__ = {} - -#------------------------------------------------------------------------------- -# Copyright (C) 2008-2011 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 cPickle as pickle - -try: - import numpy -except ImportError: - numpy = None - -class SerializationError(Exception): - pass - -if sys.version_info[0] >= 3: - buffer = memoryview - py3k = True -else: - py3k = False - if sys.version_info[:2] <= (2,6): - memoryview = buffer - -#----------------------------------------------------------------------------- -# Classes and functions -#----------------------------------------------------------------------------- - -class ISerialized: - - def getData(): - """""" - - def getDataSize(units=10.0**6): - """""" - - def getTypeDescriptor(): - """""" - - def getMetadata(): - """""" - - -class IUnSerialized: - - def getObject(): - """""" - -class Serialized(object): - - # implements(ISerialized) - - def __init__(self, data, typeDescriptor, metadata={}): - self.data = data - self.typeDescriptor = typeDescriptor - self.metadata = metadata - - def getData(self): - return self.data - - def getDataSize(self, units=10.0**6): - return len(self.data)/units - - def getTypeDescriptor(self): - return self.typeDescriptor - - def getMetadata(self): - return self.metadata - - -class UnSerialized(object): - - # implements(IUnSerialized) - - def __init__(self, obj): - self.obj = obj - - def getObject(self): - return self.obj - - -class SerializeIt(object): - - # implements(ISerialized) - - def __init__(self, unSerialized): - self.data = None - self.obj = unSerialized.getObject() - if numpy is not None and isinstance(self.obj, numpy.ndarray): - if len(self.obj.shape) == 0: # length 0 arrays are just pickled - self.typeDescriptor = 'pickle' - self.metadata = {} - else: - self.obj = numpy.ascontiguousarray(self.obj, dtype=None) - self.typeDescriptor = 'ndarray' - self.metadata = {'shape':self.obj.shape, - 'dtype':self.obj.dtype} - elif isinstance(self.obj, bytes): - self.typeDescriptor = 'bytes' - self.metadata = {} - elif isinstance(self.obj, buffer): - self.typeDescriptor = 'buffer' - self.metadata = {} - else: - self.typeDescriptor = 'pickle' - self.metadata = {} - self._generateData() - - def _generateData(self): - if self.typeDescriptor == 'ndarray': - self.data = buffer(self.obj) - elif self.typeDescriptor in ('bytes', 'buffer'): - self.data = self.obj - elif self.typeDescriptor == 'pickle': - self.data = pickle.dumps(self.obj, -1) - else: - raise SerializationError("Really wierd serialization error.") - del self.obj - - def getData(self): - return self.data - - def getDataSize(self, units=10.0**6): - return 1.0*len(self.data)/units - - def getTypeDescriptor(self): - return self.typeDescriptor - - def getMetadata(self): - return self.metadata - - -class UnSerializeIt(UnSerialized): - - # implements(IUnSerialized) - - def __init__(self, serialized): - self.serialized = serialized - - def getObject(self): - typeDescriptor = self.serialized.getTypeDescriptor() - if numpy is not None and typeDescriptor == 'ndarray': - buf = self.serialized.getData() - if isinstance(buf, (bytes, buffer, memoryview)): - result = numpy.frombuffer(buf, dtype = self.serialized.metadata['dtype']) - else: - raise TypeError("Expected bytes or buffer/memoryview, but got %r"%type(buf)) - result.shape = self.serialized.metadata['shape'] - elif typeDescriptor == 'pickle': - result = pickle.loads(self.serialized.getData()) - elif typeDescriptor in ('bytes', 'buffer'): - result = self.serialized.getData() - else: - raise SerializationError("Really wierd serialization error.") - return result - -def serialize(obj): - return SerializeIt(UnSerialized(obj)) - -def unserialize(serialized): - return UnSerializeIt(serialized).getObject() diff --git a/IPython/utils/notification.py b/IPython/utils/notification.py deleted file mode 100644 index 506356c..0000000 --- a/IPython/utils/notification.py +++ /dev/null @@ -1,142 +0,0 @@ -# encoding: utf-8 -""" -The IPython Core Notification Center. - -See docs/source/development/notification_blueprint.txt for an overview of the -notification module. - -Authors: - -* Barry Wark -* Brian Granger -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 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. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Code -#----------------------------------------------------------------------------- - - -class NotificationError(Exception): - pass - - -class NotificationCenter(object): - """Synchronous notification center. - - Examples - -------- - Here is a simple example of how to use this:: - - import IPython.util.notification as notification - def callback(ntype, theSender, args={}): - print ntype,theSender,args - - notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None) - notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS - NOTIFICATION_TYPE ... - """ - def __init__(self): - super(NotificationCenter, self).__init__() - self._init_observers() - - def _init_observers(self): - """Initialize observer storage""" - - self.registered_types = set() #set of types that are observed - self.registered_senders = set() #set of senders that are observed - self.observers = {} #map (type,sender) => callback (callable) - - def post_notification(self, ntype, sender, *args, **kwargs): - """Post notification to all registered observers. - - The registered callback will be called as:: - - callback(ntype, sender, *args, **kwargs) - - Parameters - ---------- - ntype : hashable - The notification type. - sender : hashable - The object sending the notification. - *args : tuple - The positional arguments to be passed to the callback. - **kwargs : dict - The keyword argument to be passed to the callback. - - Notes - ----- - * If no registered observers, performance is O(1). - * Notificaiton order is undefined. - * Notifications are posted synchronously. - """ - - if(ntype==None or sender==None): - raise NotificationError( - "Notification type and sender are required.") - - # If there are no registered observers for the type/sender pair - if((ntype not in self.registered_types and - None not in self.registered_types) or - (sender not in self.registered_senders and - None not in self.registered_senders)): - return - - for o in self._observers_for_notification(ntype, sender): - o(ntype, sender, *args, **kwargs) - - def _observers_for_notification(self, ntype, sender): - """Find all registered observers that should recieve notification""" - - keys = ( - (ntype,sender), - (ntype, None), - (None, sender), - (None,None) - ) - - obs = set() - for k in keys: - obs.update(self.observers.get(k, set())) - - return obs - - def add_observer(self, callback, ntype, sender): - """Add an observer callback to this notification center. - - The given callback will be called upon posting of notifications of - the given type/sender and will receive any additional arguments passed - to post_notification. - - Parameters - ---------- - callback : callable - The callable that will be called by :meth:`post_notification` - as ``callback(ntype, sender, *args, **kwargs)`` - ntype : hashable - The notification type. If None, all notifications from sender - will be posted. - sender : hashable - The notification sender. If None, all notifications of ntype - will be posted. - """ - assert(callback != None) - self.registered_types.add(ntype) - self.registered_senders.add(sender) - self.observers.setdefault((ntype,sender), set()).add(callback) - - def remove_all_observers(self): - """Removes all observers from this notification center""" - - self._init_observers() - - - -shared_center = NotificationCenter() diff --git a/IPython/utils/openpy.py b/IPython/utils/openpy.py index 1b3d8b5..dde5229 100644 --- a/IPython/utils/openpy.py +++ b/IPython/utils/openpy.py @@ -8,6 +8,7 @@ from __future__ import absolute_import import io from io import TextIOWrapper, BytesIO +import os.path import re cookie_re = re.compile(ur"coding[:=]\s*([-\w.]+)", re.UNICODE) @@ -217,3 +218,22 @@ def _list_readline(x): def readline(): return next(x) return readline + +# Code for going between .py files and cached .pyc files ---------------------- + +try: # Python 3.2, see PEP 3147 + from imp import source_from_cache, cache_from_source +except ImportError: + # Python <= 3.1: .pyc files go next to .py + def source_from_cache(path): + basename, ext = os.path.splitext(path) + if ext not in ('.pyc', '.pyo'): + raise ValueError('Not a cached Python file extension', ext) + # Should we look for .pyw files? + return basename + '.py' + + def cache_from_source(path, debug_override=None): + if debug_override is None: + debug_override = __debug__ + basename, ext = os.path.splitext(path) + return basename + '.pyc' if debug_override else '.pyo' diff --git a/IPython/utils/pyfile.py b/IPython/utils/pyfile.py deleted file mode 100644 index e663c81..0000000 --- a/IPython/utils/pyfile.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Utilities for working with Python source files. - -Exposes various functions from recent Python standard libraries, along with -equivalents for older Python versions. -""" -import os.path - -try: # Python 3.2 - from imp import source_from_cache, cache_from_source -except ImportError: - # Python <= 3.1: .pyc files go next to .py - def source_from_cache(path): - basename, ext = os.path.splitext(path) - if ext not in ('.pyc', '.pyo'): - raise ValueError('Not a cached Python file extension', ext) - # Should we look for .pyw files? - return basename + '.py' - - def cache_from_source(path, debug_override=None): - if debug_override is None: - debug_override = __debug__ - basename, ext = os.path.splitext(path) - return basename + '.pyc' if debug_override else '.pyo' diff --git a/IPython/utils/tests/test_notification.py b/IPython/utils/tests/test_notification.py deleted file mode 100644 index 7a58d9e..0000000 --- a/IPython/utils/tests/test_notification.py +++ /dev/null @@ -1,150 +0,0 @@ -# encoding: utf-8 - -"""This file contains unittests for the notification.py module.""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 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 unittest - -from IPython.utils.notification import shared_center - -#----------------------------------------------------------------------------- -# Support Classes -#----------------------------------------------------------------------------- - - -class Observer(object): - - def __init__(self, expected_ntype, expected_sender, - center=shared_center, *args, **kwargs): - super(Observer, self).__init__() - self.expected_ntype = expected_ntype - self.expected_sender = expected_sender - self.expected_args = args - self.expected_kwargs = kwargs - self.recieved = False - center.add_observer(self.callback, - self.expected_ntype, - self.expected_sender) - - def callback(self, ntype, sender, *args, **kwargs): - assert(ntype == self.expected_ntype or - self.expected_ntype == None) - assert(sender == self.expected_sender or - self.expected_sender == None) - assert(args == self.expected_args) - assert(kwargs == self.expected_kwargs) - self.recieved = True - - def verify(self): - assert(self.recieved) - - def reset(self): - self.recieved = False - - -class Notifier(object): - - def __init__(self, ntype, **kwargs): - super(Notifier, self).__init__() - self.ntype = ntype - self.kwargs = kwargs - - def post(self, center=shared_center): - - center.post_notification(self.ntype, self, - **self.kwargs) - - -#----------------------------------------------------------------------------- -# Tests -#----------------------------------------------------------------------------- - - -class NotificationTests(unittest.TestCase): - - def tearDown(self): - shared_center.remove_all_observers() - - def test_notification_delivered(self): - """Test that notifications are delivered""" - - expected_ntype = 'EXPECTED_TYPE' - sender = Notifier(expected_ntype) - observer = Observer(expected_ntype, sender) - - sender.post() - observer.verify() - - def test_type_specificity(self): - """Test that observers are registered by type""" - - expected_ntype = 1 - unexpected_ntype = "UNEXPECTED_TYPE" - sender = Notifier(expected_ntype) - unexpected_sender = Notifier(unexpected_ntype) - observer = Observer(expected_ntype, sender) - - sender.post() - unexpected_sender.post() - observer.verify() - - def test_sender_specificity(self): - """Test that observers are registered by sender""" - - expected_ntype = "EXPECTED_TYPE" - sender1 = Notifier(expected_ntype) - sender2 = Notifier(expected_ntype) - observer = Observer(expected_ntype, sender1) - - sender1.post() - sender2.post() - - observer.verify() - - def test_remove_all_observers(self): - """White-box test for remove_all_observers""" - - for i in xrange(10): - Observer('TYPE', None, center=shared_center) - - self.assertTrue(len(shared_center.observers[('TYPE',None)]) >= 10, - "observers registered") - - shared_center.remove_all_observers() - self.assertTrue(len(shared_center.observers) == 0, "observers removed") - - def test_any_sender(self): - expected_ntype = "EXPECTED_TYPE" - sender1 = Notifier(expected_ntype) - sender2 = Notifier(expected_ntype) - observer = Observer(expected_ntype, None) - - sender1.post() - observer.verify() - - observer.reset() - sender2.post() - observer.verify() - - def test_post_performance(self): - """Test that post_notification, even with many registered irrelevant - observers is fast""" - - for i in xrange(10): - Observer("UNRELATED_TYPE", None) - - o = Observer('EXPECTED_TYPE', None) - shared_center.post_notification('EXPECTED_TYPE', self) - o.verify() - - diff --git a/IPython/utils/text.py b/IPython/utils/text.py index 35ca6bc..44b19b9 100644 --- a/IPython/utils/text.py +++ b/IPython/utils/text.py @@ -30,25 +30,12 @@ from string import Formatter from IPython.external.path import path from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest from IPython.utils import py3compat -from IPython.utils.io import nlprint from IPython.utils.data import flatten #----------------------------------------------------------------------------- # Code #----------------------------------------------------------------------------- -def unquote_ends(istr): - """Remove a single pair of quotes from the endpoints of a string.""" - - if not istr: - return istr - if (istr[0]=="'" and istr[-1]=="'") or \ - (istr[0]=='"' and istr[-1]=='"'): - return istr[1:-1] - else: - return istr - - class LSString(str): """String derivative with a special access attributes. @@ -265,105 +252,11 @@ class SList(list): # arg.hideonce = False # return # -# nlprint(arg) +# nlprint(arg) # This was a nested list printer, now removed. # # print_slist = result_display.when_type(SList)(print_slist) -def esc_quotes(strng): - """Return the input string with single and double quotes escaped out""" - - return strng.replace('"','\\"').replace("'","\\'") - - -def qw(words,flat=0,sep=None,maxsplit=-1): - """Similar to Perl's qw() operator, but with some more options. - - qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit) - - words can also be a list itself, and with flat=1, the output will be - recursively flattened. - - Examples: - - >>> qw('1 2') - ['1', '2'] - - >>> qw(['a b','1 2',['m n','p q']]) - [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]] - - >>> qw(['a b','1 2',['m n','p q']],flat=1) - ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] - """ - - if isinstance(words, basestring): - return [word.strip() for word in words.split(sep,maxsplit) - if word and not word.isspace() ] - if flat: - return flatten(map(qw,words,[1]*len(words))) - return map(qw,words) - - -def qwflat(words,sep=None,maxsplit=-1): - """Calls qw(words) in flat mode. It's just a convenient shorthand.""" - return qw(words,1,sep,maxsplit) - - -def qw_lol(indata): - """qw_lol('a b') -> [['a','b']], - otherwise it's just a call to qw(). - - We need this to make sure the modules_some keys *always* end up as a - list of lists.""" - - if isinstance(indata, basestring): - return [qw(indata)] - else: - return qw(indata) - - -def grep(pat,list,case=1): - """Simple minded grep-like function. - grep(pat,list) returns occurrences of pat in list, None on failure. - - It only does simple string matching, with no support for regexps. Use the - option case=0 for case-insensitive matching.""" - - # This is pretty crude. At least it should implement copying only references - # to the original data in case it's big. Now it copies the data for output. - out=[] - if case: - for term in list: - if term.find(pat)>-1: out.append(term) - else: - lpat=pat.lower() - for term in list: - if term.lower().find(lpat)>-1: out.append(term) - - if len(out): return out - else: return None - - -def dgrep(pat,*opts): - """Return grep() on dir()+dir(__builtins__). - - A very common use of grep() when working interactively.""" - - return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts) - - -def idgrep(pat): - """Case-insensitive dgrep()""" - - return dgrep(pat,0) - - -def igrep(pat,list): - """Synonym for case-insensitive grep.""" - - return grep(pat,list,case=0) - - def indent(instr,nspaces=4, ntabs=0, flatten=False): """Indent a string a given number of spaces or tabstops.