Compare commits

...
20 Commits
Author SHA1 Message Date
mdipierro f7bf1020df reverted gluon/packages/dal 2015-04-18 15:28:12 -05:00
mdipierro 75b8ceb022 Merge pull request #923 from gi0baro/validators
Fix serializers injection over new pydal
2015-04-18 15:17:06 -05:00
mdipierro b4f3784136 Merge pull request #922 from dokime7/patch-7
Fix crash with list:reference field
2015-04-18 15:16:25 -05:00
mdipierro f1297bb827 Merge pull request #918 from niphlod/enhancement/anyserver
added waitress to anyserver
2015-04-18 15:15:02 -05:00
mdipierro 435ebeaae4 more consulting companies 2015-04-18 15:13:03 -05:00
gi0baro 537045082c Updated dal test due to new serializers 2015-04-18 15:08:39 +02:00
gi0baro 4bea52a7b5 Fix serializers injection over new pydal 2015-04-18 15:04:01 +02:00
Jeremie Dokime 33295e516f Fix crash with list:reference field
When using validate_and_update() or validate_and_insert() on a table with a list:reference field, the request crashes after timeout with:
  File "web2py/gluon/globals.py", line 270, in body
    raise HTTP(400, "Bad Request - HTTP body is incomplete")

The request crashes because there is an hidden exception with the isinstance function:
isinstance() arg 2 must be a class, type, or tuple of classes and types

When no using GAE, the GoogleDatastoreAdapter variable is None, so isinstance crash.
See the last line of pydal/adapters/__init__.py

