fixws and 'new' button in grid query

This commit is contained in:
Massimo Di Pierro
2011-12-05 11:39:42 -06:00
parent 01f6f82cdf
commit d281acb421
305 changed files with 8352 additions and 8032 deletions
+2
View File
@@ -23,3 +23,5 @@ from compileapp import LOAD
+1
View File
@@ -453,3 +453,4 @@ def create_missing_app_folders(request):
+1
View File
@@ -430,3 +430,4 @@ class Cache(object):
+1
View File
@@ -51,3 +51,4 @@ def getcfs(key, filename, filter=None):
+4 -3
View File
@@ -127,7 +127,7 @@ def LOAD(c=None, f='index', args=None, vars=None,
else:
if not isinstance(args,(list,tuple)):
args = [args]
c = c or request.controller
c = c or request.controller
other_request = Storage()
for key, value in request.items():
other_request[key] = value
@@ -160,9 +160,9 @@ def LOAD(c=None, f='index', args=None, vars=None,
copy.copy(current.response.generic_patterns)
other_environment['request'] = other_request
other_environment['response'] = other_response
## some magic here because current are thread-locals
original_request, current.request = current.request, other_request
original_response, current.response = current.response, other_response
page = run_controller_in(c, f, other_environment)
@@ -656,3 +656,4 @@ if __name__ == '__main__':
+1
View File
@@ -719,3 +719,4 @@ def contenttype(filename, default='text/plain'):
+2
View File
@@ -259,3 +259,5 @@ if __name__=='__main__':
test()
+20 -18
View File
@@ -44,7 +44,7 @@ class DowCommerce:
self.parameters = {}
self.setParameter('username', username)
self.setParameter('password', password)
def process(self):
encoded_args = urllib.urlencode(self.parameters)
@@ -58,11 +58,11 @@ class DowCommerce:
results += str(opened.read()).split(self.delimiter)
finally:
opened.close()
for result in results:
(key,val) = result.split('=')
self.results[key] = val
if self.results['response'] == '1':
self.error = False
self.success = True
@@ -74,7 +74,7 @@ class DowCommerce:
elif self.results['response'] == '3':
self.error = True
self.success = False
self.declined = False
self.declined = False
else:
self.error = True
self.success = False
@@ -82,7 +82,7 @@ class DowCommerce:
raise DowCommerce.DowCommerceError(self.results)
def setTransaction(self, creditcard, expiration, total, cvv=None, orderid=None, orderdescription=None,
ipaddress=None, tax=None, shipping=None,
ipaddress=None, tax=None, shipping=None,
firstname=None, lastname=None, company=None, address1=None, address2=None, city=None, state=None, zipcode=None,
country=None, phone=None, fax=None, emailaddress=None, website=None,
shipping_firstname=None, shipping_lastname=None, shipping_company=None, shipping_address1=None, shipping_address2=None,
@@ -93,11 +93,11 @@ class DowCommerce:
raise DowCommerce.DowCommerceError('No expiration number passed to setTransaction(): {0}'.format(expiration))
if str(total).strip() == '' or total == None:
raise DowCommerce.DowCommerceError('No total amount passed to setTransaction(): {0}'.format(total))
self.setParameter('ccnumber', creditcard)
self.setParameter('ccexp', expiration)
self.setParameter('amount', total)
if cvv:
self.setParameter('cvv', cvv)
if orderid:
@@ -110,10 +110,10 @@ class DowCommerce:
self.setParameter('tax', tax)
if shipping:
self.setParameter('shipping', shipping)
## billing info
## billing info
if firstname:
self.setParameter('firstname', firstname)
self.setParameter('firstname', firstname)
if lastname:
self.setParameter('lastname', lastname)
if company:
@@ -138,7 +138,7 @@ class DowCommerce:
self.setParameter('email', emailaddress)
if website:
self.setParameter('website', website)
## shipping info
if shipping_firstname:
self.setParameter('shipping_firstname', shipping_firstname)
@@ -147,9 +147,9 @@ class DowCommerce:
if shipping_company:
self.setParameter('shipping_company', shipping_company)
if shipping_address1:
self.setParameter('shipping_address1', shipping_address1)
self.setParameter('shipping_address1', shipping_address1)
if shipping_address2:
self.setParameter('shipping_address2', shipping_address2)
self.setParameter('shipping_address2', shipping_address2)
if shipping_city:
self.setParameter('shipping_city', shipping_city)
if shipping_state:
@@ -188,12 +188,12 @@ class DowCommerce:
def getResultResponseShort(self):
responses = ['', 'Approved', 'Declined', 'Error']
return responses[int(self.results['response'])]
def getFullResponse(self):
return self.results
return self.results
def getResponseText(self):
return self.results['responsetext']
return self.results['responsetext']
def test():
import socket
@@ -220,7 +220,7 @@ def test():
payment.setTransaction(creditcard, expiration, total, cvv=cvv, tax=tax, orderid=orderid, orderdescription='Test Transaction',
firstname='John', lastname='Doe', company='Acme', address1='123 Min Street', city='Hometown', state='VA',
zipcode='12345', country='US', phone='888-555-1212', emailaddress='john@noemail.local', ipaddress='192.168.1.1')
payment.process()
if payment.isApproved():
print 'Payment approved!'
@@ -240,3 +240,5 @@ if __name__=='__main__':
test()
+2
View File
@@ -1,3 +1,5 @@
+2
View File
@@ -190,3 +190,5 @@ if __name__ == "__main__":
tornado.ioloop.IOLoop.instance().start()
+2
View File
@@ -3906,3 +3906,5 @@ def parse(url_file_stream_or_string, etag=None, modified=None, agent=None, refer
result['namespaces'] = feedparser.namespacesInUse
return result
+2
View File
@@ -51,3 +51,5 @@ class MemcacheClient(Client):
key = '%s/%s' % (self.request.application, key)
self.delete(key)
+2
View File
@@ -86,3 +86,5 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
apiproxy_stub_map.MakeSyncCall = wrapper
+2
View File
@@ -63,3 +63,5 @@ def pdf_from_html(html):
return pyfpdf_from_html(html)
+3 -1
View File
@@ -14,4 +14,6 @@ def button(merchant_id="123456789012345",
button = '<form action="https://checkout.google.com/api/checkout/v2/checkoutForm/Merchant/%s" id="BB_BuyButtonForm" method="post" name="BB_BuyButtonForm" target="_top">%s<input name="_charset_" type="hidden" value="utf-8"/><input alt="" src="https://checkout.google.com/buttons/buy.gif?merchant_id=%s&amp;w=117&amp;h=48&amp;style=white&amp;variant=text&amp;loc=en_US" type="image"/></form>' % (merchant_id, list_products, merchant_id)
return XML(button)
+2
View File
@@ -5,3 +5,5 @@ __all__ = ['DAL','Field','drivers','gae']
from gluon.dal import DAL, Field, Table, Query, Set, Expression, Row, Rows, drivers, BaseAdapter, SQLField, SQLTable, SQLXorable, SQLQuery, SQLSet, SQLRows, SQLStorage, SQLDB, GQLDB, SQLALL, SQLCustomType, gae
+2
View File
@@ -906,3 +906,5 @@ if __name__ == '__main__':
doctest.testmod()
+2
View File
@@ -123,3 +123,5 @@ if __name__ == "__main__":
print authenticate(getpass.getuser(), getpass.getpass())
+2
View File
@@ -164,3 +164,5 @@ if __name__ == '__main__':
print ell.generate(1000,prefix=None)
+11 -9
View File
@@ -21,15 +21,15 @@ def RedisCache(*args, **vars):
from gluon.contrib.redis import RedisCache
cache.redis = RedisCache('localhost:6379',db=None, debug=True)
cache.redis.stats()
cache.redis.stats()
return a dictionary with statistics of Redis server
with one additional key ('w2p_keys') showing all keys currently set
from web2py with their TTL
if debug=True additional tracking is activate and another key is added
('w2p_stats') showing total_hits and misses
('w2p_stats') showing total_hits and misses
"""
locker.acquire()
try:
if not hasattr(RedisCache, 'redis_instance'):
@@ -52,7 +52,7 @@ class RedisClient(object):
app = request.application
else:
app = ''
if not app in self.meta_storage:
self.storage = self.meta_storage[app] = {
CacheAbstract.cache_stats_name: {
@@ -72,7 +72,7 @@ class RedisClient(object):
obj = self.r_server.get(key)
if obj:
if self.debug:
self.r_server.incr('web2py_cache_statistics:hit_total')
self.r_server.incr('web2py_cache_statistics:hit_total')
value = pickle.loads(obj)
elif f is None:
if obj: self.r_server.delete(key)
@@ -94,7 +94,7 @@ class RedisClient(object):
def clear(self, regex):
"""
Auxiliary function called by `clear` to search and
Auxiliary function called by `clear` to search and
clear cache entries
"""
r = re.compile(regex)
@@ -120,7 +120,9 @@ class RedisClient(object):
statscollector['w2p_keys']["%s_expire_in_sec" % (a)] = \
self.r_server.ttl(a)
return statscollector
def __keyFormat__(self, key):
return 'w2p:%s:%s' % (self.request.application,
return 'w2p:%s:%s' % (self.request.application,
key.replace(' ', '_'))
+2
View File
@@ -588,3 +588,5 @@ if __name__ == '__main__':
print test()
+2
View File
@@ -266,3 +266,5 @@ if __name__=='__main__':
while True: print run(history, raw_input('>>> ')).rstrip()
+12 -10
View File
@@ -24,7 +24,7 @@ from cStringIO import StringIO
import random
import sys
try:
import gluon.contrib.simplejson as json # try web2py json serializer
import gluon.contrib.simplejson as json # try web2py json serializer
except ImportError:
try:
import json # try stdlib (py2.6)
@@ -40,7 +40,7 @@ class JSONRPCError(RuntimeError):
def __unicode__(self):
return u"%s: %s" % (self.code, self.message)
def __str__(self):
return self.__unicode__().encode("ascii","ignore")
return self.__unicode__().encode("ascii","ignore")
class JSONDummyParser:
@@ -55,11 +55,11 @@ class JSONDummyParser:
class JSONTransportMixin:
"json wrapper for xmlrpclib transport interfase"
def send_content(self, connection, request_body):
connection.putheader("Content-Type", "application/json")
connection.putheader("Content-Length", str(len(request_body)))
connection.endheaders()
connection.endheaders()
if request_body:
connection.send(request_body)
# todo: add gzip compression
@@ -76,7 +76,7 @@ class JSONTransport(JSONTransportMixin, Transport):
class JSONSafeTransport(JSONTransportMixin, SafeTransport):
pass
class ServerProxy(object):
"JSON RPC Simple Client Service Proxy"
@@ -99,12 +99,12 @@ class ServerProxy(object):
transport = JSONTransport()
self.__transport = transport
self.__encoding = encoding
self.__verbose = verbose
self.__verbose = verbose
def __getattr__(self, attr):
"pseudo method that can be called"
return lambda *args: self.call(attr, *args)
def call(self, method, *args):
"JSON RPC communication (method invocation)"
@@ -120,15 +120,15 @@ class ServerProxy(object):
request,
verbose=self.__verbose
)
# store plain request and response for further debugging
self.json_request = request
self.json_response = response
# parse json data coming from service
# parse json data coming from service
# {'version': '1.1', 'id': id, 'result': result, 'error': None}
response = json.loads(response)
if response['id'] != request_id:
raise JSONRPCError(0, "JSON Request ID != Response ID")
@@ -145,3 +145,5 @@ if __name__ == "__main__":
client = ServerProxy(location, verbose='--verbose' in sys.argv,)
print client.add(1, 2)
+2
View File
@@ -112,3 +112,5 @@ def sms_email(number,provider):
return number+SMSCODES[provider]
+2
View File
@@ -262,3 +262,5 @@ if __name__ == '__main__':
print s['c'].computed_value
+5 -3
View File
@@ -17,7 +17,7 @@ class Stripe:
print Stripe(key).check(d['id'])
print Stripe(key).refund(d['id'])
Sample output (python dict):
{u'fee': 0, u'description': u'test charge', u'created': 1321242072, u'refunded': False, u'livemode': False, u'object': u'charge', u'currency': u'usd', u'amount': 100, u'paid': True, u'id': u'ch_sdjasgfga83asf', u'card': {u'exp_month': 5, u'country': u'US', u'object': u'card', u'last4': u'4242', u'exp_year': 2012, u'type': u'Visa'}}
{u'fee': 0, u'description': u'test charge', u'created': 1321242072, u'refunded': False, u'livemode': False, u'object': u'charge', u'currency': u'usd', u'amount': 100, u'paid': True, u'id': u'ch_sdjasgfga83asf', u'card': {u'exp_month': 5, u'country': u'US', u'object': u'card', u'last4': u'4242', u'exp_year': 2012, u'type': u'Visa'}}
if paid is True than transaction was processed
"""
@@ -27,11 +27,11 @@ class Stripe:
def charge(self,
amount,
currency='usd',
card_number='4242424242424242',
card_number='4242424242424242',
card_exp_month='5',
card_exp_year='2012',
card_cvc_check='123',
description='test charge'):
description='test charge'):
params = urllib.urlencode({'amount':amount,
'currency':currency,
'card[number]':card_number,
@@ -62,3 +62,5 @@ if __name__=='__main__':
print 'paid',s['paid'],s['amount'] ,s['currency']
s = Stripe(key).refund(d[u'id'])
print 'refunded',s['refunded']
+2
View File
@@ -243,3 +243,5 @@ class TaskBarIcon:
STOPPED = 1
+22 -20
View File
@@ -10,7 +10,7 @@ Aim is
Taken from http://pypi.python.org/pypi/httpagentparser (MIT license)
Modified my Ross Peoples for web2py to better support iPhone and iPad.
Modified by Angelo Compagnucci <angelo.compagnucci@gmail.com> to better support a wide ringe of mobile devices.
Now it supports: tablet device (is_tablet), BlackBerry, BlackBerry PlayBook, Android Tablets, Windows Mobile,
Now it supports: tablet device (is_tablet), BlackBerry, BlackBerry PlayBook, Android Tablets, Windows Mobile,
Symbian.
"""
import sys
@@ -81,11 +81,11 @@ class DetectorBase(object):
result['is_mobile'] = is_mobile
if is_tablet:
result['is_tablet'] = is_tablet
version = self.getVersion(agent)
if version:
result[self.info_type]['version'] = version
return True
return False
@@ -222,13 +222,13 @@ class BlackBerry(OS):
look_for = ['BlackBerry']
prefs = dict( flavor=['PlayBook'])
is_mobile = True
# Manual check for tablet
def checkWords(self, agent):
if 'BlackBerry' in agent or 'PlayBook' in agent:
return True
return False
def getVersion(self, agent):
pass
@@ -236,14 +236,14 @@ class PlayBook(Flavor):
look_for = ['PlayBook']
is_mobile=True
is_tablet=True
def getVersion(self, agent):
return agent.partition('Tablet OS')[2].partition(';')[0].strip()
class Macintosh(OS):
look_for = ['Macintosh']
prefs = dict(dist=None, flavor=['MacOS'])
def getVersion(self, agent):
pass
@@ -269,7 +269,7 @@ class Windows(OS):
def getVersion(self, agent):
v = agent.partition('NT')
return v[1]+' '+v[2].replace(')',';').partition(';')[0].strip()
return v[1]+' '+v[2].replace(')',';').partition(';')[0].strip()
class WindowsMobile(Dist):
name = 'Phone'
@@ -320,7 +320,7 @@ class SymbianOS(OS):
class Series(Flavor):
look_for = ['SymbianOS', 'Series']
version_splitters = ['/', ';']
def getVersion(self, agent):
return agent.partition('Series')[2].partition(' ')[0].replace('/',' ')
@@ -330,8 +330,8 @@ class BrowserNG(Browser):
class iPhone(Dist):
look_for = ['iPhone']
is_mobile = True
prefs = dict(browser=['SafariMobile'])
is_mobile = True
prefs = dict(browser=['SafariMobile'])
def getVersion(self, agent):
version_end_chars = ['like', ';', ')']
@@ -377,7 +377,7 @@ def detect(agent):
prefs = detector.prefs
break
except Exception, ex:
result['exception'] = ex
result['exception'] = ex
return result
@@ -415,8 +415,8 @@ if __name__ == '__main__':
import unittest
data = (
('Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 Nokia6120c/3.83; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413',
('Series SymbianOS 60 3.1', 'Safari', True),
{'is_mobile': True, 'is_tablet': False, 'flavor': {'name': 'Series', 'version': '60 3.1'}, 'os': {'name': 'SymbianOS', 'version': '9.2'}, 'browser': {'name': 'Safari'}},),
@@ -503,16 +503,18 @@ if __name__ == '__main__':
unittest.main()
class mobilize(object):
class mobilize(object):
def __init__(self, func):
self.func = func
def __init__(self, func):
self.func = func
def __call__(self):
from gluon import current
from gluon import current
user_agent = current.request.user_agent()
if user_agent.is_mobile:
if user_agent.is_mobile:
items = current.response.view.split('.')
items.insert(-1,'mobile')
current.response.view = '.'.join(items)
return self.func()
return self.func()
+1
View File
@@ -325,3 +325,4 @@ class _Web2pyDateTrackerImporter(_Web2pyImporter, _DateTrackerImporter):
+8 -7
View File
@@ -1139,7 +1139,7 @@ class BaseAdapter(ConnectionPool):
def _select(self, query, fields, attributes):
for key in set(attributes.keys())-set(('orderby', 'groupby', 'limitby',
'required', 'cache', 'left',
'distinct', 'having', 'join',
'distinct', 'having', 'join',
'for_update')):
raise SyntaxError, 'invalid select attribute: %s' % key
# ## if no fields specified take them all from the requested tables
@@ -1150,7 +1150,7 @@ class BaseAdapter(ConnectionPool):
else:
new_fields.append(item)
fields = new_fields
tablenames = self.tables(query)
tablenames = self.tables(query)
if query and not query.ignore_common_filters:
query = self.common_filter(query,tablenames)
@@ -3414,7 +3414,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter):
if not query.ignore_common_filters:
query = self.common_filter(query,[tablename])
tableobj = self.db[tablename]._tableobj
items = tableobj.all()
filters = self.expand(query)
@@ -3800,8 +3800,8 @@ class MongoDBAdapter(NoSQLAdapter):
ctable = self.connection[table._tablename]
values = dict((k.name,self.represent(v,table[k.name].type)) for k,v in fields)
ctable.insert(values)
return int(str(values['_id']), 16)
return int(str(values['_id']), 16)
def create_table(self, table, migrate=True, fake_migrate=False, polymodel=None, isCapped=False):
if isCapped:
raise RuntimeError, "Not implemented"
@@ -4622,13 +4622,13 @@ def index():
if self._common_fields:
fields = [f for f in fields] + [f for f in self._common_fields]
common_filter = args.get('common_filter', None)
common_filter = args.get('common_filter', None)
t = self[tablename] = table_class(self, tablename, *fields,
**dict(primarykey=primarykey,
trigger_name=trigger_name,
sequence_name=sequence_name,
common_filter=common_filter))
common_filter=common_filter))
# db magic
if self._uri in (None,'None'):
@@ -6502,3 +6502,4 @@ if __name__ == '__main__':
+1
View File
@@ -85,3 +85,4 @@ def communicate(command=None):
+1
View File
@@ -75,3 +75,4 @@ def decoder(buffer):
+1
View File
@@ -397,3 +397,4 @@ def make_fake_file_like_object():
+9 -8
View File
@@ -42,7 +42,7 @@ try:
have_minify = True
except ImportError:
have_minify = False
regex_session_id = re.compile('^([\w\-]+/)?[\w\-\.]+$')
__all__ = ['Request', 'Response', 'Session']
@@ -207,11 +207,11 @@ class Response(Storage):
def include_files(self):
"""
Caching method for writing out files.
Caching method for writing out files.
By default, caches in ram for 5 minutes. To change,
response.cache_includes = (cache_method, time_expire).
response.cache_includes = (cache_method, time_expire).
Example: (cache.disk, 60) # caches to disk for 1 minute.
"""
from gluon import URL
@@ -222,7 +222,7 @@ class Response(Storage):
if have_minify and (self.optimize_css or self.optimize_js):
# cache for 5 minutes by default
cache = self.cache_includes or (current.cache.ram, 60*5)
def call_minify():
def call_minify():
return minify.minify(files,URL('static','temp'),
current.request.folder,
self.optimize_css,self.optimize_js)
@@ -233,7 +233,7 @@ class Response(Storage):
else:
files = call_minify()
s = ''
for item in files:
for item in files:
if isinstance(item,str):
f = item.lower()
if f.endswith('.css'): s += css_template % item
@@ -358,10 +358,10 @@ class Response(Storage):
if hasattr(thread,'instances'):
dbstats = [TABLE(*[TR(PRE(row[0]),'%.2fms' % (row[1]*1000)) \
for row in i.db._timings]) \
for i in thread.instances]
for i in thread.instances]
else:
dbstats = [] # if no db or on GAE
u = web2py_uuid()
u = web2py_uuid()
return DIV(
BUTTON('design',_onclick="document.location='%s'" % admin),
BUTTON('request',_onclick="jQuery('#request-%s').slideToggle()"%u),
@@ -600,3 +600,4 @@ class Session(Storage):
pass
+1
View File
@@ -336,3 +336,4 @@ if __name__ == '__main__':
+2 -1
View File
@@ -2100,7 +2100,7 @@ class MENU(DIV):
return self.serialize_mobile(self.data, 0).xml()
else:
return self.serialize(self.data, 0).xml()
def embed64(
filename = None,
@@ -2303,3 +2303,4 @@ if __name__ == '__main__':
+1
View File
@@ -129,3 +129,4 @@ def redirect(location, how=303):
+1
View File
@@ -110,3 +110,4 @@ for module in base_modules + contributed_modules:
+1
View File
@@ -354,3 +354,4 @@ if __name__ == '__main__':
+2 -1
View File
@@ -788,7 +788,7 @@ class HttpServer(object):
sock_list.extend([ssl_private_key, ssl_certificate])
if ssl_ca_certificate:
sock_list.append(ssl_ca_certificate)
logger.info('SSL is ON')
app_info = {'wsgi_app': appfactory(wsgibase,
log_filename,
@@ -830,3 +830,4 @@ class HttpServer(object):
+1
View File
@@ -29,3 +29,4 @@ regex_extend = re.compile(\
+3 -2
View File
@@ -26,7 +26,7 @@ _cron_stopping = False
def absolute_path_link(path):
"""
Return an absolute path for the destination of a symlink
"""
if os.path.islink(path):
link = os.readlink(path)
@@ -263,7 +263,7 @@ def crondance(applications_parent, ctype='soft', startup=False):
if _cron_stopping:
break;
apath = os.path.join(apppath,app)
# if app is a symbolic link to other app, skip it
full_apath_link = absolute_path_link(apath)
if full_apath_link in full_apath_links:
@@ -336,3 +336,4 @@ def crondance(applications_parent, ctype='soft', startup=False):
+1
View File
@@ -125,3 +125,4 @@ if __name__ == '__main__':
+1
View File
@@ -1714,3 +1714,4 @@ ADAPTERS['all'] = reduce(lambda a,b:a.union(b),(x for x in ADAPTERS.values()))
+1
View File
@@ -303,3 +303,4 @@ def snapshot(info=None, context=5, code=None, environment=None):
+2 -1
View File
@@ -188,7 +188,7 @@ def try_rewrite_on_error(http_response, request, environ, ticket=None):
else:
error_raising_path = environ['PATH_INFO']
# Rewrite routes_onerror path.
path_info = '/' + path_info.lstrip('/') # add leading '/' if missing
path_info = '/' + path_info.lstrip('/') # add leading '/' if missing
environ['PATH_INFO'] = path_info
error_handling_path = url_in(request, environ)[1]['PATH_INFO']
# Avoid infinite loop.
@@ -1273,3 +1273,4 @@ def get_effective_router(appname):
+2 -1
View File
@@ -458,7 +458,7 @@ class Listener(Thread):
self.err_log.error("Cannot find root ca certificate file "
"'%s'. Cannot bind to %s:%s" % data)
return
# Set socket options
try:
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -2074,3 +2074,4 @@ def demo():
if __name__=='__main__':
demo()
+1
View File
@@ -225,3 +225,4 @@ def sanitize(text, permitted_tags=[
+26 -25
View File
@@ -109,9 +109,9 @@ def demo_function(*argv,**kwargs):
""" test function """
for i in range(argv[0]):
print 'click',i
time.sleep(1)
time.sleep(1)
return 'done'
#the two functions below deal with simplejson decoding as unicode, esp for the dict decode
#and subsequent usage as function Keyword arguments unicode variable names won't work!
#borrowed from http://stackoverflow.com/questions/956867/how-to-get-string-objects-instead-unicode-ones-from-json-in-python
@@ -136,12 +136,12 @@ def _decode_dict(dct):
v = _decode_list(v)
newdict[k] = v
return newdict
def executor(queue,task):
""" the background process """
logging.debug(' task started')
stdout, sys.stdout = sys.stdout, cStringIO.StringIO()
try:
try:
if task.app:
os.chdir(os.environ['WEB2PY_PATH'])
from gluon.shell import env
@@ -152,9 +152,9 @@ def executor(queue,task):
_env = env(task.app,import_models=True)
logging.getLogger().setLevel(level)
scheduler = current._scheduler
scheduler_tasks = current._scheduler.tasks
scheduler_tasks = current._scheduler.tasks
_function = scheduler_tasks[task.function]
globals().update(_env)
globals().update(_env)
args = loads(task.args)
vars = loads(task.vars, object_hook=_decode_dict)
result = dumps(_function(*args,**vars))
@@ -182,7 +182,7 @@ class MetaScheduler(threading.Thread):
('terminated',None,None)
"""
queue = multiprocessing.Queue(maxsize=1)
p = multiprocessing.Process(target=executor,args=(queue,task))
p = multiprocessing.Process(target=executor,args=(queue,task))
self.process = p
logging.debug(' task starting')
p.start()
@@ -196,7 +196,7 @@ class MetaScheduler(threading.Thread):
return TaskReport(STOPPED)
if p.is_alive():
p.terminate()
p.join()
p.join()
logging.debug(' task timeout')
return TaskReport(TIMEOUT)
elif queue.empty():
@@ -211,7 +211,7 @@ class MetaScheduler(threading.Thread):
logging.info('die!')
self.have_heartbeat = False
self.terminate_process()
def terminate_process(self):
try:
self.process.terminate()
@@ -221,17 +221,17 @@ class MetaScheduler(threading.Thread):
def run(self):
""" the thread that sends heartbeat """
counter = 0
while self.have_heartbeat:
while self.have_heartbeat:
self.send_heartbeat(counter)
counter += 1
def start_heartbeats(self):
self.start()
def send_heartbeat(self,counter):
print 'thum'
time.sleep(1)
def pop_task(self):
return Task(
app = None,
@@ -243,7 +243,7 @@ class MetaScheduler(threading.Thread):
def report_task(self,task,task_report):
print 'reporting task'
pass
def sleep(self):
pass
@@ -304,7 +304,7 @@ class Scheduler(MetaScheduler):
self.worker_name = worker_name or socket.gethostname()+'#'+str(web2py_uuid())
from gluon import current
current._scheduler = self
current._scheduler = self
self.define_tables(db,migrate=migrate)
@@ -364,7 +364,7 @@ class Scheduler(MetaScheduler):
def pop_task(self):
now = datetime.datetime.now()
db, ts = self.db, self.db.scheduler_task
db, ts = self.db, self.db.scheduler_task
try:
logging.debug(' grabbing all queued tasks')
all_available = db(ts.status.belongs((QUEUED,RUNNING)))\
@@ -385,7 +385,7 @@ class Scheduler(MetaScheduler):
grabbed = db(ts.assigned_worker_name==self.worker_name)\
(ts.status==ASSIGNED)
task = grabbed.select(limitby=(0,1), orderby=ts.next_run_time).first()
logging.debug(' releasing all but one (running)')
if task:
task.update_record(status=RUNNING,last_run_time=now)
@@ -399,7 +399,7 @@ class Scheduler(MetaScheduler):
run_again = True
else:
run_again = False
logging.debug(' new scheduler_run record')
logging.debug(' new scheduler_run record')
while True:
try:
run_id = db.scheduler_run.insert(
@@ -432,7 +432,7 @@ class Scheduler(MetaScheduler):
stop_time = datetime.datetime.now(),
result = task_report.result,
output = task_report.output,
traceback = task_report.tb)
traceback = task_report.tb)
if task_report.status == COMPLETED:
d = dict(status = task.run_again and QUEUED or COMPLETED,
next_run_time = task.next_run_time,
@@ -447,27 +447,27 @@ class Scheduler(MetaScheduler):
db(db.scheduler_task.id==task.task_id)\
(db.scheduler_task.status==RUNNING).update(**d)
db.commit()
logging.info('task completed (%s)' % task_report.status)
logging.info('task completed (%s)' % task_report.status)
def send_heartbeat(self,counter):
if not self.db_thread:
logging.debug('thread building own DAL object')
logging.debug('thread building own DAL object')
self.db_thread = DAL(self.db._uri,folder = self.db._adapter.folder)
self.define_tables(self.db_thread,migrate=False)
try:
db = self.db_thread
sw, st = db.scheduler_worker, db.scheduler_task
now = datetime.datetime.now()
expiration = now-datetime.timedelta(seconds=self.heartbeat*3)
expiration = now-datetime.timedelta(seconds=self.heartbeat*3)
# record heartbeat
logging.debug('........recording heartbeat')
logging.debug('........recording heartbeat')
if not db(sw.worker_name==self.worker_name)\
.update(last_heartbeat = now, status = ACTIVE):
sw.insert(status = ACTIVE,worker_name = self.worker_name,
first_heartbeat = now,last_heartbeat = now)
if counter % 10 == 0:
# deallocate jobs assigned to inactive workers and requeue them
logging.debug(' freeing workers that have not sent heartbeat')
logging.debug(' freeing workers that have not sent heartbeat')
inactive_workers = db(sw.last_heartbeat<expiration)
db(st.assigned_worker_name.belongs(
inactive_workers._select(sw.worker_name)))\
@@ -478,7 +478,7 @@ class Scheduler(MetaScheduler):
except:
db.rollback()
time.sleep(self.heartbeat)
def sleep(self):
time.sleep(self.heartbeat) # should only sleep until next available task
@@ -546,3 +546,4 @@ def main():
if __name__=='__main__':
main()
+1
View File
@@ -86,3 +86,4 @@ def rss(feed):
+1
View File
@@ -11,3 +11,4 @@ settings = global_settings # legacy compatibility
+1
View File
@@ -419,3 +419,4 @@ if __name__ == '__main__':
+1
View File
@@ -6,3 +6,4 @@ from dal import DAL, Field, Table, Query, Set, Expression, Row, Rows, drivers, B
+12 -8
View File
@@ -60,19 +60,19 @@ def safe_float(x):
class FormWidget(object):
"""
helper for SQLFORM to generate form input fields
helper for SQLFORM to generate form input fields
(widget), related to the fieldtype
"""
_class = 'generic-widget'
@classmethod
def _attributes(cls, field,
def _attributes(cls, field,
widget_attributes, **attributes):
"""
helper to build a common set of attributes
:param field: the field involved,
:param field: the field involved,
some attributes are derived from this
:param widget_attributes: widget related attributes
:param attributes: any other supplied attributes
@@ -162,7 +162,7 @@ class TextWidget(FormWidget):
"""
default = dict(value = value)
attr = cls._attributes(field, default,
attr = cls._attributes(field, default,
**attributes)
return TEXTAREA(**attr)
@@ -214,7 +214,7 @@ class OptionsWidget(FormWidget):
if hasattr(requires[0], 'options'):
options = requires[0].options()
else:
raise SyntaxError, 'widget cannot determine options of %s' % field
raise SyntaxError, 'widget cannot determine options of %s' % field
opts = [OPTION(v, _value=k) for (k, v) in options]
return SELECT(*opts, **attr)
@@ -1333,11 +1333,14 @@ class SQLFORM(FORM):
_id="w2p_value_"+name)
else:
value_input = INPUT(_type='text',_id="w2p_value_"+name,_class=field.type)
new_button = INPUT(_type="button", _value=T('New'),
_onclick="w2p_build_query('new','"+str(field)+"')")
and_button = INPUT(_type="button", _value=T('And'),
_onclick="w2p_build_query('and','"+str(field)+"')")
or_button = INPUT(_type="button", _value=T('Or'),
_onclick="w2p_build_query('or','"+str(field)+"')")
criterion.extend([operators,value_input,and_button,or_button])
criterion.extend([operators,value_input,new_button,and_button,or_button])
criteria.append(DIV(criterion, _id='w2p_field_%s' % name,
_class='w2p_query_row hidden'))
criteria.insert(0,SELECT(
@@ -1355,7 +1358,7 @@ class SQLFORM(FORM):
var s=a+' '+option+' "'+value+'"';
var k=jQuery('#web2py_keywords');
var v=k.val();
k.val((v?(v+' '+ aggregator +' '):'')+s);
if(aggregator=='new') k.val(s); else k.val((v?(v+' '+ aggregator +' '):'')+s);
jQuery('#w2p_query_fields').val('').change();
jQuery('#w2p_query_panel').slideUp();
}
@@ -1590,7 +1593,7 @@ class SQLFORM(FORM):
table = db[request.args[-2]]
if ondelete:
ondelete(table,request.args[-1],ret)
ret = db(table.id==request.args[-1]).delete()
ret = db(table.id==request.args[-1]).delete()
return ret
elif csv and len(request.args)>0 and request.args[-1]=='csv':
if request.vars.keywords:
@@ -2253,3 +2256,4 @@ form_factory = SQLFORM.factory # for backward compatibility, deprecated
+1
View File
@@ -224,3 +224,4 @@ if __name__ == '__main__':
+1
View File
@@ -109,3 +109,4 @@ def stream_file_or_304_or_206(
+1
View File
@@ -931,3 +931,4 @@ if __name__ == '__main__':
+17 -16
View File
@@ -39,7 +39,7 @@ except ImportError:
except:
import contrib.simplejson as json_parser # fallback to pure-Python module
__all__ = ['Mail', 'Auth', 'Recaptcha', 'Crud', 'Service',
__all__ = ['Mail', 'Auth', 'Recaptcha', 'Crud', 'Service',
'PluginManager', 'fetch', 'geocode', 'prettydate']
### mind there are two loggers here (logger and crud.settings.logger)!
@@ -834,7 +834,7 @@ class Auth(object):
def here(self):
return URL(args=current.request.args,vars=current.request.vars)
def __init__(self, environment=None, db=None, mailer=True,
hmac_key=None, controller='default', cas_provider=None):
"""
@@ -1443,7 +1443,7 @@ class Auth(object):
If the user doesn't yet exist, then they are created.
"""
table_user = self.settings.table_user
user = None
user = None
checks = []
# make a guess about who this user is
for fieldname in ['registration_id','username','email']:
@@ -1540,7 +1540,7 @@ class Auth(object):
del session._cas_service
if request.vars.has_key('warn'):
response.headers['refresh'] = "5;URL=%s"%service+"?ticket="+ticket
return A("Continue to %s"%service,
return A("Continue to %s"%service,
_href=service+"?ticket="+ticket)
else:
redirect(service+"?ticket="+ticket)
@@ -1690,7 +1690,7 @@ class Auth(object):
captcha = self.settings.login_captcha or \
(self.settings.login_captcha!=False and self.settings.captcha)
if captcha:
addrow(form, captcha.label, captcha, captcha.comment,
addrow(form, captcha.label, captcha, captcha.comment,
self.settings.formstyle,'captcha__row')
accepted_form = False
@@ -1764,7 +1764,7 @@ class Auth(object):
cas_user[passfield] = None
user = self.get_or_create_user(table_user._filter_fields(cas_user))
elif hasattr(cas,'login_form'):
return cas.login_form()
return cas.login_form()
else:
# we need to pass through login again before going on
next = self.url('user',args='login')
@@ -1861,8 +1861,8 @@ class Auth(object):
if log is DEFAULT:
log = self.messages.register_log
passfield = self.settings.password_field
formstyle = self.settings.formstyle
passfield = self.settings.password_field
formstyle = self.settings.formstyle
form = SQLFORM(table_user,
fields = self.settings.register_fields,
hidden = dict(_next=next),
@@ -2501,7 +2501,7 @@ class Auth(object):
def f(*a, **b):
basic_allowed,basic_accepted,user = self.basic()
basic_allowed,basic_accepted,user = self.basic()
user = user or self.user
if requires_login:
if not user:
@@ -2517,9 +2517,9 @@ class Auth(object):
self.settings.on_failed_authentication,
self.settings.login_url+\
'?_next='+urllib.quote(next))
#Check condition variable.
#Since condition could be callable, following cases could occur:
#Since condition could be callable, following cases could occur:
# 1. condition == True => ok
# 2. condition == False => failed
# 3. condition is NOT callable but it NOT None and NOT False and NOT 0 => failed
@@ -2796,20 +2796,20 @@ class Auth(object):
If you have a table (db.mytable) that needs full revision history you can just do:
form=crud.update(db.mytable,myrecord,onaccept=auth.archive)
or
form=SQLFORM(db.mytable,myrecord).process(onaccept=auth.archive)
crud.archive will define a new table "mytable_archive" and store
a copy of the current record (if archive_current=True)
or a copy of the previous record (if archive_current=False)
crud.archive will define a new table "mytable_archive" and store
a copy of the current record (if archive_current=True)
or a copy of the previous record (if archive_current=False)
in the newly created table including a reference
to the current record.
fields allows to specify extra fields that need to be archived.
If you want to access such table you need to define it yourself
If you want to access such table you need to define it yourself
in a model:
db.define_table('mytable_archive',
@@ -4109,3 +4109,4 @@ class PluginManager(object):
if __name__ == '__main__':
import doctest
doctest.testmod()
+1
View File
@@ -127,3 +127,4 @@ def web2py_uuid():
+4 -3
View File
@@ -2290,7 +2290,7 @@ class IS_LIST_OF(Validator):
self.minimum = minimum
self.maximum = maximum
self.error_message = error_message or "enter between %(min)g and %(max)g values"
def __call__(self, value):
ivalue = value
if not isinstance(value, list):
@@ -2514,10 +2514,10 @@ class CRYPT(object):
If the digest_alg is specified this is used to replace the
MD5 with, for example, SHA512. The digest_alg can be
the name of a hashlib algorithm as a string or the algorithm itself.
min_length is the minimal password length (default 4) - IS_STRONG for serious security
error_message is the message if password is too short
Notice that an empty password is accepted but invalid. It will not allow login back.
Stores junk as hashed password.
"""
@@ -2978,3 +2978,4 @@ if __name__ == '__main__':
+2 -1
View File
@@ -813,7 +813,7 @@ def start_schedulers(options):
p.terminate()
p.join()
def start(cron=True):
""" Start server """
@@ -982,3 +982,4 @@ def start(cron=True):
+1
View File
@@ -164,3 +164,4 @@ if __name__ == '__main__':
+1
View File
@@ -22,3 +22,4 @@ def handler(request, response, methods):