Merge branch 'master' of github.com:web2py/web2py
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.00.0 (2012-05-16 11:15:52) dev
|
Version 2.00.0 (2012-05-21 16:49:59) dev
|
||||||
|
|||||||
+116
-6
@@ -283,6 +283,12 @@ if not 'google' in drivers:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
logger.debug('no MSSQL/DB2/Teradata driver')
|
logger.debug('no MSSQL/DB2/Teradata driver')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import Sybase
|
||||||
|
drivers.append('Sybase')
|
||||||
|
except ImportError:
|
||||||
|
logger.debug('no Sybase driver')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import kinterbasdb
|
import kinterbasdb
|
||||||
drivers.append('Interbase')
|
drivers.append('Interbase')
|
||||||
@@ -1124,7 +1130,9 @@ class BaseAdapter(ConnectionPool):
|
|||||||
elif not isinstance(expression.op, str):
|
elif not isinstance(expression.op, str):
|
||||||
return expression.op()
|
return expression.op()
|
||||||
else:
|
else:
|
||||||
return '(%s)' % expression.op
|
op = expression.op
|
||||||
|
if op.endswith(';'): op=op[:-1]
|
||||||
|
return '(%s)' % op
|
||||||
elif field_type:
|
elif field_type:
|
||||||
return str(self.represent(expression,field_type))
|
return str(self.represent(expression,field_type))
|
||||||
elif isinstance(expression,(list,tuple)):
|
elif isinstance(expression,(list,tuple)):
|
||||||
@@ -2747,6 +2755,101 @@ class MSSQL2Adapter(MSSQLAdapter):
|
|||||||
def execute(self,a):
|
def execute(self,a):
|
||||||
return self.log_execute(a.decode('utf8'))
|
return self.log_execute(a.decode('utf8'))
|
||||||
|
|
||||||
|
class SybaseAdapter(MSSQLAdapter):
|
||||||
|
|
||||||
|
driver = globals().get('Sybase',None)
|
||||||
|
|
||||||
|
types = {
|
||||||
|
'boolean': 'BIT',
|
||||||
|
'string': 'CHAR VARYING(%(length)s)',
|
||||||
|
'text': 'TEXT',
|
||||||
|
'password': 'CHAR VARYING(%(length)s)',
|
||||||
|
'blob': 'IMAGE',
|
||||||
|
'upload': 'CHAR VARYING(%(length)s)',
|
||||||
|
'integer': 'INT',
|
||||||
|
'bigint': 'BIGINT',
|
||||||
|
'float': 'FLOAT',
|
||||||
|
'double': 'FLOAT',
|
||||||
|
'decimal': 'NUMERIC(%(precision)s,%(scale)s)',
|
||||||
|
'date': 'DATETIME',
|
||||||
|
'time': 'CHAR(8)',
|
||||||
|
'datetime': 'DATETIME',
|
||||||
|
'id': 'INT IDENTITY PRIMARY KEY',
|
||||||
|
'reference': 'INT NULL, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
|
||||||
|
'list:integer': 'TEXT',
|
||||||
|
'list:string': 'TEXT',
|
||||||
|
'list:reference': 'TEXT',
|
||||||
|
'geometry': 'geometry',
|
||||||
|
'geography': 'geography',
|
||||||
|
'big-id': 'BIGINT IDENTITY PRIMARY KEY',
|
||||||
|
'big-reference': 'BIGINT NULL, CONSTRAINT %(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
|
||||||
|
'reference FK': ', CONSTRAINT FK_%(constraint_name)s FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
|
||||||
|
'reference TFK': ' CONSTRAINT FK_%(foreign_table)s_PK FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_table)s (%(foreign_key)s) ON DELETE %(on_delete_action)s',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self,db,uri,pool_size=0,folder=None,db_codec ='UTF-8',
|
||||||
|
credential_decoder=lambda x:x, driver_args={},
|
||||||
|
adapter_args={}, fake_connect=False, srid=4326):
|
||||||
|
### Fix this for sybase
|
||||||
|
if not self.driver:
|
||||||
|
raise RuntimeError, "Unable to import driver"
|
||||||
|
self.db = db
|
||||||
|
self.dbengine = "sybase"
|
||||||
|
self.uri = uri
|
||||||
|
self.pool_size = pool_size
|
||||||
|
self.folder = folder
|
||||||
|
self.db_codec = db_codec
|
||||||
|
self.srid = srid
|
||||||
|
self.find_or_make_work_folder()
|
||||||
|
# ## read: http://bytes.com/groups/python/460325-cx_oracle-utf8
|
||||||
|
uri = uri.split('://')[1]
|
||||||
|
if '@' not in uri:
|
||||||
|
try:
|
||||||
|
m = re.compile('^(?P<dsn>.+)$').match(uri)
|
||||||
|
if not m:
|
||||||
|
raise SyntaxError, \
|
||||||
|
'Parsing uri string(%s) has no result' % self.uri
|
||||||
|
dsn = m.group('dsn')
|
||||||
|
if not dsn:
|
||||||
|
raise SyntaxError, 'DSN required'
|
||||||
|
except SyntaxError, e:
|
||||||
|
logger.error('NdGpatch error')
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
m = re.compile('^(?P<user>[^:@]+)(\:(?P<password>[^@]*))?@(?P<host>[^\:/]+)(\:(?P<port>[0-9]+))?/(?P<db>[^\?]+)(\?(?P<urlargs>.*))?$').match(uri)
|
||||||
|
if not m:
|
||||||
|
raise SyntaxError, \
|
||||||
|
"Invalid URI string in DAL: %s" % uri
|
||||||
|
user = credential_decoder(m.group('user'))
|
||||||
|
if not user:
|
||||||
|
raise SyntaxError, 'User required'
|
||||||
|
password = credential_decoder(m.group('password'))
|
||||||
|
if not password:
|
||||||
|
password = ''
|
||||||
|
host = m.group('host')
|
||||||
|
if not host:
|
||||||
|
raise SyntaxError, 'Host name required'
|
||||||
|
db = m.group('db')
|
||||||
|
if not db:
|
||||||
|
raise SyntaxError, 'Database name required'
|
||||||
|
port = m.group('port') or '1433'
|
||||||
|
|
||||||
|
dsn = 'sybase:host=%s:%s;dbname=%s' % (host,port,db)
|
||||||
|
|
||||||
|
driver_args.update(dict(user = credential_decoder(user),
|
||||||
|
password = credential_decoder(password),
|
||||||
|
locale = charset))
|
||||||
|
|
||||||
|
def connect(dsn=dsn,driver_args=driver_args):
|
||||||
|
return self.driver.connect(dsn,**driver_args)
|
||||||
|
if not fake_connect:
|
||||||
|
self.pool_connection(connect)
|
||||||
|
self.after_connection()
|
||||||
|
|
||||||
|
def integrity_error_class(self):
|
||||||
|
return RuntimeError # FIX THIS
|
||||||
|
|
||||||
|
|
||||||
class FireBirdAdapter(BaseAdapter):
|
class FireBirdAdapter(BaseAdapter):
|
||||||
|
|
||||||
@@ -5760,6 +5863,7 @@ ADAPTERS = {
|
|||||||
'oracle': OracleAdapter,
|
'oracle': OracleAdapter,
|
||||||
'mssql': MSSQLAdapter,
|
'mssql': MSSQLAdapter,
|
||||||
'mssql2': MSSQL2Adapter,
|
'mssql2': MSSQL2Adapter,
|
||||||
|
'sybase': SybaseAdapter,
|
||||||
'db2': DB2Adapter,
|
'db2': DB2Adapter,
|
||||||
'teradata': TeradataAdapter,
|
'teradata': TeradataAdapter,
|
||||||
'informix': InformixAdapter,
|
'informix': InformixAdapter,
|
||||||
@@ -6062,7 +6166,8 @@ def smart_query(fields,text):
|
|||||||
value = constants[item[1:]]
|
value = constants[item[1:]]
|
||||||
else:
|
else:
|
||||||
value = item
|
value = item
|
||||||
if op == '=': op = 'like'
|
if field.type in ('text','string'):
|
||||||
|
if op == '=': op = 'like'
|
||||||
if op == '=': new_query = field==value
|
if op == '=': new_query = field==value
|
||||||
elif op == '<': new_query = field<value
|
elif op == '<': new_query = field<value
|
||||||
elif op == '>': new_query = field>value
|
elif op == '>': new_query = field>value
|
||||||
@@ -6512,7 +6617,8 @@ def index():
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return Row({'status':400,'pattern':pattern,
|
return Row({'status':400,'pattern':pattern,
|
||||||
'error':'invalid path','response':None})
|
'error':'invalid path','response':None})
|
||||||
return Row({'status':200,'response':response,'pattern':pattern})
|
return Row({'status':200,'response':response,
|
||||||
|
'pattern':pattern,'count':count})
|
||||||
return Row({'status':400,'error':'no matching pattern','response':None})
|
return Row({'status':400,'error':'no matching pattern','response':None})
|
||||||
|
|
||||||
|
|
||||||
@@ -7376,6 +7482,9 @@ class Expression(object):
|
|||||||
def len(self):
|
def len(self):
|
||||||
return Expression(self.db, self.db._adapter.AGGREGATE, self, 'LENGTH', 'integer')
|
return Expression(self.db, self.db._adapter.AGGREGATE, self, 'LENGTH', 'integer')
|
||||||
|
|
||||||
|
def avg(self):
|
||||||
|
return Expression(self.db, self.db._adapter.AGGREGATE, self, 'AVG', self.type)
|
||||||
|
|
||||||
def lower(self):
|
def lower(self):
|
||||||
return Expression(self.db, self.db._adapter.LOWER, self, None, self.type)
|
return Expression(self.db, self.db._adapter.LOWER, self, None, self.type)
|
||||||
|
|
||||||
@@ -7874,8 +7983,6 @@ class Field(Expression):
|
|||||||
return '<no table>.%s' % self.name
|
return '<no table>.%s' % self.name
|
||||||
|
|
||||||
|
|
||||||
def raw(s): return Expression(None,s)
|
|
||||||
|
|
||||||
class Query(object):
|
class Query(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -7964,7 +8071,7 @@ class Set(object):
|
|||||||
if isinstance(query,Table):
|
if isinstance(query,Table):
|
||||||
query = query._id>0
|
query = query._id>0
|
||||||
elif isinstance(query,str):
|
elif isinstance(query,str):
|
||||||
query = raw(query)
|
query = Expression(self.db,query)
|
||||||
elif isinstance(query,Field):
|
elif isinstance(query,Field):
|
||||||
query = query!=None
|
query = query!=None
|
||||||
if self.query:
|
if self.query:
|
||||||
@@ -8002,6 +8109,9 @@ class Set(object):
|
|||||||
fields = adapter.expand_all(fields, adapter.tables(self.query))
|
fields = adapter.expand_all(fields, adapter.tables(self.query))
|
||||||
return adapter.select(self.query,fields,attributes)
|
return adapter.select(self.query,fields,attributes)
|
||||||
|
|
||||||
|
def nested_select(self,*fields,**attributes):
|
||||||
|
return Expression(self.db,self._select(*fields,**attributes))
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
tablename=self.db._adapter.get_table(self.query)
|
tablename=self.db._adapter.get_table(self.query)
|
||||||
table = self.db[tablename]
|
table = self.db[tablename]
|
||||||
|
|||||||
+5
-4
@@ -2150,10 +2150,11 @@ class MENU(DIV):
|
|||||||
if not select:
|
if not select:
|
||||||
select = SELECT(**self.attributes)
|
select = SELECT(**self.attributes)
|
||||||
for item in data:
|
for item in data:
|
||||||
if item[2]:
|
if len(item) <= 4 or item[4] == True:
|
||||||
select.append(OPTION(CAT(prefix, item[0]), _value=item[2], _selected=item[1]))
|
if item[2]:
|
||||||
if len(item)>3 and len(item[3]):
|
select.append(OPTION(CAT(prefix, item[0]), _value=item[2], _selected=item[1]))
|
||||||
self.serialize_mobile(item[3], select, prefix = CAT(prefix, item[0], '/'))
|
if len(item)>3 and len(item[3]):
|
||||||
|
self.serialize_mobile(item[3], select, prefix = CAT(prefix, item[0], '/'))
|
||||||
select['_onchange'] = 'window.location=this.value'
|
select['_onchange'] = 'window.location=this.value'
|
||||||
return select
|
return select
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,13 @@ create_missing_folders()
|
|||||||
# set up logging for subsequent imports
|
# set up logging for subsequent imports
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
|
# This needed to prevent exception on Python 2.5:
|
||||||
|
# NameError: name 'gluon' is not defined
|
||||||
|
# See http://bugs.python.org/issue1436
|
||||||
|
import gluon.messageboxhandler
|
||||||
|
logging.gluon = gluon
|
||||||
|
|
||||||
logpath = abspath("logging.conf")
|
logpath = abspath("logging.conf")
|
||||||
if os.path.exists(logpath):
|
if os.path.exists(logpath):
|
||||||
logging.config.fileConfig(abspath("logging.conf"))
|
logging.config.fileConfig(abspath("logging.conf"))
|
||||||
|
|||||||
+4
-1
@@ -1016,13 +1016,16 @@ class MapUrlIn(object):
|
|||||||
self.request.args = self.args
|
self.request.args = self.args
|
||||||
if self.language:
|
if self.language:
|
||||||
self.request.uri_language = self.language
|
self.request.uri_language = self.language
|
||||||
uri = '/%s/%s/%s' % (self.application, self.controller, self.function)
|
uri = '/%s/%s' % (self.controller, self.function)
|
||||||
|
app = self.application
|
||||||
if self.map_hyphen:
|
if self.map_hyphen:
|
||||||
uri = uri.replace('_', '-')
|
uri = uri.replace('_', '-')
|
||||||
|
app = app.replace('_', '-')
|
||||||
if self.extension != 'html':
|
if self.extension != 'html':
|
||||||
uri += '.' + self.extension
|
uri += '.' + self.extension
|
||||||
if self.language:
|
if self.language:
|
||||||
uri = '/%s%s' % (self.language, uri)
|
uri = '/%s%s' % (self.language, uri)
|
||||||
|
uri = '/%s%s' % (app, uri)
|
||||||
uri += self.args and urllib.quote('/' + '/'.join([str(x) for x in self.args])) or ''
|
uri += self.args and urllib.quote('/' + '/'.join([str(x) for x in self.args])) or ''
|
||||||
uri += (self.query and ('?' + self.query) or '')
|
uri += (self.query and ('?' + self.query) or '')
|
||||||
self.env['REQUEST_URI'] = uri
|
self.env['REQUEST_URI'] = uri
|
||||||
|
|||||||
+18
-18
@@ -1323,7 +1323,7 @@ class SQLFORM(FORM):
|
|||||||
def smartdictform(session,name,filename=None,query=None,**kwargs):
|
def smartdictform(session,name,filename=None,query=None,**kwargs):
|
||||||
import os
|
import os
|
||||||
if query:
|
if query:
|
||||||
session[name] = db(query).select().first().as_dict()
|
session[name] = query.db(query).select().first().as_dict()
|
||||||
elif os.path.exists(filename):
|
elif os.path.exists(filename):
|
||||||
env = {'datetime':datetime}
|
env = {'datetime':datetime}
|
||||||
session[name] = eval(open(filename).read(),{},env)
|
session[name] = eval(open(filename).read(),{},env)
|
||||||
@@ -1331,7 +1331,7 @@ class SQLFORM(FORM):
|
|||||||
if form.process().accepted:
|
if form.process().accepted:
|
||||||
session[name].update(form.vars)
|
session[name].update(form.vars)
|
||||||
if query:
|
if query:
|
||||||
db(query).update(**form.vars)
|
query.db(query).update(**form.vars)
|
||||||
else:
|
else:
|
||||||
open(filename,'w').write(repr(session[name]))
|
open(filename,'w').write(repr(session[name]))
|
||||||
return form
|
return form
|
||||||
@@ -1546,27 +1546,27 @@ class SQLFORM(FORM):
|
|||||||
buttonurl=url(args=[]),callback=None,delete=None,trap=True):
|
buttonurl=url(args=[]),callback=None,delete=None,trap=True):
|
||||||
if showbuttontext:
|
if showbuttontext:
|
||||||
if callback:
|
if callback:
|
||||||
return A(SPAN(_class=ui.get(buttonclass,'')),
|
return A(SPAN(_class=ui.get(buttonclass)),
|
||||||
SPAN(T(buttontext),_title=buttontext,
|
SPAN(T(buttontext),_title=buttontext,
|
||||||
_class=ui.get('buttontext','')),
|
_class=ui.get('buttontext')),
|
||||||
callback=callback,delete=delete,
|
callback=callback,delete=delete,
|
||||||
_class=trap_class(ui.get('button',''),trap))
|
_class=trap_class(ui.get('button'),trap))
|
||||||
else:
|
else:
|
||||||
return A(SPAN(_class=ui.get(buttonclass,'')),
|
return A(SPAN(_class=ui.get(buttonclass)),
|
||||||
SPAN(T(buttontext),_title=buttontext,
|
SPAN(T(buttontext),_title=buttontext,
|
||||||
_class=ui.get('buttontext','')),
|
_class=ui.get('buttontext')),
|
||||||
_href=buttonurl,
|
_href=buttonurl,
|
||||||
_class=trap_class(ui.get('button',''),trap))
|
_class=trap_class(ui.get('button'),trap))
|
||||||
else:
|
else:
|
||||||
if callback:
|
if callback:
|
||||||
return A(SPAN(_class=ui.get(buttonclass,'')),
|
return A(SPAN(_class=ui.get(buttonclass)),
|
||||||
callback=callback,delete=delete,
|
callback=callback,delete=delete,
|
||||||
_title=buttontext,
|
_title=buttontext,
|
||||||
_class=trap_class(ui.get('buttontext',''),trap))
|
_class=trap_class(ui.get('buttontext'),trap))
|
||||||
else:
|
else:
|
||||||
return A(SPAN(_class=ui.get(buttonclass,'')),
|
return A(SPAN(_class=ui.get(buttonclass)),
|
||||||
_href=buttonurl,_title=buttontext,
|
_href=buttonurl,_title=buttontext,
|
||||||
_class=trap_class(ui.get('buttontext',''),trap))
|
_class=trap_class(ui.get('buttontext'),trap))
|
||||||
dbset = db(query)
|
dbset = db(query)
|
||||||
tablenames = db._adapter.tables(dbset.query)
|
tablenames = db._adapter.tables(dbset.query)
|
||||||
if left!=None: tablenames+=db._adapter.tables(left)
|
if left!=None: tablenames+=db._adapter.tables(left)
|
||||||
@@ -1772,9 +1772,9 @@ class SQLFORM(FORM):
|
|||||||
else:
|
else:
|
||||||
orderby = (order[:1]=='~' and ~sort_field) or sort_field
|
orderby = (order[:1]=='~' and ~sort_field) or sort_field
|
||||||
|
|
||||||
head = TR(_class=ui.get('header',''))
|
head = TR(_class=ui.get('header'))
|
||||||
if selectable:
|
if selectable:
|
||||||
head.append(TH(_class=ui.get('default','')))
|
head.append(TH(_class=ui.get('default')))
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if columns and not str(field) in columns: continue
|
if columns and not str(field) in columns: continue
|
||||||
if not field.readable: continue
|
if not field.readable: continue
|
||||||
@@ -1791,19 +1791,19 @@ class SQLFORM(FORM):
|
|||||||
header = A(header,marker,_href=url(vars=dict(
|
header = A(header,marker,_href=url(vars=dict(
|
||||||
keywords=request.vars.keywords or '',
|
keywords=request.vars.keywords or '',
|
||||||
order=key)),_class=trap_class())
|
order=key)),_class=trap_class())
|
||||||
head.append(TH(header, _class=ui.get('default','')))
|
head.append(TH(header, _class=ui.get('default')))
|
||||||
|
|
||||||
if links and links_in_grid:
|
if links and links_in_grid:
|
||||||
for link in links:
|
for link in links:
|
||||||
if isinstance(link,dict):
|
if isinstance(link,dict):
|
||||||
head.append(TH(link['header'], _class=ui.get('default','')))
|
head.append(TH(link['header'], _class=ui.get('default')))
|
||||||
|
|
||||||
# Include extra column for buttons if needed.
|
# Include extra column for buttons if needed.
|
||||||
include_buttons_column = (details or editable or deletable or
|
include_buttons_column = (details or editable or deletable or
|
||||||
(links and links_in_grid and
|
(links and links_in_grid and
|
||||||
not all([isinstance(link, dict) for link in links])))
|
not all([isinstance(link, dict) for link in links])))
|
||||||
if include_buttons_column:
|
if include_buttons_column:
|
||||||
head.append(TH(_class=ui.get('default','')))
|
head.append(TH(_class=ui.get('default')))
|
||||||
|
|
||||||
paginator = UL()
|
paginator = UL()
|
||||||
if paginate and paginate<nrows:
|
if paginate and paginate<nrows:
|
||||||
@@ -1938,7 +1938,7 @@ class SQLFORM(FORM):
|
|||||||
DIV(htmltable,_class="web2py_table"),
|
DIV(htmltable,_class="web2py_table"),
|
||||||
DIV(paginator,_class=\
|
DIV(paginator,_class=\
|
||||||
"web2py_paginator %(header)s %(cornerbottom)s" % ui),
|
"web2py_paginator %(header)s %(cornerbottom)s" % ui),
|
||||||
_class='%s %s' % (_class, ui.get('widget','')))
|
_class='%s %s' % (_class, ui.get('widget')))
|
||||||
res.create_form = create_form
|
res.create_form = create_form
|
||||||
res.update_form = update_form
|
res.update_form = update_form
|
||||||
res.view_form = view_form
|
res.view_form = view_form
|
||||||
|
|||||||
+2
-2
@@ -47,8 +47,8 @@ class SuperNode(Node):
|
|||||||
if self.value:
|
if self.value:
|
||||||
return str(self.value)
|
return str(self.value)
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("Undefined parent block ``%s``. \n" % self.name + \
|
# raise SyntaxError("Undefined parent block ``%s``. \n" % self.name + "You must define a block before referencing it.\nMake sure you have not left out an ``{{end}}`` tag." )
|
||||||
"You must define a block before referencing it.\nMake sure you have not left out an ``{{end}}`` tag." )
|
return ''
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s->%s" % (self.name, self.value)
|
return "%s->%s" % (self.name, self.value)
|
||||||
|
|||||||
+3
-3
@@ -646,7 +646,7 @@ class Mail(object):
|
|||||||
server.ehlo()
|
server.ehlo()
|
||||||
server.starttls()
|
server.starttls()
|
||||||
server.ehlo()
|
server.ehlo()
|
||||||
if not self.settings.login is None:
|
if not self.settings.login:
|
||||||
server.login(*self.settings.login.split(':',1))
|
server.login(*self.settings.login.split(':',1))
|
||||||
result = server.sendmail(self.settings.sender, to, payload.as_string())
|
result = server.sendmail(self.settings.sender, to, payload.as_string())
|
||||||
server.quit()
|
server.quit()
|
||||||
@@ -861,14 +861,14 @@ class Auth(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_or_create_key(filename=None):
|
def get_or_create_key(filename=None, alg='sha512'):
|
||||||
request = current.request
|
request = current.request
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = os.path.join(request.folder,'private','auth.key')
|
filename = os.path.join(request.folder,'private','auth.key')
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
key = open(filename,'r').read().strip()
|
key = open(filename,'r').read().strip()
|
||||||
else:
|
else:
|
||||||
key = web2py_uuid()
|
key = alg+':'+web2py_uuid()
|
||||||
open(filename,'w').write(key)
|
open(filename,'w').write(key)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -896,7 +896,7 @@ def start(cron=True):
|
|||||||
if hasattr(options,key):
|
if hasattr(options,key):
|
||||||
setattr(options,key,getattr(options2,key))
|
setattr(options,key,getattr(options2,key))
|
||||||
|
|
||||||
if not os.path.exists('logging.conf') and \
|
if False and not os.path.exists('logging.conf') and \
|
||||||
os.path.exists('logging.example.conf'):
|
os.path.exists('logging.example.conf'):
|
||||||
import shutil
|
import shutil
|
||||||
sys.stdout.write("Copying logging.conf.example to logging.conf ... ")
|
sys.stdout.write("Copying logging.conf.example to logging.conf ... ")
|
||||||
@@ -983,6 +983,17 @@ def start(cron=True):
|
|||||||
|
|
||||||
if root:
|
if root:
|
||||||
root.focus_force()
|
root.focus_force()
|
||||||
|
|
||||||
|
# Mac OS X - make the GUI window rise to the top
|
||||||
|
if os.path.exists("/usr/bin/osascript"):
|
||||||
|
applescript = """
|
||||||
|
tell application "System Events"
|
||||||
|
set proc to first process whose unix id is %d
|
||||||
|
set frontmost of proc to true
|
||||||
|
end tell
|
||||||
|
""" % (os.getpid())
|
||||||
|
os.system("/usr/bin/osascript -e '%s'" % applescript)
|
||||||
|
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
presentation(root)
|
presentation(root)
|
||||||
master = web2pyDialog(root, options)
|
master = web2pyDialog(root, options)
|
||||||
|
|||||||
@@ -1,81 +1,79 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
echo 'setup-web2py-nginx-uwsgi-ubuntu.sh'
|
echo 'setup-web2py-nginx-uwsgi-ubuntu-precise.sh'
|
||||||
echo 'Requires Ubuntu 10.04 (LTS) and installs Nginx + uWSGI + Web2py'
|
echo 'Requires Ubuntu 12.04 and installs Nginx + uWSGI + Web2py'
|
||||||
|
|
||||||
# Get Web2py Admin Password
|
# Get Web2py Admin Password
|
||||||
echo -e "Web2py Admin Password: \c "
|
echo -e "Web2py Admin Password: \c "
|
||||||
read PW
|
read PW
|
||||||
|
|
||||||
# Upgrade and install needed software
|
# Upgrade and install needed software
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get -y upgrade
|
apt-get -y upgrade
|
||||||
apt-get install python-software-properties
|
apt-get -y dist-upgrade
|
||||||
add-apt-repository ppa:nginx/stable
|
apt-get autoremove
|
||||||
add-apt-repository ppa:uwsgi/release
|
apt-get autoclean
|
||||||
apt-get update
|
apt-get -y install nginx-full
|
||||||
apt-get -y install nginx-full
|
apt-get -y install uwsgi uwsgi-plugin-python
|
||||||
apt-get -y install uwsgi-python
|
|
||||||
|
# Create configuration file /etc/nginx/sites-available/web2py
|
||||||
# Create configuration file /etc/nginx/sites-available/web2py
|
echo 'server {
|
||||||
echo 'server {
|
listen 80;
|
||||||
listen 80;
|
server_name $hostname;
|
||||||
server_name $hostname;
|
location ~* /(\w+)/static/ {
|
||||||
location ~* /(\w+)/static/ {
|
root /home/www-data/web2py/applications/;
|
||||||
root /home/www-data/web2py/applications/;
|
}
|
||||||
}
|
location / {
|
||||||
location / {
|
uwsgi_pass 127.0.0.1:9001;
|
||||||
uwsgi_pass 127.0.0.1:9001;
|
include uwsgi_params;
|
||||||
include uwsgi_params;
|
uwsgi_param UWSGI_SCHEME $scheme;
|
||||||
uwsgi_param UWSGI_SCHEME $scheme;
|
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
server {
|
||||||
server {
|
listen 443;
|
||||||
listen 443;
|
server_name $hostname;
|
||||||
server_name $hostname;
|
ssl on;
|
||||||
ssl on;
|
ssl_certificate /etc/nginx/ssl/web2py.crt;
|
||||||
ssl_certificate /etc/nginx/ssl/web2py.crt;
|
ssl_certificate_key /etc/nginx/ssl/web2py.key;
|
||||||
ssl_certificate_key /etc/nginx/ssl/web2py.key;
|
location / {
|
||||||
location / {
|
uwsgi_pass 127.0.0.1:9001;
|
||||||
uwsgi_pass 127.0.0.1:9001;
|
include uwsgi_params;
|
||||||
include uwsgi_params;
|
uwsgi_param UWSGI_SCHEME $scheme;
|
||||||
uwsgi_param UWSGI_SCHEME $scheme;
|
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
}
|
||||||
}
|
|
||||||
|
}' >/etc/nginx/sites-available/web2py
|
||||||
}' >/etc/nginx/sites-available/web2py
|
|
||||||
|
ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py
|
||||||
ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py
|
rm /etc/nginx/sites-enabled/default
|
||||||
rm /etc/nginx/sites-enabled/default
|
mkdir /etc/nginx/ssl
|
||||||
rm /etc/nginx/sites-available/default
|
cd /etc/nginx/ssl
|
||||||
mkdir /etc/nginx/ssl
|
openssl genrsa -out web2py.key 1024
|
||||||
cd /etc/nginx/ssl
|
openssl req -batch -new -key web2py.key -out web2py.csr
|
||||||
openssl genrsa -out web2py.key 1024
|
openssl x509 -req -days 1780 -in web2py.csr -signkey web2py.key -out web2py.crt
|
||||||
openssl req -batch -new -key web2py.key -out web2py.csr
|
|
||||||
openssl x509 -req -days 1780 -in web2py.csr -signkey web2py.key -out web2py.crt
|
# Create configuration file /etc/uwsgi/apps-available/web2py.xml
|
||||||
|
echo '<uwsgi>
|
||||||
# Create configuration file /etc/uwsgi-python/apps-available/web2py.xml
|
<plugin>python</plugin>
|
||||||
echo '<uwsgi>
|
<socket>127.0.0.1:9001</socket>
|
||||||
<socket>127.0.0.1:9001</socket>
|
<pythonpath>/home/www-data/web2py/</pythonpath>
|
||||||
<pythonpath>/home/www-data/web2py/</pythonpath>
|
<app mountpoint="/">
|
||||||
<app mountpoint="/">
|
<script>wsgihandler</script>
|
||||||
<script>wsgihandler</script>
|
</app>
|
||||||
</app>
|
</uwsgi>' >/etc/uwsgi/apps-available/web2py.xml
|
||||||
</uwsgi>' >/etc/uwsgi-python/apps-available/web2py.xml
|
ln -s /etc/uwsgi/apps-available/web2py.xml /etc/uwsgi/apps-enabled/web2py.xml
|
||||||
ln -s /etc/uwsgi-python/apps-available/web2py.xml /etc/uwsgi-python/apps-enabled/web2py.xml
|
|
||||||
|
# Install Web2py
|
||||||
# Install Web2py
|
apt-get -y install unzip
|
||||||
apt-get -y install unzip
|
mkdir /home/www-data
|
||||||
cd /home
|
cd /home/www-data
|
||||||
mkdir www-data
|
wget http://web2py.com/examples/static/web2py_src.zip
|
||||||
cd www-data
|
unzip web2py_src.zip
|
||||||
wget http://web2py.com/examples/static/web2py_src.zip
|
rm web2py_src.zip
|
||||||
unzip web2py_src.zip
|
chown -R www-data:www-data web2py
|
||||||
rm web2py_src.zip
|
cd /home/www-data/web2py
|
||||||
chown -R www-data:www-data web2py
|
sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)"
|
||||||
cd /home/www-data/web2py
|
/etc/init.d/uwsgi restart
|
||||||
sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)"
|
/etc/init.d/nginx restart
|
||||||
/etc/init.d/uwsgi-python restart
|
|
||||||
/etc/init.d/nginx restart
|
|
||||||
|
|||||||
Reference in New Issue
Block a user