Skip to content

Instantly share code, notes, and snippets.

@trdarr
Last active December 20, 2015 06:59
Show Gist options
  • Save trdarr/6089840 to your computer and use it in GitHub Desktop.
Save trdarr/6089840 to your computer and use it in GitHub Desktop.
PaRappa the Wrapper
#!/usr/bin/env python
# This prints a useless representation of a _sre.SRE_Pattern object.
import re
uuid_pattern = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{8}'
print re.compile(uuid_pattern, re.I)
# _sre.SRE_Pattern has pattern and __repr__ methods.
if not hasattr(re, '_pattern_type'):
re._pattern_type = type(re.compile(''))
assert hasattr(re._pattern_type, 'pattern')
assert hasattr(re._pattern_type, '__repr__')
# _sre.SRE_Pattern can't be monkey patched.
try:
re._pattern_type.__repr__ = lambda self: self.pattern
except TypeError as error:
print 'TypeError: {}'.format(error.message)
# _sre.SRE_Pattern can't be subclassed.
try:
class RegexObject(re._pattern_type):
def __repr__(self):
return self.message
except TypeError as error:
print 'TypeError: {}'.format(error.message)
# Create a 'RegexObject' wrapper for whatever re.compile returns.
import wrapper
wrapper.create(re, 'RegexObject', re.compile)
# Add a more useful __repr__ function to the wrapper.
re.RegexObject.__repr__ = lambda self: self.pattern
# Much better!
much_better = re.compile(uuid_pattern, re.I)
print much_better
# Wrapper objects delegate "missing methods" to the objects they wrap.
import uuid
uuid_string = str(uuid.uuid4())
matches = much_better.match(uuid_string)
assert matches is not None
class Wrapper(object):
def __init__(self, delegate):
self.delegate = delegate
def __getattr__(self, name):
return getattr(self.delegate, name)
def create(target, class_name, constructor):
# Create a subclass of Wrapper in the target module.
wrapper = type(class_name, (Wrapper,), {'__module__': target.__name__})
setattr(target, class_name, wrapper)
# A wrapper wraps a delegate created by that delegate's constructor.
def wrapper_constructor(*args, **kwargs):
delegate = constructor(*args, **kwargs)
return wrapper(delegate)
# Replace the delegate's constructor with our wrapper constructor.
from importlib import import_module
constructor_module = import_module(constructor.__module__)
setattr(constructor_module, constructor.__name__, wrapper_constructor)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment