Permalink
Browse files

More PEP8.

  • Loading branch information...
ralphbean committed Mar 21, 2012
1 parent 07fb3c9 commit b387fa47025c4d09ba8c28bce7895215ac5b417d
Showing with 91 additions and 92 deletions.
  1. +2 −0 tw2/core/i18n.py
  2. +79 −85 tw2/core/js.py
  3. +5 −5 tw2/core/middleware.py
  4. +4 −2 tw2/core/resources.py
  5. +1 −0 tw2/core/testbase/base.py
@@ -6,7 +6,9 @@
import logging
log = logging.getLogger(__name__)
def tw2_translation_string(sval):
def lookup_provided_translator(_sval):
mw = core.request_local().get('middleware')
if not mw:
@@ -4,10 +4,10 @@
This moudle doesn't aim to serve as a Python-JS "translator". You should code
your client-side code in JavaScript and make it available in static files which
you include as JSLinks or inline using JSSources. This module is only intended
as a "bridge" or interface between Python and JavaScript so JS function
as a "bridge" or interface between Python and JavaScript so JS function
**calls** can be generated programatically.
"""
import sys
import sys
import logging
from itertools import imap
@@ -17,27 +17,32 @@
log = logging.getLogger(__name__)
class TWEncoder(simplejson.encoder.JSONEncoder):
"""A JSON encoder that can encode Widgets, js_calls, js_symbols and
js_callbacks.
Example::
>> encode = TWEncoder().encode
>> print encode({'onLoad': js_function("do_something")(js_symbol("this"))})
>>> encode = TWEncoder().encode
>>> print encode({
... 'onLoad': js_function("do_something")(js_symbol("this"))
... })
{"onLoad": do_something(this)}
>> from tw2.core.api import Widget
>> w = Widget("foo")
>> args = {'onLoad': js_callback(js_function('jQuery')(w).click(js_symbol('onClick')))}
>> print encode(args)
>>> from tw2.core.api import Widget
>>> w = Widget("foo")
>>> args = {
... 'onLoad': js_callback(
... js_function('jQuery')(w).click(js_symbol('onClick'))
... )
... }
>>> print encode(args)
{"onLoad": function(){jQuery(\\"foo\\").click(onClick)}}
>> print encode({'args':args})
>>> print encode({'args':args})
{"args": {"onLoad": function(){jQuery(\\"foo\\").click(onClick)}}}
"""
def __init__(self, *args, **kw):
kw['namedtuple_as_object'] = False
self.pass_through = (_js_call, js_callback, js_symbol, js_function)
@@ -58,7 +63,7 @@ def mark_for_escape(self, obj):
return '*#*%s*#*' % obj
def unescape_marked(self, encoded):
return encoded.replace('"*#*','').replace('*#*"', '')
return encoded.replace('"*#*', '').replace('*#*"', '')
encoder = None # This gets reset at the bottom of the file.
@@ -84,32 +89,31 @@ class js_callback(object):
Examples:
.. sourcecode:: python
>>> str(js_callback("update_div"))
'update_div'
>> str(js_callback("update_div"))
'update_div'
>>> str(js_callback("function (event) { .... }"))
'function (event) { .... }'
>> str(js_callback("function (event) { .... }"))
'function (event) { .... }'
Can also create callbacks for deferred js calls
# Can also create callbacks for deferred js calls
>>> str(js_callback(js_function('foo')(1,2,3)))
'function(){foo(1, 2, 3)}'
>> str(js_callback(js_function('foo')(1,2,3)))
'function(){foo(1, 2, 3)}'
Or equivalently
# Or equivalently
>>> str(js_callback(js_function('foo'), 1,2,3))
'function(){foo(1, 2, 3)}'
>> str(js_callback(js_function('foo'), 1,2,3))
'function(){foo(1, 2, 3)}'
A more realistic example
# A more realistic example
>> jQuery = js_function('jQuery')
>> my_cb = js_callback('function() { alert(this.text)}')
>> on_doc_load = jQuery('#foo').bind('click', my_cb)
>> call = jQuery(js_callback(on_doc_load))
>> print call
jQuery(function(){jQuery(\\"#foo\\").bind(\\"click\\", function() { alert(this.text)})})
>>> jQuery = js_function('jQuery')
>>> my_cb = js_callback('function() { alert(this.text)}')
>>> on_doc_load = jQuery('#foo').bind('click', my_cb)
>>> call = jQuery(js_callback(on_doc_load))
>>> print call
jQuery(function(){jQuery(\\"#foo\\").bind(
\\"click\\", function() { alert(this.text)})})
"""
def __init__(self, cb, *args):
@@ -124,10 +128,11 @@ def __init__(self, cb, *args):
def __call__(self, *args):
raise TypeError("A js_callback cannot be called from Python")
def __str__(self):
return self.cb
class js_function(object):
"""A JS function that can be "called" from python and and added to
a widget by widget.add_call() so it get's called every time the widget
@@ -138,79 +143,68 @@ class js_function(object):
programatically. Calls can be chained and parameters are automatically
json-encoded into something JavaScript undersrtands. Example::
.. sourcecode:: python
>> jQuery = js_function('jQuery')
>> call = jQuery('#foo').datePicker({'option1': 'value1'})
>> str(call)
'jQuery("#foo").datePicker({"option1": "value1"})'
>>> jQuery = js_function('jQuery')
>>> call = jQuery('#foo').datePicker({'option1': 'value1'})
>>> str(call)
'jQuery("#foo").datePicker({"option1": "value1"})'
Calls are added to the widget call stack with the ``add_call`` method.
If made at Widget initialization those calls will be placed in
the template for every request that renders the widget.
.. sourcecode:: python
>> from tw.api import Widget
>> class SomeWidget(Widget):
... params = ["pickerOptions"]
... pickerOptions = {}
... def __init__(self, *args, **kw):
... super(SomeWidget, self).__init__(*args, **kw)
... self.add_call(
... jQuery('#%s' % self.id).datePicker(self.pickerOptions)
... )
If we want to dynamically make calls on every request, we ca also add_calls
inside the ``prepare`` method.
.. sourcecode:: python
>> class SomeWidget(Widget):
... params = ["pickerOptions"]
... pickerOptions = {}
... def prepare(self):
... super(SomeWidget, self).prepare()
... self.add_call(
... jQuery('#%s' % d.id).datePicker(d.pickerOptions)
... )
>>> import tw2.core as twc
>>> class SomeWidget(twc.Widget):
... pickerOptions = twc.Param(default={})
>>> SomeWidget.add_call(
... jQuery('#%s' % SomeWidget.id).datePicker(SomeWidget.pickerOptions)
... )
More likely, we will want to dynamically make calls on every
request. Here we will call add_calls inside the ``prepare`` method.
>>> class SomeWidget(Widget):
... pickerOptions = twc.Param(default={})
... def prepare(self):
... super(SomeWidget, self).prepare()
... self.add_call(
... jQuery('#%s' % d.id).datePicker(d.pickerOptions)
... )
This would allow to pass different options to the datePicker on every
display.
JS calls are rendered by the same mechanisms that render required css and
js for a widget and places those calls at bodybottom so DOM elements which
JS calls are rendered by the same mechanisms that render required css and
js for a widget and places those calls at bodybottom so DOM elements which
we might target are available.
Examples:
.. sourcecode:: python
>> call = js_function('jQuery')("a .async")
>> str(call)
'jQuery("a .async")'
>>> call = js_function('jQuery')("a .async")
>>> str(call)
'jQuery("a .async")'
# js_function calls can be chained:
js_function calls can be chained:
>> call = js_function('jQuery')("a .async").foo().bar()
>> str(call)
'jQuery("a .async").foo().bar()'
>>> call = js_function('jQuery')("a .async").foo().bar()
>>> str(call)
'jQuery("a .async").foo().bar()'
"""
def __init__(self, name):
self.__name = name
def __call__(self, *args):
return _js_call(self.__name, [], args, called=True)
def __str__(self):
return self.__name
class _js_call(object):
__slots__ = ('__name', '__call_list', '__args', '__called')
def __init__(self, name, call_list, args=None, called=False):
self.__name = name
self.__args = args
@@ -220,12 +214,12 @@ def __init__(self, name, call_list, args=None, called=False):
def __getattr__(self, name):
return self.__class__(name, self.__call_list)
def __call__(self, *args):
self.__args = args
self.__called = True
return self
def __get_js_repr(self):
if self.__called:
args = self.__args
@@ -235,12 +229,12 @@ def __get_js_repr(self):
)
else:
return self.__name
def __str__(self):
if not self.__called:
raise TypeError('Last element in the chain has to be called')
return '.'.join(c.__get_js_repr() for c in self.__call_list)
def __unicode__(self):
return str(self).decode(sys.getdefaultencoding())
@@ -185,7 +185,6 @@ def __init__(self, app, controllers=None, **config):
rl['queued_resources'] = []
def __call__(self, environ, start_response):
rl = core.request_local()
rl.clear()
@@ -270,12 +269,12 @@ def register_resource(modname, filename, whole_dir):
A resource must be registered for serving for it to be also registered for
injection.
If the middleware is available, the resource is directly registered with the
ResourcesApp.
If the middleware is available, the resource is directly registered with
the ResourcesApp.
If the middleware is not available, the resource is stored in the
request_local dict. When the middleware is later initialized, those waiting
registrations are processed.
request_local dict. When the middleware is later initialized, those
waiting registrations are processed.
"""
rl = core.request_local()
@@ -289,6 +288,7 @@ def register_resource(modname, filename, whole_dir):
log.debug("No middleware in place. Queued %r->%r(%r) registration." %
(modname, filename, whole_dir))
def register_controller(widget, path):
""" API function for registering widget controllers.
@@ -45,7 +45,6 @@ def __init__(self, *args, **kw):
self.src = self._name
class Resource(wd.Widget):
location = pm.Param(
'Location on the page where the resource should be placed.' \
@@ -208,6 +207,7 @@ class JSSource(Resource):
def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)
class CSSSource(Resource):
"""
Inline Cascading Style-Sheet code.
@@ -219,6 +219,7 @@ class CSSSource(Resource):
def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)
class _JSFuncCall(JSSource):
"""
Internal use inline JavaScript function call.
@@ -404,7 +405,8 @@ class _ResourceInjector(util.MultipleReplacer):
>>> JSLink(link="http://example.com").inject()
>>> html = "<html><head></head><body></body></html>"
>>> inject_resources(html)
'<html><head><script type="text/javascript" src="http://example.com"></script></head><body></body></html>'
'<html><head><script type="text/javascript"
src="http://example.com"></script></head><body></body></html>'
Once resources have been injected they are popped from request local and
cannot be injected again (in the same request). This is useful in case
@@ -390,6 +390,7 @@ def test_to_python(self):
import tw2.core as twc
import os
class TestInPage(object):
content_type = 'text/html'
charset = 'UTF8'

0 comments on commit b387fa4

Please sign in to comment.