This is a regression intruduced after the v2.9.12.
2015-04-18 02:15:45 +02:00
mdipierro f33ccf3366 experimental fix for represent 2015-04-16 16:53:12 -05:00
niphlod 0784680c90 added waitress to anyserver 2015-04-15 23:55:44 +02:00
mdipierro e940228eaf Merge pull request #912 from ilvalle/sqlcustomtype
extend sqlcustomform to support widget/represent
2015-04-15 13:01:50 -05:00
mdipierro 50769a627a Merge pull request #916 from gi0baro/issue-904
Fixes #904
2015-04-15 13:01:19 -05:00
mdipierro e68ecaa131 Merge pull request #915 from BuhtigithuB/update/gluon-contrib-pypyodbc
Update gluon/contrib/pypyodbc.py 1.3.0 -> 1.3.3
2015-04-15 13:01:01 -05:00
gi0baro 95e6e8577b Fixes #904 2015-04-14 15:25:26 +02:00
Hardirc 19c83d4ad6 Update gluon/contrib/pypyodbc.py 1.3.0 -> 1.3.3 2015-04-13 18:43:48 -04:00
ilvalle 9c92bd1050 extend sqlcustomform to support widget/represent (possible fix to web2py/pydal#127) 2015-04-12 21:04:05 +02:00
mdipierro b3b95ccf5f Merge pull request #906 from niphlod/fix/895
file is already open at this point... fixes #895
2015-04-08 23:24:16 -05:00
niphlod cefa30841b file is already open at this point... fixes #895 2015-04-08 21:47:04 +02:00
mdipierro 15ff8669cb fixed dal tracking, thanks Niphlod 2015-04-06 16:24:49 -05:00
mdipierro a921751e8e stripe form bs3 compatible, disabled cache.ram max utilization 2015-04-05 18:17:27 -05:00
11 changed files with 513 additions and 474 deletions
+5
View File
@@ -180,6 +180,11 @@ class Servers:
s = wsgi.WSGIServer(callable=app, bind="%s:%d" % address) s = wsgi.WSGIServer(callable=app, bind="%s:%d" % address)
s.start() s.start()
@staticmethod
def waitress(app, address, **options):
from waitress import serve
serve(app, host=address[0], port=address[1], _quiet=True)
def mongrel2_handler(application, conn, debug=False): def mongrel2_handler(application, conn, debug=False):
""" """
+6 -6
View File
@@ -18,7 +18,7 @@
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" id="alltables"> <div class="tab-pane active" id="alltables">
<table> <table class="table">
{{for db in sorted(databases):}} {{for db in sorted(databases):}}
{{for table in databases[db].tables:}} {{for table in databases[db].tables:}}
{{qry='%s.%s.id>0'%(db,table)}} {{qry='%s.%s.id>0'%(db,table)}}
@@ -40,7 +40,7 @@
{{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}}
</th> </th>
<td> <td>
{{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn")}} {{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn btn-default")}}
</td> </td>
</tr> </tr>
{{pass}} {{pass}}
@@ -61,7 +61,7 @@
</pre> </pre>
{{pass}} {{pass}}
{{if table:}} {{if table:}}
{{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}<br/><br/> {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn btn-default")}}<br/><br/>
<h3>{{=T("Rows in Table")}}</h3><br/> <h3>{{=T("Rows in Table")}}</h3><br/>
{{else:}} {{else:}}
<h3>{{=T("Rows selected")}}</h3><br/> <h3>{{=T("Rows selected")}}</h3><br/>
@@ -72,8 +72,8 @@
{{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}</p> {{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}</p>
<br/><br/> <br/><br/>
<h4>{{=T("%s selected", nrows)}}</h4> <h4>{{=T("%s selected", nrows)}}</h4>
{{if start>0:}}{{=A(T('previous %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start-step)),_class="btn")}}{{pass}} {{if start>0:}}{{=A(T('previous %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start-step)),_class="btn btn-default")}}{{pass}}
{{if stop<nrows:}}{{=A(T('next %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start+step)),_class="btn")}}{{pass}} {{if stop<nrows:}}{{=A(T('next %s rows') % step,_href=URL('select',args=request.args[0],vars=dict(start=start+step)),_class="btn btn-default")}}{{pass}}
{{if rows:}} {{if rows:}}
<div style="overflow:auto; width:80%;"> <div style="overflow:auto; width:80%;">
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}} {{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
@@ -82,7 +82,7 @@
</div> </div>
{{pass}} {{pass}}
<br/><br/><h3>{{=T("Import/Export")}}</h3><br/> <br/><br/><h3>{{=T("Import/Export")}}</h3><br/>
<a href="{{=URL('csv',args=request.args[0],vars=dict(query=query))}}" class="btn">{{=T("export as csv file")}}</a> <a href="{{=URL('csv',args=request.args[0],vars=dict(query=query))}}" class="btn btn-default">{{=T("export as csv file")}}</a>
{{=formcsv or ''}} {{=formcsv or ''}}
{{elif request.function=='insert':}} {{elif request.function=='insert':}}
@@ -33,6 +33,9 @@
<li><a target="_blank" href="https://loadinfo-net.appspot.com">LoadInfo</a> (Bulgaria)</li> <li><a target="_blank" href="https://loadinfo-net.appspot.com">LoadInfo</a> (Bulgaria)</li>
<li><a target="_blank" href="http://www.appliedobjects.com">Applied Objects</a> (New Zealand)</li> <li><a target="_blank" href="http://www.appliedobjects.com">Applied Objects</a> (New Zealand)</li>
<li><a target="_blank" href="http://www.sistemasagiles.com.ar/">Sistemas Ágiles</a> ("Agile Systems") (Argentina)</li> <li><a target="_blank" href="http://www.sistemasagiles.com.ar/">Sistemas Ágiles</a> ("Agile Systems") (Argentina)</li>
<li><a target="_blank" href="http://www.definescope.com/en/services/consulting/">DefineScope</a> (Portugal)</li>
<li><a target="_blank" href="http://10Biosystems.com">10BioSystems</a></li>
<li><a target="_blank" href="http://www.dutveul.nl">Dutveul</a> (Netherlands)</li>
</ul> </ul>
</div> </div>
+2 -2
View File
@@ -99,7 +99,7 @@ class CacheAbstract(object):
""" """
cache_stats_name = 'web2py_cache_statistics' cache_stats_name = 'web2py_cache_statistics'
max_ram_utilization = 90 # percent max_ram_utilization = None # percent
def __init__(self, request=None): def __init__(self, request=None):
"""Initializes the object """Initializes the object
@@ -353,7 +353,7 @@ class CacheOnDisk(CacheAbstract):
raise KeyError raise KeyError
self.wait_portalock(val_file) self.wait_portalock(val_file)
value = pickle.load(recfile.open(key, 'rb', path=self.folder)) value = pickle.load(val_file)
val_file.close() val_file.close()
return value return value
+439 -421
View File
File diff suppressed because it is too large Load Diff
+35 -35
View File
@@ -4,7 +4,24 @@ from hashlib import sha1
class Stripe: class Stripe:
""" """
Usage: Use in WEB2PY (guaranteed PCI compliant)
def pay():
from gluon.contrib.stripe import StripeForm
form = StripeForm(
pk=STRIPE_PUBLISHABLE_KEY,
sk=STRIPE_SECRET_KEY,
amount=150, # $1.5 (amount is in cents)
description="Nothing").process()
if form.accepted:
payment_id = form.response['id']
redirect(URL('thank_you'))
elif form.errors:
redirect(URL('pay_error'))
return dict(form=form)
Low level API:
key='<api key>' key='<api key>'
d = Stripe(key).charge( d = Stripe(key).charge(
amount=100, # 1 dollar!!!! amount=100, # 1 dollar!!!!
@@ -22,22 +39,6 @@ class Stripe:
{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 if paid is True than transaction was processed
Use in WEB2PY (guaranteed PCI compliant)
def pay():
from gluon.contrib.stripe import StripeForm
form = StripeForm(
pk=STRIPE_PUBLISHABLE_KEY,
sk=STRIPE_SECRET_KEY,
amount=150, # $1.5 (amount is in cents)
description="Nothing").process()
if form.accepted:
payment_id = form.response['id']
redirect(URL('thank_you'))
elif form.errors:
redirect(URL('pay_error'))
return dict(form=form)
""" """
URL_CHARGE = 'https://%s:@api.stripe.com/v1/charges' URL_CHARGE = 'https://%s:@api.stripe.com/v1/charges'
@@ -188,37 +189,36 @@ jQuery(function(){
<h3>Payment Amount: {{=currency_symbol}} {{="%.2f" % (0.01*amount)}}</h3> <h3>Payment Amount: {{=currency_symbol}} {{="%.2f" % (0.01*amount)}}</h3>
<form action="" method="POST" id="payment-form" class="form-horizontal"> <form action="" method="POST" id="payment-form" class="form-horizontal">
<div class="form-row control-group"> <div class="form-row form-group">
<label class="control-label">Card Number</label> <label class="col-sm-2 control-label">Card Number</label>
<div class="controls"> <div class="controls col-sm-10">
<input type="text" size="20" data-stripe="number" <input type="text" size="20" data-stripe="number"
placeholder="4242424242424242"/> placeholder="4242424242424242" class="form-control"/>
</div> </div>
</div> </div>
<div class="form-row control-group"> <div class="form-row form-group">
<label class="control-label">CVC</label> <label class="col-sm-2 control-label">CVC</label>
<div class="controls"> <div class="controls col-sm-10">
<input type="text" size="4" style="width:80px" data-stripe="cvc" <input type="text" size="4" style="width:80px" data-stripe="cvc"
placeholder="XXX"/> placeholder="XXX" class="form-control"/>
<a href="http://en.wikipedia.org/wiki/Card_Verification_Code" target="_blank">What is this?</a> <a href="http://en.wikipedia.org/wiki/Card_Verification_Code" target="_blank">What is this?</a>
</div> </div>
</div> </div>
<div class="form-row control-group"> <div class="form-row form-group">
<label class="control-label">Expiration</label> <label class="col-sm-2 control-label">Expiration</label>
<div class="controls"> <div class="controls col-sm-10">
<input type="text" size="2" style="width:40px" data-stripe="exp-month" <input type="text" size="2" style="width:40px; display:inline-block"
placeholder="MM"/> data-stripe="exp-month" placeholder="MM" class="form-control"/>
/ /
<input type="text" size="4" style="width:80px" data-stripe="exp-year" <input type="text" size="4" style="width:80px; display:inline-block"
placeholder="YYYY"/> data-stripe="exp-year" placeholder="YYYY" class="form-control"/>
</div> </div>
</div> </div>
<div class="form-row form-group">
<div class="control-group"> <div class="controls col-sm-offset-2 col-sm-10">
<div class="controls">
<button type="submit" class="btn btn-primary">Submit Payment</button> <button type="submit" class="btn btn-primary">Submit Payment</button>
<div class="payment-errors error hidden"></div> <div class="payment-errors error hidden"></div>
</div> </div>
+3 -3
View File
@@ -14,7 +14,7 @@ from pydal import DAL as DAL
from pydal import Field from pydal import Field
from pydal.objects import Row, Rows, Table, Query, Expression from pydal.objects import Row, Rows, Table, Query, Expression
from pydal import SQLCustomType, geoPoint, geoLine, geoPolygon from pydal import SQLCustomType, geoPoint, geoLine, geoPolygon
import copy_reg as copyreg
def _default_validators(db, field): def _default_validators(db, field):
""" """
@@ -81,12 +81,12 @@ def _default_validators(db, field):
requires[0] = validators.IS_EMPTY_OR(requires[0]) requires[0] = validators.IS_EMPTY_OR(requires[0])
return requires return requires
from gluon import serializers as w2p_serializers from gluon.serializers import custom_json, xml
from gluon.utils import web2py_uuid from gluon.utils import web2py_uuid
from gluon import sqlhtml from gluon import sqlhtml
DAL.serializers = w2p_serializers DAL.serializers = {'json': custom_json, 'xml': xml}
DAL.validators_method = _default_validators DAL.validators_method = _default_validators
DAL.uuid = lambda x: web2py_uuid() DAL.uuid = lambda x: web2py_uuid()
DAL.representers = { DAL.representers = {
+15 -3
View File
@@ -58,9 +58,12 @@ def represent(field, value, record):
f = field.represent f = field.represent
if not callable(f): if not callable(f):
return str(value) return str(value)
n = f.func_code.co_argcount - len(f.func_defaults or []) if hasattr(f,'func_code'):
if getattr(f, 'im_self', None): n = f.func_code.co_argcount - len(f.func_defaults or [])
n -= 1 if getattr(f, 'im_self', None):
n -= 1
else:
n = 1
if n == 1: if n == 1:
return f(value) return f(value)
elif n == 2: elif n == 2:
@@ -1205,6 +1208,9 @@ class SQLFORM(FORM):
elif field.type == 'boolean': elif field.type == 'boolean':
inp = self.widgets.boolean.widget( inp = self.widgets.boolean.widget(
field, default, _disabled=True) field, default, _disabled=True)
elif isinstance(field.type, SQLCustomType) and callable(field.type.represent):
# SQLCustomType has a represent, use it
inp = field.type.represent(default, record)
else: else:
inp = field.formatter(default) inp = field.formatter(default)
if getattr(field, 'show_if', None): if getattr(field, 'show_if', None):
@@ -1246,6 +1252,9 @@ class SQLFORM(FORM):
dspval = '' dspval = ''
elif field.type == 'blob': elif field.type == 'blob':
continue continue
elif isinstance(field.type, SQLCustomType) and callable(field.type.widget):
# SQLCustomType has a widget, use it
inp = field.type.widget(field, default)
else: else:
field_type = widget_class.match(str(field.type)).group() field_type = widget_class.match(str(field.type)).group()
field_type = field_type in self.widgets and field_type or 'string' field_type = field_type in self.widgets and field_type or 'string'
@@ -2708,6 +2717,9 @@ class SQLFORM(FORM):
_href='%s/%s' % (upload, value)) _href='%s/%s' % (upload, value))
else: else:
value = '' value = ''
elif isinstance(field.type, SQLCustomType) and callable(field.type.represent):
# SQLCustomType has a represent, use it
value = field.type.represent(value, row)
if isinstance(value, str): if isinstance(value, str):
value = truncate_string(value, maxlength) value = truncate_string(value, maxlength)
elif not isinstance(value, XmlComponent): elif not isinstance(value, XmlComponent):
+3 -2
View File
@@ -15,10 +15,11 @@ from gluon.dal import DAL, Field
class TestDALSubclass(unittest.TestCase): class TestDALSubclass(unittest.TestCase):
def testRun(self): def testRun(self):
import gluon.serializers as mserializers from gluon.serializers import custom_json, xml
from gluon import sqlhtml from gluon import sqlhtml
db = DAL(check_reserved=['all']) db = DAL(check_reserved=['all'])
self.assertEqual(db.serializers, mserializers) self.assertEqual(db.serializers['json'], custom_json)
self.assertEqual(db.serializers['xml'], xml)
self.assertEqual(db.representers['rows_render'], sqlhtml.represent) self.assertEqual(db.representers['rows_render'], sqlhtml.represent)
self.assertEqual(db.representers['rows_xml'], sqlhtml.SQLTABLE) self.assertEqual(db.representers['rows_xml'], sqlhtml.SQLTABLE)
+1 -1
View File
@@ -611,7 +611,7 @@ class IS_IN_DB(Validator):
def count(values, s=self.dbset, f=field): def count(values, s=self.dbset, f=field):
return s(f.belongs(map(int, values))).count() return s(f.belongs(map(int, values))).count()
if isinstance(self.dbset.db._adapter, GoogleDatastoreAdapter): if GoogleDatastoreAdapter is not None and isinstance(self.dbset.db._adapter, GoogleDatastoreAdapter):
range_ids = range(0, len(values), 30) range_ids = range(0, len(values), 30)
total = sum(count(values[i:i + 30]) for i in range_ids) total = sum(count(values[i:i + 30]) for i in range_ids)
if total == len(values): if total == len(values):