Created
April 30, 2010 05:14
-
-
Save ianb/384784 to your computer and use it in GitHub Desktop.
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
## Descriptors | |
## Anything with __get__ and optionally __set__: | |
class classinstancemethod(object): | |
def __init__(self, func): | |
self.func = func | |
def __get__(self, obj, type=None): | |
def repl(*args, **kw): | |
return self.func(obj, type, *args, **kw) | |
return repl | |
## Then to use it: | |
class MyValidator(object): | |
date_format = '%Y-%m-%d' | |
def __init__(self, date_format=None): | |
if date_format is not None: | |
self.date_format = date_format | |
@classinstancemethod | |
def check_input(self, cls, input): | |
if self is None: | |
self = cls() | |
return time.strptime(input, self.date_format) | |
MyValidator('%m-%d-%Y').check_input('5-1-2010') | |
MyValidator.check_input('2010-05-01') | |
## A simple mock object: | |
class Mock(object): | |
def __init__(self, name, returns=None): | |
self.name = name | |
self.returns = returns | |
def __getattr__(self, attr): | |
obj = Mock(self.name + '.' + attr) | |
setattr(self, attr, obj) | |
return obj | |
def __call__(self, *args, **kw): | |
args = [repr(a) for a in args] | |
args.extend(['%s=%r' % (n, v) for n, v in sorted(kw.items())]) | |
print 'Calling %s(%s)' % (self.name, ', '.join(args)) | |
return self.returns | |
## Use in a doctest: | |
>>> import smtplib | |
>>> smtplib.SMTP = Mock('SMTP') | |
>>> smtplib.SMTP.returns = Mock('smtplib_connection') | |
>>> conn = smtplib.SMTP() | |
Calling SMTP() | |
>>> conn.sendmail('dest@example.com', 'me@example.com', 'An email...') | |
Calling smtplib_connection.sendmail('dest@example.com', 'me@example.com', 'An email...') | |
## lxml stuff: | |
def webob.dec import wsgify | |
@wsgify.middleware | |
def link_rewriter(app, req, dest_href): | |
if dest_href.endswith('/'): | |
dest_href = dest_href[:-1] | |
dest_path = req.path_info | |
dest_href = dest_href + dest_path | |
req_href = req.application_url | |
def link_repl_func(link): | |
link = urlparse.urljoin(dest_href, link) | |
if not link.startswith(dest_href): | |
# Not a local link | |
return link | |
new_url = req_href + '/' + link[len(dest_href):] | |
return new_url | |
resp = req.get_response(self.app) | |
resp.decode_content() | |
if (resp.status_int == 200 | |
and resp.content_type == 'text/html'): | |
doc = html.fromstring(resp.body, base_url=dest_href) | |
doc.rewrite_links(link_repl_func) | |
resp.body = html.tostring(doc) | |
if resp.location: | |
resp.location = link_repl_func(resp.location) | |
return resp(environ, start_response) | |
from lxml import html | |
from random import shuffle | |
@wsgify.middleware | |
def jumble_words(app, req): | |
resp = req.get_response(app) | |
doc = html.fromstring(resp.body) | |
words = doc.text_content().split() | |
shuffle(words) | |
for el in doc.body.iterdescendants(): | |
el.text = random_words(el.text, words) | |
el.tail = random_words(el.tail, words) | |
resp.body = html.tostring(doc) | |
return resp | |
def random_words(text, words): | |
if not text: | |
return text | |
return ' '.join(words.pop() for i in range(len(text.split()))) | |
from paste.proxy import Proxy | |
from paste.httpserver import serve | |
def make_proxy(proxy_url): | |
app = Proxy(proxy_url) | |
app = link_rewriter(app, dest_href=proxy_url) | |
serve(app) | |
## generic functions: | |
class multimethod(object): | |
def __init__(self, default): | |
self.default = default.__doc__ | |
self.typemap = {} | |
def __call__(self, *args): | |
types = tuple(arg.__class__ for arg in args) | |
function = self.typemap.get(types, self.default) | |
return function(*args) | |
def register(self, *types): | |
def decorator(func): | |
self.typemap[types] = func | |
return self | |
return decorator | |
@multimethod | |
def html(obj): | |
return cgi.escape(unicode(obj)) | |
from tempita import HTMLTemplate | |
@html.register(dict) | |
def html(obj): | |
return HTMLTemplate("""\ | |
<table> | |
{{for key, value in sorted(obj.items())}} | |
<tr><td>{{html(key)}}</td> | |
<td>{{html(value)}}</td></tr> | |
{{endfor}} | |
</table> | |
""").substitute(obj=obj, html=html) | |
## monkey patching | |
import inspect | |
def set(on_obj): | |
def decorator(func): | |
args = inspect.getargspec(func)[0] | |
set = func | |
if args and args[0] == 'self': | |
if not isinstance(on_obj, type): | |
set = func.__get__(on_obj) | |
elif args and args[0] in ('cls', 'klass'): | |
if isinstance(on_obj, type): | |
set = classmethod(func) | |
else: | |
set = func.__get__(type(on_obj)) | |
setattr(on_obj, func.__name__, set) | |
return func | |
return decorator | |
@set(smtplib) | |
def new_function(): | |
print 'hi' | |
assert smtplib.new_function == new_function | |
@set(smtplib.SMTP) | |
def send_hi(self, person): | |
self.sendmail(person, 'me@example.com', 'Hi!') | |
def exec_maybe_eval(code, globs, locs, name='<web>'): | |
c_single = compile(code, name, 'single', 0, 1) | |
c_exec = compile(code, name, 'exec', 0, 1) | |
if c_single.co_code == c_exec.co_code: | |
# this is a statement | |
exec c_exec in globs, locs | |
return None | |
else: | |
c_eval = compile(code, name, 'eval', 0, 1) | |
value = eval(c_eval, globs, locs) | |
return value | |
def html_repl(): | |
globs = locs = {} | |
while 1: | |
expr = raw_input('>>> ') | |
value = exec_maybe_eval(expr, globs, locs) | |
print html(value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Small error on line 97: s/def/from.