Source code for rootpy.core

"""
This module contains base classes defining core functionality
"""
import ROOT
import re
import uuid
import inspect
from . import rootpy_globals


[docs]class RequireFile(object): def __init__(self): if ROOT.gDirectory.GetName() == 'PyROOT': raise RuntimeError("You must first create a File " "before creating a %s" % self.__class__.__name__) self.__directory = rootpy_globals.directory @staticmethod
[docs] def cd(f): """ A decorator Useful for TTree.Write... """ def g(self, *args, **kwargs): pwd = rootpy_globals.directory self.__directory.cd() return f(self, *args, **kwargs) pwd.cd() return g
[docs]def wrap_call(cls, method, *args, **kwargs): """ Will provide more detailed info in the case that a method call on a ROOT object raises a TypeError """ pass
class _repr_mixin: def __str__(self): return self.__repr__() class _copy_construct_mixin: def set_from(self, other): self.__class__.__bases__[-1].__init__(self, other) class _resetable_mixin: def reset(self): self.__init__()
[docs]def isbasictype(thing): """ Is this thing a basic builtin numeric type? """ return isinstance(thing, (float, int, long))
FIRST_CAP_RE = re.compile('(.)([A-Z][a-z]+)') ALL_CAP_RE = re.compile('([a-z0-9])([A-Z])')
[docs]def camel_to_snake(name): """ http://stackoverflow.com/questions/1175208/ elegant-python-function-to-convert-camelcase-to-camel-case """ s1 = FIRST_CAP_RE.sub(r'\1_\2', name) return ALL_CAP_RE.sub(r'\1_\2', s1).lower()
[docs]def snake_case_methods(cls, debug=False): """ A class decorator adding snake_case methods that alias capitalized ROOT methods """ # Fix both the class and its corresponding ROOT base class root_base = cls.__bases__[-1] members = inspect.getmembers(root_base) # filter out any methods that already exist in lower and uppercase forms # i.e. TDirectory::cd and Cd... names = [item[0].capitalize() for item in members] duplicate_idx = set() seen = [] for i, n in enumerate(names): try: idx = seen.index(n) duplicate_idx.add(i) duplicate_idx.add(idx) except ValueError: seen.append(n) for i, (name, member) in enumerate(members): if i in duplicate_idx: continue # Don't touch special methods or methods without cap letters if name[0] == '_' or name.islower(): continue # Is this a method of the ROOT base class? if inspect.ismethod(member): # convert CamelCase to snake_case new_name = camel_to_snake(name) if debug: print "%s -> %s" % (name, new_name) if hasattr(cls, new_name): raise ValueError( '%s is already a method for %s' % (new_name, cls.__name__)) setattr(cls, new_name, getattr(cls, name)) return cls
[docs]class Object(object): """ Overrides TObject methods. Name and title for TObject-derived classes are optional. If no name is specified, a UUID is used to ensure uniqueness. """ def __init__(self, name, title, *args, **kwargs): if name is None: name = uuid.uuid4().hex if title is None: title = "" self.__class__.__bases__[-1].__init__( self, name, title, *args, **kwargs)
[docs] def Clone(self, name=None, title=None, **kwargs): if name is not None: clone = self.__class__.__bases__[-1].Clone(self, name) else: clone = self.__class__.__bases__[-1].Clone(self, uuid.uuid4().hex) clone.__class__ = self.__class__ if title is not None: clone.SetTitle(title) if hasattr(clone, "_post_init"): from .plotting.core import Plottable if isinstance(self, Plottable): kwds = self.decorators kwds.update(kwargs) clone._post_init(**kwds) else: clone._post_init(**kwargs) return clone
@property def name(self): return self.GetName() @name.setter
[docs] def name(self, _name): self.SetName(_name)
@property def title(self): return self.GetTitle() @title.setter
[docs] def title(self, _title): self.SetTitle(_title)
def __copy__(self): return self.Clone() def __deepcopy__(self, memo): return self.Clone() def __repr__(self): return self.__str__() def __str__(self): return "%s('%s')" % (self.__class__.__name__, self.GetName())
[docs]class NamelessConstructorObject(Object): """ Handle special cases like TGraph where the ROOT constructor does not take name/title """ def __init__(self, name, title, *args, **kwargs): if name is None: name = uuid.uuid4().hex if title is None: title = "" self.__class__.__bases__[-1].__init__(self, *args, **kwargs) self.SetName(name) self.SetTitle(title)