Last active
December 20, 2015 06:59
-
-
Save trdarr/6089840 to your computer and use it in GitHub Desktop.
PaRappa the Wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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