Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aca3d43f0a | ||
|
|
5a898cc80a | ||
|
|
bfb3a320bd | ||
|
|
c0b1e387b1 | ||
|
|
c175e6340d | ||
|
|
3a5f7b05df | ||
|
|
26babd7e96 | ||
|
|
349088a96e | ||
|
|
a4ff77bdb9 | ||
|
|
8f70d3a802 | ||
|
|
89021b6409 | ||
|
|
4a078705b3 | ||
|
|
6eea834777 | ||
|
|
0f0a62ef7f | ||
|
|
cc8a21aedf | ||
|
|
38fff6fb91 | ||
|
|
e87a2bf0d5 | ||
|
|
6b3cdb5a99 | ||
|
|
e2191175da | ||
|
|
4a7f15bb04 | ||
|
|
e6c58c3c6f | ||
|
|
bb2407b468 | ||
|
|
07e809acb3 | ||
|
|
7714b5dc7b | ||
|
|
ca85d9adab | ||
|
|
41a9f12024 | ||
|
|
669691bbea | ||
|
|
6ac38e7c56 | ||
|
|
359758804b | ||
|
|
9400a0c7a1 | ||
|
|
ea34d1b3a0 | ||
|
|
72e9921901 | ||
|
|
d6af8279bc | ||
|
|
cd005b01c0 | ||
|
|
fa04c23bbf | ||
|
|
6ecc09f286 | ||
|
|
4b0f6aff73 | ||
|
|
c451f57d4e | ||
|
|
721cb2b90a | ||
|
|
01d5302a2d | ||
|
|
706324b9c6 | ||
|
|
244d3c68eb | ||
|
|
fcfa8aa917 | ||
|
|
8438a432e9 | ||
|
|
9d5e0b24f7 | ||
|
|
4480acd6f7 | ||
|
|
cd1ce28639 | ||
|
|
bf5fbd8b09 | ||
|
|
515e284c22 | ||
|
|
f98548827a | ||
|
|
b67e57f275 | ||
|
|
7005fb655c | ||
|
|
b9189771d0 | ||
|
|
b15211064d | ||
|
|
30ea9ac56b | ||
|
|
dab4950f14 | ||
|
|
0fce3655d5 | ||
|
|
91504fbc2c | ||
|
|
4b17684980 | ||
|
|
675245eb15 | ||
|
|
3494fa2d0d | ||
|
|
87a593845c |
@@ -1,3 +1,10 @@
|
|||||||
|
## 2.4.6
|
||||||
|
|
||||||
|
- better tests
|
||||||
|
- new ANY_OF and IS_IPV6 validators
|
||||||
|
- new custom save option
|
||||||
|
- many small bug fixes
|
||||||
|
|
||||||
## 2.4.5
|
## 2.4.5
|
||||||
|
|
||||||
- travis.ci integration (thanks Marc Abramowitz and Niphlod). Passes all tests (thanks Niplod).
|
- travis.ci integration (thanks Marc Abramowitz and Niphlod). Passes all tests (thanks Niplod).
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ update:
|
|||||||
echo "remember that pymysql was tweaked"
|
echo "remember that pymysql was tweaked"
|
||||||
src:
|
src:
|
||||||
### Use semantic versioning
|
### Use semantic versioning
|
||||||
echo 'Version 2.4.5-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
echo 'Version 2.4.6-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||||
### rm -f all junk files
|
### rm -f all junk files
|
||||||
make clean
|
make clean
|
||||||
### clean up baisc apps
|
### clean up baisc apps
|
||||||
@@ -114,7 +114,6 @@ commit:
|
|||||||
make src
|
make src
|
||||||
echo '' > NEWINSTALL
|
echo '' > NEWINSTALL
|
||||||
hg commit -m "$(S)"
|
hg commit -m "$(S)"
|
||||||
#bzr commit -m "$(S)"
|
|
||||||
git commit -a -m "$(S)"
|
git commit -a -m "$(S)"
|
||||||
push:
|
push:
|
||||||
hg push
|
hg push
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +1 @@
|
|||||||
Version 2.4.5-stable+timestamp.2013.03.18.17.37.19
|
Version 2.4.6-stable+timestamp.2013.04.06.12.11.51
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ default_expiration: "24h" # for static files
|
|||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
|
|
||||||
|
# Warning! Static mapping - below - isn't compatible with
|
||||||
|
# the parametric router's language logic.
|
||||||
|
# You cannot use them together.
|
||||||
|
|
||||||
- url: /(?P<a>.+?)/static/(?P<b>.+)
|
- url: /(?P<a>.+?)/static/(?P<b>.+)
|
||||||
static_files: applications/\1/static/\2
|
static_files: applications/\1/static/\2
|
||||||
upload: applications/(.+?)/static/(.+)
|
upload: applications/(.+?)/static/(.+)
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ response.menu = [[T('design'), False, URL('admin', 'default', 'design',
|
|||||||
# ## auxiliary functions
|
# ## auxiliary functions
|
||||||
# ###########################################################
|
# ###########################################################
|
||||||
|
|
||||||
|
if False and request.tickets_db:
|
||||||
|
from gluon.restricted import TicketStorage
|
||||||
|
ts = TicketStorage()
|
||||||
|
ts._get_table(request.tickets_db, ts.tablename, request.application)
|
||||||
|
|
||||||
def get_databases(request):
|
def get_databases(request):
|
||||||
dbs = {}
|
dbs = {}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from gluon.languages import (read_possible_languages, read_dict, write_dict,
|
|||||||
read_plural_dict, write_plural_dict)
|
read_plural_dict, write_plural_dict)
|
||||||
|
|
||||||
|
|
||||||
if DEMO_MODE and request.function in ['change_password', 'pack', 'pack_plugin', 'upgrade_web2py', 'uninstall', 'cleanup', 'compile_app', 'remove_compiled_app', 'delete', 'delete_plugin', 'create_file', 'upload_file', 'update_languages', 'reload_routes', 'git_push', 'git_pull']:
|
if DEMO_MODE and request.function in ['change_password', 'pack', 'pack_custom','pack_plugin', 'upgrade_web2py', 'uninstall', 'cleanup', 'compile_app', 'remove_compiled_app', 'delete', 'delete_plugin', 'create_file', 'upload_file', 'update_languages', 'reload_routes', 'git_push', 'git_pull']:
|
||||||
session.flash = T('disabled in demo mode')
|
session.flash = T('disabled in demo mode')
|
||||||
redirect(URL('site'))
|
redirect(URL('site'))
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ def check_version():
|
|||||||
elif new_version != True:
|
elif new_version != True:
|
||||||
return A(T('web2py is up to date'), _href=WEB2PY_URL)
|
return A(T('web2py is up to date'), _href=WEB2PY_URL)
|
||||||
elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"):
|
elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"):
|
||||||
return SPAN('You should upgrade to version %s.%s.%s' % version_number[:3])
|
return SPAN('You should upgrade to version %s' % version_number)
|
||||||
else:
|
else:
|
||||||
return sp_button(URL('upgrade_web2py'), T('upgrade now to %s') % version_number.split('-')[0])
|
return sp_button(URL('upgrade_web2py'), T('upgrade now to %s') % version_number.split('-')[0])
|
||||||
|
|
||||||
@@ -341,7 +341,6 @@ def pack():
|
|||||||
session.flash = T('internal error: %s' % e)
|
session.flash = T('internal error: %s' % e)
|
||||||
redirect(URL('site'))
|
redirect(URL('site'))
|
||||||
|
|
||||||
|
|
||||||
def pack_plugin():
|
def pack_plugin():
|
||||||
app = get_app()
|
app = get_app()
|
||||||
if len(request.args) == 2:
|
if len(request.args) == 2:
|
||||||
@@ -356,6 +355,33 @@ def pack_plugin():
|
|||||||
session.flash = T('internal error')
|
session.flash = T('internal error')
|
||||||
redirect(URL('plugin', args=request.args))
|
redirect(URL('plugin', args=request.args))
|
||||||
|
|
||||||
|
def pack_custom():
|
||||||
|
app = get_app()
|
||||||
|
base = apath(app, r=request)
|
||||||
|
if request.post_vars.file:
|
||||||
|
files = request.post_vars.file
|
||||||
|
files = [files] if not isinstance(files,list) else files
|
||||||
|
fname = 'web2py.app.%s.w2p' % app
|
||||||
|
try:
|
||||||
|
filename = app_pack(app, request, raise_ex=True, filenames=files)
|
||||||
|
except Exception, e:
|
||||||
|
filename = None
|
||||||
|
if filename:
|
||||||
|
response.headers['Content-Type'] = 'application/w2p'
|
||||||
|
disposition = 'attachment; filename=%s' % fname
|
||||||
|
response.headers['Content-Disposition'] = disposition
|
||||||
|
return safe_read(filename, 'rb')
|
||||||
|
else:
|
||||||
|
session.flash = T('internal error: %s' % e)
|
||||||
|
redirect(URL(args=request.args))
|
||||||
|
def ignore(fs):
|
||||||
|
return [f for f in fs if not (
|
||||||
|
f[:1] in '#' or f.endswith('~') or f.endswith('.bak'))]
|
||||||
|
files = {}
|
||||||
|
for (r,d,f) in os.walk(base):
|
||||||
|
files[r] = {'folders':ignore(d),'files':ignore(f)}
|
||||||
|
return locals()
|
||||||
|
|
||||||
|
|
||||||
def upgrade_web2py():
|
def upgrade_web2py():
|
||||||
dialog = FORM.confirm(T('Upgrade'),
|
dialog = FORM.confirm(T('Upgrade'),
|
||||||
@@ -682,7 +708,7 @@ def edit():
|
|||||||
cfilename = os.path.join(request.args[0], 'controllers',
|
cfilename = os.path.join(request.args[0], 'controllers',
|
||||||
request.args[2] + '.py')
|
request.args[2] + '.py')
|
||||||
if os.path.exists(apath(cfilename, r=request)):
|
if os.path.exists(apath(cfilename, r=request)):
|
||||||
edit_controller = URL('edit', args=[cfilename])
|
edit_controller = URL('edit',args=[cfilename.replace(os.sep, "/")])
|
||||||
view = request.args[3].replace('.html', '')
|
view = request.args[3].replace('.html', '')
|
||||||
view_link = URL(request.args[0], request.args[2], view)
|
view_link = URL(request.args[0], request.args[2], view)
|
||||||
elif filetype == 'python' and request.args[1] == 'controllers':
|
elif filetype == 'python' and request.args[1] == 'controllers':
|
||||||
|
|||||||
+480
-390
@@ -1,390 +1,480 @@
|
|||||||
# coding: utf8
|
# coding: utf8
|
||||||
{
|
{
|
||||||
'!langcode!': 'cs-cz',
|
'!langcode!': 'cs-cz',
|
||||||
'!langname!': '?e?tina',
|
'!langname!': 'čeština',
|
||||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': 'Kolonka "Upravit" je nepovinn? v?raz, nap??klad "pole1=\'nov?hodnota\'". V?sledky datab?zov?ho JOINu nem??ete mazat ani upravovat.',
|
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': 'Kolonka "Upravit" je nepovinný výraz, například "pole1=\'nováhodnota\'". Výsledky databázového JOINu nemůžete mazat ani upravovat.',
|
||||||
'%%{Row} in Table': '%%{??dek} v tabulce',
|
'"User Exception" debug mode. An error ticket could be issued!': '"User Exception" debug mode. An error ticket could be issued!',
|
||||||
'%%{Row} selected': 'ozna?en?ch %%{??dek}',
|
'%%{Row} in Table': '%%{řádek} v tabulce',
|
||||||
'%s %%{row} deleted': '%s smazan?ch %%{z?znam}',
|
'%%{Row} selected': 'označených %%{řádek}',
|
||||||
'%s %%{row} updated': '%s upraven?ch %%{z?znam}',
|
'%s %%{row} deleted': '%s smazaných %%{záznam}',
|
||||||
'%s selected': '%s ozna?en?ch',
|
'%s %%{row} updated': '%s upravených %%{záznam}',
|
||||||
'%Y-%m-%d': '%d.%m.%Y',
|
'%s selected': '%s označených',
|
||||||
'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
|
'%Y-%m-%d': '%d.%m.%Y',
|
||||||
'(requires internet access)': '(vy?aduje p?ipojen? k internetu)',
|
'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
|
||||||
'(something like "it-it")': '(nap??klad "cs-cs")',
|
'(requires internet access)': '(vyžaduje připojení k internetu)',
|
||||||
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(soubor **gluon/contrib/plural_rules/%s.py** nenalezen)',
|
'(requires internet access, experimental)': '(requires internet access, experimental)',
|
||||||
'@markmin\x01Searching: **%s** %%{file}': 'Hled?n?: **%s** %%{soubor}',
|
'(something like "it-it")': '(například "cs-cs")',
|
||||||
'About': 'O programu',
|
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(soubor **gluon/contrib/plural_rules/%s.py** nenalezen)',
|
||||||
'About application': 'O aplikaci',
|
'@markmin\x01Searching: **%s** %%{file}': 'Hledání: **%s** %%{soubor}',
|
||||||
'Access Control': '??zen? p??stupu',
|
'About': 'O programu',
|
||||||
'Add breakpoint': 'P?idat bod p?eru?en?',
|
'About application': 'O aplikaci',
|
||||||
'Additional code for your application': 'Dal?? k?d pro Va?i aplikaci',
|
'Access Control': 'Řízení přístupu',
|
||||||
'Admin language': 'jazyk rozhran?',
|
'Add breakpoint': 'Přidat bod přerušení',
|
||||||
'Administrative interface': 'pro administr?torsk? rozhran? klikn?te sem',
|
'Additional code for your application': 'Další kód pro Vaši aplikaci',
|
||||||
'Administrative Interface': 'Administr?torsk? rozhran?',
|
'Admin design page': 'Admin design page',
|
||||||
'administrative interface': 'rozhran? pro spr?vu',
|
'Admin language': 'jazyk rozhraní',
|
||||||
'Administrator Password:': 'Administr?torsk? heslo:',
|
'Administrative interface': 'pro administrátorské rozhraní klikněte sem',
|
||||||
'Ajax Recipes': 'Recepty s ajaxem',
|
'Administrative Interface': 'Administrátorské rozhraní',
|
||||||
'and rename it:': 'a p?ejmenovat na:',
|
'administrative interface': 'rozhraní pro správu',
|
||||||
'appadmin': 'appadmin',
|
'Administrator Password:': 'Administrátorské heslo:',
|
||||||
'appadmin is disabled because insecure channel': 'appadmin je zak?zan? bez zabezpe?en?ho spojen?',
|
'Ajax Recipes': 'Recepty s ajaxem',
|
||||||
'application "%s" uninstalled': 'application "%s" odinstalov?na',
|
'An error occured, please %s the page': 'An error occured, please %s the page',
|
||||||
'application compiled': 'aplikace zkompilov?na',
|
'and rename it:': 'a přejmenovat na:',
|
||||||
'Application name:': 'N?zev aplikace:',
|
'appadmin': 'appadmin',
|
||||||
'are not used': 'nepou?ita',
|
'appadmin is disabled because insecure channel': 'appadmin je zakázaná bez zabezpečeného spojení',
|
||||||
'are not used yet': 'je?t? nepou?ita',
|
'Application': 'Application',
|
||||||
'Are you sure you want to delete this object?': 'Opravdu chcete odstranit tento objekt?',
|
'application "%s" uninstalled': 'application "%s" odinstalována',
|
||||||
'Are you sure you want to uninstall application "%s"?': 'Opravdu chcete odinstalovat aplikaci "%s"?',
|
'application compiled': 'aplikace zkompilována',
|
||||||
'Available Databases and Tables': 'Dostupn? datab?ze a tabulky',
|
'Application name:': 'Název aplikace:',
|
||||||
'back': 'zp?t',
|
'are not used': 'nepoužita',
|
||||||
'Basics': 'Basics',
|
'are not used yet': 'ještě nepoužita',
|
||||||
'Begin': 'Za??t',
|
'Are you sure you want to delete this object?': 'Opravdu chcete odstranit tento objekt?',
|
||||||
'breakpoint': 'bod p?eru?en?',
|
'Are you sure you want to uninstall application "%s"?': 'Opravdu chcete odinstalovat aplikaci "%s"?',
|
||||||
'Breakpoints': 'Body p?eru?en?',
|
'arguments': 'arguments',
|
||||||
'breakpoints': 'body p?eru?en?',
|
'at char %s': 'at char %s',
|
||||||
'Buy this book': 'Koupit web2py knihu',
|
'at line %s': 'at line %s',
|
||||||
'Cache': 'Cache',
|
'ATTENTION:': 'ATTENTION:',
|
||||||
'cache': 'cache',
|
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.',
|
||||||
'Cache Keys': 'Kl??e cache',
|
'Available Databases and Tables': 'Dostupné databáze a tabulky',
|
||||||
'cache, errors and sessions cleaned': 'cache, chyby a relace byly pro?i?t?ny',
|
'back': 'zpět',
|
||||||
'can be a git repo': 'm??e to b?t git repo',
|
'Back to wizard': 'Back to wizard',
|
||||||
'Cancel': 'Storno',
|
'Basics': 'Basics',
|
||||||
'Cannot be empty': 'Nem??e b?t pr?zdn?',
|
'Begin': 'Začít',
|
||||||
'Change admin password': 'Zm?nit heslo pro str?vu aplikac?',
|
'breakpoint': 'bod přerušení',
|
||||||
'Change password': 'Zm?na hesla',
|
'Breakpoints': 'Body přerušení',
|
||||||
'check all': 'v?e ozna?it',
|
'breakpoints': 'body přerušení',
|
||||||
'Check for upgrades': 'Zkusit aktualizovat',
|
'Buy this book': 'Koupit web2py knihu',
|
||||||
'Check to delete': 'Ozna?it ke smaz?n?',
|
'Cache': 'Cache',
|
||||||
'Check to delete:': 'Ozna?it ke smaz?n?:',
|
'cache': 'cache',
|
||||||
'Checking for upgrades...': 'Zji??uji, zda jsou k dispozici aktualizace...',
|
'Cache Keys': 'Klíče cache',
|
||||||
'Clean': 'Pro?istit',
|
'cache, errors and sessions cleaned': 'cache, chyby a relace byly pročištěny',
|
||||||
'Clear CACHE?': 'Vymazat CACHE?',
|
'can be a git repo': 'může to být git repo',
|
||||||
'Clear DISK': 'Vymazat DISK',
|
'Cancel': 'Storno',
|
||||||
'Clear RAM': 'Vymazat RAM',
|
'Cannot be empty': 'Nemůže být prázdné',
|
||||||
'Click row to expand traceback': 'Pro rozbalen? stopy, klikn?te na ??dek',
|
'Change Admin Password': 'Změnit heslo pro správu',
|
||||||
'Click row to view a ticket': 'Pro zobrazen? chyby (ticketu), klikn?te na ??dku...',
|
'Change admin password': 'Změnit heslo pro správu aplikací',
|
||||||
'Client IP': 'IP adresa klienta',
|
'Change password': 'Změna hesla',
|
||||||
'collapse/expand all': 'v?e sbalit/rozbalit',
|
'check all': 'vše označit',
|
||||||
'Community': 'Komunita',
|
'Check for upgrades': 'Zkusit aktualizovat',
|
||||||
'Compile': 'Zkompilovat',
|
'Check to delete': 'Označit ke smazání',
|
||||||
'compiled application removed': 'zkompilovan? aplikace smaz?na',
|
'Check to delete:': 'Označit ke smazání:',
|
||||||
'Components and Plugins': 'Komponenty a z?suvn? moduly',
|
'Checking for upgrades...': 'Zjišťuji, zda jsou k dispozici aktualizace...',
|
||||||
'Condition': 'Podm?nka',
|
'Clean': 'Pročistit',
|
||||||
'Controller': 'Kontrol?r (Controller)',
|
'Clear CACHE?': 'Vymazat CACHE?',
|
||||||
'Controllers': 'Kontrol?ry',
|
'Clear DISK': 'Vymazat DISK',
|
||||||
'controllers': 'kontrol?ry',
|
'Clear RAM': 'Vymazat RAM',
|
||||||
'Copyright': 'Copyright',
|
'Click row to expand traceback': 'Pro rozbalení stopy, klikněte na řádek',
|
||||||
'Count': 'Po?et',
|
'Click row to view a ticket': 'Pro zobrazení chyby (ticketu), klikněte na řádku...',
|
||||||
'Create': 'Vytvo?it',
|
'Client IP': 'IP adresa klienta',
|
||||||
'create file with filename:': 'vytvo?it soubor s n?zvem:',
|
'code': 'code',
|
||||||
'created by': 'vytvo?il',
|
'Code listing': 'Code listing',
|
||||||
'Created By': 'Vytvo?eno - k?m',
|
'collapse/expand all': 'vše sbalit/rozbalit',
|
||||||
'Created On': 'Vytvo?eno - kdy',
|
'Community': 'Komunita',
|
||||||
'crontab': 'crontab',
|
'Compile': 'Zkompilovat',
|
||||||
'Current request': 'Aktu?ln? po?adavek',
|
'compiled application removed': 'zkompilovaná aplikace smazána',
|
||||||
'Current response': 'Aktu?ln? odpov??',
|
'Components and Plugins': 'Komponenty a zásuvné moduly',
|
||||||
'Current session': 'Aktu?ln? relace',
|
'Condition': 'Podmínka',
|
||||||
'currently running': 'pr?v? b???',
|
'continue': 'continue',
|
||||||
'currently saved or': 'ulo?eno nebo',
|
'Controller': 'Kontrolér (Controller)',
|
||||||
'customize me!': 'upravte m?!',
|
'Controllers': 'Kontroléry',
|
||||||
'data uploaded': 'data nahr?na',
|
'controllers': 'kontroléry',
|
||||||
'Database': 'Rozhran? datab?ze',
|
'Copyright': 'Copyright',
|
||||||
'Database %s select': 'datab?ze %s v?b?r',
|
'Count': 'Počet',
|
||||||
'database administration': 'spr?va datab?ze',
|
'Create': 'Vytvořit',
|
||||||
'Date and Time': 'Datum a ?as',
|
'create file with filename:': 'vytvořit soubor s názvem:',
|
||||||
'day': 'den',
|
'created by': 'vytvořil',
|
||||||
'db': 'db',
|
'Created By': 'Vytvořeno - kým',
|
||||||
'DB Model': 'Datab?zov? model',
|
'Created On': 'Vytvořeno - kdy',
|
||||||
'Debug': 'Lad?n?',
|
'crontab': 'crontab',
|
||||||
'Delete': 'Smazat',
|
'Current request': 'Aktuální požadavek',
|
||||||
'delete': 'smazat',
|
'Current response': 'Aktuální odpověď',
|
||||||
'delete all checked': 'smazat v?e ozna?en?',
|
'Current session': 'Aktuální relace',
|
||||||
'Delete this file (you will be asked to confirm deletion)': 'Smazat tento soubor (budete po??d?n o potvrzen? maz?n?)',
|
'currently running': 'právě běží',
|
||||||
'Delete:': 'Smazat:',
|
'currently saved or': 'uloženo nebo',
|
||||||
'deleted after first hit': 'smazat po prvn?m dosa?en?',
|
'customize me!': 'upravte mě!',
|
||||||
'Demo': 'Demo',
|
'data uploaded': 'data nahrána',
|
||||||
'Deploy': 'Nahr?t',
|
'Database': 'Rozhraní databáze',
|
||||||
'Deploy on Google App Engine': 'Nahr?t na Google App Engine',
|
'Database %s select': 'databáze %s výběr',
|
||||||
'Deploy to OpenShift': 'Nahr?t na OpenShift',
|
'Database administration': 'Database administration',
|
||||||
'Deployment Recipes': 'Postupy pro deployment',
|
'database administration': 'správa databáze',
|
||||||
'Description': 'Popis',
|
'Date and Time': 'Datum a čas',
|
||||||
'design': 'n?vrh',
|
'day': 'den',
|
||||||
'direction: ltr': 'direction: ltr',
|
'db': 'db',
|
||||||
'Disable': 'Zablokovat',
|
'DB Model': 'Databázový model',
|
||||||
'DISK': 'DISK',
|
'Debug': 'Ladění',
|
||||||
'Disk Cache Keys': 'Kl??e diskov? cache',
|
'defines tables': 'defines tables',
|
||||||
'Disk Cleared': 'Disk smaz?n',
|
'Delete': 'Smazat',
|
||||||
'docs': 'dokumentace',
|
'delete': 'smazat',
|
||||||
'Documentation': 'Dokumentace',
|
'delete all checked': 'smazat vše označené',
|
||||||
"Don't know what to do?": 'Nev?te kudy kam?',
|
'delete plugin': 'delete plugin',
|
||||||
'done!': 'hotovo!',
|
'Delete this file (you will be asked to confirm deletion)': 'Smazat tento soubor (budete požádán o potvrzení mazání)',
|
||||||
'Download': 'St?hnout',
|
'Delete:': 'Smazat:',
|
||||||
'download layouts': 'st?hnout moduly rozvr?en? str?nky',
|
'deleted after first hit': 'smazat po prvním dosažení',
|
||||||
'download plugins': 'st?hnout z?suvn? moduly',
|
'Demo': 'Demo',
|
||||||
'E-mail': 'E-mail',
|
'Deploy': 'Nahrát',
|
||||||
'Edit': 'Upravit',
|
'Deploy on Google App Engine': 'Nahrát na Google App Engine',
|
||||||
'edit all': 'edit all',
|
'Deploy to OpenShift': 'Nahrát na OpenShift',
|
||||||
'Edit application': 'Spr?va aplikace',
|
'Deployment Recipes': 'Postupy pro deployment',
|
||||||
'Edit current record': 'Upravit aktu?ln? z?znam',
|
'Description': 'Popis',
|
||||||
'Edit Profile': 'Upravit profil',
|
'design': 'návrh',
|
||||||
'Editing file "%s"': '?prava souboru "%s"',
|
'Detailed traceback description': 'Podrobný výpis prostředí',
|
||||||
'Editing Language file': '?prava jazykov?ho souboru',
|
'details': 'podrobnosti',
|
||||||
'Email and SMS': 'Email a SMS',
|
'direction: ltr': 'směr: ltr',
|
||||||
'Enable': 'Odblokovat',
|
'Disable': 'Zablokovat',
|
||||||
'enter a number between %(min)g and %(max)g': 'zadejte ??slo mezi %(min)g a %(max)g',
|
'DISK': 'DISK',
|
||||||
'enter an integer between %(min)g and %(max)g': 'zadejte cel? ??slo mezi %(min)g a %(max)g',
|
'Disk Cache Keys': 'Klíče diskové cache',
|
||||||
'Error': 'Chyba',
|
'Disk Cleared': 'Disk smazán',
|
||||||
'Error logs for "%(app)s"': 'Seznam v?skytu chyb pro aplikaci "%(app)s"',
|
'docs': 'dokumentace',
|
||||||
'Errors': 'Chyby',
|
'Documentation': 'Dokumentace',
|
||||||
'export as csv file': 'exportovat do .csv souboru',
|
"Don't know what to do?": 'Nevíte kudy kam?',
|
||||||
'exposes': 'vystavuje',
|
'done!': 'hotovo!',
|
||||||
'extends': 'roz?i?uje',
|
'Download': 'Stáhnout',
|
||||||
'FAQ': '?asto kladen? dotazy',
|
'download layouts': 'stáhnout moduly rozvržení stránky',
|
||||||
'File': 'Soubor',
|
'download plugins': 'stáhnout zásuvné moduly',
|
||||||
'file': 'soubor',
|
'E-mail': 'E-mail',
|
||||||
'file saved on %(time)s': 'soubor ulo?en %(time)s',
|
'Edit': 'Upravit',
|
||||||
'Filename': 'N?zev souboru',
|
'edit all': 'edit all',
|
||||||
'filter': 'filtr',
|
'Edit application': 'Správa aplikace',
|
||||||
'Find Next': 'Naj?t dal??',
|
'edit controller': 'edit controller',
|
||||||
'Find Previous': 'Naj?t p?edchoz?',
|
'Edit current record': 'Upravit aktuální záznam',
|
||||||
'First name': 'K?estn? jm?no',
|
'Edit Profile': 'Upravit profil',
|
||||||
'Forgot username?': 'Zapomn?l jste svoje p?ihla?ovac? jm?no?',
|
'edit views:': 'upravit pohled:',
|
||||||
'forgot username?': 'zapomn?l jste svoje p?ihla?ovac? jm?no?',
|
'Editing file "%s"': 'Úprava souboru "%s"',
|
||||||
'Forms and Validators': 'Formul??e a valid?tory',
|
'Editing Language file': 'Úprava jazykového souboru',
|
||||||
'Free Applications': 'Aplikace zdarma',
|
'Editing Plural Forms File': 'Editing Plural Forms File',
|
||||||
'Generate': 'Vytvo?it',
|
'Email and SMS': 'Email a SMS',
|
||||||
'Get from URL:': 'St?hnout z internetu:',
|
'Enable': 'Odblokovat',
|
||||||
'Git Pull': 'Git Pull',
|
'enter a number between %(min)g and %(max)g': 'zadejte číslo mezi %(min)g a %(max)g',
|
||||||
'Git Push': 'Git Push',
|
'enter an integer between %(min)g and %(max)g': 'zadejte celé číslo mezi %(min)g a %(max)g',
|
||||||
'Globals##debug': 'Glob?ln? prom?nn?',
|
'Error': 'Chyba',
|
||||||
'go!': 'OK!',
|
'Error logs for "%(app)s"': 'Seznam výskytu chyb pro aplikaci "%(app)s"',
|
||||||
'Group %(group_id)s created': 'Skupina %(group_id)s vytvo?ena',
|
'Error snapshot': 'Snapshot chyby',
|
||||||
'Group ID': 'ID skupiny',
|
'Error ticket': 'Ticket chyby',
|
||||||
'Groups': 'Skupiny',
|
'Errors': 'Chyby',
|
||||||
'Hello World': 'Ahoj sv?te',
|
'Exception %(extype)s: %(exvalue)s': 'Exception %(extype)s: %(exvalue)s',
|
||||||
'Help': 'N?pov?da',
|
'Exception %s': 'Exception %s',
|
||||||
'Hide/Show Translated strings': 'Skr?t/Zobrazit p?elo?en? texty',
|
'Exception instance attributes': 'Prvky instance výjimky',
|
||||||
'Hits': 'Kolikr?t dosa?eno',
|
'Expand Abbreviation': 'Expand Abbreviation',
|
||||||
'Home': 'Domovsk? str?nka',
|
'export as csv file': 'exportovat do .csv souboru',
|
||||||
'honored only if the expression evaluates to true': 'br?t v potaz jen kdy? se tato podm?nka vyhodnot? kladn?',
|
'exposes': 'vystavuje',
|
||||||
'How did you get here?': 'Jak jste se sem vlastn? dostal?',
|
'exposes:': 'vystavuje funkce:',
|
||||||
'import': 'import',
|
'extends': 'rozšiřuje',
|
||||||
'Import/Export': 'Import/Export',
|
'failed to compile file because:': 'soubor se nepodařilo zkompilovat, protože:',
|
||||||
'includes': 'zahrnuje',
|
'FAQ': 'Často kladené dotazy',
|
||||||
'Index': 'Index',
|
'File': 'Soubor',
|
||||||
'insert new': 'vlo?it nov? z?znam ',
|
'file': 'soubor',
|
||||||
'insert new %s': 'vlo?it nov? z?znam %s',
|
'file "%(filename)s" created': 'file "%(filename)s" created',
|
||||||
'Install': 'Instalovat',
|
'file saved on %(time)s': 'soubor uložen %(time)s',
|
||||||
'Installed applications': 'Nainstalovan? aplikace',
|
'file saved on %s': 'soubor uložen %s',
|
||||||
'Internal State': 'Vnit?n? stav',
|
'Filename': 'Název souboru',
|
||||||
'Introduction': '?vod',
|
'filter': 'filtr',
|
||||||
'Invalid email': 'Neplatn? email',
|
'Find Next': 'Najít další',
|
||||||
'Invalid password': 'Nespr?vn? heslo',
|
'Find Previous': 'Najít předchozí',
|
||||||
'invalid password.': 'neplatn? heslo',
|
'First name': 'Křestní jméno',
|
||||||
'Invalid Query': 'Neplatn? dotaz',
|
'Forgot username?': 'Zapomněl jste svoje přihlašovací jméno?',
|
||||||
'invalid request': 'Neplatn? po?adavek',
|
'forgot username?': 'zapomněl jste svoje přihlašovací jméno?',
|
||||||
'Is Active': 'Je aktivn?',
|
'Forms and Validators': 'Formuláře a validátory',
|
||||||
'It is %s %%{day} today.': 'Dnes je to %s %%{den}.',
|
'Frames': 'Frames',
|
||||||
'Key': 'Kl??',
|
'Free Applications': 'Aplikace zdarma',
|
||||||
'Key bindings': 'Vazby kl???',
|
'Functions with no doctests will result in [passed] tests.': 'Functions with no doctests will result in [passed] tests.',
|
||||||
'languages': 'jazyky',
|
'Generate': 'Vytvořit',
|
||||||
'Languages': 'Jazyky',
|
'Get from URL:': 'Stáhnout z internetu:',
|
||||||
'Last name': 'P??jmen?',
|
'Git Pull': 'Git Pull',
|
||||||
'Last saved on:': 'Naposledy ulo?eno:',
|
'Git Push': 'Git Push',
|
||||||
'Layout': 'Rozvr?en? str?nky (layout)',
|
'Globals##debug': 'Globální proměnné',
|
||||||
'Layout Plugins': 'Moduly rozvr?en? str?nky (Layout Plugins)',
|
'go!': 'OK!',
|
||||||
'Layouts': 'Rozvr?en? str?nek',
|
'Goto': 'Goto',
|
||||||
'License for': 'Licence pro',
|
'graph model': 'graph model',
|
||||||
'Line number': '??slo ??dku',
|
'Group %(group_id)s created': 'Skupina %(group_id)s vytvořena',
|
||||||
'LineNo': '?.??dku',
|
'Group ID': 'ID skupiny',
|
||||||
'Live Chat': 'Online pokec',
|
'Groups': 'Skupiny',
|
||||||
'loading...': 'nahr?v?m...',
|
'Hello World': 'Ahoj světe',
|
||||||
'Locals##debug': 'Lok?ln? prom?nn?',
|
'Help': 'Nápověda',
|
||||||
'Logged in': 'P?ihl??en? prob?hlo ?sp??n?',
|
'Hide/Show Translated strings': 'Skrýt/Zobrazit přeložené texty',
|
||||||
'Logged out': 'Odhl??en? prob?hlo ?sp??n?',
|
'Hits': 'Kolikrát dosaženo',
|
||||||
'Login': 'P?ihl?sit se',
|
'Home': 'Domovská stránka',
|
||||||
'login': 'p?ihl?sit se',
|
'honored only if the expression evaluates to true': 'brát v potaz jen když se tato podmínka vyhodnotí kladně',
|
||||||
'Login to the Administrative Interface': 'P?ihl?sit se do Spr?vce aplikac?',
|
'How did you get here?': 'Jak jste se sem vlastně dostal?',
|
||||||
'logout': 'odhl?sit se',
|
'If start the upgrade, be patient, it may take a while to download': 'If start the upgrade, be patient, it may take a while to download',
|
||||||
'Logout': 'Odhl?sit se',
|
'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.',
|
||||||
'Lost Password': 'Zapomn?l jste heslo',
|
'import': 'import',
|
||||||
'Lost password?': 'Zapomn?l jste heslo?',
|
'Import/Export': 'Import/Export',
|
||||||
'lost password?': 'zapomn?l jste heslo?',
|
'includes': 'zahrnuje',
|
||||||
'Manage Cache': 'Manage Cache',
|
'Index': 'Index',
|
||||||
'Menu Model': 'Model rozbalovac? nab?dky',
|
'insert new': 'vložit nový záznam ',
|
||||||
'Models': 'Modely',
|
'insert new %s': 'vložit nový záznam %s',
|
||||||
'models': 'modely',
|
'inspect attributes': 'inspect attributes',
|
||||||
'Modified By': 'Zm?n?no - k?m',
|
'Install': 'Instalovat',
|
||||||
'Modified On': 'Zm?n?no - kdy',
|
'Installed applications': 'Nainstalované aplikace',
|
||||||
'Modules': 'Moduly',
|
'Interaction at %s line %s': 'Interakce v %s, na řádce %s',
|
||||||
'modules': 'moduly',
|
'Interactive console': 'Interaktivní příkazová řádka',
|
||||||
'My Sites': 'Spr?va aplikac?',
|
'Internal State': 'Vnitřní stav',
|
||||||
'Name': 'Jm?no',
|
'Introduction': 'Úvod',
|
||||||
'New Application Wizard': 'Nov? pr?vodce aplikac?',
|
'Invalid email': 'Neplatný email',
|
||||||
'New application wizard': 'Nov? pr?vodce aplikac?',
|
'Invalid password': 'Nesprávné heslo',
|
||||||
'New password': 'Nov? heslo',
|
'invalid password.': 'neplatné heslo',
|
||||||
'New Record': 'Nov? z?znam',
|
'Invalid Query': 'Neplatný dotaz',
|
||||||
'new record inserted': 'nov? z?znam byl zalo?en',
|
'invalid request': 'Neplatný požadavek',
|
||||||
'New simple application': 'Vytvo?it primitivn? aplikaci',
|
'Is Active': 'Je aktivní',
|
||||||
'next 100 rows': 'dal??ch 100 ??dk?',
|
'It is %s %%{day} today.': 'Dnes je to %s %%{den}.',
|
||||||
'No databases in this application': 'V t?to aplik?ci nejsou ??dn? datab?ze',
|
'Key': 'Klíč',
|
||||||
'No Interaction yet': 'Je?t? ??dn? interakce nenastala',
|
'Key bindings': 'Vazby klíčů',
|
||||||
'No ticket_storage.txt found under /private folder': 'Soubor ticket_storage.txt v adres??i /private nenalezen',
|
'Key bindings for ZenCoding Plugin': 'Key bindings for ZenCoding Plugin',
|
||||||
'Object or table name': 'Objekt ?i tabulka',
|
'languages': 'jazyky',
|
||||||
'Old password': 'P?vodn? heslo',
|
'Languages': 'Jazyky',
|
||||||
'online designer': 'online n?vrh??',
|
'Last name': 'Příjmení',
|
||||||
'Online examples': 'P??klady online',
|
'Last saved on:': 'Naposledy uloženo:',
|
||||||
'or import from csv file': 'nebo importovat z .csv souboru',
|
'Layout': 'Rozvržení stránky (layout)',
|
||||||
'Origin': 'P?vod',
|
'Layout Plugins': 'Moduly rozvržení stránky (Layout Plugins)',
|
||||||
'Original/Translation': 'Origin?l/P?eklad',
|
'Layouts': 'Rozvržení stránek',
|
||||||
'Other Plugins': 'Ostatn? moduly',
|
'License for': 'Licence pro',
|
||||||
'Other Recipes': 'Ostatn? z?suvn? moduly',
|
'Line number': 'Číslo řádku',
|
||||||
'Overview': 'P?ehled',
|
'LineNo': 'Č.řádku',
|
||||||
'Overwrite installed app': 'P?epsat instalovanou aplikaci',
|
'Live Chat': 'Online pokec',
|
||||||
'Pack all': 'Zabalit',
|
'loading...': 'nahrávám...',
|
||||||
'Pack compiled': 'Zabalit zkompilovan?',
|
'locals': 'locals',
|
||||||
'password': 'heslo',
|
'Locals##debug': 'Lokální proměnné',
|
||||||
'Password': 'Heslo',
|
'Logged in': 'Přihlášení proběhlo úspěšně',
|
||||||
"Password fields don't match": 'Hesla se neshoduj?',
|
'Logged out': 'Odhlášení proběhlo úspěšně',
|
||||||
'Please': 'Pros?m',
|
'Login': 'Přihlásit se',
|
||||||
'plugins': 'z?suvn? moduly',
|
'login': 'přihlásit se',
|
||||||
'Plugins': 'Z?suvn? moduly',
|
'Login to the Administrative Interface': 'Přihlásit se do Správce aplikací',
|
||||||
'Plural-Forms:': 'Mno?n? ??sla:',
|
'logout': 'odhlásit se',
|
||||||
'Powered by': 'Poh?n?no',
|
'Logout': 'Odhlásit se',
|
||||||
'Preface': 'P?edmluva',
|
'Lost Password': 'Zapomněl jste heslo',
|
||||||
'previous 100 rows': 'p?edchoz?ch 100 ??dk?',
|
'Lost password?': 'Zapomněl jste heslo?',
|
||||||
'Private files': 'Soukrom? soubory',
|
'lost password?': 'zapomněl jste heslo?',
|
||||||
'private files': 'soukrom? soubory',
|
'Manage': 'Manage',
|
||||||
'profile': 'profil',
|
'Manage Cache': 'Manage Cache',
|
||||||
'Project Progress': 'V?voj projektu',
|
'Menu Model': 'Model rozbalovací nabídky',
|
||||||
'Python': 'Python',
|
'Models': 'Modely',
|
||||||
'Query:': 'Dotaz:',
|
'models': 'modely',
|
||||||
'Quick Examples': 'Kr?tk? p??klady',
|
'Modified By': 'Změněno - kým',
|
||||||
'RAM': 'RAM',
|
'Modified On': 'Změněno - kdy',
|
||||||
'RAM Cache Keys': 'Kl??e RAM Cache',
|
'Modules': 'Moduly',
|
||||||
'Ram Cleared': 'RAM smaz?na',
|
'modules': 'moduly',
|
||||||
'Readme': 'N?pov?da',
|
'My Sites': 'Správa aplikací',
|
||||||
'Recipes': 'Postupy jak na to',
|
'Name': 'Jméno',
|
||||||
'Record': 'Z?znam',
|
'new application "%s" created': 'nová aplikace "%s" vytvořena',
|
||||||
'record does not exist': 'z?znam neexistuje',
|
'New Application Wizard': 'Nový průvodce aplikací',
|
||||||
'Record ID': 'ID z?znamu',
|
'New application wizard': 'Nový průvodce aplikací',
|
||||||
'Record id': 'id z?znamu',
|
'New password': 'Nové heslo',
|
||||||
'refresh': 'obnovte',
|
'New Record': 'Nový záznam',
|
||||||
'register': 'registrovat',
|
'new record inserted': 'nový záznam byl založen',
|
||||||
'Register': 'Zaregistrovat se',
|
'New simple application': 'Vytvořit primitivní aplikaci',
|
||||||
'Registration identifier': 'Registra?n? identifik?tor',
|
'next': 'next',
|
||||||
'Registration key': 'Registra?n? kl??',
|
'next 100 rows': 'dalších 100 řádků',
|
||||||
'Reload routes': 'Znovu nahr?t cesty',
|
'No databases in this application': 'V této aplikaci nejsou žádné databáze',
|
||||||
'Remember me (for 30 days)': 'Zapamatovat na 30 dn?',
|
'No Interaction yet': 'Ještě žádná interakce nenastala',
|
||||||
'Remove compiled': 'Odstranit zkompilovan?',
|
'No ticket_storage.txt found under /private folder': 'Soubor ticket_storage.txt v adresáři /private nenalezen',
|
||||||
'Removed Breakpoint on %s at line %s': 'Bod p?eru?en? smaz?n - soubor %s na ??dce %s',
|
'Object or table name': 'Objekt či tabulka',
|
||||||
'Replace': 'Zam?nit',
|
'Old password': 'Původní heslo',
|
||||||
'Replace All': 'Zam?nit v?e',
|
'online designer': 'online návrhář',
|
||||||
'Reset Password key': 'Reset registra?n?ho kl??e',
|
'Online examples': 'Příklady online',
|
||||||
'restart': 'restart',
|
'Open new app in new window': 'Open new app in new window',
|
||||||
'restore': 'obnovit',
|
'or alternatively': 'or alternatively',
|
||||||
'Retrieve username': 'Z?skat p?ihla?ovac? jm?no',
|
'Or Get from URL:': 'Or Get from URL:',
|
||||||
'revert': 'vr?tit se k p?vodn?mu',
|
'or import from csv file': 'nebo importovat z .csv souboru',
|
||||||
'Role': 'Role',
|
'Origin': 'Původ',
|
||||||
'Rows in Table': 'Z?znamy v tabulce',
|
'Original/Translation': 'Originál/Překlad',
|
||||||
'Rows selected': 'Z?znam? zobrazeno',
|
'Other Plugins': 'Ostatní moduly',
|
||||||
'rules are not defined': 'pravidla nejsou definov?na',
|
'Other Recipes': 'Ostatní zásuvné moduly',
|
||||||
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Spust? testy v tomto souboru (ke spu?t?n? v?ech test?, pou?ijte tla??tko 'test')",
|
'Overview': 'Přehled',
|
||||||
'Running on %s': 'B??? na %s',
|
'Overwrite installed app': 'Přepsat instalovanou aplikaci',
|
||||||
'Save': 'Ulo?it',
|
'Pack all': 'Zabalit',
|
||||||
'Save via Ajax': 'Ulo?it pomoc? Ajaxu',
|
'Pack compiled': 'Zabalit zkompilované',
|
||||||
'Saved file hash:': 'hash ulo?en?ho souboru:',
|
'pack plugin': 'pack plugin',
|
||||||
'Semantic': 'Modul semantic',
|
'password': 'heslo',
|
||||||
'Services': 'Slu?by',
|
'Password': 'Heslo',
|
||||||
'Set Breakpoint on %s at line %s: %s': 'Bod p?eru?en? nastaven v souboru %s na ??dce %s: %s',
|
"Password fields don't match": 'Hesla se neshodují',
|
||||||
'shell': 'p??kazov? ??dka',
|
'Peeking at file': 'Peeking at file',
|
||||||
'Site': 'Spr?va aplikac?',
|
'Please': 'Prosím',
|
||||||
'Size of cache:': 'Velikost cache:',
|
'Plugin "%s" in application': 'Plugin "%s" in application',
|
||||||
'skip to generate': 'skip to generate',
|
'plugins': 'zásuvné moduly',
|
||||||
'Sorry, could not find mercurial installed': 'Bohu?el mercurial nen? nainstalov?n.',
|
'Plugins': 'Zásuvné moduly',
|
||||||
'Start a new app': 'Vytvo?it novou aplikaci',
|
'Plural Form #%s': 'Plural Form #%s',
|
||||||
'Start searching': 'Za??t hled?n?',
|
'Plural-Forms:': 'Množná čísla:',
|
||||||
'Start wizard': 'Spustit pr?vodce',
|
'Powered by': 'Poháněno',
|
||||||
'state': 'stav',
|
'Preface': 'Předmluva',
|
||||||
'static': 'statick? soubory',
|
'previous 100 rows': 'předchozích 100 řádků',
|
||||||
'Static files': 'Statick? soubory',
|
'Private files': 'Soukromé soubory',
|
||||||
'Statistics': 'Statistika',
|
'private files': 'soukromé soubory',
|
||||||
'Step': 'Step',
|
'profile': 'profil',
|
||||||
'Stylesheet': 'CSS styly',
|
'Project Progress': 'Vývoj projektu',
|
||||||
'submit': 'odeslat',
|
'Python': 'Python',
|
||||||
'Submit': 'Odeslat',
|
'Query:': 'Dotaz:',
|
||||||
'successful': '?sp??n?',
|
'Quick Examples': 'Krátké příklady',
|
||||||
'Support': 'Podpora',
|
'RAM': 'RAM',
|
||||||
'Sure you want to delete this object?': 'Opravdu chcete smazat tento objekt?',
|
'RAM Cache Keys': 'Klíče RAM Cache',
|
||||||
'Table': 'tabulka',
|
'Ram Cleared': 'RAM smazána',
|
||||||
'Table name': 'N?zev tabulky',
|
'Readme': 'Nápověda',
|
||||||
'Temporary': 'Do?asn?',
|
'Recipes': 'Postupy jak na to',
|
||||||
'test': 'test',
|
'Record': 'Záznam',
|
||||||
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Dotaz" je podm?nka, nap??klad "db.tabulka1.pole1==\'hodnota\'". Podm?nka "db.tabulka1.pole1==db.tabulka2.pole2" pak vytvo?? SQL JOIN.',
|
'record does not exist': 'záznam neexistuje',
|
||||||
'The application logic, each URL path is mapped in one exposed function in the controller': 'Logika aplikace: ka?d? URL je mapov?na na funkci vystavovanou kontrol?rem.',
|
'Record ID': 'ID záznamu',
|
||||||
'The Core': 'J?dro (The Core)',
|
'Record id': 'id záznamu',
|
||||||
'The data representation, define database tables and sets': 'Reprezentace dat: definovat tabulky datab?ze a z?znamy',
|
'refresh': 'obnovte',
|
||||||
'The output of the file is a dictionary that was rendered by the view %s': 'V?stup ze souboru je slovn?k, kter? se zobrazil v pohledu %s.',
|
'register': 'registrovat',
|
||||||
'The presentations layer, views are also known as templates': 'Prezenta?n? vrstva: pohledy ?i templaty (?ablony)',
|
'Register': 'Zaregistrovat se',
|
||||||
'The Views': 'Pohledy (The Views)',
|
'Registration identifier': 'Registrační identifikátor',
|
||||||
'There are no plugins': '??dn? moduly nejsou instalov?ny.',
|
'Registration key': 'Registrační klíč',
|
||||||
'There are no private files': '??dn? soukrom? soubory neexistuj?.',
|
'reload': 'reload',
|
||||||
'These files are not served, they are only available from within your app': 'Tyto soubory jsou klient?m nep??stupn?. K dispozici jsou pouze v r?mci aplikace.',
|
'Reload routes': 'Znovu nahrát cesty',
|
||||||
'These files are served without processing, your images go here': 'Tyto soubory jsou serv?rov?ny bez p??davn? logiky, sem pat?? nap?. obr?zky.',
|
'Remember me (for 30 days)': 'Zapamatovat na 30 dní',
|
||||||
'This App': 'Tato aplikace',
|
'Remove compiled': 'Odstranit zkompilované',
|
||||||
'This is a copy of the scaffolding application': 'Toto je kopie aplikace skelet.',
|
'Removed Breakpoint on %s at line %s': 'Bod přerušení smazán - soubor %s na řádce %s',
|
||||||
'this page to see if a breakpoint was hit and debug interaction is required.': 'tuto str?nku, abyste uvid?li, zda se dos?hlo bodu p?eru?en?.',
|
'Replace': 'Zaměnit',
|
||||||
'Ticket': 'Ticket',
|
'Replace All': 'Zaměnit vše',
|
||||||
'Time in Cache (h:m:s)': '?as v Cache (h:m:s)',
|
'request': 'request',
|
||||||
'Timestamp': '?asov? raz?tko',
|
'Reset Password key': 'Reset registračního klíče',
|
||||||
'to previous version.': 'k p?edchoz? verzi.',
|
'response': 'response',
|
||||||
'To create a plugin, name a file/folder plugin_[name]': 'Z?suvn? modul vytvo??te tak, ?e pojmenujete soubor/adres?? plugin_[jm?no modulu]',
|
'restart': 'restart',
|
||||||
'To emulate a breakpoint programatically, write:': 'K nastaven? bodu p?eru?en? v k?du programu, napi?te:',
|
'restore': 'obnovit',
|
||||||
'to use the debugger!': ', abyste mohli lad?c? program pou??vat!',
|
'Retrieve username': 'Získat přihlašovací jméno',
|
||||||
'toggle breakpoint': 'vyp./zap. bod p?eru?en?',
|
'return': 'return',
|
||||||
'Toggle Fullscreen': 'Na celou obrazovku a zp?t',
|
'revert': 'vrátit se k původnímu',
|
||||||
'too short': 'P??li? kr?tk?',
|
'Role': 'Role',
|
||||||
'Translation strings for the application': 'P?eklad text? pro aplikaci',
|
'Rows in Table': 'Záznamy v tabulce',
|
||||||
'Try the mobile interface': 'Zkuste rozhran? pro mobiln? za??zen?',
|
'Rows selected': 'Záznamů zobrazeno',
|
||||||
'Twitter': 'Twitter',
|
'rules are not defined': 'pravidla nejsou definována',
|
||||||
'unable to parse csv file': 'csv soubor ned? sa zpracovat',
|
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Spustí testy v tomto souboru (ke spuštění všech testů, použijte tlačítko 'test')",
|
||||||
'uncheck all': 'v?e odzna?it',
|
'Running on %s': 'Běží na %s',
|
||||||
'Uninstall': 'Odinstalovat',
|
'Save': 'Uložit',
|
||||||
'update': 'aktualizovat',
|
'Save file:': 'Save file:',
|
||||||
'update all languages': 'aktualizovat v?echny jazyky',
|
'Save via Ajax': 'Uložit pomocí Ajaxu',
|
||||||
'Update:': 'Upravit:',
|
'Saved file hash:': 'hash uloženého souboru:',
|
||||||
'upload': 'nahr?t',
|
'Semantic': 'Modul semantic',
|
||||||
'Upload a package:': 'Nahr?t bal?k:',
|
'Services': 'Služby',
|
||||||
'Upload and install packed application': 'Nahr?t a instalovat zabalenou aplikaci',
|
'session': 'session',
|
||||||
'upload file:': 'nahr?t soubor:',
|
'session expired': 'session expired',
|
||||||
'upload plugin file:': 'nahr?t soubor modulu:',
|
'Set Breakpoint on %s at line %s: %s': 'Bod přerušení nastaven v souboru %s na řádce %s: %s',
|
||||||
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Pou?ijte (...)&(...) pro AND, (...)|(...) pro OR a ~(...) pro NOT pro sestaven? slo?it?j??ch dotaz?.',
|
'shell': 'příkazová řádka',
|
||||||
'User %(id)s Logged-in': 'U?ivatel %(id)s p?ihl??en',
|
'Singular Form': 'Singular Form',
|
||||||
'User %(id)s Logged-out': 'U?ivatel %(id)s odhl??en',
|
'Site': 'Správa aplikací',
|
||||||
'User %(id)s Password changed': 'U?ivatel %(id)s zm?nil heslo',
|
'Size of cache:': 'Velikost cache:',
|
||||||
'User %(id)s Profile updated': 'U?ivatel %(id)s upravil profil',
|
'skip to generate': 'skip to generate',
|
||||||
'User %(id)s Registered': 'U?ivatel %(id)s se zaregistroval',
|
'Sorry, could not find mercurial installed': 'Bohužel mercurial není nainstalován.',
|
||||||
'User %(id)s Username retrieved': 'U?ivatel %(id)s si nachal zaslat p?ihla?ovac? jm?no',
|
'Start a new app': 'Vytvořit novou aplikaci',
|
||||||
'User ID': 'ID u?ivatele',
|
'Start searching': 'Začít hledání',
|
||||||
'Username': 'P?ihla?ovac? jm?no',
|
'Start wizard': 'Spustit průvodce',
|
||||||
'Verify Password': 'Zopakujte heslo',
|
'state': 'stav',
|
||||||
'Version %s.%s.%s (%s) %s': 'Verze %s.%s.%s (%s) %s',
|
'Static': 'Static',
|
||||||
'Versioning': 'Verzov?n?',
|
'static': 'statické soubory',
|
||||||
'Videos': 'Videa',
|
'Static files': 'Statické soubory',
|
||||||
'View': 'Pohled (View)',
|
'Statistics': 'Statistika',
|
||||||
'Views': 'Pohledy',
|
'Step': 'Step',
|
||||||
'views': 'pohledy',
|
'step': 'step',
|
||||||
'Web Framework': 'Web Framework',
|
'stop': 'stop',
|
||||||
'web2py is up to date': 'M?te aktu?ln? verzi web2py.',
|
'Stylesheet': 'CSS styly',
|
||||||
'web2py online debugger': 'Lad?c? online web2py program',
|
'submit': 'odeslat',
|
||||||
'web2py Recent Tweets': '?t?bet?n? na Twitteru o web2py',
|
'Submit': 'Odeslat',
|
||||||
'Welcome': 'V?tejte',
|
'successful': 'úspěšně',
|
||||||
'Welcome to web2py': 'Vitejte ve web2py',
|
'Support': 'Podpora',
|
||||||
'Welcome to web2py!': 'V?tejte ve web2py!',
|
'Sure you want to delete this object?': 'Opravdu chcete smazat tento objekt?',
|
||||||
'Which called the function %s located in the file %s': 'kter? zavolala funkci %s v souboru (kontrol?ru) %s.',
|
'Table': 'tabulka',
|
||||||
'You are successfully running web2py': '?sp??n? jste spustili web2py.',
|
'Table name': 'Název tabulky',
|
||||||
'You can also set and remove breakpoint in the edit window, using the Toggle Breakpoint button': 'Nastavovat a mazat body p?eru?en? je t?? mo?no v r?mci editov?n? zdrojov?ho souboru p?es tla??tko Vyp./Zap. bod p?eru?en?',
|
'Temporary': 'Dočasný',
|
||||||
'You can modify this application and adapt it to your needs': 'Tuto aplikaci si m??ete upravit a p?izp?sobit ji sv?m pot?eb?m.',
|
'test': 'test',
|
||||||
'You need to set up and reach a': 'Je t?eba nejprve nastavit a doj?t a? na',
|
'Testing application': 'Testing application',
|
||||||
'You visited the url %s': 'Nav?t?vili jste str?nku %s,',
|
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Dotaz" je podmínka, například "db.tabulka1.pole1==\'hodnota\'". Podmínka "db.tabulka1.pole1==db.tabulka2.pole2" pak vytvoří SQL JOIN.',
|
||||||
}
|
'The application logic, each URL path is mapped in one exposed function in the controller': 'Logika aplikace: každá URL je mapována na funkci vystavovanou kontrolérem.',
|
||||||
|
'The Core': 'Jádro (The Core)',
|
||||||
|
'The data representation, define database tables and sets': 'Reprezentace dat: definovat tabulky databáze a záznamy',
|
||||||
|
'The output of the file is a dictionary that was rendered by the view %s': 'Výstup ze souboru je slovník, který se zobrazil v pohledu %s.',
|
||||||
|
'The presentations layer, views are also known as templates': 'Prezentační vrstva: pohledy či templaty (šablony)',
|
||||||
|
'The Views': 'Pohledy (The Views)',
|
||||||
|
'There are no controllers': 'There are no controllers',
|
||||||
|
'There are no modules': 'There are no modules',
|
||||||
|
'There are no plugins': 'Žádné moduly nejsou instalovány.',
|
||||||
|
'There are no private files': 'Žádné soukromé soubory neexistují.',
|
||||||
|
'There are no static files': 'There are no static files',
|
||||||
|
'There are no translators, only default language is supported': 'There are no translators, only default language is supported',
|
||||||
|
'There are no views': 'There are no views',
|
||||||
|
'These files are not served, they are only available from within your app': 'Tyto soubory jsou klientům nepřístupné. K dispozici jsou pouze v rámci aplikace.',
|
||||||
|
'These files are served without processing, your images go here': 'Tyto soubory jsou servírovány bez přídavné logiky, sem patří např. obrázky.',
|
||||||
|
'This App': 'Tato aplikace',
|
||||||
|
'This is a copy of the scaffolding application': 'Toto je kopie aplikace skelet.',
|
||||||
|
'This is an experimental feature and it needs more testing. If you decide to upgrade you do it at your own risk': 'This is an experimental feature and it needs more testing. If you decide to upgrade you do it at your own risk',
|
||||||
|
'This is the %(filename)s template': 'This is the %(filename)s template',
|
||||||
|
'this page to see if a breakpoint was hit and debug interaction is required.': 'tuto stránku, abyste uviděli, zda se dosáhlo bodu přerušení.',
|
||||||
|
'Ticket': 'Ticket',
|
||||||
|
'Ticket ID': 'Ticket ID',
|
||||||
|
'Time in Cache (h:m:s)': 'Čas v Cache (h:m:s)',
|
||||||
|
'Timestamp': 'Časové razítko',
|
||||||
|
'to previous version.': 'k předchozí verzi.',
|
||||||
|
'To create a plugin, name a file/folder plugin_[name]': 'Zásuvný modul vytvoříte tak, že pojmenujete soubor/adresář plugin_[jméno modulu]',
|
||||||
|
'To emulate a breakpoint programatically, write:': 'K nastavení bodu přerušení v kódu programu, napište:',
|
||||||
|
'to use the debugger!': ', abyste mohli ladící program používat!',
|
||||||
|
'toggle breakpoint': 'vyp./zap. bod přerušení',
|
||||||
|
'Toggle Fullscreen': 'Na celou obrazovku a zpět',
|
||||||
|
'too short': 'Příliš krátké',
|
||||||
|
'Traceback': 'Traceback',
|
||||||
|
'Translation strings for the application': 'Překlad textů pro aplikaci',
|
||||||
|
'try something like': 'try something like',
|
||||||
|
'Try the mobile interface': 'Zkuste rozhraní pro mobilní zařízení',
|
||||||
|
'try view': 'try view',
|
||||||
|
'Twitter': 'Twitter',
|
||||||
|
'Type python statement in here and hit Return (Enter) to execute it.': 'Type python statement in here and hit Return (Enter) to execute it.',
|
||||||
|
'Type some Python code in here and hit Return (Enter) to execute it.': 'Type some Python code in here and hit Return (Enter) to execute it.',
|
||||||
|
'Unable to check for upgrades': 'Unable to check for upgrades',
|
||||||
|
'unable to parse csv file': 'csv soubor nedá sa zpracovat',
|
||||||
|
'uncheck all': 'vše odznačit',
|
||||||
|
'Uninstall': 'Odinstalovat',
|
||||||
|
'update': 'aktualizovat',
|
||||||
|
'update all languages': 'aktualizovat všechny jazyky',
|
||||||
|
'Update:': 'Upravit:',
|
||||||
|
'Upgrade': 'Upgrade',
|
||||||
|
'upgrade now': 'upgrade now',
|
||||||
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
|
'upload': 'nahrát',
|
||||||
|
'Upload': 'Upload',
|
||||||
|
'Upload a package:': 'Nahrát balík:',
|
||||||
|
'Upload and install packed application': 'Nahrát a instalovat zabalenou aplikaci',
|
||||||
|
'upload file:': 'nahrát soubor:',
|
||||||
|
'upload plugin file:': 'nahrát soubor modulu:',
|
||||||
|
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Použijte (...)&(...) pro AND, (...)|(...) pro OR a ~(...) pro NOT pro sestavení složitějších dotazů.',
|
||||||
|
'User %(id)s Logged-in': 'Uživatel %(id)s přihlášen',
|
||||||
|
'User %(id)s Logged-out': 'Uživatel %(id)s odhlášen',
|
||||||
|
'User %(id)s Password changed': 'Uživatel %(id)s změnil heslo',
|
||||||
|
'User %(id)s Profile updated': 'Uživatel %(id)s upravil profil',
|
||||||
|
'User %(id)s Registered': 'Uživatel %(id)s se zaregistroval',
|
||||||
|
'User %(id)s Username retrieved': 'Uživatel %(id)s si nachal zaslat přihlašovací jméno',
|
||||||
|
'User ID': 'ID uživatele',
|
||||||
|
'Username': 'Přihlašovací jméno',
|
||||||
|
'variables': 'variables',
|
||||||
|
'Verify Password': 'Zopakujte heslo',
|
||||||
|
'Version': 'Verze',
|
||||||
|
'Version %s.%s.%s (%s) %s': 'Verze %s.%s.%s (%s) %s',
|
||||||
|
'Versioning': 'Verzování',
|
||||||
|
'Videos': 'Videa',
|
||||||
|
'View': 'Pohled (View)',
|
||||||
|
'Views': 'Pohledy',
|
||||||
|
'views': 'pohledy',
|
||||||
|
'Web Framework': 'Web Framework',
|
||||||
|
'web2py is up to date': 'Máte aktuální verzi web2py.',
|
||||||
|
'web2py online debugger': 'Ladící online web2py program',
|
||||||
|
'web2py Recent Tweets': 'Štěbetání na Twitteru o web2py',
|
||||||
|
'web2py upgrade': 'web2py upgrade',
|
||||||
|
'web2py upgraded; please restart it': 'web2py upgraded; please restart it',
|
||||||
|
'Welcome': 'Vítejte',
|
||||||
|
'Welcome to web2py': 'Vitejte ve web2py',
|
||||||
|
'Welcome to web2py!': 'Vítejte ve web2py!',
|
||||||
|
'Which called the function %s located in the file %s': 'která zavolala funkci %s v souboru (kontroléru) %s.',
|
||||||
|
'You are successfully running web2py': 'Úspěšně jste spustili web2py.',
|
||||||
|
'You can also set and remove breakpoint in the edit window, using the Toggle Breakpoint button': 'Nastavovat a mazat body přerušení je též možno v rámci editování zdrojového souboru přes tlačítko Vyp./Zap. bod přerušení',
|
||||||
|
'You can modify this application and adapt it to your needs': 'Tuto aplikaci si můžete upravit a přizpůsobit ji svým potřebám.',
|
||||||
|
'You need to set up and reach a': 'Je třeba nejprve nastavit a dojít až na',
|
||||||
|
'You visited the url %s': 'Navštívili jste stránku %s,',
|
||||||
|
'Your application will be blocked until you click an action button (next, step, continue, etc.)': 'Aplikace bude blokována než se klikne na jedno z tlačítek (další, krok, pokračovat, atd.)',
|
||||||
|
'Your can inspect variables using the console bellow': 'Níže pomocí příkazové řádky si můžete prohlédnout proměnné',
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{{extend 'layout.html'}}
|
||||||
|
{{import os}}
|
||||||
|
|
||||||
|
{{def tree(path):}}
|
||||||
|
<input type="checkbox" onclick="jQuery(this).parent().find(':checkbox').attr('checked',this.checked)" checked="checked"/>
|
||||||
|
<a href="#" onclick="jQuery(this).next().slideToggle();return false;">
|
||||||
|
{{=path[len(base):] or '/%s' % app}}
|
||||||
|
</a>
|
||||||
|
<ul class="collapsible">
|
||||||
|
{{for file in files[path]['files']:}}
|
||||||
|
<li style="list-style-type: none;">
|
||||||
|
{{p = os.path.relpath(os.path.join(path,file),base)}}
|
||||||
|
<input type="checkbox" value="{{=p}}" name="file" checked="checked"/>
|
||||||
|
{{=file}}
|
||||||
|
</li>
|
||||||
|
{{pass}}
|
||||||
|
{{for dir in files[path]['folders']:}}
|
||||||
|
<li style="list-style-type: none;">
|
||||||
|
{{tree(os.path.join(path,dir))}}
|
||||||
|
</li>
|
||||||
|
{{pass}}
|
||||||
|
</ul>
|
||||||
|
{{return}}
|
||||||
|
|
||||||
|
<form action="{{=URL(args=request.args)}}" method="POST">
|
||||||
|
<h2>{{=T('Select Files to Package')}}</h2>
|
||||||
|
<input type="submit" value="{{=T('Download .w2p')}}" class="btn"/>
|
||||||
|
<div style="margin-top:20px">
|
||||||
|
{{tree(base)}}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<script>jQuery(function(){jQuery('.collapsible').hide();});</script>
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
{{buttons.append((URL('errors',args=a), T("Errors")))}}
|
{{buttons.append((URL('errors',args=a), T("Errors")))}}
|
||||||
{{buttons.append((URL('cleanup',args=a), T("Clean")))}}
|
{{buttons.append((URL('cleanup',args=a), T("Clean")))}}
|
||||||
{{buttons.append((URL('pack',args=a), T("Pack all")))}}
|
{{buttons.append((URL('pack',args=a), T("Pack all")))}}
|
||||||
|
{{buttons.append((URL('pack_custom',args=a), T("Pack custom")))}}
|
||||||
{{if not os.path.exists('applications/%s/compiled' % a):}}
|
{{if not os.path.exists('applications/%s/compiled' % a):}}
|
||||||
{{buttons.append((URL('compile_app',args=a), T("Compile")))}}
|
{{buttons.append((URL('compile_app',args=a), T("Compile")))}}
|
||||||
{{else:}}
|
{{else:}}
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ response.menu = [[T('design'), False, URL('admin', 'default', 'design',
|
|||||||
# ## auxiliary functions
|
# ## auxiliary functions
|
||||||
# ###########################################################
|
# ###########################################################
|
||||||
|
|
||||||
|
if False and request.tickets_db:
|
||||||
|
from gluon.restricted import TicketStorage
|
||||||
|
ts = TicketStorage()
|
||||||
|
ts._get_table(request.tickets_db, ts.tablename, request.application)
|
||||||
|
|
||||||
def get_databases(request):
|
def get_databases(request):
|
||||||
dbs = {}
|
dbs = {}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Here is a more complex complete application that lets the visitor upload images
|
|||||||
``
|
``
|
||||||
db=DAL('sqlite://storage.db')
|
db=DAL('sqlite://storage.db')
|
||||||
db.define_table('image',
|
db.define_table('image',
|
||||||
Field('name'),
|
Field('name', notnull=True),
|
||||||
Field('file','upload'))
|
Field('file','upload'))
|
||||||
``:code_python
|
``:code_python
|
||||||
|
|
||||||
@@ -55,10 +55,10 @@ db.define_table('image',
|
|||||||
|
|
||||||
``
|
``
|
||||||
def index():
|
def index():
|
||||||
form = SQLFORM(db.image)
|
form = SQLFORM(db.image).process()
|
||||||
if form.process().accepted:
|
if form.accepted:
|
||||||
response.flash = 'image uploaded'
|
response.flash = 'image uploaded'
|
||||||
return dict(form = form)""",counter=None,_class='boxCode')}}
|
return locals()
|
||||||
``:code_python
|
``:code_python
|
||||||
|
|
||||||
### In View
|
### In View
|
||||||
@@ -66,7 +66,7 @@ def index():
|
|||||||
``
|
``
|
||||||
{{extend 'layout.html'}}
|
{{extend 'layout.html'}}
|
||||||
<h1>Image upload form</h1>
|
<h1>Image upload form</h1>
|
||||||
{{form}}
|
{{=form}}
|
||||||
``:code_python
|
``:code_python
|
||||||
|
|
||||||
Uploaded images are safely renamed to avoid directory traversal vulnerabilities, stored on the filesystem (or database) and a corresponding entry is inserted in the database, linking the file. A built-in mechanism prevents involuntary double form submission. All DB IO is transaction safe by default. Any exception in the code causes the transaction to rollback.
|
Uploaded images are safely renamed to avoid directory traversal vulnerabilities, stored on the filesystem (or database) and a corresponding entry is inserted in the database, linking the file. A built-in mechanism prevents involuntary double form submission. All DB IO is transaction safe by default. Any exception in the code causes the transaction to rollback.
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ response.menu = [[T('design'), False, URL('admin', 'default', 'design',
|
|||||||
# ## auxiliary functions
|
# ## auxiliary functions
|
||||||
# ###########################################################
|
# ###########################################################
|
||||||
|
|
||||||
|
if False and request.tickets_db:
|
||||||
|
from gluon.restricted import TicketStorage
|
||||||
|
ts = TicketStorage()
|
||||||
|
ts._get_table(request.tickets_db, ts.tablename, request.application)
|
||||||
|
|
||||||
def get_databases(request):
|
def get_databases(request):
|
||||||
dbs = {}
|
dbs = {}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
'!langcode!': 'cs-cz',
|
'!langcode!': 'cs-cz',
|
||||||
'!langname!': 'čeština',
|
'!langname!': 'čeština',
|
||||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': 'Kolonka "Upravit" je nepovinný výraz, například "pole1=\'nováhodnota\'". Výsledky databázového JOINu nemůžete mazat ani upravovat.',
|
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': 'Kolonka "Upravit" je nepovinný výraz, například "pole1=\'nováhodnota\'". Výsledky databázového JOINu nemůžete mazat ani upravovat.',
|
||||||
|
'"User Exception" debug mode. An error ticket could be issued!': '"User Exception" debug mode. An error ticket could be issued!',
|
||||||
'%%{Row} in Table': '%%{řádek} v tabulce',
|
'%%{Row} in Table': '%%{řádek} v tabulce',
|
||||||
'%%{Row} selected': 'označených %%{řádek}',
|
'%%{Row} selected': 'označených %%{řádek}',
|
||||||
'%s %%{row} deleted': '%s smazaných %%{záznam}',
|
'%s %%{row} deleted': '%s smazaných %%{záznam}',
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
'%Y-%m-%d': '%d.%m.%Y',
|
'%Y-%m-%d': '%d.%m.%Y',
|
||||||
'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
|
'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
|
||||||
'(requires internet access)': '(vyžaduje připojení k internetu)',
|
'(requires internet access)': '(vyžaduje připojení k internetu)',
|
||||||
|
'(requires internet access, experimental)': '(requires internet access, experimental)',
|
||||||
'(something like "it-it")': '(například "cs-cs")',
|
'(something like "it-it")': '(například "cs-cs")',
|
||||||
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(soubor **gluon/contrib/plural_rules/%s.py** nenalezen)',
|
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(soubor **gluon/contrib/plural_rules/%s.py** nenalezen)',
|
||||||
'@markmin\x01Searching: **%s** %%{file}': 'Hledání: **%s** %%{soubor}',
|
'@markmin\x01Searching: **%s** %%{file}': 'Hledání: **%s** %%{soubor}',
|
||||||
@@ -19,15 +21,18 @@
|
|||||||
'Access Control': 'Řízení přístupu',
|
'Access Control': 'Řízení přístupu',
|
||||||
'Add breakpoint': 'Přidat bod přerušení',
|
'Add breakpoint': 'Přidat bod přerušení',
|
||||||
'Additional code for your application': 'Další kód pro Vaši aplikaci',
|
'Additional code for your application': 'Další kód pro Vaši aplikaci',
|
||||||
|
'Admin design page': 'Admin design page',
|
||||||
'Admin language': 'jazyk rozhraní',
|
'Admin language': 'jazyk rozhraní',
|
||||||
'Administrative interface': 'pro administrátorské rozhraní klikněte sem',
|
'Administrative interface': 'pro administrátorské rozhraní klikněte sem',
|
||||||
'Administrative Interface': 'Administrátorské rozhraní',
|
'Administrative Interface': 'Administrátorské rozhraní',
|
||||||
'administrative interface': 'rozhraní pro správu',
|
'administrative interface': 'rozhraní pro správu',
|
||||||
'Administrator Password:': 'Administrátorské heslo:',
|
'Administrator Password:': 'Administrátorské heslo:',
|
||||||
'Ajax Recipes': 'Recepty s ajaxem',
|
'Ajax Recipes': 'Recepty s ajaxem',
|
||||||
|
'An error occured, please %s the page': 'An error occured, please %s the page',
|
||||||
'and rename it:': 'a přejmenovat na:',
|
'and rename it:': 'a přejmenovat na:',
|
||||||
'appadmin': 'appadmin',
|
'appadmin': 'appadmin',
|
||||||
'appadmin is disabled because insecure channel': 'appadmin je zakázaná bez zabezpečeného spojení',
|
'appadmin is disabled because insecure channel': 'appadmin je zakázaná bez zabezpečeného spojení',
|
||||||
|
'Application': 'Application',
|
||||||
'application "%s" uninstalled': 'application "%s" odinstalována',
|
'application "%s" uninstalled': 'application "%s" odinstalována',
|
||||||
'application compiled': 'aplikace zkompilována',
|
'application compiled': 'aplikace zkompilována',
|
||||||
'Application name:': 'Název aplikace:',
|
'Application name:': 'Název aplikace:',
|
||||||
@@ -36,8 +41,13 @@
|
|||||||
'Are you sure you want to delete this object?': 'Opravdu chcete odstranit tento objekt?',
|
'Are you sure you want to delete this object?': 'Opravdu chcete odstranit tento objekt?',
|
||||||
'Are you sure you want to uninstall application "%s"?': 'Opravdu chcete odinstalovat aplikaci "%s"?',
|
'Are you sure you want to uninstall application "%s"?': 'Opravdu chcete odinstalovat aplikaci "%s"?',
|
||||||
'arguments': 'arguments',
|
'arguments': 'arguments',
|
||||||
|
'at char %s': 'at char %s',
|
||||||
|
'at line %s': 'at line %s',
|
||||||
|
'ATTENTION:': 'ATTENTION:',
|
||||||
|
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.',
|
||||||
'Available Databases and Tables': 'Dostupné databáze a tabulky',
|
'Available Databases and Tables': 'Dostupné databáze a tabulky',
|
||||||
'back': 'zpět',
|
'back': 'zpět',
|
||||||
|
'Back to wizard': 'Back to wizard',
|
||||||
'Basics': 'Basics',
|
'Basics': 'Basics',
|
||||||
'Begin': 'Začít',
|
'Begin': 'Začít',
|
||||||
'breakpoint': 'bod přerušení',
|
'breakpoint': 'bod přerušení',
|
||||||
@@ -51,7 +61,8 @@
|
|||||||
'can be a git repo': 'může to být git repo',
|
'can be a git repo': 'může to být git repo',
|
||||||
'Cancel': 'Storno',
|
'Cancel': 'Storno',
|
||||||
'Cannot be empty': 'Nemůže být prázdné',
|
'Cannot be empty': 'Nemůže být prázdné',
|
||||||
'Change admin password': 'Změnit heslo pro strávu aplikací',
|
'Change Admin Password': 'Změnit heslo pro správu',
|
||||||
|
'Change admin password': 'Změnit heslo pro správu aplikací',
|
||||||
'Change password': 'Změna hesla',
|
'Change password': 'Změna hesla',
|
||||||
'check all': 'vše označit',
|
'check all': 'vše označit',
|
||||||
'Check for upgrades': 'Zkusit aktualizovat',
|
'Check for upgrades': 'Zkusit aktualizovat',
|
||||||
@@ -94,6 +105,7 @@
|
|||||||
'data uploaded': 'data nahrána',
|
'data uploaded': 'data nahrána',
|
||||||
'Database': 'Rozhraní databáze',
|
'Database': 'Rozhraní databáze',
|
||||||
'Database %s select': 'databáze %s výběr',
|
'Database %s select': 'databáze %s výběr',
|
||||||
|
'Database administration': 'Database administration',
|
||||||
'database administration': 'správa databáze',
|
'database administration': 'správa databáze',
|
||||||
'Date and Time': 'Datum a čas',
|
'Date and Time': 'Datum a čas',
|
||||||
'day': 'den',
|
'day': 'den',
|
||||||
@@ -104,6 +116,7 @@
|
|||||||
'Delete': 'Smazat',
|
'Delete': 'Smazat',
|
||||||
'delete': 'smazat',
|
'delete': 'smazat',
|
||||||
'delete all checked': 'smazat vše označené',
|
'delete all checked': 'smazat vše označené',
|
||||||
|
'delete plugin': 'delete plugin',
|
||||||
'Delete this file (you will be asked to confirm deletion)': 'Smazat tento soubor (budete požádán o potvrzení mazání)',
|
'Delete this file (you will be asked to confirm deletion)': 'Smazat tento soubor (budete požádán o potvrzení mazání)',
|
||||||
'Delete:': 'Smazat:',
|
'Delete:': 'Smazat:',
|
||||||
'deleted after first hit': 'smazat po prvním dosažení',
|
'deleted after first hit': 'smazat po prvním dosažení',
|
||||||
@@ -114,9 +127,9 @@
|
|||||||
'Deployment Recipes': 'Postupy pro deployment',
|
'Deployment Recipes': 'Postupy pro deployment',
|
||||||
'Description': 'Popis',
|
'Description': 'Popis',
|
||||||
'design': 'návrh',
|
'design': 'návrh',
|
||||||
'Detailed traceback description': 'Detailed traceback description',
|
'Detailed traceback description': 'Podrobný výpis prostředí',
|
||||||
'details': 'details',
|
'details': 'podrobnosti',
|
||||||
'direction: ltr': 'direction: ltr',
|
'direction: ltr': 'směr: ltr',
|
||||||
'Disable': 'Zablokovat',
|
'Disable': 'Zablokovat',
|
||||||
'DISK': 'DISK',
|
'DISK': 'DISK',
|
||||||
'Disk Cache Keys': 'Klíče diskové cache',
|
'Disk Cache Keys': 'Klíče diskové cache',
|
||||||
@@ -132,29 +145,37 @@
|
|||||||
'Edit': 'Upravit',
|
'Edit': 'Upravit',
|
||||||
'edit all': 'edit all',
|
'edit all': 'edit all',
|
||||||
'Edit application': 'Správa aplikace',
|
'Edit application': 'Správa aplikace',
|
||||||
|
'edit controller': 'edit controller',
|
||||||
'Edit current record': 'Upravit aktuální záznam',
|
'Edit current record': 'Upravit aktuální záznam',
|
||||||
'Edit Profile': 'Upravit profil',
|
'Edit Profile': 'Upravit profil',
|
||||||
'edit views:': 'upravit pohled:',
|
'edit views:': 'upravit pohled:',
|
||||||
'Editing file "%s"': 'Úprava souboru "%s"',
|
'Editing file "%s"': 'Úprava souboru "%s"',
|
||||||
'Editing Language file': 'Úprava jazykového souboru',
|
'Editing Language file': 'Úprava jazykového souboru',
|
||||||
|
'Editing Plural Forms File': 'Editing Plural Forms File',
|
||||||
'Email and SMS': 'Email a SMS',
|
'Email and SMS': 'Email a SMS',
|
||||||
'Enable': 'Odblokovat',
|
'Enable': 'Odblokovat',
|
||||||
'enter a number between %(min)g and %(max)g': 'zadejte číslo mezi %(min)g a %(max)g',
|
'enter a number between %(min)g and %(max)g': 'zadejte číslo mezi %(min)g a %(max)g',
|
||||||
'enter an integer between %(min)g and %(max)g': 'zadejte celé číslo mezi %(min)g a %(max)g',
|
'enter an integer between %(min)g and %(max)g': 'zadejte celé číslo mezi %(min)g a %(max)g',
|
||||||
'Error': 'Chyba',
|
'Error': 'Chyba',
|
||||||
'Error logs for "%(app)s"': 'Seznam výskytu chyb pro aplikaci "%(app)s"',
|
'Error logs for "%(app)s"': 'Seznam výskytu chyb pro aplikaci "%(app)s"',
|
||||||
'Error snapshot': 'Error snapshot',
|
'Error snapshot': 'Snapshot chyby',
|
||||||
'Error ticket': 'Error ticket',
|
'Error ticket': 'Ticket chyby',
|
||||||
'Errors': 'Chyby',
|
'Errors': 'Chyby',
|
||||||
'Exception instance attributes': 'Exception instance attributes',
|
'Exception %(extype)s: %(exvalue)s': 'Exception %(extype)s: %(exvalue)s',
|
||||||
|
'Exception %s': 'Exception %s',
|
||||||
|
'Exception instance attributes': 'Prvky instance výjimky',
|
||||||
|
'Expand Abbreviation': 'Expand Abbreviation',
|
||||||
'export as csv file': 'exportovat do .csv souboru',
|
'export as csv file': 'exportovat do .csv souboru',
|
||||||
'exposes': 'vystavuje',
|
'exposes': 'vystavuje',
|
||||||
'exposes:': 'vystavuje funkce:',
|
'exposes:': 'vystavuje funkce:',
|
||||||
'extends': 'rozšiřuje',
|
'extends': 'rozšiřuje',
|
||||||
|
'failed to compile file because:': 'soubor se nepodařilo zkompilovat, protože:',
|
||||||
'FAQ': 'Často kladené dotazy',
|
'FAQ': 'Často kladené dotazy',
|
||||||
'File': 'Soubor',
|
'File': 'Soubor',
|
||||||
'file': 'soubor',
|
'file': 'soubor',
|
||||||
|
'file "%(filename)s" created': 'file "%(filename)s" created',
|
||||||
'file saved on %(time)s': 'soubor uložen %(time)s',
|
'file saved on %(time)s': 'soubor uložen %(time)s',
|
||||||
|
'file saved on %s': 'soubor uložen %s',
|
||||||
'Filename': 'Název souboru',
|
'Filename': 'Název souboru',
|
||||||
'filter': 'filtr',
|
'filter': 'filtr',
|
||||||
'Find Next': 'Najít další',
|
'Find Next': 'Najít další',
|
||||||
@@ -165,12 +186,15 @@
|
|||||||
'Forms and Validators': 'Formuláře a validátory',
|
'Forms and Validators': 'Formuláře a validátory',
|
||||||
'Frames': 'Frames',
|
'Frames': 'Frames',
|
||||||
'Free Applications': 'Aplikace zdarma',
|
'Free Applications': 'Aplikace zdarma',
|
||||||
|
'Functions with no doctests will result in [passed] tests.': 'Functions with no doctests will result in [passed] tests.',
|
||||||
'Generate': 'Vytvořit',
|
'Generate': 'Vytvořit',
|
||||||
'Get from URL:': 'Stáhnout z internetu:',
|
'Get from URL:': 'Stáhnout z internetu:',
|
||||||
'Git Pull': 'Git Pull',
|
'Git Pull': 'Git Pull',
|
||||||
'Git Push': 'Git Push',
|
'Git Push': 'Git Push',
|
||||||
'Globals##debug': 'Globální proměnné',
|
'Globals##debug': 'Globální proměnné',
|
||||||
'go!': 'OK!',
|
'go!': 'OK!',
|
||||||
|
'Goto': 'Goto',
|
||||||
|
'graph model': 'graph model',
|
||||||
'Group %(group_id)s created': 'Skupina %(group_id)s vytvořena',
|
'Group %(group_id)s created': 'Skupina %(group_id)s vytvořena',
|
||||||
'Group ID': 'ID skupiny',
|
'Group ID': 'ID skupiny',
|
||||||
'Groups': 'Skupiny',
|
'Groups': 'Skupiny',
|
||||||
@@ -181,6 +205,8 @@
|
|||||||
'Home': 'Domovská stránka',
|
'Home': 'Domovská stránka',
|
||||||
'honored only if the expression evaluates to true': 'brát v potaz jen když se tato podmínka vyhodnotí kladně',
|
'honored only if the expression evaluates to true': 'brát v potaz jen když se tato podmínka vyhodnotí kladně',
|
||||||
'How did you get here?': 'Jak jste se sem vlastně dostal?',
|
'How did you get here?': 'Jak jste se sem vlastně dostal?',
|
||||||
|
'If start the upgrade, be patient, it may take a while to download': 'If start the upgrade, be patient, it may take a while to download',
|
||||||
|
'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.',
|
||||||
'import': 'import',
|
'import': 'import',
|
||||||
'Import/Export': 'Import/Export',
|
'Import/Export': 'Import/Export',
|
||||||
'includes': 'zahrnuje',
|
'includes': 'zahrnuje',
|
||||||
@@ -190,8 +216,8 @@
|
|||||||
'inspect attributes': 'inspect attributes',
|
'inspect attributes': 'inspect attributes',
|
||||||
'Install': 'Instalovat',
|
'Install': 'Instalovat',
|
||||||
'Installed applications': 'Nainstalované aplikace',
|
'Installed applications': 'Nainstalované aplikace',
|
||||||
'Interaction at %s line %s': 'Interaction at %s line %s',
|
'Interaction at %s line %s': 'Interakce v %s, na řádce %s',
|
||||||
'Interactive console': 'Interactive console',
|
'Interactive console': 'Interaktivní příkazová řádka',
|
||||||
'Internal State': 'Vnitřní stav',
|
'Internal State': 'Vnitřní stav',
|
||||||
'Introduction': 'Úvod',
|
'Introduction': 'Úvod',
|
||||||
'Invalid email': 'Neplatný email',
|
'Invalid email': 'Neplatný email',
|
||||||
@@ -203,6 +229,7 @@
|
|||||||
'It is %s %%{day} today.': 'Dnes je to %s %%{den}.',
|
'It is %s %%{day} today.': 'Dnes je to %s %%{den}.',
|
||||||
'Key': 'Klíč',
|
'Key': 'Klíč',
|
||||||
'Key bindings': 'Vazby klíčů',
|
'Key bindings': 'Vazby klíčů',
|
||||||
|
'Key bindings for ZenCoding Plugin': 'Key bindings for ZenCoding Plugin',
|
||||||
'languages': 'jazyky',
|
'languages': 'jazyky',
|
||||||
'Languages': 'Jazyky',
|
'Languages': 'Jazyky',
|
||||||
'Last name': 'Příjmení',
|
'Last name': 'Příjmení',
|
||||||
@@ -227,6 +254,7 @@
|
|||||||
'Lost Password': 'Zapomněl jste heslo',
|
'Lost Password': 'Zapomněl jste heslo',
|
||||||
'Lost password?': 'Zapomněl jste heslo?',
|
'Lost password?': 'Zapomněl jste heslo?',
|
||||||
'lost password?': 'zapomněl jste heslo?',
|
'lost password?': 'zapomněl jste heslo?',
|
||||||
|
'Manage': 'Manage',
|
||||||
'Manage Cache': 'Manage Cache',
|
'Manage Cache': 'Manage Cache',
|
||||||
'Menu Model': 'Model rozbalovací nabídky',
|
'Menu Model': 'Model rozbalovací nabídky',
|
||||||
'Models': 'Modely',
|
'Models': 'Modely',
|
||||||
@@ -237,6 +265,7 @@
|
|||||||
'modules': 'moduly',
|
'modules': 'moduly',
|
||||||
'My Sites': 'Správa aplikací',
|
'My Sites': 'Správa aplikací',
|
||||||
'Name': 'Jméno',
|
'Name': 'Jméno',
|
||||||
|
'new application "%s" created': 'nová aplikace "%s" vytvořena',
|
||||||
'New Application Wizard': 'Nový průvodce aplikací',
|
'New Application Wizard': 'Nový průvodce aplikací',
|
||||||
'New application wizard': 'Nový průvodce aplikací',
|
'New application wizard': 'Nový průvodce aplikací',
|
||||||
'New password': 'Nové heslo',
|
'New password': 'Nové heslo',
|
||||||
@@ -245,13 +274,16 @@
|
|||||||
'New simple application': 'Vytvořit primitivní aplikaci',
|
'New simple application': 'Vytvořit primitivní aplikaci',
|
||||||
'next': 'next',
|
'next': 'next',
|
||||||
'next 100 rows': 'dalších 100 řádků',
|
'next 100 rows': 'dalších 100 řádků',
|
||||||
'No databases in this application': 'V této aplikáci nejsou žádné databáze',
|
'No databases in this application': 'V této aplikaci nejsou žádné databáze',
|
||||||
'No Interaction yet': 'Ještě žádná interakce nenastala',
|
'No Interaction yet': 'Ještě žádná interakce nenastala',
|
||||||
'No ticket_storage.txt found under /private folder': 'Soubor ticket_storage.txt v adresáři /private nenalezen',
|
'No ticket_storage.txt found under /private folder': 'Soubor ticket_storage.txt v adresáři /private nenalezen',
|
||||||
'Object or table name': 'Objekt či tabulka',
|
'Object or table name': 'Objekt či tabulka',
|
||||||
'Old password': 'Původní heslo',
|
'Old password': 'Původní heslo',
|
||||||
'online designer': 'online návrhář',
|
'online designer': 'online návrhář',
|
||||||
'Online examples': 'Příklady online',
|
'Online examples': 'Příklady online',
|
||||||
|
'Open new app in new window': 'Open new app in new window',
|
||||||
|
'or alternatively': 'or alternatively',
|
||||||
|
'Or Get from URL:': 'Or Get from URL:',
|
||||||
'or import from csv file': 'nebo importovat z .csv souboru',
|
'or import from csv file': 'nebo importovat z .csv souboru',
|
||||||
'Origin': 'Původ',
|
'Origin': 'Původ',
|
||||||
'Original/Translation': 'Originál/Překlad',
|
'Original/Translation': 'Originál/Překlad',
|
||||||
@@ -261,12 +293,16 @@
|
|||||||
'Overwrite installed app': 'Přepsat instalovanou aplikaci',
|
'Overwrite installed app': 'Přepsat instalovanou aplikaci',
|
||||||
'Pack all': 'Zabalit',
|
'Pack all': 'Zabalit',
|
||||||
'Pack compiled': 'Zabalit zkompilované',
|
'Pack compiled': 'Zabalit zkompilované',
|
||||||
|
'pack plugin': 'pack plugin',
|
||||||
'password': 'heslo',
|
'password': 'heslo',
|
||||||
'Password': 'Heslo',
|
'Password': 'Heslo',
|
||||||
"Password fields don't match": 'Hesla se neshodují',
|
"Password fields don't match": 'Hesla se neshodují',
|
||||||
|
'Peeking at file': 'Peeking at file',
|
||||||
'Please': 'Prosím',
|
'Please': 'Prosím',
|
||||||
|
'Plugin "%s" in application': 'Plugin "%s" in application',
|
||||||
'plugins': 'zásuvné moduly',
|
'plugins': 'zásuvné moduly',
|
||||||
'Plugins': 'Zásuvné moduly',
|
'Plugins': 'Zásuvné moduly',
|
||||||
|
'Plural Form #%s': 'Plural Form #%s',
|
||||||
'Plural-Forms:': 'Množná čísla:',
|
'Plural-Forms:': 'Množná čísla:',
|
||||||
'Powered by': 'Poháněno',
|
'Powered by': 'Poháněno',
|
||||||
'Preface': 'Předmluva',
|
'Preface': 'Předmluva',
|
||||||
@@ -292,6 +328,7 @@
|
|||||||
'Register': 'Zaregistrovat se',
|
'Register': 'Zaregistrovat se',
|
||||||
'Registration identifier': 'Registrační identifikátor',
|
'Registration identifier': 'Registrační identifikátor',
|
||||||
'Registration key': 'Registrační klíč',
|
'Registration key': 'Registrační klíč',
|
||||||
|
'reload': 'reload',
|
||||||
'Reload routes': 'Znovu nahrát cesty',
|
'Reload routes': 'Znovu nahrát cesty',
|
||||||
'Remember me (for 30 days)': 'Zapamatovat na 30 dní',
|
'Remember me (for 30 days)': 'Zapamatovat na 30 dní',
|
||||||
'Remove compiled': 'Odstranit zkompilované',
|
'Remove compiled': 'Odstranit zkompilované',
|
||||||
@@ -313,6 +350,7 @@
|
|||||||
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Spustí testy v tomto souboru (ke spuštění všech testů, použijte tlačítko 'test')",
|
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Spustí testy v tomto souboru (ke spuštění všech testů, použijte tlačítko 'test')",
|
||||||
'Running on %s': 'Běží na %s',
|
'Running on %s': 'Běží na %s',
|
||||||
'Save': 'Uložit',
|
'Save': 'Uložit',
|
||||||
|
'Save file:': 'Save file:',
|
||||||
'Save via Ajax': 'Uložit pomocí Ajaxu',
|
'Save via Ajax': 'Uložit pomocí Ajaxu',
|
||||||
'Saved file hash:': 'hash uloženého souboru:',
|
'Saved file hash:': 'hash uloženého souboru:',
|
||||||
'Semantic': 'Modul semantic',
|
'Semantic': 'Modul semantic',
|
||||||
@@ -321,6 +359,7 @@
|
|||||||
'session expired': 'session expired',
|
'session expired': 'session expired',
|
||||||
'Set Breakpoint on %s at line %s: %s': 'Bod přerušení nastaven v souboru %s na řádce %s: %s',
|
'Set Breakpoint on %s at line %s: %s': 'Bod přerušení nastaven v souboru %s na řádce %s: %s',
|
||||||
'shell': 'příkazová řádka',
|
'shell': 'příkazová řádka',
|
||||||
|
'Singular Form': 'Singular Form',
|
||||||
'Site': 'Správa aplikací',
|
'Site': 'Správa aplikací',
|
||||||
'Size of cache:': 'Velikost cache:',
|
'Size of cache:': 'Velikost cache:',
|
||||||
'skip to generate': 'skip to generate',
|
'skip to generate': 'skip to generate',
|
||||||
@@ -329,6 +368,7 @@
|
|||||||
'Start searching': 'Začít hledání',
|
'Start searching': 'Začít hledání',
|
||||||
'Start wizard': 'Spustit průvodce',
|
'Start wizard': 'Spustit průvodce',
|
||||||
'state': 'stav',
|
'state': 'stav',
|
||||||
|
'Static': 'Static',
|
||||||
'static': 'statické soubory',
|
'static': 'statické soubory',
|
||||||
'Static files': 'Statické soubory',
|
'Static files': 'Statické soubory',
|
||||||
'Statistics': 'Statistika',
|
'Statistics': 'Statistika',
|
||||||
@@ -345,6 +385,7 @@
|
|||||||
'Table name': 'Název tabulky',
|
'Table name': 'Název tabulky',
|
||||||
'Temporary': 'Dočasný',
|
'Temporary': 'Dočasný',
|
||||||
'test': 'test',
|
'test': 'test',
|
||||||
|
'Testing application': 'Testing application',
|
||||||
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Dotaz" je podmínka, například "db.tabulka1.pole1==\'hodnota\'". Podmínka "db.tabulka1.pole1==db.tabulka2.pole2" pak vytvoří SQL JOIN.',
|
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Dotaz" je podmínka, například "db.tabulka1.pole1==\'hodnota\'". Podmínka "db.tabulka1.pole1==db.tabulka2.pole2" pak vytvoří SQL JOIN.',
|
||||||
'The application logic, each URL path is mapped in one exposed function in the controller': 'Logika aplikace: každá URL je mapována na funkci vystavovanou kontrolérem.',
|
'The application logic, each URL path is mapped in one exposed function in the controller': 'Logika aplikace: každá URL je mapována na funkci vystavovanou kontrolérem.',
|
||||||
'The Core': 'Jádro (The Core)',
|
'The Core': 'Jádro (The Core)',
|
||||||
@@ -352,13 +393,19 @@
|
|||||||
'The output of the file is a dictionary that was rendered by the view %s': 'Výstup ze souboru je slovník, který se zobrazil v pohledu %s.',
|
'The output of the file is a dictionary that was rendered by the view %s': 'Výstup ze souboru je slovník, který se zobrazil v pohledu %s.',
|
||||||
'The presentations layer, views are also known as templates': 'Prezentační vrstva: pohledy či templaty (šablony)',
|
'The presentations layer, views are also known as templates': 'Prezentační vrstva: pohledy či templaty (šablony)',
|
||||||
'The Views': 'Pohledy (The Views)',
|
'The Views': 'Pohledy (The Views)',
|
||||||
|
'There are no controllers': 'There are no controllers',
|
||||||
|
'There are no modules': 'There are no modules',
|
||||||
'There are no plugins': 'Žádné moduly nejsou instalovány.',
|
'There are no plugins': 'Žádné moduly nejsou instalovány.',
|
||||||
'There are no private files': 'Žádné soukromé soubory neexistují.',
|
'There are no private files': 'Žádné soukromé soubory neexistují.',
|
||||||
'There are no static files': 'There are no static files',
|
'There are no static files': 'There are no static files',
|
||||||
|
'There are no translators, only default language is supported': 'There are no translators, only default language is supported',
|
||||||
|
'There are no views': 'There are no views',
|
||||||
'These files are not served, they are only available from within your app': 'Tyto soubory jsou klientům nepřístupné. K dispozici jsou pouze v rámci aplikace.',
|
'These files are not served, they are only available from within your app': 'Tyto soubory jsou klientům nepřístupné. K dispozici jsou pouze v rámci aplikace.',
|
||||||
'These files are served without processing, your images go here': 'Tyto soubory jsou servírovány bez přídavné logiky, sem patří např. obrázky.',
|
'These files are served without processing, your images go here': 'Tyto soubory jsou servírovány bez přídavné logiky, sem patří např. obrázky.',
|
||||||
'This App': 'Tato aplikace',
|
'This App': 'Tato aplikace',
|
||||||
'This is a copy of the scaffolding application': 'Toto je kopie aplikace skelet.',
|
'This is a copy of the scaffolding application': 'Toto je kopie aplikace skelet.',
|
||||||
|
'This is an experimental feature and it needs more testing. If you decide to upgrade you do it at your own risk': 'This is an experimental feature and it needs more testing. If you decide to upgrade you do it at your own risk',
|
||||||
|
'This is the %(filename)s template': 'This is the %(filename)s template',
|
||||||
'this page to see if a breakpoint was hit and debug interaction is required.': 'tuto stránku, abyste uviděli, zda se dosáhlo bodu přerušení.',
|
'this page to see if a breakpoint was hit and debug interaction is required.': 'tuto stránku, abyste uviděli, zda se dosáhlo bodu přerušení.',
|
||||||
'Ticket': 'Ticket',
|
'Ticket': 'Ticket',
|
||||||
'Ticket ID': 'Ticket ID',
|
'Ticket ID': 'Ticket ID',
|
||||||
@@ -373,16 +420,24 @@
|
|||||||
'too short': 'Příliš krátké',
|
'too short': 'Příliš krátké',
|
||||||
'Traceback': 'Traceback',
|
'Traceback': 'Traceback',
|
||||||
'Translation strings for the application': 'Překlad textů pro aplikaci',
|
'Translation strings for the application': 'Překlad textů pro aplikaci',
|
||||||
|
'try something like': 'try something like',
|
||||||
'Try the mobile interface': 'Zkuste rozhraní pro mobilní zařízení',
|
'Try the mobile interface': 'Zkuste rozhraní pro mobilní zařízení',
|
||||||
|
'try view': 'try view',
|
||||||
'Twitter': 'Twitter',
|
'Twitter': 'Twitter',
|
||||||
'Type python statement in here and hit Return (Enter) to execute it.': 'Type python statement in here and hit Return (Enter) to execute it.',
|
'Type python statement in here and hit Return (Enter) to execute it.': 'Type python statement in here and hit Return (Enter) to execute it.',
|
||||||
|
'Type some Python code in here and hit Return (Enter) to execute it.': 'Type some Python code in here and hit Return (Enter) to execute it.',
|
||||||
|
'Unable to check for upgrades': 'Unable to check for upgrades',
|
||||||
'unable to parse csv file': 'csv soubor nedá sa zpracovat',
|
'unable to parse csv file': 'csv soubor nedá sa zpracovat',
|
||||||
'uncheck all': 'vše odznačit',
|
'uncheck all': 'vše odznačit',
|
||||||
'Uninstall': 'Odinstalovat',
|
'Uninstall': 'Odinstalovat',
|
||||||
'update': 'aktualizovat',
|
'update': 'aktualizovat',
|
||||||
'update all languages': 'aktualizovat všechny jazyky',
|
'update all languages': 'aktualizovat všechny jazyky',
|
||||||
'Update:': 'Upravit:',
|
'Update:': 'Upravit:',
|
||||||
|
'Upgrade': 'Upgrade',
|
||||||
|
'upgrade now': 'upgrade now',
|
||||||
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
'upload': 'nahrát',
|
'upload': 'nahrát',
|
||||||
|
'Upload': 'Upload',
|
||||||
'Upload a package:': 'Nahrát balík:',
|
'Upload a package:': 'Nahrát balík:',
|
||||||
'Upload and install packed application': 'Nahrát a instalovat zabalenou aplikaci',
|
'Upload and install packed application': 'Nahrát a instalovat zabalenou aplikaci',
|
||||||
'upload file:': 'nahrát soubor:',
|
'upload file:': 'nahrát soubor:',
|
||||||
@@ -409,6 +464,8 @@
|
|||||||
'web2py is up to date': 'Máte aktuální verzi web2py.',
|
'web2py is up to date': 'Máte aktuální verzi web2py.',
|
||||||
'web2py online debugger': 'Ladící online web2py program',
|
'web2py online debugger': 'Ladící online web2py program',
|
||||||
'web2py Recent Tweets': 'Štěbetání na Twitteru o web2py',
|
'web2py Recent Tweets': 'Štěbetání na Twitteru o web2py',
|
||||||
|
'web2py upgrade': 'web2py upgrade',
|
||||||
|
'web2py upgraded; please restart it': 'web2py upgraded; please restart it',
|
||||||
'Welcome': 'Vítejte',
|
'Welcome': 'Vítejte',
|
||||||
'Welcome to web2py': 'Vitejte ve web2py',
|
'Welcome to web2py': 'Vitejte ve web2py',
|
||||||
'Welcome to web2py!': 'Vítejte ve web2py!',
|
'Welcome to web2py!': 'Vítejte ve web2py!',
|
||||||
|
|||||||
@@ -8,23 +8,23 @@
|
|||||||
'%s selected': '%s seleccionado(s)',
|
'%s selected': '%s seleccionado(s)',
|
||||||
'%Y-%m-%d': '%Y-%m-%d',
|
'%Y-%m-%d': '%Y-%m-%d',
|
||||||
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
|
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
|
||||||
'(something like "it-it")': '(algo como "it-it")',
|
'(something like "it-it")': '(algo como "eso-eso")',
|
||||||
'A new version of web2py is available': 'Hay una nueva versión de web2py disponible',
|
'A new version of web2py is available': 'Hay una nueva versión de web2py disponible',
|
||||||
'A new version of web2py is available: %s': 'Hay una nueva versión de web2py disponible: %s',
|
'A new version of web2py is available: %s': 'Hay una nueva versión de web2py disponible: %s',
|
||||||
'about': 'acerca de',
|
'about': 'acerca de',
|
||||||
'About': 'Acerca de',
|
'About': 'Acerca de',
|
||||||
'About application': 'Acerca de la aplicación',
|
'About application': 'Acerca de la aplicación',
|
||||||
'Access Control': 'Access Control',
|
'Access Control': 'Control de Acceso',
|
||||||
'additional code for your application': 'código adicional para su aplicación',
|
'additional code for your application': 'código adicional para su aplicación',
|
||||||
'admin disabled because no admin password': ' por falta de contraseña',
|
'admin disabled because no admin password': ' por falta de contraseña',
|
||||||
'admin disabled because not supported on google app engine': 'admin deshabilitado, no es soportado en GAE',
|
'admin disabled because not supported on google app engine': 'admin deshabilitado, no es soportado en GAE',
|
||||||
'admin disabled because unable to access password file': 'admin deshabilitado, imposible acceder al archivo con la contraseña',
|
'admin disabled because unable to access password file': 'admin deshabilitado, imposible acceder al archivo con la contraseña',
|
||||||
'Admin is disabled because insecure channel': 'Admin deshabilitado, el canal no es seguro',
|
'Admin is disabled because insecure channel': 'Admin deshabilitado, el canal no es seguro',
|
||||||
'Admin is disabled because unsecure channel': 'Admin deshabilitado, el canal no es seguro',
|
'Admin is disabled because unsecure channel': 'Admin deshabilitado, el canal no es seguro',
|
||||||
'Administrative Interface': 'Administrative Interface',
|
'Administrative Interface': 'Interfaz Administrativa',
|
||||||
'Administrative interface': 'Interfaz administrativa',
|
'Administrative interface': 'Interfaz administrativa',
|
||||||
'Administrator Password:': 'Contraseña del Administrador:',
|
'Administrator Password:': 'Contraseña del Administrador:',
|
||||||
'Ajax Recipes': 'Ajax Recipes',
|
'Ajax Recipes': 'Recetas AJAX',
|
||||||
'and rename it (required):': 'y renombrela (requerido):',
|
'and rename it (required):': 'y renombrela (requerido):',
|
||||||
'and rename it:': ' y renombrelo:',
|
'and rename it:': ' y renombrelo:',
|
||||||
'appadmin': 'appadmin',
|
'appadmin': 'appadmin',
|
||||||
@@ -33,37 +33,37 @@
|
|||||||
'application compiled': 'aplicación compilada',
|
'application compiled': 'aplicación compilada',
|
||||||
'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada',
|
'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada',
|
||||||
'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?',
|
'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?',
|
||||||
'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?',
|
'Are you sure you want to delete this object?': '¿Está seguro que desea borrar este objeto?',
|
||||||
'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"',
|
'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"',
|
||||||
'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?',
|
'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?',
|
||||||
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENCION: Inicio de sesión requiere una conexión segura (HTTPS) o localhost.',
|
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ATENCION: Inicio de sesión requiere una conexión segura (HTTPS) o localhost.',
|
||||||
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.',
|
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.',
|
||||||
'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que se ejecuta!',
|
'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que está ejecutandose!',
|
||||||
'Authentication': 'Autenticación',
|
'Authentication': 'Autenticación',
|
||||||
'Available Databases and Tables': 'Bases de datos y tablas disponibles',
|
'Available Databases and Tables': 'Bases de datos y tablas disponibles',
|
||||||
'Buy this book': 'Buy this book',
|
'Buy this book': 'Compra este libro',
|
||||||
'cache': 'cache',
|
'cache': 'cache',
|
||||||
'Cache': 'Cache',
|
'Cache': 'Cache',
|
||||||
'Cache Keys': 'Cache Keys',
|
'Cache Keys': 'Llaves de la Cache',
|
||||||
'cache, errors and sessions cleaned': 'cache, errores y sesiones eliminados',
|
'cache, errors and sessions cleaned': 'cache, errores y sesiones eliminados',
|
||||||
'Cannot be empty': 'No puede estar vacío',
|
'Cannot be empty': 'No puede estar vacío',
|
||||||
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.',
|
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.',
|
||||||
'cannot create file': 'no es posible crear archivo',
|
'cannot create file': 'no es posible crear archivo',
|
||||||
'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"',
|
'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"',
|
||||||
'Change Password': 'Cambie Contraseña',
|
'Change Password': 'Cambie la contraseña',
|
||||||
'change password': 'cambie contraseña',
|
'change password': 'cambie la contraseña',
|
||||||
'check all': 'marcar todos',
|
'check all': 'marcar todos',
|
||||||
'Check to delete': 'Marque para eliminar',
|
'Check to delete': 'Marque para eliminar',
|
||||||
'clean': 'limpiar',
|
'clean': 'limpiar',
|
||||||
'Clear CACHE?': 'Clear CACHE?',
|
'Clear CACHE?': '¿Limpiar CACHE?',
|
||||||
'Clear DISK': 'Clear DISK',
|
'Clear DISK': '¿Limpiar DISCO',
|
||||||
'Clear RAM': 'Clear RAM',
|
'Clear RAM': '¿Limpiar RAM',
|
||||||
'click to check for upgrades': 'haga clic para buscar actualizaciones',
|
'click to check for upgrades': 'haga clic para buscar actualizaciones',
|
||||||
'Client IP': 'IP del Cliente',
|
'Client IP': 'IP del Cliente',
|
||||||
'Community': 'Community',
|
'Community': 'Comunidad',
|
||||||
'compile': 'compilar',
|
'compile': 'compilar',
|
||||||
'compiled application removed': 'aplicación compilada removida',
|
'compiled application removed': 'aplicación compilada removida',
|
||||||
'Components and Plugins': 'Components and Plugins',
|
'Components and Plugins': 'Componentes y Plugins',
|
||||||
'Controller': 'Controlador',
|
'Controller': 'Controlador',
|
||||||
'Controllers': 'Controladores',
|
'Controllers': 'Controladores',
|
||||||
'controllers': 'controladores',
|
'controllers': 'controladores',
|
||||||
@@ -83,24 +83,24 @@
|
|||||||
'database administration': 'administración base de datos',
|
'database administration': 'administración base de datos',
|
||||||
'Date and Time': 'Fecha y Hora',
|
'Date and Time': 'Fecha y Hora',
|
||||||
'db': 'db',
|
'db': 'db',
|
||||||
'DB Model': 'Modelo "db"',
|
'DB Model': 'Modelo "DB"',
|
||||||
'defines tables': 'define tablas',
|
'defines tables': 'define tablas',
|
||||||
'Delete': 'Elimine',
|
'Delete': 'Eliminar',
|
||||||
'delete': 'eliminar',
|
'delete': 'eliminar',
|
||||||
'delete all checked': 'eliminar marcados',
|
'delete all checked': 'eliminar marcados',
|
||||||
'Delete:': 'Elimine:',
|
'Delete:': 'Eliminar:',
|
||||||
'Demo': 'Demo',
|
'Demo': 'Demo',
|
||||||
'Deploy on Google App Engine': 'Instale en Google App Engine',
|
'Deploy on Google App Engine': 'Despliegue en Google App Engine',
|
||||||
'Deployment Recipes': 'Deployment Recipes',
|
'Deployment Recipes': 'Recetas de despliegue',
|
||||||
'Description': 'Descripción',
|
'Description': 'Descripción',
|
||||||
'DESIGN': 'DISEÑO',
|
'DESIGN': 'DISEÑO',
|
||||||
'design': 'modificar',
|
'design': 'modificar',
|
||||||
'Design for': 'Diseño para',
|
'Design for': 'Diseño por',
|
||||||
'DISK': 'DISK',
|
'DISK': 'DISK',
|
||||||
'Disk Cache Keys': 'Disk Cache Keys',
|
'Disk Cache Keys': 'Llaves de Cache en Disco',
|
||||||
'Disk Cleared': 'Disk Cleared',
|
'Disk Cleared': 'Disco limpiado',
|
||||||
'Documentation': 'Documentación',
|
'Documentation': 'Documentación',
|
||||||
"Don't know what to do?": "Don't know what to do?",
|
"Don't know what to do?": "¿No sabe que hacer?",
|
||||||
'done!': 'listo!',
|
'done!': 'listo!',
|
||||||
'Download': 'Download',
|
'Download': 'Download',
|
||||||
'E-mail': 'Correo electrónico',
|
'E-mail': 'Correo electrónico',
|
||||||
@@ -115,9 +115,9 @@
|
|||||||
'Edit This App': 'Edite esta App',
|
'Edit This App': 'Edite esta App',
|
||||||
'Editing file': 'Editando archivo',
|
'Editing file': 'Editando archivo',
|
||||||
'Editing file "%s"': 'Editando archivo "%s"',
|
'Editing file "%s"': 'Editando archivo "%s"',
|
||||||
'Email and SMS': 'Email and SMS',
|
'Email and SMS': 'Correo electrónico y SMS',
|
||||||
'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"',
|
'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"',
|
||||||
'Errors': 'Errors',
|
'Errors': 'Errores',
|
||||||
'errors': 'errores',
|
'errors': 'errores',
|
||||||
'export as csv file': 'exportar como archivo CSV',
|
'export as csv file': 'exportar como archivo CSV',
|
||||||
'exposes': 'expone',
|
'exposes': 'expone',
|
||||||
@@ -134,17 +134,17 @@
|
|||||||
'file saved on %(time)s': 'archivo guardado %(time)s',
|
'file saved on %(time)s': 'archivo guardado %(time)s',
|
||||||
'file saved on %s': 'archivo guardado %s',
|
'file saved on %s': 'archivo guardado %s',
|
||||||
'First name': 'Nombre',
|
'First name': 'Nombre',
|
||||||
'Forms and Validators': 'Forms and Validators',
|
'Forms and Validators': 'Formularios y validadores',
|
||||||
'Free Applications': 'Free Applications',
|
'Free Applications': 'Aplicaciones Libres',
|
||||||
'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].',
|
'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].',
|
||||||
'Group ID': 'ID de Grupo',
|
'Group ID': 'ID de Grupo',
|
||||||
'Groups': 'Groups',
|
'Groups': 'Groupos',
|
||||||
'Hello World': 'Hola Mundo',
|
'Hello World': 'Hola Mundo',
|
||||||
'help': 'ayuda',
|
'help': 'ayuda',
|
||||||
'Home': 'Home',
|
'Home': 'Home',
|
||||||
'How did you get here?': 'How did you get here?',
|
'How did you get here?': '¿Cómo llegasta hasta allá?',
|
||||||
'htmledit': 'htmledit',
|
'htmledit': 'htmledit',
|
||||||
'import': 'import',
|
'import': 'importar',
|
||||||
'Import/Export': 'Importar/Exportar',
|
'Import/Export': 'Importar/Exportar',
|
||||||
'includes': 'incluye',
|
'includes': 'incluye',
|
||||||
'Index': 'Indice',
|
'Index': 'Indice',
|
||||||
@@ -153,14 +153,14 @@
|
|||||||
'Installed applications': 'Aplicaciones instaladas',
|
'Installed applications': 'Aplicaciones instaladas',
|
||||||
'internal error': 'error interno',
|
'internal error': 'error interno',
|
||||||
'Internal State': 'Estado Interno',
|
'Internal State': 'Estado Interno',
|
||||||
'Introduction': 'Introduction',
|
'Introduction': 'Introducción',
|
||||||
'Invalid action': 'Acción inválida',
|
'Invalid action': 'Acción inválida',
|
||||||
'Invalid email': 'Correo inválido',
|
'Invalid email': 'Correo electrónico inválido',
|
||||||
'invalid password': 'contraseña inválida',
|
'invalid password': 'contraseña inválida',
|
||||||
'Invalid Query': 'Consulta inválida',
|
'Invalid Query': 'Consulta inválida',
|
||||||
'invalid request': 'solicitud inválida',
|
'invalid request': 'solicitud inválida',
|
||||||
'invalid ticket': 'tiquete inválido',
|
'invalid ticket': 'tiquete inválido',
|
||||||
'Key': 'Key',
|
'Key': 'Llave',
|
||||||
'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado',
|
'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado',
|
||||||
'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados',
|
'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados',
|
||||||
'languages': 'lenguajes',
|
'languages': 'lenguajes',
|
||||||
@@ -169,10 +169,10 @@
|
|||||||
'Last name': 'Apellido',
|
'Last name': 'Apellido',
|
||||||
'Last saved on:': 'Guardado en:',
|
'Last saved on:': 'Guardado en:',
|
||||||
'Layout': 'Diseño de página',
|
'Layout': 'Diseño de página',
|
||||||
'Layout Plugins': 'Layout Plugins',
|
'Layout Plugins': 'Plugins de diseño',
|
||||||
'Layouts': 'Layouts',
|
'Layouts': 'Diseños de páginas',
|
||||||
'License for': 'Licencia para',
|
'License for': 'Licencia para',
|
||||||
'Live Chat': 'Live Chat',
|
'Live Chat': 'Chat en vivo',
|
||||||
'loading...': 'cargando...',
|
'loading...': 'cargando...',
|
||||||
'login': 'inicio de sesión',
|
'login': 'inicio de sesión',
|
||||||
'Login': 'Inicio de sesión',
|
'Login': 'Inicio de sesión',
|
||||||
@@ -180,16 +180,16 @@
|
|||||||
'logout': 'fin de sesión',
|
'logout': 'fin de sesión',
|
||||||
'Logout': 'Fin de sesión',
|
'Logout': 'Fin de sesión',
|
||||||
'Lost Password': 'Contraseña perdida',
|
'Lost Password': 'Contraseña perdida',
|
||||||
'lost password?': '¿olvido la contraseña?',
|
'lost password?': '¿Olvido la contraseña?',
|
||||||
'Main Menu': 'Menú principal',
|
'Main Menu': 'Menú principal',
|
||||||
'Manage Cache': 'Manage Cache',
|
'Manage Cache': 'Manejar la Cache',
|
||||||
'Menu Model': 'Modelo "menu"',
|
'Menu Model': 'Modelo "menu"',
|
||||||
'merge': 'combinar',
|
'merge': 'combinar',
|
||||||
'Models': 'Modelos',
|
'Models': 'Modelos',
|
||||||
'models': 'modelos',
|
'models': 'modelos',
|
||||||
'Modules': 'Módulos',
|
'Modules': 'Módulos',
|
||||||
'modules': 'módulos',
|
'modules': 'módulos',
|
||||||
'My Sites': 'My Sites',
|
'My Sites': 'Mis Sitios',
|
||||||
'Name': 'Nombre',
|
'Name': 'Nombre',
|
||||||
'new application "%s" created': 'nueva aplicación "%s" creada',
|
'new application "%s" created': 'nueva aplicación "%s" creada',
|
||||||
'New Record': 'Registro nuevo',
|
'New Record': 'Registro nuevo',
|
||||||
@@ -202,9 +202,9 @@
|
|||||||
'or provide application url:': 'o provea URL de la aplicación:',
|
'or provide application url:': 'o provea URL de la aplicación:',
|
||||||
'Origin': 'Origen',
|
'Origin': 'Origen',
|
||||||
'Original/Translation': 'Original/Traducción',
|
'Original/Translation': 'Original/Traducción',
|
||||||
'Other Plugins': 'Other Plugins',
|
'Other Plugins': 'Otros Plugins',
|
||||||
'Other Recipes': 'Other Recipes',
|
'Other Recipes': 'Otas Recetas',
|
||||||
'Overview': 'Overview',
|
'Overview': 'Resumen',
|
||||||
'pack all': 'empaquetar todo',
|
'pack all': 'empaquetar todo',
|
||||||
'pack compiled': 'empaquete compiladas',
|
'pack compiled': 'empaquete compiladas',
|
||||||
'Password': 'Contraseña',
|
'Password': 'Contraseña',
|
||||||
@@ -215,20 +215,20 @@
|
|||||||
'previous 100 rows': '100 filas anteriores',
|
'previous 100 rows': '100 filas anteriores',
|
||||||
'Python': 'Python',
|
'Python': 'Python',
|
||||||
'Query:': 'Consulta:',
|
'Query:': 'Consulta:',
|
||||||
'Quick Examples': 'Quick Examples',
|
'Quick Examples': 'Ejemplos Rápidos',
|
||||||
'RAM': 'RAM',
|
'RAM': 'RAM',
|
||||||
'RAM Cache Keys': 'RAM Cache Keys',
|
'RAM Cache Keys':'Llaves de la RAM Cache',
|
||||||
'Ram Cleared': 'Ram Cleared',
|
'Ram Cleared': 'Ram Limpiada',
|
||||||
'Recipes': 'Recipes',
|
'Recipes': 'Recetas',
|
||||||
'Record': 'registro',
|
'Record': 'registro',
|
||||||
'record does not exist': 'el registro no existe',
|
'record does not exist': 'el registro no existe',
|
||||||
'Record ID': 'ID de Registro',
|
'Record ID': 'ID de Registro',
|
||||||
'Record id': 'id de registro',
|
'Record id': 'id de registro',
|
||||||
'Register': 'Registrese',
|
'Register': 'Registrese',
|
||||||
'register': 'registrese',
|
'register': 'registrese',
|
||||||
'Registration key': 'Contraseña de Registro',
|
'Registration key': 'Llave de Registro',
|
||||||
'remove compiled': 'eliminar compiladas',
|
'remove compiled': 'eliminar compiladas',
|
||||||
'Reset Password key': 'Reset Password key',
|
'Reset Password key': 'Restaurar LLavel de la Contraseña',
|
||||||
'Resolve Conflict file': 'archivo Resolución de Conflicto',
|
'Resolve Conflict file': 'archivo Resolución de Conflicto',
|
||||||
'restore': 'restaurar',
|
'restore': 'restaurar',
|
||||||
'revert': 'revertir',
|
'revert': 'revertir',
|
||||||
@@ -237,20 +237,20 @@
|
|||||||
'Rows selected': 'Filas seleccionadas',
|
'Rows selected': 'Filas seleccionadas',
|
||||||
'save': 'guardar',
|
'save': 'guardar',
|
||||||
'Saved file hash:': 'Hash del archivo guardado:',
|
'Saved file hash:': 'Hash del archivo guardado:',
|
||||||
'Semantic': 'Semantic',
|
'Semantic': 'Semantica',
|
||||||
'Services': 'Services',
|
'Services': 'Servicios',
|
||||||
'session expired': 'sesión expirada',
|
'session expired': 'sesión expirada',
|
||||||
'shell': 'shell',
|
'shell': 'terminal',
|
||||||
'site': 'sitio',
|
'site': 'sitio',
|
||||||
'Size of cache:': 'Size of cache:',
|
'Size of cache:': 'Tamaño del Cache:',
|
||||||
'some files could not be removed': 'algunos archivos no pudieron ser removidos',
|
'some files could not be removed': 'algunos archivos no pudieron ser removidos',
|
||||||
'state': 'estado',
|
'state': 'estado',
|
||||||
'static': 'estáticos',
|
'static': 'estáticos',
|
||||||
'Static files': 'Archivos estáticos',
|
'Static files': 'Archivos estáticos',
|
||||||
'Statistics': 'Statistics',
|
'Statistics': 'Estadísticas',
|
||||||
'Stylesheet': 'Hoja de estilo',
|
'Stylesheet': 'Hoja de estilo',
|
||||||
'submit': 'submit',
|
'submit': 'enviar',
|
||||||
'Support': 'Support',
|
'Support': 'Soporte',
|
||||||
'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?',
|
'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?',
|
||||||
'Table': 'tabla',
|
'Table': 'tabla',
|
||||||
'Table name': 'Nombre de la tabla',
|
'Table name': 'Nombre de la tabla',
|
||||||
@@ -258,11 +258,11 @@
|
|||||||
'Testing application': 'Probando aplicación',
|
'Testing application': 'Probando aplicación',
|
||||||
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "consulta" es una condición como "db.tabla1.campo1==\'valor\'". Algo como "db.tabla1.campo1==db.tabla2.campo2" resulta en un JOIN SQL.',
|
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "consulta" es una condición como "db.tabla1.campo1==\'valor\'". Algo como "db.tabla1.campo1==db.tabla2.campo2" resulta en un JOIN SQL.',
|
||||||
'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador',
|
'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador',
|
||||||
'The Core': 'The Core',
|
'The Core': 'El Núcleo',
|
||||||
'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos',
|
'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos',
|
||||||
'The output of the file is a dictionary that was rendered by the view %s': 'La salida del archivo es un diccionario escenificado por la vista %s',
|
'The output of the file is a dictionary that was rendered by the view %s': 'La salida del archivo es un diccionario escenificado por la vista %s',
|
||||||
'the presentations layer, views are also known as templates': 'la capa de presentación, las vistas también son llamadas plantillas',
|
'the presentations layer, views are also known as templates': 'la capa de presentación, las vistas también son llamadas plantillas',
|
||||||
'The Views': 'The Views',
|
'The Views': 'Las Vistas',
|
||||||
'There are no controllers': 'No hay controladores',
|
'There are no controllers': 'No hay controladores',
|
||||||
'There are no models': 'No hay modelos',
|
'There are no models': 'No hay modelos',
|
||||||
'There are no modules': 'No hay módulos',
|
'There are no modules': 'No hay módulos',
|
||||||
@@ -270,14 +270,14 @@
|
|||||||
'There are no translators, only default language is supported': 'No hay traductores, sólo el lenguaje por defecto es soportado',
|
'There are no translators, only default language is supported': 'No hay traductores, sólo el lenguaje por defecto es soportado',
|
||||||
'There are no views': 'No hay vistas',
|
'There are no views': 'No hay vistas',
|
||||||
'these files are served without processing, your images go here': 'estos archivos son servidos sin procesar, sus imágenes van aquí',
|
'these files are served without processing, your images go here': 'estos archivos son servidos sin procesar, sus imágenes van aquí',
|
||||||
'This App': 'This App',
|
'This App': 'Esta Aplicación',
|
||||||
'This is a copy of the scaffolding application': 'Esta es una copia de la aplicación de andamiaje',
|
'This is a copy of the scaffolding application': 'Esta es una copia de la aplicación de andamiaje',
|
||||||
'This is the %(filename)s template': 'Esta es la plantilla %(filename)s',
|
'This is the %(filename)s template': 'Esta es la plantilla %(filename)s',
|
||||||
'Ticket': 'Tiquete',
|
'Ticket': 'Tiquete',
|
||||||
'Time in Cache (h:m:s)': 'Time in Cache (h:m:s)',
|
'Time in Cache (h:m:s)': 'Tiempo en Cache (h:m:s)',
|
||||||
'Timestamp': 'Timestamp',
|
'Timestamp': 'Marca de tiempo',
|
||||||
'to previous version.': 'a la versión previa.',
|
'to previous version.': 'a la versión previa.',
|
||||||
'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación',
|
'translation strings for the application': 'cadenas de carácteres de traducción para la aplicación',
|
||||||
'try': 'intente',
|
'try': 'intente',
|
||||||
'try something like': 'intente algo como',
|
'try something like': 'intente algo como',
|
||||||
'Twitter': 'Twitter',
|
'Twitter': 'Twitter',
|
||||||
@@ -306,12 +306,12 @@
|
|||||||
'views': 'vistas',
|
'views': 'vistas',
|
||||||
'web2py is up to date': 'web2py está actualizado',
|
'web2py is up to date': 'web2py está actualizado',
|
||||||
'web2py Recent Tweets': 'Tweets Recientes de web2py',
|
'web2py Recent Tweets': 'Tweets Recientes de web2py',
|
||||||
'Welcome': 'Welcome',
|
'Welcome': 'Bienvenido',
|
||||||
'Welcome %s': 'Bienvenido %s',
|
'Welcome %s': 'Bienvenido %s',
|
||||||
'Welcome to web2py': 'Bienvenido a web2py',
|
'Welcome to web2py': 'Bienvenido a web2py',
|
||||||
'Welcome to web2py!': 'Welcome to web2py!',
|
'Welcome to web2py!': '¡Bienvenido to web2py!',
|
||||||
'Which called the function %s located in the file %s': 'La cual llamó la función %s localizada en el archivo %s',
|
'Which called the function %s located in the file %s': 'La cual llamó la función %s localizada en el archivo %s',
|
||||||
'YES': 'SI',
|
'YES': 'SÍ',
|
||||||
'You are successfully running web2py': 'Usted está ejecutando web2py exitosamente',
|
'You are successfully running web2py': 'Usted está ejecutando web2py exitosamente',
|
||||||
'You can modify this application and adapt it to your needs': 'Usted puede modificar esta aplicación y adaptarla a sus necesidades',
|
'You can modify this application and adapt it to your needs': 'Usted puede modificar esta aplicación y adaptarla a sus necesidades',
|
||||||
'You visited the url %s': 'Usted visitó la url %s',
|
'You visited the url %s': 'Usted visitó la url %s',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
'Administrative Interface': 'Interfaccia Amministrativa',
|
'Administrative Interface': 'Interfaccia Amministrativa',
|
||||||
'Administrative interface': 'Interfaccia amministrativa',
|
'Administrative interface': 'Interfaccia amministrativa',
|
||||||
'Ajax Recipes': 'Ajax Recipes',
|
'Ajax Recipes': 'Ajax Recipes',
|
||||||
'An error occured, please %s the page': "E' stato rilevato un errore, prego %s la pagina",
|
'An error occured, please %s the page': "È stato rilevato un errore, prego %s la pagina",
|
||||||
'And': 'E',
|
'And': 'E',
|
||||||
'appadmin is disabled because insecure channel': 'Amministrazione (appadmin) disabilitata: comunicazione non sicura',
|
'appadmin is disabled because insecure channel': 'Amministrazione (appadmin) disabilitata: comunicazione non sicura',
|
||||||
'Are you sure you want to delete this object?': 'Sicuro di voler cancellare questo oggetto ?',
|
'Are you sure you want to delete this object?': 'Sicuro di voler cancellare questo oggetto ?',
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
response.logo = A(B('web',SPAN(2),'py'),XML('™ '),
|
response.logo = A(B('web',SPAN(2),'py'),XML('™ '),
|
||||||
_class="brand",_href="http://www.web2py.com/")
|
_class="brand",_href="http://www.web2py.com/")
|
||||||
response.title = ' '.join(
|
response.title = request.application.replace('_',' ').title()
|
||||||
word.capitalize() for word in request.application.split('_'))
|
|
||||||
response.subtitle = T('customize me!')
|
response.subtitle = T('customize me!')
|
||||||
|
|
||||||
## read more at http://dev.w3.org/html5/markup/meta.name.html
|
## read more at http://dev.w3.org/html5/markup/meta.name.html
|
||||||
|
|||||||
@@ -91,16 +91,18 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- Masthead ================================================== -->
|
<!-- Masthead ================================================== -->
|
||||||
|
{{if response.title:}}
|
||||||
<header class="mastheader row" id="header">
|
<header class="mastheader row" id="header">
|
||||||
<div class="span12">
|
<div class="span12">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>
|
<h1>
|
||||||
{{=response.title or request.application}}
|
{{=response.title}}
|
||||||
<small>{{=response.subtitle or ''}}</small>
|
<small>{{=response.subtitle or ''}}</small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
{{pass}}
|
||||||
|
|
||||||
<section id="main" class="main row">
|
<section id="main" class="main row">
|
||||||
{{if left_sidebar_enabled:}}
|
{{if left_sidebar_enabled:}}
|
||||||
|
|||||||
+4
-4
@@ -43,7 +43,7 @@ def apath(path='', r=None):
|
|||||||
return os.path.join(opath, path).replace('\\', '/')
|
return os.path.join(opath, path).replace('\\', '/')
|
||||||
|
|
||||||
|
|
||||||
def app_pack(app, request, raise_ex=False):
|
def app_pack(app, request, raise_ex=False, filenames=None):
|
||||||
"""
|
"""
|
||||||
Builds a w2p package for the application
|
Builds a w2p package for the application
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ def app_pack(app, request, raise_ex=False):
|
|||||||
filename of the w2p file or None on error
|
filename of the w2p file or None on error
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
app_cleanup(app, request)
|
if filenames is None: app_cleanup(app, request)
|
||||||
filename = apath('../deposit/web2py.app.%s.w2p' % app, request)
|
filename = apath('../deposit/web2py.app.%s.w2p' % app, request)
|
||||||
w2p_pack(filename, apath(app, request))
|
w2p_pack(filename, apath(app, request), filenames=filenames)
|
||||||
return filename
|
return filename
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if raise_ex:
|
if raise_ex:
|
||||||
@@ -373,7 +373,7 @@ def check_new_version(myversion, version_URL):
|
|||||||
the most up-to-version available
|
the most up-to-version available
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from urllib import urlopen
|
from urllib import urlopen
|
||||||
version = urlopen(version_URL).read()
|
version = urlopen(version_URL).read()
|
||||||
pversion = parse_version(version)
|
pversion = parse_version(version)
|
||||||
pmyversion = parse_version(myversion)
|
pmyversion = parse_version(myversion)
|
||||||
|
|||||||
+2
-2
@@ -457,7 +457,7 @@ class Cache(object):
|
|||||||
public: if False forces the Cache-Control to be 'private'
|
public: if False forces the Cache-Control to be 'private'
|
||||||
valid_statuses: by default only status codes starting with 1,2,3 will be cached.
|
valid_statuses: by default only status codes starting with 1,2,3 will be cached.
|
||||||
pass an explicit list of statuses on which turn the cache on
|
pass an explicit list of statuses on which turn the cache on
|
||||||
quick: Session,Vars,Lang,User-agent,Public,duration:
|
quick: Session,Vars,Lang,User-agent,Public:
|
||||||
fast overrides with initial strings, e.g. 'SVLP' or 'VLP', or 'VLP'
|
fast overrides with initial strings, e.g. 'SVLP' or 'VLP', or 'VLP'
|
||||||
"""
|
"""
|
||||||
from gluon import current
|
from gluon import current
|
||||||
@@ -512,7 +512,7 @@ class Cache(object):
|
|||||||
current.response.headers['Expires'] = expires
|
current.response.headers['Expires'] = expires
|
||||||
current.response.headers['Cache-Control'] = cache_control
|
current.response.headers['Cache-Control'] = cache_control
|
||||||
if cache_model and not send_headers:
|
if cache_model and not send_headers:
|
||||||
cache_model.clear(cache_key)
|
cache_model(cache_key, None)
|
||||||
return rtn
|
return rtn
|
||||||
return func()
|
return func()
|
||||||
wrapped_f.__name__ = func.__name__
|
wrapped_f.__name__ = func.__name__
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
|||||||
CONTENT_TYPE dictionary created against freedesktop.org' shared mime info
|
CONTENT_TYPE dictionary created against freedesktop.org' shared mime info
|
||||||
database version 1.1.
|
database version 1.1.
|
||||||
|
|
||||||
Deviations from official standards:
|
Deviations from official standards:
|
||||||
- '.md': 'application/x-genesis-rom' --> 'text/x-markdown'
|
- '.md': 'application/x-genesis-rom' --> 'text/x-markdown'
|
||||||
- '.png': 'image/x-apple-ios-png' --> 'image/png'
|
- '.png': 'image/x-apple-ios-png' --> 'image/png'
|
||||||
Additions:
|
Additions:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
|
|||||||
@@ -653,7 +653,8 @@ def ldap_auth(server='ldap', port=None,
|
|||||||
ldap_groups_of_the_user = list()
|
ldap_groups_of_the_user = list()
|
||||||
for group_row in group_search_result:
|
for group_row in group_search_result:
|
||||||
group = group_row[1]
|
group = group_row[1]
|
||||||
ldap_groups_of_the_user.extend(group[group_name_attrib])
|
if type(group) == dict and group.has_key(group_name_attrib):
|
||||||
|
ldap_groups_of_the_user.extend(group[group_name_attrib])
|
||||||
|
|
||||||
con.unbind()
|
con.unbind()
|
||||||
logger.debug('User groups: %s' % ldap_groups_of_the_user)
|
logger.debug('User groups: %s' % ldap_groups_of_the_user)
|
||||||
@@ -662,4 +663,3 @@ def ldap_auth(server='ldap', port=None,
|
|||||||
if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax
|
if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax
|
||||||
filterstr = filterstr[1:-1] # parens added again where used
|
filterstr = filterstr[1:-1] # parens added again where used
|
||||||
return ldap_auth_aux
|
return ldap_auth_aux
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ server for requests. It can be used for the optional"scope" parameters for Face
|
|||||||
# reuse token until expiration
|
# reuse token until expiration
|
||||||
if expires == 0 or expires > time.time():
|
if expires == 0 or expires > time.time():
|
||||||
return current.session.token['access_token']
|
return current.session.token['access_token']
|
||||||
|
|
||||||
code = current.request.vars.code
|
code = current.request.vars.code
|
||||||
|
|
||||||
if code:
|
if code:
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class OpenIDAuth(object):
|
|||||||
Otherwise it's always 'openid' and you
|
Otherwise it's always 'openid' and you
|
||||||
may not need it. This should be easy to changed.
|
may not need it. This should be easy to changed.
|
||||||
(Just remove the field of "type" and remove the
|
(Just remove the field of "type" and remove the
|
||||||
"and db.alt_logins.oidtype == type_"
|
"and db.alt_logins.oidtype == type_"
|
||||||
in _find_matched_openid function)
|
in _find_matched_openid function)
|
||||||
"""
|
"""
|
||||||
db = self.db
|
db = self.db
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ def da_du_ma(n=4):
|
|||||||
[random.randint(0, 11)] for i in range(n)])
|
[random.randint(0, 11)] for i in range(n)])
|
||||||
|
|
||||||
|
|
||||||
def populate(table, n, default=True, compute=False):
|
def populate(table, n, default=True, compute=False, contents={}):
|
||||||
ell = Learner()
|
ell = Learner()
|
||||||
#ell.learn(open('20417.txt','r').read())
|
#ell.learn(open('20417.txt','r').read())
|
||||||
#ell.save('frequencies.pickle')
|
#ell.save('frequencies.pickle')
|
||||||
@@ -84,7 +84,14 @@ def populate(table, n, default=True, compute=False):
|
|||||||
ids = {}
|
ids = {}
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
record = {}
|
record = {}
|
||||||
|
|
||||||
|
record.update(contents) # load user supplied contents.
|
||||||
|
|
||||||
for fieldname in table.fields:
|
for fieldname in table.fields:
|
||||||
|
|
||||||
|
if record.get(fieldname) is not None:
|
||||||
|
continue # if user supplied it, let it be.
|
||||||
|
|
||||||
field = table[fieldname]
|
field = table[fieldname]
|
||||||
if not isinstance(field.type, (str, unicode)):
|
if not isinstance(field.type, (str, unicode)):
|
||||||
continue
|
continue
|
||||||
|
|||||||
+2364
-2364
File diff suppressed because it is too large
Load Diff
@@ -15,12 +15,12 @@ mostly for testing purposes
|
|||||||
|
|
||||||
Some examples at the bottom.
|
Some examples at the bottom.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
import urllib2
|
import urllib2
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_HEADERS = {
|
DEFAULT_HEADERS = {
|
||||||
'user-agent': 'Mozilla/4.0', # some servers are picky
|
'user-agent': 'Mozilla/4.0', # some servers are picky
|
||||||
'accept-language': 'en',
|
'accept-language': 'en',
|
||||||
@@ -126,7 +126,11 @@ class WebClient(object):
|
|||||||
self.time = time.time() - t0
|
self.time = time.time() - t0
|
||||||
self.response = error
|
self.response = error
|
||||||
|
|
||||||
self.status = self.response.getcode()
|
if hasattr(self.response, 'getcode'):
|
||||||
|
self.status = self.response.getcode()
|
||||||
|
else:#python2.5
|
||||||
|
self.status = None
|
||||||
|
|
||||||
self.text = self.response.read()
|
self.text = self.response.read()
|
||||||
self.headers = dict(self.response.headers)
|
self.headers = dict(self.response.headers)
|
||||||
|
|
||||||
|
|||||||
+119
-69
@@ -122,6 +122,7 @@ Supported DAL URI strings:
|
|||||||
'google:sql' # for google app engine with sql (mysql compatible)
|
'google:sql' # for google app engine with sql (mysql compatible)
|
||||||
'teradata://DSN=dsn;UID=user;PWD=pass; DATABASE=database' # experimental
|
'teradata://DSN=dsn;UID=user;PWD=pass; DATABASE=database' # experimental
|
||||||
'imap://user:password@server:port' # experimental
|
'imap://user:password@server:port' # experimental
|
||||||
|
'mongodb://user:password@server:port/database' # experimental
|
||||||
|
|
||||||
For more info:
|
For more info:
|
||||||
help(DAL)
|
help(DAL)
|
||||||
@@ -199,7 +200,7 @@ TABLE_ARGS = set(
|
|||||||
|
|
||||||
SELECT_ARGS = set(
|
SELECT_ARGS = set(
|
||||||
('orderby', 'groupby', 'limitby','required', 'cache', 'left',
|
('orderby', 'groupby', 'limitby','required', 'cache', 'left',
|
||||||
'distinct', 'having', 'join','for_update', 'processor','cacheable'))
|
'distinct', 'having', 'join','for_update', 'processor','cacheable', 'orderby_on_limitby'))
|
||||||
|
|
||||||
ogetattr = object.__getattribute__
|
ogetattr = object.__getattribute__
|
||||||
osetattr = object.__setattr__
|
osetattr = object.__setattr__
|
||||||
@@ -1126,6 +1127,9 @@ class BaseAdapter(ConnectionPool):
|
|||||||
def EPOCH(self, first):
|
def EPOCH(self, first):
|
||||||
return self.EXTRACT(first, 'epoch')
|
return self.EXTRACT(first, 'epoch')
|
||||||
|
|
||||||
|
def LENGTH(self, first):
|
||||||
|
return "LENGTH(%s)" % self.expand(first)
|
||||||
|
|
||||||
def AGGREGATE(self, first, what):
|
def AGGREGATE(self, first, what):
|
||||||
return "%s(%s)" % (what, self.expand(first))
|
return "%s(%s)" % (what, self.expand(first))
|
||||||
|
|
||||||
@@ -1251,24 +1255,15 @@ class BaseAdapter(ConnectionPool):
|
|||||||
return '(%s LIKE %s)' % (self.expand(first),
|
return '(%s LIKE %s)' % (self.expand(first),
|
||||||
self.expand('%'+second, 'string'))
|
self.expand('%'+second, 'string'))
|
||||||
|
|
||||||
def CONTAINS(self, first, second, case_sensitive=False):
|
def CONTAINS(self,first,second,case_sensitive=False):
|
||||||
if isinstance(second,Expression):
|
if first.type in ('string','text', 'json'):
|
||||||
field = self.expand(first)
|
second = Expression(None,self.CONCAT('%',Expression(
|
||||||
expr = self.expand(second,'string')
|
None,self.REPLACE(second,('%','%%'))),'%'))
|
||||||
if first.type.startswith('list:'):
|
elif first.type.startswith('list:'):
|
||||||
expr = 'CONCAT("|", %s, "|")' % expr
|
second = Expression(None,self.CONCAT('%|',Expression(None,self.REPLACE(
|
||||||
elif not first.type in ('string', 'text', 'json'):
|
Expression(None,self.REPLACE(second,('%','%%'))),('|','||'))),'|%'))
|
||||||
raise RuntimeError("Expression Not Supported")
|
op = case_sensitive and self.LIKE or self.ILIKE
|
||||||
return 'INSTR(%s,%s)' % (field, expr)
|
return op(first,second)
|
||||||
else:
|
|
||||||
if first.type in ('string', 'text', 'json'):
|
|
||||||
key = '%'+str(second).replace('%','%%')+'%'
|
|
||||||
elif first.type.startswith('list:'):
|
|
||||||
key = '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Expression Not Supported")
|
|
||||||
op = case_sensitive and self.LIKE or self.ILIKE
|
|
||||||
return op(first,key)
|
|
||||||
|
|
||||||
def EQ(self, first, second=None):
|
def EQ(self, first, second=None):
|
||||||
if second is None:
|
if second is None:
|
||||||
@@ -1306,9 +1301,24 @@ class BaseAdapter(ConnectionPool):
|
|||||||
return '(%s >= %s)' % (self.expand(first),
|
return '(%s >= %s)' % (self.expand(first),
|
||||||
self.expand(second,first.type))
|
self.expand(second,first.type))
|
||||||
|
|
||||||
|
def is_numerical_type(self, ftype):
|
||||||
|
return ftype in ('integer','boolean','double','bigint') or \
|
||||||
|
ftype.startswith('decimal')
|
||||||
|
|
||||||
|
def REPLACE(self, first, (second, third)):
|
||||||
|
return 'REPLACE(%s,%s,%s)' % (self.expand(first,'string'),
|
||||||
|
self.expand(second,'string'),
|
||||||
|
self.expand(third,'string'))
|
||||||
|
|
||||||
|
def CONCAT(self, *items):
|
||||||
|
return '(%s)' % ' || '.join(self.expand(x,'string') for x in items)
|
||||||
|
|
||||||
def ADD(self, first, second):
|
def ADD(self, first, second):
|
||||||
return '(%s + %s)' % (self.expand(first),
|
if self.is_numerical_type(first.type):
|
||||||
self.expand(second, first.type))
|
return '(%s + %s)' % (self.expand(first),
|
||||||
|
self.expand(second, first.type))
|
||||||
|
else:
|
||||||
|
return self.CONCAT(first, second)
|
||||||
|
|
||||||
def SUB(self, first, second):
|
def SUB(self, first, second):
|
||||||
return '(%s - %s)' % (self.expand(first),
|
return '(%s - %s)' % (self.expand(first),
|
||||||
@@ -1499,6 +1509,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
raise SyntaxError('invalid select attribute: %s' % key)
|
raise SyntaxError('invalid select attribute: %s' % key)
|
||||||
args_get = attributes.get
|
args_get = attributes.get
|
||||||
tablenames = tables(query)
|
tablenames = tables(query)
|
||||||
|
tablenames_for_common_filters = tablenames
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if isinstance(field, basestring) \
|
if isinstance(field, basestring) \
|
||||||
and REGEX_TABLE_DOT_FIELD.match(field):
|
and REGEX_TABLE_DOT_FIELD.match(field):
|
||||||
@@ -1525,6 +1536,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
orderby = args_get('orderby', False)
|
orderby = args_get('orderby', False)
|
||||||
having = args_get('having', False)
|
having = args_get('having', False)
|
||||||
limitby = args_get('limitby', False)
|
limitby = args_get('limitby', False)
|
||||||
|
orderby_on_limitby = args_get('orderby_on_limitby', True)
|
||||||
for_update = args_get('for_update', False)
|
for_update = args_get('for_update', False)
|
||||||
if self.can_select_for_update is False and for_update is True:
|
if self.can_select_for_update is False and for_update is True:
|
||||||
raise SyntaxError('invalid select attribute: for_update')
|
raise SyntaxError('invalid select attribute: for_update')
|
||||||
@@ -1562,6 +1574,8 @@ class BaseAdapter(ConnectionPool):
|
|||||||
dict.fromkeys(tables(t))) for t in joinon]
|
dict.fromkeys(tables(t))) for t in joinon]
|
||||||
joinont = [t.first._tablename for t in joinon]
|
joinont = [t.first._tablename for t in joinon]
|
||||||
[tables_to_merge.pop(t) for t in joinont if t in tables_to_merge]
|
[tables_to_merge.pop(t) for t in joinont if t in tables_to_merge]
|
||||||
|
tablenames_for_common_filters = [t for t in tablenames
|
||||||
|
if not t in joinont ]
|
||||||
important_tablenames = joint + joinont + tables_to_merge.keys()
|
important_tablenames = joint + joinont + tables_to_merge.keys()
|
||||||
excluded = [t for t in tablenames
|
excluded = [t for t in tablenames
|
||||||
if not t in important_tablenames ]
|
if not t in important_tablenames ]
|
||||||
@@ -1569,7 +1583,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
excluded = tablenames
|
excluded = tablenames
|
||||||
|
|
||||||
if use_common_filters(query):
|
if use_common_filters(query):
|
||||||
query = self.common_filter(query,excluded)
|
query = self.common_filter(query,tablenames_for_common_filters)
|
||||||
sql_w = ' WHERE ' + self.expand(query) if query else ''
|
sql_w = ' WHERE ' + self.expand(query) if query else ''
|
||||||
|
|
||||||
def alias(t):
|
def alias(t):
|
||||||
@@ -1616,7 +1630,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
else:
|
else:
|
||||||
sql_o += ' ORDER BY %s' % self.expand(orderby)
|
sql_o += ' ORDER BY %s' % self.expand(orderby)
|
||||||
if limitby:
|
if limitby:
|
||||||
if not orderby and tablenames:
|
if orderby_on_limitby and not orderby and tablenames:
|
||||||
sql_o += ' ORDER BY %s' % ', '.join(['%s.%s'%(t,x) for t in tablenames for x in (hasattr(self.db[t],'_primarykey') and self.db[t]._primarykey or [self.db[t]._id.name])])
|
sql_o += ' ORDER BY %s' % ', '.join(['%s.%s'%(t,x) for t in tablenames for x in (hasattr(self.db[t],'_primarykey') and self.db[t]._primarykey or [self.db[t]._id.name])])
|
||||||
# oracle does not support limitby
|
# oracle does not support limitby
|
||||||
sql = self.select_limitby(sql_s, sql_f, sql_t, sql_w, sql_o, limitby)
|
sql = self.select_limitby(sql_s, sql_f, sql_t, sql_w, sql_o, limitby)
|
||||||
@@ -1939,17 +1953,17 @@ class BaseAdapter(ConnectionPool):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
def parse_list_integers(self, value, field_type):
|
def parse_list_integers(self, value, field_type):
|
||||||
if not self.dbengine=='google:datastore':
|
if not isinstance(self, NoSQLAdapter):
|
||||||
value = bar_decode_integer(value)
|
value = bar_decode_integer(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def parse_list_references(self, value, field_type):
|
def parse_list_references(self, value, field_type):
|
||||||
if not self.dbengine=='google:datastore':
|
if not isinstance(self, NoSQLAdapter):
|
||||||
value = bar_decode_integer(value)
|
value = bar_decode_integer(value)
|
||||||
return [self.parse_reference(r, field_type[5:]) for r in value]
|
return [self.parse_reference(r, field_type[5:]) for r in value]
|
||||||
|
|
||||||
def parse_list_strings(self, value, field_type):
|
def parse_list_strings(self, value, field_type):
|
||||||
if not self.dbengine=='google:datastore':
|
if not isinstance(self, NoSQLAdapter):
|
||||||
value = bar_decode_string(value)
|
value = bar_decode_string(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@@ -2260,7 +2274,7 @@ class SpatiaLiteAdapter(SQLiteAdapter):
|
|||||||
# Linux uses libspatialite.so
|
# Linux uses libspatialite.so
|
||||||
# Mac OS X uses libspatialite.dylib
|
# Mac OS X uses libspatialite.dylib
|
||||||
libspatialite = SPATIALLIBS[platform.system()]
|
libspatialite = SPATIALLIBS[platform.system()]
|
||||||
self.execute(r'SELECT load_extension("%s");') % libspatialite
|
self.execute(r'SELECT load_extension("%s");' % libspatialite)
|
||||||
|
|
||||||
self.connection.create_function('web2py_extract', 2,
|
self.connection.create_function('web2py_extract', 2,
|
||||||
SQLiteAdapter.web2py_extract)
|
SQLiteAdapter.web2py_extract)
|
||||||
@@ -2410,6 +2424,9 @@ class MySQLAdapter(BaseAdapter):
|
|||||||
def EPOCH(self, first):
|
def EPOCH(self, first):
|
||||||
return "UNIX_TIMESTAMP(%s)" % self.expand(first)
|
return "UNIX_TIMESTAMP(%s)" % self.expand(first)
|
||||||
|
|
||||||
|
def CONCAT(self, *items):
|
||||||
|
return 'CONCAT(%s)' % ','.join(self.expand(x,'string') for x in items)
|
||||||
|
|
||||||
def REGEXP(self,first,second):
|
def REGEXP(self,first,second):
|
||||||
return '(%s REGEXP %s)' % (self.expand(first),
|
return '(%s REGEXP %s)' % (self.expand(first),
|
||||||
self.expand(second,'string'))
|
self.expand(second,'string'))
|
||||||
@@ -2606,7 +2623,11 @@ class PostgreSQLAdapter(BaseAdapter):
|
|||||||
"port=%s password='%s'") \
|
"port=%s password='%s'") \
|
||||||
% (db, user, host, port, password)
|
% (db, user, host, port, password)
|
||||||
# choose diver according uri
|
# choose diver according uri
|
||||||
self.__version__ = "%s %s" % (self.driver.__name__, self.driver.__version__)
|
if self.driver:
|
||||||
|
self.__version__ = "%s %s" % (self.driver.__name__,
|
||||||
|
self.driver.__version__)
|
||||||
|
else:
|
||||||
|
self.__version__ = None
|
||||||
def connector(msg=msg,driver_args=driver_args):
|
def connector(msg=msg,driver_args=driver_args):
|
||||||
return self.driver.connect(msg,**driver_args)
|
return self.driver.connect(msg,**driver_args)
|
||||||
self.connector = connector
|
self.connector = connector
|
||||||
@@ -2661,14 +2682,6 @@ class PostgreSQLAdapter(BaseAdapter):
|
|||||||
return '(%s ILIKE %s)' % (self.expand(first),
|
return '(%s ILIKE %s)' % (self.expand(first),
|
||||||
self.expand('%'+second,'string'))
|
self.expand('%'+second,'string'))
|
||||||
|
|
||||||
def CONTAINS(self,first,second,case_sensitive=False):
|
|
||||||
if first.type in ('string','text', 'json'):
|
|
||||||
second = '%'+str(second).replace('%','%%')+'%'
|
|
||||||
elif first.type.startswith('list:'):
|
|
||||||
second = '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
|
|
||||||
op = case_sensitive and self.LIKE or self.ILIKE
|
|
||||||
return op(first,second)
|
|
||||||
|
|
||||||
# GIS functions
|
# GIS functions
|
||||||
|
|
||||||
def ST_ASGEOJSON(self, first, second):
|
def ST_ASGEOJSON(self, first, second):
|
||||||
@@ -3103,7 +3116,9 @@ class MSSQLAdapter(BaseAdapter):
|
|||||||
(lmin, lmax) = limitby
|
(lmin, lmax) = limitby
|
||||||
sql_s += ' TOP %i' % lmax
|
sql_s += ' TOP %i' % lmax
|
||||||
if 'GROUP BY' in sql_o:
|
if 'GROUP BY' in sql_o:
|
||||||
sql_o = sql_o[:sql_o.find('ORDER BY ')]
|
orderfound = sql_o.find('ORDER BY ')
|
||||||
|
if orderfound >= 0:
|
||||||
|
sql_o = sql_o[:orderfound]
|
||||||
return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o)
|
return 'SELECT %s %s FROM %s%s%s;' % (sql_s, sql_f, sql_t, sql_w, sql_o)
|
||||||
|
|
||||||
TRUE = 1
|
TRUE = 1
|
||||||
@@ -3193,6 +3208,9 @@ class MSSQLAdapter(BaseAdapter):
|
|||||||
def EPOCH(self, first):
|
def EPOCH(self, first):
|
||||||
return "DATEDIFF(second, '1970-01-01 00:00:00', %s)" % self.expand(first)
|
return "DATEDIFF(second, '1970-01-01 00:00:00', %s)" % self.expand(first)
|
||||||
|
|
||||||
|
def CONCAT(self, *items):
|
||||||
|
return '(%s)' % ' + '.join(self.expand(x,'string') for x in items)
|
||||||
|
|
||||||
# GIS Spatial Extensions
|
# GIS Spatial Extensions
|
||||||
|
|
||||||
# No STAsGeoJSON in MSSQL
|
# No STAsGeoJSON in MSSQL
|
||||||
@@ -3448,18 +3466,16 @@ class FireBirdAdapter(BaseAdapter):
|
|||||||
def SUBSTRING(self,field,parameters):
|
def SUBSTRING(self,field,parameters):
|
||||||
return 'SUBSTRING(%s from %s for %s)' % (self.expand(field), parameters[0], parameters[1])
|
return 'SUBSTRING(%s from %s for %s)' % (self.expand(field), parameters[0], parameters[1])
|
||||||
|
|
||||||
def CONTAINING(self,first,second):
|
def LENGTH(self, first):
|
||||||
"case in-sensitive like operator"
|
return "CHAR_LENGTH(%s)" % self.expand(first)
|
||||||
|
|
||||||
|
def CONTAINS(self,first,second,case_sensitive=False):
|
||||||
|
if first.type.startswith('list:'):
|
||||||
|
second = Expression(None,self.CONCAT('|',Expression(
|
||||||
|
None,self.REPLACE(second,('|','||'))),'|'))
|
||||||
return '(%s CONTAINING %s)' % (self.expand(first),
|
return '(%s CONTAINING %s)' % (self.expand(first),
|
||||||
self.expand(second, 'string'))
|
self.expand(second, 'string'))
|
||||||
|
|
||||||
def CONTAINS(self, first, second, case_sensitive=False):
|
|
||||||
if first.type in ('string','text'):
|
|
||||||
second = str(second).replace('%','%%')
|
|
||||||
elif first.type.startswith('list:'):
|
|
||||||
second = '|'+str(second).replace('|','||').replace('%','%%')+'|'
|
|
||||||
return self.CONTAINING(first,second)
|
|
||||||
|
|
||||||
def _drop(self,table,mode):
|
def _drop(self,table,mode):
|
||||||
sequence_name = table._sequence_name
|
sequence_name = table._sequence_name
|
||||||
return ['DROP TABLE %s %s;' % (table, mode), 'DROP GENERATOR %s;' % sequence_name]
|
return ['DROP TABLE %s %s;' % (table, mode), 'DROP GENERATOR %s;' % sequence_name]
|
||||||
@@ -4358,13 +4374,14 @@ class NoSQLAdapter(BaseAdapter):
|
|||||||
elif fieldtype == 'blob':
|
elif fieldtype == 'blob':
|
||||||
pass
|
pass
|
||||||
elif fieldtype == 'json':
|
elif fieldtype == 'json':
|
||||||
obj = self.to_unicode(obj)
|
if isinstance(obj, basestring):
|
||||||
if have_serializers:
|
obj = self.to_unicode(obj)
|
||||||
obj = serializers.loads_json(obj)
|
if have_serializers:
|
||||||
elif simplejson:
|
obj = serializers.loads_json(obj)
|
||||||
obj = simplejson.loads(obj)
|
elif simplejson:
|
||||||
else:
|
obj = simplejson.loads(obj)
|
||||||
raise RuntimeError("missing simplejson")
|
else:
|
||||||
|
raise RuntimeError("missing simplejson")
|
||||||
elif is_string and field_is_type('list:string'):
|
elif is_string and field_is_type('list:string'):
|
||||||
return map(self.to_unicode,obj)
|
return map(self.to_unicode,obj)
|
||||||
elif is_list:
|
elif is_list:
|
||||||
@@ -4422,6 +4439,7 @@ class NoSQLAdapter(BaseAdapter):
|
|||||||
def LOWER(self,first): raise SyntaxError("Not supported")
|
def LOWER(self,first): raise SyntaxError("Not supported")
|
||||||
def UPPER(self,first): raise SyntaxError("Not supported")
|
def UPPER(self,first): raise SyntaxError("Not supported")
|
||||||
def EXTRACT(self,first,what): raise SyntaxError("Not supported")
|
def EXTRACT(self,first,what): raise SyntaxError("Not supported")
|
||||||
|
def LENGTH(self, first): raise SyntaxError("Not supported")
|
||||||
def AGGREGATE(self,first,what): raise SyntaxError("Not supported")
|
def AGGREGATE(self,first,what): raise SyntaxError("Not supported")
|
||||||
def LEFT_JOIN(self): raise SyntaxError("Not supported")
|
def LEFT_JOIN(self): raise SyntaxError("Not supported")
|
||||||
def RANDOM(self): raise SyntaxError("Not supported")
|
def RANDOM(self): raise SyntaxError("Not supported")
|
||||||
@@ -5181,6 +5199,7 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
"Requires an integer or base 16 value")
|
"Requires an integer or base 16 value")
|
||||||
elif isinstance(arg, self.ObjectId):
|
elif isinstance(arg, self.ObjectId):
|
||||||
return arg
|
return arg
|
||||||
|
|
||||||
if not isinstance(arg, (int, long)):
|
if not isinstance(arg, (int, long)):
|
||||||
raise TypeError("object_id argument must be of type " +
|
raise TypeError("object_id argument must be of type " +
|
||||||
"ObjectId or an objectid representable integer")
|
"ObjectId or an objectid representable integer")
|
||||||
@@ -5190,8 +5209,26 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
hexvalue = hex(arg)[2:].replace("L", "")
|
hexvalue = hex(arg)[2:].replace("L", "")
|
||||||
return self.ObjectId(hexvalue)
|
return self.ObjectId(hexvalue)
|
||||||
|
|
||||||
|
def parse_reference(self, value, field_type):
|
||||||
|
# here we have to check for ObjectID before base parse
|
||||||
|
if isinstance(value, self.ObjectId):
|
||||||
|
value = int(str(value), 16)
|
||||||
|
return super(MongoDBAdapter,
|
||||||
|
self).parse_reference(value, field_type)
|
||||||
|
|
||||||
|
def parse_id(self, value, field_type):
|
||||||
|
if isinstance(value, self.ObjectId):
|
||||||
|
value = int(str(value), 16)
|
||||||
|
return super(MongoDBAdapter,
|
||||||
|
self).parse_id(value, field_type)
|
||||||
|
|
||||||
def represent(self, obj, fieldtype):
|
def represent(self, obj, fieldtype):
|
||||||
value = NoSQLAdapter.represent(self, obj, fieldtype)
|
# the base adatpter does not support MongoDB ObjectId
|
||||||
|
if isinstance(obj, self.ObjectId):
|
||||||
|
value = obj
|
||||||
|
else:
|
||||||
|
value = NoSQLAdapter.represent(self, obj, fieldtype)
|
||||||
|
# reference types must be convert to ObjectID
|
||||||
if fieldtype =='date':
|
if fieldtype =='date':
|
||||||
if value == None:
|
if value == None:
|
||||||
return value
|
return value
|
||||||
@@ -5208,15 +5245,24 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
# mongodb doesn't has a time object and so it must datetime,
|
# mongodb doesn't has a time object and so it must datetime,
|
||||||
# string or integer
|
# string or integer
|
||||||
return datetime.datetime.combine(d, value)
|
return datetime.datetime.combine(d, value)
|
||||||
elif fieldtype == 'list:string' or \
|
elif (isinstance(fieldtype, basestring) and
|
||||||
fieldtype == 'list:integer' or \
|
fieldtype.startswith('list:')):
|
||||||
fieldtype == 'list:reference':
|
if fieldtype.startswith('list:reference'):
|
||||||
|
newval = []
|
||||||
|
for v in value:
|
||||||
|
newval.append(self.object_id(v))
|
||||||
|
return newval
|
||||||
return value
|
return value
|
||||||
|
elif ((isinstance(fieldtype, basestring) and
|
||||||
|
fieldtype.startswith("reference")) or
|
||||||
|
(isinstance(fieldtype, Table))):
|
||||||
|
value = self.object_id(value)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# Safe determines whether a asynchronious request is done or a
|
# Safe determines whether a asynchronious request is done or a
|
||||||
# synchronious action is done
|
# synchronious action is done
|
||||||
# For safety, we use by default synchronious requests
|
# For safety, we use by default synchronous requests
|
||||||
def insert(self, table, fields, safe=None):
|
def insert(self, table, fields, safe=None):
|
||||||
if safe==None:
|
if safe==None:
|
||||||
safe = self.safe
|
safe = self.safe
|
||||||
@@ -5264,14 +5310,18 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
if expression.first.type == 'id':
|
if expression.first.type == 'id':
|
||||||
expression.first.name = '_id'
|
expression.first.name = '_id'
|
||||||
# cast to Mongo ObjectId
|
# cast to Mongo ObjectId
|
||||||
expression.second = self.object_id(expression.second)
|
if isinstance(expression.second, (tuple, list, set)):
|
||||||
|
expression.second = [self.object_id(item) for
|
||||||
|
item in expression.second]
|
||||||
|
else:
|
||||||
|
expression.second = self.object_id(expression.second)
|
||||||
result = expression.op(expression.first, expression.second)
|
result = expression.op(expression.first, expression.second)
|
||||||
|
|
||||||
if isinstance(expression, Field):
|
if isinstance(expression, Field):
|
||||||
if expression.type=='id':
|
if expression.type=='id':
|
||||||
result = "_id"
|
result = "_id"
|
||||||
else:
|
else:
|
||||||
result = expression.name
|
result = expression.name
|
||||||
|
|
||||||
elif isinstance(expression, (Expression, Query)):
|
elif isinstance(expression, (Expression, Query)):
|
||||||
if not expression.second is None:
|
if not expression.second is None:
|
||||||
result = expression.op(expression.first, expression.second)
|
result = expression.op(expression.first, expression.second)
|
||||||
@@ -5282,7 +5332,7 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
else:
|
else:
|
||||||
result = expression.op
|
result = expression.op
|
||||||
elif field_type:
|
elif field_type:
|
||||||
result = str(self.represent(expression,field_type))
|
result = self.represent(expression,field_type)
|
||||||
elif isinstance(expression,(list,tuple)):
|
elif isinstance(expression,(list,tuple)):
|
||||||
result = ','.join(self.represent(item,field_type) for
|
result = ','.join(self.represent(item,field_type) for
|
||||||
item in expression)
|
item in expression)
|
||||||
@@ -5336,7 +5386,6 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
else:
|
else:
|
||||||
raise SyntaxError("The table name could not be found in " +
|
raise SyntaxError("The table name could not be found in " +
|
||||||
"the query nor from the select statement.")
|
"the query nor from the select statement.")
|
||||||
|
|
||||||
mongoqry_dict = self.expand(query)
|
mongoqry_dict = self.expand(query)
|
||||||
fields = fields or self.db[tablename]
|
fields = fields or self.db[tablename]
|
||||||
for field in fields:
|
for field in fields:
|
||||||
@@ -5386,15 +5435,12 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
# record id's
|
# record id's
|
||||||
if fieldname == "id": fieldname = "_id"
|
if fieldname == "id": fieldname = "_id"
|
||||||
if fieldname in record:
|
if fieldname in record:
|
||||||
if isinstance(record[fieldname],
|
value = record[fieldname]
|
||||||
self.ObjectId):
|
|
||||||
value = int(str(record[fieldname]), 16)
|
|
||||||
else:
|
|
||||||
value = record[fieldname]
|
|
||||||
else:
|
else:
|
||||||
value = None
|
value = None
|
||||||
row.append(value)
|
row.append(value)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
processor = attributes.get('processor', self.parse)
|
processor = attributes.get('processor', self.parse)
|
||||||
result = processor(rows, fields, newnames, False)
|
result = processor(rows, fields, newnames, False)
|
||||||
return result
|
return result
|
||||||
@@ -5494,7 +5540,7 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
def BELONGS(self, first, second):
|
def BELONGS(self, first, second):
|
||||||
if isinstance(second, str):
|
if isinstance(second, str):
|
||||||
return {self.expand(first) : {"$in" : [ second[:-1]]} }
|
return {self.expand(first) : {"$in" : [ second[:-1]]} }
|
||||||
elif second==[] or second==():
|
elif second==[] or second==() or second==set():
|
||||||
return {1:0}
|
return {1:0}
|
||||||
items = [self.expand(item, first.type) for item in second]
|
items = [self.expand(item, first.type) for item in second]
|
||||||
return {self.expand(first) : {"$in" : items} }
|
return {self.expand(first) : {"$in" : items} }
|
||||||
@@ -8746,7 +8792,7 @@ class Expression(object):
|
|||||||
|
|
||||||
def len(self):
|
def len(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
return Expression(db, db._adapter.AGGREGATE, self, 'LENGTH', 'integer')
|
return Expression(db, db._adapter.LENGTH, self, None, 'integer')
|
||||||
|
|
||||||
def avg(self):
|
def avg(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
@@ -8764,6 +8810,10 @@ class Expression(object):
|
|||||||
db = self.db
|
db = self.db
|
||||||
return Expression(db, db._adapter.UPPER, self, None, self.type)
|
return Expression(db, db._adapter.UPPER, self, None, self.type)
|
||||||
|
|
||||||
|
def replace(self,a,b):
|
||||||
|
db = self.db
|
||||||
|
return Expression(db, db._adapter.REPLACE, self, (a,b), self.type)
|
||||||
|
|
||||||
def year(self):
|
def year(self):
|
||||||
db = self.db
|
db = self.db
|
||||||
return Expression(db, db._adapter.EXTRACT, self, 'year', 'integer')
|
return Expression(db, db._adapter.EXTRACT, self, 'year', 'integer')
|
||||||
|
|||||||
+11
-7
@@ -223,19 +223,20 @@ def _extractall(filename, path='.', members=None):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def tar(file, dir, expression='^.+$'):
|
def tar(file, dir, expression='^.+$', filenames=None):
|
||||||
"""
|
"""
|
||||||
tars dir into file, only tars file that match expression
|
tars dir into file, only tars file that match expression
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tar = tarfile.TarFile(file, 'w')
|
tar = tarfile.TarFile(file, 'w')
|
||||||
try:
|
try:
|
||||||
for file in listdir(dir, expression, add_dirs=True):
|
if filenames is None:
|
||||||
|
filenames = listdir(dir, expression, add_dirs=True)
|
||||||
|
for file in filenames:
|
||||||
tar.add(os.path.join(dir, file), file, False)
|
tar.add(os.path.join(dir, file), file, False)
|
||||||
finally:
|
finally:
|
||||||
tar.close()
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
def untar(file, dir):
|
def untar(file, dir):
|
||||||
"""
|
"""
|
||||||
untar file into dir
|
untar file into dir
|
||||||
@@ -244,14 +245,14 @@ def untar(file, dir):
|
|||||||
_extractall(file, dir)
|
_extractall(file, dir)
|
||||||
|
|
||||||
|
|
||||||
def w2p_pack(filename, path, compiled=False):
|
def w2p_pack(filename, path, compiled=False, filenames=None):
|
||||||
filename = abspath(filename)
|
filename = abspath(filename)
|
||||||
path = abspath(path)
|
path = abspath(path)
|
||||||
tarname = filename + '.tar'
|
tarname = filename + '.tar'
|
||||||
if compiled:
|
if compiled:
|
||||||
tar_compiled(tarname, path, '^[\w\.\-]+$')
|
tar_compiled(tarname, path, '^[\w\.\-]+$')
|
||||||
else:
|
else:
|
||||||
tar(tarname, path, '^[\w\.\-]+$')
|
tar(tarname, path, '^[\w\.\-]+$', filenames=filenames)
|
||||||
w2pfp = gzopen(filename, 'wb')
|
w2pfp = gzopen(filename, 'wb')
|
||||||
tarfp = open(tarname, 'rb')
|
tarfp = open(tarname, 'rb')
|
||||||
w2pfp.write(tarfp.read())
|
w2pfp.write(tarfp.read())
|
||||||
@@ -366,16 +367,19 @@ def get_session(request, other_application='admin'):
|
|||||||
return osession
|
return osession
|
||||||
|
|
||||||
|
|
||||||
def check_credentials(request, other_application='admin', expiration=60 * 60):
|
def check_credentials(request, other_application='admin',
|
||||||
|
expiration=60 * 60, gae_login=True):
|
||||||
""" checks that user is authorized to access other_application"""
|
""" checks that user is authorized to access other_application"""
|
||||||
if request.env.web2py_runtime_gae:
|
if request.env.web2py_runtime_gae:
|
||||||
from google.appengine.api import users
|
from google.appengine.api import users
|
||||||
if users.is_current_user_admin():
|
if users.is_current_user_admin():
|
||||||
return True
|
return True
|
||||||
else:
|
elif gae_login:
|
||||||
login_html = '<a href="%s">Sign in with your google account</a>.' \
|
login_html = '<a href="%s">Sign in with your google account</a>.' \
|
||||||
% users.create_login_url(request.env.path_info)
|
% users.create_login_url(request.env.path_info)
|
||||||
raise HTTP(200, '<html><body>%s</body></html>' % login_html)
|
raise HTTP(200, '<html><body>%s</body></html>' % login_html)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
dt = time.time() - expiration
|
dt = time.time() - expiration
|
||||||
s = get_session(request, other_application)
|
s = get_session(request, other_application)
|
||||||
|
|||||||
+1
-1
@@ -695,7 +695,7 @@ class Session(Storage):
|
|||||||
|
|
||||||
def forget(self, response=None):
|
def forget(self, response=None):
|
||||||
self._close(response)
|
self._close(response)
|
||||||
self._forget = True
|
self._forget = True
|
||||||
|
|
||||||
def _try_store_in_cookie(self, request, response):
|
def _try_store_in_cookie(self, request, response):
|
||||||
if response.session_storage_type != 'cookie':
|
if response.session_storage_type != 'cookie':
|
||||||
|
|||||||
+2
-3
@@ -840,9 +840,8 @@ class DIV(XmlComponent):
|
|||||||
c.latest = self.latest
|
c.latest = self.latest
|
||||||
c.session = self.session
|
c.session = self.session
|
||||||
c.formname = self.formname
|
c.formname = self.formname
|
||||||
if hideerror and not \
|
c['hideerror'] = hideerror or \
|
||||||
self.attributes.get('hideerror', False):
|
self.attributes.get('hideerror', False)
|
||||||
c['hideerror'] = hideerror
|
|
||||||
newstatus = c._traverse(status, hideerror) and newstatus
|
newstatus = c._traverse(status, hideerror) and newstatus
|
||||||
|
|
||||||
# for input, textarea, select, option
|
# for input, textarea, select, option
|
||||||
|
|||||||
+1
-1
@@ -238,7 +238,7 @@ def read_possible_languages_aux(langdir):
|
|||||||
|
|
||||||
plurals = {}
|
plurals = {}
|
||||||
flist = oslistdir(langdir) if isdir(langdir) else []
|
flist = oslistdir(langdir) if isdir(langdir) else []
|
||||||
|
|
||||||
# scan languages directory for plural dict files:
|
# scan languages directory for plural dict files:
|
||||||
for pname in flist:
|
for pname in flist:
|
||||||
if regex_plural_file.match(pname):
|
if regex_plural_file.match(pname):
|
||||||
|
|||||||
@@ -226,4 +226,3 @@ def sanitize(text, permitted_tags=[
|
|||||||
return str(text)
|
return str(text)
|
||||||
return XssCleaner(permitted_tags=permitted_tags,
|
return XssCleaner(permitted_tags=permitted_tags,
|
||||||
allowed_attributes=allowed_attributes).strip(text, escape)
|
allowed_attributes=allowed_attributes).strip(text, escape)
|
||||||
|
|
||||||
|
|||||||
+15
-7
@@ -563,16 +563,18 @@ class Scheduler(MetaScheduler):
|
|||||||
self.die()
|
self.die()
|
||||||
|
|
||||||
def wrapped_assign_tasks(self, db):
|
def wrapped_assign_tasks(self, db):
|
||||||
|
logger.debug('Assigning tasks...')
|
||||||
db.commit() #db.commit() only for Mysql
|
db.commit() #db.commit() only for Mysql
|
||||||
x = 0
|
x = 0
|
||||||
while x < 10:
|
while x < 10:
|
||||||
try:
|
try:
|
||||||
self.assign_tasks(db)
|
self.assign_tasks(db)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
logger.debug('Tasks assigned...')
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
db.rollback()
|
db.rollback()
|
||||||
logger.error('TICKER: error assigning tasks')
|
logger.error('TICKER: error assigning tasks (%s)', x)
|
||||||
x += 1
|
x += 1
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
@@ -766,7 +768,7 @@ class Scheduler(MetaScheduler):
|
|||||||
db(sw.worker_name == self.worker_name).update(
|
db(sw.worker_name == self.worker_name).update(
|
||||||
last_heartbeat=now, status=ACTIVE)
|
last_heartbeat=now, status=ACTIVE)
|
||||||
self.worker_status[1] = 1 # re-activating the process
|
self.worker_status[1] = 1 # re-activating the process
|
||||||
if self.worker_status[0] <> RUNNING:
|
if self.worker_status[0] != RUNNING:
|
||||||
self.worker_status[0] = ACTIVE
|
self.worker_status[0] = ACTIVE
|
||||||
|
|
||||||
self.do_assign_tasks = False
|
self.do_assign_tasks = False
|
||||||
@@ -786,13 +788,17 @@ class Scheduler(MetaScheduler):
|
|||||||
inactive_workers._select(sw.worker_name)))(st.status == RUNNING)\
|
inactive_workers._select(sw.worker_name)))(st.status == RUNNING)\
|
||||||
.update(assigned_worker_name='', status=QUEUED)
|
.update(assigned_worker_name='', status=QUEUED)
|
||||||
inactive_workers.delete()
|
inactive_workers.delete()
|
||||||
self.is_a_ticker = self.being_a_ticker()
|
try:
|
||||||
|
self.is_a_ticker = self.being_a_ticker()
|
||||||
|
except:
|
||||||
|
logger.error('Error coordinating TICKER')
|
||||||
if self.worker_status[0] == ACTIVE:
|
if self.worker_status[0] == ACTIVE:
|
||||||
self.do_assign_tasks = True
|
self.do_assign_tasks = True
|
||||||
except:
|
except:
|
||||||
pass
|
logger.error('Error cleaning up')
|
||||||
db.commit()
|
db.commit()
|
||||||
except:
|
except:
|
||||||
|
logger.error('Error retrieving status')
|
||||||
db.rollback()
|
db.rollback()
|
||||||
self.adj_hibernation()
|
self.adj_hibernation()
|
||||||
self.sleep()
|
self.sleep()
|
||||||
@@ -806,14 +812,16 @@ class Scheduler(MetaScheduler):
|
|||||||
ticker = all_active.find(lambda row: row.is_ticker is True).first()
|
ticker = all_active.find(lambda row: row.is_ticker is True).first()
|
||||||
not_busy = self.worker_status[0] == ACTIVE
|
not_busy = self.worker_status[0] == ACTIVE
|
||||||
if not ticker:
|
if not ticker:
|
||||||
|
#if no other tickers are around
|
||||||
if not_busy:
|
if not_busy:
|
||||||
#only if this worker isn't busy, otherwise wait for a free one
|
#only if I'm not busy
|
||||||
db(sw.worker_name == self.worker_name).update(is_ticker=True)
|
db(sw.worker_name == self.worker_name).update(is_ticker=True)
|
||||||
db(sw.worker_name != self.worker_name).update(is_ticker=False)
|
db(sw.worker_name != self.worker_name).update(is_ticker=False)
|
||||||
logger.info("TICKER: I'm a ticker")
|
logger.info("TICKER: I'm a ticker")
|
||||||
else:
|
else:
|
||||||
#giving up, only if I'm not alone
|
#I'm busy
|
||||||
if len(all_active) > 1:
|
if len(all_active) >= 1:
|
||||||
|
#so I'll "downgrade" myself to a "poor worker"
|
||||||
db(sw.worker_name == self.worker_name).update(is_ticker=False)
|
db(sw.worker_name == self.worker_name).update(is_ticker=False)
|
||||||
else:
|
else:
|
||||||
not_busy = True
|
not_busy = True
|
||||||
|
|||||||
@@ -160,18 +160,19 @@ def rss(feed):
|
|||||||
if not 'entries' in feed and 'items' in feed:
|
if not 'entries' in feed and 'items' in feed:
|
||||||
feed['entries'] = feed['items']
|
feed['entries'] = feed['items']
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
rss = rss2.RSS2(title=str(feed.get('title', '(notitle)')),
|
rss = rss2.RSS2(title=str(feed.get('title', '(notitle)').encode('utf-8', 'replace')),
|
||||||
link=str(feed.get('link', None)),
|
link=str(feed.get('link', None).encode('utf-8', 'replace')),
|
||||||
description=str(feed.get('description', '')),
|
description=str(feed.get('description', '').encode('utf-8', 'replace')),
|
||||||
lastBuildDate=feed.get('created_on', now),
|
lastBuildDate=feed.get('created_on', now),
|
||||||
items=[rss2.RSSItem(
|
items=[rss2.RSSItem(
|
||||||
title=str(entry.get('title', '(notitle)')),
|
title=str(entry.get('title', '(notitle)').encode('utf-8', 'replace')),
|
||||||
link=str(entry.get('link', None)),
|
link=str(entry.get('link', None).encode('utf-8', 'replace')),
|
||||||
description=str(entry.get('description', '')),
|
description=str(entry.get('description', '').encode('utf-8', 'replace')),
|
||||||
pubDate=entry.get('created_on', now)
|
pubDate=entry.get('created_on', now)
|
||||||
) for entry in feed.get('entries', [])])
|
) for entry in feed.get('entries', [])])
|
||||||
return rss.to_xml(encoding='utf-8')
|
return rss.to_xml(encoding='utf-8')
|
||||||
|
|
||||||
|
|
||||||
def yaml(data):
|
def yaml(data):
|
||||||
if have_yaml:
|
if have_yaml:
|
||||||
return yamlib.dump(data)
|
return yamlib.dump(data)
|
||||||
@@ -181,4 +182,3 @@ def loads_yaml(data):
|
|||||||
if have_yaml:
|
if have_yaml:
|
||||||
return yamlib.load(data)
|
return yamlib.load(data)
|
||||||
else: raise ImportError("No YAML serializer available")
|
else: raise ImportError("No YAML serializer available")
|
||||||
|
|
||||||
|
|||||||
+78
-33
@@ -19,6 +19,7 @@ except ImportError:
|
|||||||
from cgi import parse_qs as psq
|
from cgi import parse_qs as psq
|
||||||
import os
|
import os
|
||||||
from http import HTTP
|
from http import HTTP
|
||||||
|
from html import XmlComponent
|
||||||
from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG, SCRIPT
|
from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG, SCRIPT
|
||||||
from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON
|
from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON
|
||||||
from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE
|
from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE
|
||||||
@@ -349,6 +350,12 @@ class RadioWidget(OptionsWidget):
|
|||||||
see also: :meth:`FormWidget.widget`
|
see also: :meth:`FormWidget.widget`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if isinstance(value, (list,tuple)):
|
||||||
|
value = str(value[0])
|
||||||
|
else:
|
||||||
|
value = str(value)
|
||||||
|
|
||||||
|
|
||||||
attr = cls._attributes(field, {}, **attributes)
|
attr = cls._attributes(field, {}, **attributes)
|
||||||
attr['_class'] = attr.get('_class', 'web2py_radiowidget')
|
attr['_class'] = attr.get('_class', 'web2py_radiowidget')
|
||||||
|
|
||||||
@@ -1174,9 +1181,10 @@ class SQLFORM(FORM):
|
|||||||
xfields.append(
|
xfields.append(
|
||||||
(self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_ROW_SUFFIX,
|
(self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_ROW_SUFFIX,
|
||||||
LABEL(
|
LABEL(
|
||||||
delete_label, separator,
|
T(delete_label), separator,
|
||||||
_for=self.FIELDKEY_DELETE_RECORD,
|
_for=self.FIELDKEY_DELETE_RECORD,
|
||||||
_id=self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_LABEL_SUFFIX),
|
_id=self.FIELDKEY_DELETE_RECORD + \
|
||||||
|
SQLFORM.ID_LABEL_SUFFIX),
|
||||||
widget,
|
widget,
|
||||||
col3.get(self.FIELDKEY_DELETE_RECORD, '')))
|
col3.get(self.FIELDKEY_DELETE_RECORD, '')))
|
||||||
self.custom.delete = self.custom.deletable = widget
|
self.custom.delete = self.custom.deletable = widget
|
||||||
@@ -1223,7 +1231,8 @@ class SQLFORM(FORM):
|
|||||||
table = TABLE()
|
table = TABLE()
|
||||||
for id, a, b, c in xfields:
|
for id, a, b, c in xfields:
|
||||||
newrows = formstyle(id, a, b, c)
|
newrows = formstyle(id, a, b, c)
|
||||||
self.field_parent[id] = getattr(b, 'parent', None)
|
self.field_parent[id] = getattr(b, 'parent', None) \
|
||||||
|
if isinstance(b,XmlComponent) else None
|
||||||
if type(newrows).__name__ != "tuple":
|
if type(newrows).__name__ != "tuple":
|
||||||
newrows = [newrows]
|
newrows = [newrows]
|
||||||
for newrow in newrows:
|
for newrow in newrows:
|
||||||
@@ -1231,7 +1240,8 @@ class SQLFORM(FORM):
|
|||||||
else:
|
else:
|
||||||
table = formstyle(self, xfields)
|
table = formstyle(self, xfields)
|
||||||
for id, a, b, c in xfields:
|
for id, a, b, c in xfields:
|
||||||
self.field_parent[id] = getattr(b, 'parent', None)
|
self.field_parent[id] = getattr(b, 'parent', None) \
|
||||||
|
if isinstance(b,XmlComponent) else None
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('formstyle not supported')
|
raise RuntimeError('formstyle not supported')
|
||||||
return table
|
return table
|
||||||
@@ -1581,7 +1591,7 @@ class SQLFORM(FORM):
|
|||||||
|
|
||||||
table_name = attributes.get('table_name', 'no_table')
|
table_name = attributes.get('table_name', 'no_table')
|
||||||
|
|
||||||
# So it won't interfear with SQLDB.define_table
|
# So it won't interfere with SQLDB.define_table
|
||||||
if 'table_name' in attributes:
|
if 'table_name' in attributes:
|
||||||
del attributes['table_name']
|
del attributes['table_name']
|
||||||
|
|
||||||
@@ -1760,6 +1770,7 @@ class SQLFORM(FORM):
|
|||||||
createargs={},
|
createargs={},
|
||||||
editargs={},
|
editargs={},
|
||||||
viewargs={},
|
viewargs={},
|
||||||
|
selectable_submit_button='Submit',
|
||||||
buttons_placement = 'right',
|
buttons_placement = 'right',
|
||||||
links_placement = 'right',
|
links_placement = 'right',
|
||||||
noconfirm=False
|
noconfirm=False
|
||||||
@@ -1892,7 +1903,7 @@ class SQLFORM(FORM):
|
|||||||
tablename = table._tablename
|
tablename = table._tablename
|
||||||
if upload == '<default>':
|
if upload == '<default>':
|
||||||
upload = lambda filename: url(args=['download', filename])
|
upload = lambda filename: url(args=['download', filename])
|
||||||
if len(request.args) > 1 and request.args[-2] == 'download':
|
if request.args(-2) == 'download':
|
||||||
stream = response.download(request, db)
|
stream = response.download(request, db)
|
||||||
raise HTTP(200, stream, **response.headers)
|
raise HTTP(200, stream, **response.headers)
|
||||||
|
|
||||||
@@ -1929,7 +1940,7 @@ class SQLFORM(FORM):
|
|||||||
create_form = update_form = view_form = search_form = None
|
create_form = update_form = view_form = search_form = None
|
||||||
sqlformargs = dict(formargs)
|
sqlformargs = dict(formargs)
|
||||||
|
|
||||||
if create and len(request.args) > 1 and request.args[-2] == 'new':
|
if create and request.args(-2) == 'new':
|
||||||
table = db[request.args[-1]]
|
table = db[request.args[-1]]
|
||||||
sqlformargs.update(createargs)
|
sqlformargs.update(createargs)
|
||||||
create_form = SQLFORM(
|
create_form = SQLFORM(
|
||||||
@@ -1948,7 +1959,7 @@ class SQLFORM(FORM):
|
|||||||
res.search_form = search_form
|
res.search_form = search_form
|
||||||
return res
|
return res
|
||||||
|
|
||||||
elif details and len(request.args) > 2 and request.args[-3] == 'view':
|
elif details and request.args(-3) == 'view':
|
||||||
table = db[request.args[-2]]
|
table = db[request.args[-2]]
|
||||||
record = table(request.args[-1]) or redirect(referrer)
|
record = table(request.args[-1]) or redirect(referrer)
|
||||||
sqlformargs.update(viewargs)
|
sqlformargs.update(viewargs)
|
||||||
@@ -1963,7 +1974,7 @@ class SQLFORM(FORM):
|
|||||||
res.view_form = view_form
|
res.view_form = view_form
|
||||||
res.search_form = search_form
|
res.search_form = search_form
|
||||||
return res
|
return res
|
||||||
elif editable and len(request.args) > 2 and request.args[-3] == 'edit':
|
elif editable and request.args(-3) == 'edit':
|
||||||
table = db[request.args[-2]]
|
table = db[request.args[-2]]
|
||||||
record = table(request.args[-1]) or redirect(URL('error'))
|
record = table(request.args[-1]) or redirect(URL('error'))
|
||||||
sqlformargs.update(editargs)
|
sqlformargs.update(editargs)
|
||||||
@@ -1988,7 +1999,7 @@ class SQLFORM(FORM):
|
|||||||
res.view_form = view_form
|
res.view_form = view_form
|
||||||
res.search_form = search_form
|
res.search_form = search_form
|
||||||
return res
|
return res
|
||||||
elif deletable and len(request.args) > 2 and request.args[-3] == 'delete':
|
elif deletable and request.args(-3) == 'delete':
|
||||||
table = db[request.args[-2]]
|
table = db[request.args[-2]]
|
||||||
if ondelete:
|
if ondelete:
|
||||||
ondelete(table, request.args[-1])
|
ondelete(table, request.args[-1])
|
||||||
@@ -2111,10 +2122,15 @@ class SQLFORM(FORM):
|
|||||||
if subquery:
|
if subquery:
|
||||||
dbset = dbset(subquery)
|
dbset = dbset(subquery)
|
||||||
try:
|
try:
|
||||||
if left or groupby:
|
if groupby:
|
||||||
c = 'count(*)'
|
c = 'count(*)'
|
||||||
nrows = dbset.select(c, left=left, cacheable=True,
|
nrows = db.executesql(
|
||||||
groupby=groupby).first()[c]
|
'select count(*) from (%s);' %
|
||||||
|
dbset._select(c, left=left, cacheable=True,
|
||||||
|
groupby=groupby)[:-1])[0][0]
|
||||||
|
elif left:
|
||||||
|
c = 'count(*)'
|
||||||
|
nrows = dbset.select(c, left=left, cacheable=True).first()[c]
|
||||||
elif dbset._db._adapter.dbengine=='google:datastore':
|
elif dbset._db._adapter.dbengine=='google:datastore':
|
||||||
#if we don't set a limit, this can timeout for a large table
|
#if we don't set a limit, this can timeout for a large table
|
||||||
nrows = dbset.db._adapter.count(dbset.query, limit=1000)
|
nrows = dbset.db._adapter.count(dbset.query, limit=1000)
|
||||||
@@ -2368,9 +2384,12 @@ class SQLFORM(FORM):
|
|||||||
tr = TR(*trcols, **dict(_class=classtr))
|
tr = TR(*trcols, **dict(_class=classtr))
|
||||||
tbody.append(tr)
|
tbody.append(tr)
|
||||||
htmltable.append(tbody)
|
htmltable.append(tbody)
|
||||||
htmltable = DIV(htmltable, _style='width:100%;overflow-x:auto')
|
htmltable = DIV(
|
||||||
|
htmltable, _class='web2py_htmltable',
|
||||||
|
_style='width:100%;overflow-x:auto;-ms-overflow-x:scroll')
|
||||||
if selectable:
|
if selectable:
|
||||||
htmltable = FORM(htmltable, INPUT(_type="submit"))
|
htmltable = FORM(htmltable, INPUT(
|
||||||
|
_type="submit", _value=T(selectable_submit_button)))
|
||||||
if htmltable.process(formname=formname).accepted:
|
if htmltable.process(formname=formname).accepted:
|
||||||
htmltable.vars.records = htmltable.vars.records or []
|
htmltable.vars.records = htmltable.vars.records or []
|
||||||
htmltable.vars.records = htmltable.vars.records if type(htmltable.vars.records) == list else [htmltable.vars.records]
|
htmltable.vars.records = htmltable.vars.records if type(htmltable.vars.records) == list else [htmltable.vars.records]
|
||||||
@@ -2518,8 +2537,9 @@ class SQLFORM(FORM):
|
|||||||
break
|
break
|
||||||
if nargs > len(args) + 1:
|
if nargs > len(args) + 1:
|
||||||
query = (field == id)
|
query = (field == id)
|
||||||
if isinstance(linked_tables, dict):
|
# cjk
|
||||||
linked_tables = linked_tables.get(table._tablename, [])
|
# if isinstance(linked_tables, dict):
|
||||||
|
# linked_tables = linked_tables.get(table._tablename, [])
|
||||||
if linked_tables is None or referee in linked_tables:
|
if linked_tables is None or referee in linked_tables:
|
||||||
field.represent = lambda id, r=None, referee=referee, rep=field.represent: A(callable(rep) and rep(id) or id, _class=trap_class(), _href=url(args=['view', referee, id]))
|
field.represent = lambda id, r=None, referee=referee, rep=field.represent: A(callable(rep) and rep(id) or id, _class=trap_class(), _href=url(args=['view', referee, id]))
|
||||||
except (KeyError, ValueError, TypeError):
|
except (KeyError, ValueError, TypeError):
|
||||||
@@ -2544,20 +2564,45 @@ class SQLFORM(FORM):
|
|||||||
check[rfield.tablename] = \
|
check[rfield.tablename] = \
|
||||||
check.get(rfield.tablename, []) + [rfield.name]
|
check.get(rfield.tablename, []) + [rfield.name]
|
||||||
if isinstance(linked_tables, dict):
|
if isinstance(linked_tables, dict):
|
||||||
linked_tables = linked_tables.get(table._tablename, [])
|
for tbl in linked_tables.keys():
|
||||||
for tablename in sorted(check):
|
tb = db[tbl]
|
||||||
linked_fieldnames = check[tablename]
|
if isinstance(linked_tables[tbl], list):
|
||||||
tb = db[tablename]
|
if len(linked_tables[tbl]) > 1:
|
||||||
multiple_links = len(linked_fieldnames) > 1
|
t = T('%s(%s)' %(tbl, fld))
|
||||||
for fieldname in linked_fieldnames:
|
else:
|
||||||
if linked_tables is None or tablename in linked_tables:
|
t = T(tb._plural)
|
||||||
t = T(tb._plural) if not multiple_links else \
|
for fld in linked_tables[tbl]:
|
||||||
T(tb._plural + '(' + fieldname + ')')
|
if fld not in db[tbl].fields:
|
||||||
args0 = tablename + '.' + fieldname
|
raise ValueError('Field %s not in table' %fld)
|
||||||
|
args0 = tbl + '.' + fld
|
||||||
|
links.append(
|
||||||
|
lambda row, t=t, nargs=nargs, args0=args0:
|
||||||
|
A(SPAN(t), _class=trap_class(), _href=url(
|
||||||
|
args=[args0, row[id_field_name]])))
|
||||||
|
else:
|
||||||
|
t = T(tb._plural)
|
||||||
|
fld = linked_tables[tbl]
|
||||||
|
if fld not in db[tbl].fields:
|
||||||
|
raise ValueError('Field %s not in table' %fld)
|
||||||
|
args0 = tbl + '.' + fld
|
||||||
links.append(
|
links.append(
|
||||||
lambda row, t=t, nargs=nargs, args0=args0:
|
lambda row, t=t, nargs=nargs, args0=args0:
|
||||||
A(SPAN(t), _class=trap_class(), _href=url(
|
A(SPAN(t), _class=trap_class(), _href=url(
|
||||||
args=[args0, row[id_field_name]])))
|
args=[args0, row[id_field_name]])))
|
||||||
|
else:
|
||||||
|
for tablename in sorted(check):
|
||||||
|
linked_fieldnames = check[tablename]
|
||||||
|
tb = db[tablename]
|
||||||
|
multiple_links = len(linked_fieldnames) > 1
|
||||||
|
for fieldname in linked_fieldnames:
|
||||||
|
if linked_tables is None or tablename in linked_tables:
|
||||||
|
t = T(tb._plural) if not multiple_links else \
|
||||||
|
T(tb._plural + '(' + fieldname + ')')
|
||||||
|
args0 = tablename + '.' + fieldname
|
||||||
|
links.append(
|
||||||
|
lambda row, t=t, nargs=nargs, args0=args0:
|
||||||
|
A(SPAN(t), _class=trap_class(), _href=url(
|
||||||
|
args=[args0, row[id_field_name]])))
|
||||||
|
|
||||||
grid = SQLFORM.grid(query, args=request.args[:nargs], links=links,
|
grid = SQLFORM.grid(query, args=request.args[:nargs], links=links,
|
||||||
links_in_grid=links_in_grid,
|
links_in_grid=links_in_grid,
|
||||||
@@ -2567,7 +2612,7 @@ class SQLFORM(FORM):
|
|||||||
header = table._plural
|
header = table._plural
|
||||||
next = grid.create_form or grid.update_form or grid.view_form
|
next = grid.create_form or grid.update_form or grid.view_form
|
||||||
breadcrumbs.append(LI(
|
breadcrumbs.append(LI(
|
||||||
A(T(header), _class=trap_class(),_href=url()),
|
A(T(header), _class=trap_class(),_href=url()),
|
||||||
SPAN(divider, _class='divider') if next else '',
|
SPAN(divider, _class='divider') if next else '',
|
||||||
_class='active w2p_grid_breadcrumb_elem'))
|
_class='active w2p_grid_breadcrumb_elem'))
|
||||||
if grid.create_form:
|
if grid.create_form:
|
||||||
@@ -2578,7 +2623,7 @@ class SQLFORM(FORM):
|
|||||||
header = T('View %s' % format(table,grid.view_form.record))
|
header = T('View %s' % format(table,grid.view_form.record))
|
||||||
if next:
|
if next:
|
||||||
breadcrumbs.append(LI(
|
breadcrumbs.append(LI(
|
||||||
A(T(header), _class=trap_class(),_href=url()),
|
A(T(header), _class=trap_class(),_href=url()),
|
||||||
_class='active w2p_grid_breadcrumb_elem'))
|
_class='active w2p_grid_breadcrumb_elem'))
|
||||||
grid.insert(
|
grid.insert(
|
||||||
0, DIV(UL(*breadcrumbs, **{'_class': breadcrumbs_class}),
|
0, DIV(UL(*breadcrumbs, **{'_class': breadcrumbs_class}),
|
||||||
@@ -2635,7 +2680,7 @@ class SQLTABLE(TABLE):
|
|||||||
:param selectid: The id you want to select
|
:param selectid: The id you want to select
|
||||||
:param renderstyle: Boolean render the style with the table
|
:param renderstyle: Boolean render the style with the table
|
||||||
|
|
||||||
:param extracolums = [{'label':A('Extra',_href='#'),
|
:param extracolumns = [{'label':A('Extra',_href='#'),
|
||||||
'class': '', #class name of the header
|
'class': '', #class name of the header
|
||||||
'width':'', #width in pixels or %
|
'width':'', #width in pixels or %
|
||||||
'content':lambda row, rc: A('Edit',_href='edit/%s'%row.id),
|
'content':lambda row, rc: A('Edit',_href='edit/%s'%row.id),
|
||||||
@@ -2657,8 +2702,8 @@ class SQLTABLE(TABLE):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
table = SQLTABLE(rows, headers=headers, extracolums=extracolums)
|
table = SQLTABLE(rows, headers=headers, extracolumns=extracolumns)
|
||||||
|
`<
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ from test_template import *
|
|||||||
from test_utils import *
|
from test_utils import *
|
||||||
from test_contribs import *
|
from test_contribs import *
|
||||||
from test_markmin import *
|
from test_markmin import *
|
||||||
# from test_web import *
|
from test_web import *
|
||||||
|
|||||||
+72
-45
@@ -250,26 +250,26 @@ class TestSelect(unittest.TestCase):
|
|||||||
self.assertEqual(db.tt.insert(aa='1'), 1)
|
self.assertEqual(db.tt.insert(aa='1'), 1)
|
||||||
self.assertEqual(db.tt.insert(aa='2'), 2)
|
self.assertEqual(db.tt.insert(aa='2'), 2)
|
||||||
self.assertEqual(db.tt.insert(aa='3'), 3)
|
self.assertEqual(db.tt.insert(aa='3'), 3)
|
||||||
self.assertEqual(len(db(db.tt.id > 0).select()), 3)
|
self.assertEqual(db(db.tt.id > 0).count(), 3)
|
||||||
self.assertEqual(db(db.tt.id > 0).select(orderby=~db.tt.aa
|
self.assertEqual(db(db.tt.id > 0).select(orderby=~db.tt.aa
|
||||||
| db.tt.id)[0].aa, '3')
|
| db.tt.id)[0].aa, '3')
|
||||||
self.assertEqual(len(db(db.tt.id > 0).select(limitby=(1, 2))), 1)
|
self.assertEqual(len(db(db.tt.id > 0).select(limitby=(1, 2))), 1)
|
||||||
self.assertEqual(db(db.tt.id > 0).select(limitby=(1, 2))[0].aa,
|
self.assertEqual(db(db.tt.id > 0).select(limitby=(1, 2))[0].aa,
|
||||||
'2')
|
'2')
|
||||||
self.assertEqual(len(db().select(db.tt.ALL)), 3)
|
self.assertEqual(len(db().select(db.tt.ALL)), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa == None).select()), 0)
|
self.assertEqual(db(db.tt.aa == None).count(), 0)
|
||||||
self.assertEqual(len(db(db.tt.aa != None).select()), 3)
|
self.assertEqual(db(db.tt.aa != None).count(), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa > '1').select()), 2)
|
self.assertEqual(db(db.tt.aa > '1').count(), 2)
|
||||||
self.assertEqual(len(db(db.tt.aa >= '1').select()), 3)
|
self.assertEqual(db(db.tt.aa >= '1').count(), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa == '1').select()), 1)
|
self.assertEqual(db(db.tt.aa == '1').count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa != '1').select()), 2)
|
self.assertEqual(db(db.tt.aa != '1').count(), 2)
|
||||||
self.assertEqual(len(db(db.tt.aa < '3').select()), 2)
|
self.assertEqual(db(db.tt.aa < '3').count(), 2)
|
||||||
self.assertEqual(len(db(db.tt.aa <= '3').select()), 3)
|
self.assertEqual(db(db.tt.aa <= '3').count(), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa > '1')(db.tt.aa < '3').select()), 1)
|
self.assertEqual(db(db.tt.aa > '1')(db.tt.aa < '3').count(), 1)
|
||||||
self.assertEqual(len(db((db.tt.aa > '1') & (db.tt.aa < '3')).select()), 1)
|
self.assertEqual(db((db.tt.aa > '1') & (db.tt.aa < '3')).count(), 1)
|
||||||
self.assertEqual(len(db((db.tt.aa > '1') | (db.tt.aa < '3')).select()), 3)
|
self.assertEqual(db((db.tt.aa > '1') | (db.tt.aa < '3')).count(), 3)
|
||||||
self.assertEqual(len(db((db.tt.aa > '1') & ~(db.tt.aa > '2')).select()), 1)
|
self.assertEqual(db((db.tt.aa > '1') & ~(db.tt.aa > '2')).count(), 1)
|
||||||
self.assertEqual(len(db(~(db.tt.aa > '1') & (db.tt.aa > '2')).select()), 0)
|
self.assertEqual(db(~(db.tt.aa > '1') & (db.tt.aa > '2')).count(), 0)
|
||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
|
|
||||||
|
|
||||||
@@ -281,15 +281,15 @@ class TestBelongs(unittest.TestCase):
|
|||||||
self.assertEqual(db.tt.insert(aa='1'), 1)
|
self.assertEqual(db.tt.insert(aa='1'), 1)
|
||||||
self.assertEqual(db.tt.insert(aa='2'), 2)
|
self.assertEqual(db.tt.insert(aa='2'), 2)
|
||||||
self.assertEqual(db.tt.insert(aa='3'), 3)
|
self.assertEqual(db.tt.insert(aa='3'), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa.belongs(('1', '3'))).select()),
|
self.assertEqual(db(db.tt.aa.belongs(('1', '3'))).count(),
|
||||||
2)
|
2)
|
||||||
self.assertEqual(len(db(db.tt.aa.belongs(db(db.tt.id
|
self.assertEqual(db(db.tt.aa.belongs(db(db.tt.id
|
||||||
> 2)._select(db.tt.aa))).select()), 1)
|
> 2)._select(db.tt.aa))).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.belongs(db(db.tt.aa.belongs(('1',
|
self.assertEqual(db(db.tt.aa.belongs(db(db.tt.aa.belongs(('1',
|
||||||
'3')))._select(db.tt.aa))).select()), 2)
|
'3')))._select(db.tt.aa))).count(), 2)
|
||||||
self.assertEqual(len(db(db.tt.aa.belongs(db(db.tt.aa.belongs(db
|
self.assertEqual(db(db.tt.aa.belongs(db(db.tt.aa.belongs(db
|
||||||
(db.tt.aa.belongs(('1', '3')))._select(db.tt.aa)))._select(
|
(db.tt.aa.belongs(('1', '3')))._select(db.tt.aa)))._select(
|
||||||
db.tt.aa))).select()),
|
db.tt.aa))).count(),
|
||||||
2)
|
2)
|
||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
|
|
||||||
@@ -297,16 +297,17 @@ class TestBelongs(unittest.TestCase):
|
|||||||
class TestContains(unittest.TestCase):
|
class TestContains(unittest.TestCase):
|
||||||
def testRun(self):
|
def testRun(self):
|
||||||
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
||||||
db.define_table('tt', Field('aa', 'list:string'))
|
db.define_table('tt', Field('aa', 'list:string'), Field('bb','string'))
|
||||||
self.assertEqual(db.tt.insert(aa=['aaa','bbb']), 1)
|
self.assertEqual(db.tt.insert(aa=['aaa','bbb'],bb='aaa'), 1)
|
||||||
self.assertEqual(db.tt.insert(aa=['bbb','ddd']), 2)
|
self.assertEqual(db.tt.insert(aa=['bbb','ddd'],bb='abb'), 2)
|
||||||
self.assertEqual(db.tt.insert(aa=['eee','aaa']), 3)
|
self.assertEqual(db.tt.insert(aa=['eee','aaa'],bb='acc'), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa.contains('aaa')).select()),
|
self.assertEqual(db(db.tt.aa.contains('aaa')).count(), 2)
|
||||||
2)
|
self.assertEqual(db(db.tt.aa.contains('bbb')).count(), 2)
|
||||||
self.assertEqual(len(db(db.tt.aa.contains('bbb')).select()),
|
self.assertEqual(db(db.tt.aa.contains('aa')).count(), 0)
|
||||||
2)
|
self.assertEqual(db(db.tt.bb.contains('a')).count(), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa.contains('aa')).select()),
|
self.assertEqual(db(db.tt.bb.contains('b')).count(), 1)
|
||||||
0)
|
self.assertEqual(db(db.tt.bb.contains('d')).count(), 0)
|
||||||
|
self.assertEqual(db(db.tt.aa.contains(db.tt.bb)).count(), 1)
|
||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
|
|
||||||
|
|
||||||
@@ -316,23 +317,23 @@ class TestLike(unittest.TestCase):
|
|||||||
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
||||||
db.define_table('tt', Field('aa'))
|
db.define_table('tt', Field('aa'))
|
||||||
self.assertEqual(db.tt.insert(aa='abc'), 1)
|
self.assertEqual(db.tt.insert(aa='abc'), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('a%')).select()), 1)
|
self.assertEqual(db(db.tt.aa.like('a%')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('%b%')).select()), 1)
|
self.assertEqual(db(db.tt.aa.like('%b%')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('%c')).select()), 1)
|
self.assertEqual(db(db.tt.aa.like('%c')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('%d%')).select()), 0)
|
self.assertEqual(db(db.tt.aa.like('%d%')).count(), 0)
|
||||||
self.assertEqual(len(db(db.tt.aa.lower().like('A%')).select()), 1)
|
self.assertEqual(db(db.tt.aa.lower().like('A%')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.lower().like('%B%')).select()),
|
self.assertEqual(db(db.tt.aa.lower().like('%B%')).count(),
|
||||||
1)
|
1)
|
||||||
self.assertEqual(len(db(db.tt.aa.lower().like('%C')).select()), 1)
|
self.assertEqual(db(db.tt.aa.lower().like('%C')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.upper().like('A%')).select()), 1)
|
self.assertEqual(db(db.tt.aa.upper().like('A%')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.upper().like('%B%')).select()),
|
self.assertEqual(db(db.tt.aa.upper().like('%B%')).count(),
|
||||||
1)
|
1)
|
||||||
self.assertEqual(len(db(db.tt.aa.upper().like('%C')).select()), 1)
|
self.assertEqual(db(db.tt.aa.upper().like('%C')).count(), 1)
|
||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
db.define_table('tt', Field('aa', 'integer'))
|
db.define_table('tt', Field('aa', 'integer'))
|
||||||
self.assertEqual(db.tt.insert(aa=1111111111), 1)
|
self.assertEqual(db.tt.insert(aa=1111111111), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('1%')).select()), 1)
|
self.assertEqual(db(db.tt.aa.like('1%')).count(), 1)
|
||||||
self.assertEqual(len(db(db.tt.aa.like('2%')).select()), 0)
|
self.assertEqual(db(db.tt.aa.like('2%')).count(), 0)
|
||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
|
|
||||||
|
|
||||||
@@ -347,8 +348,8 @@ class TestDatetime(unittest.TestCase):
|
|||||||
10, 30)), 2)
|
10, 30)), 2)
|
||||||
self.assertEqual(db.tt.insert(aa=datetime.datetime(1970, 12, 21,
|
self.assertEqual(db.tt.insert(aa=datetime.datetime(1970, 12, 21,
|
||||||
9, 30)), 3)
|
9, 30)), 3)
|
||||||
self.assertEqual(len(db(db.tt.aa == datetime.datetime(1971, 12,
|
self.assertEqual(db(db.tt.aa == datetime.datetime(1971, 12,
|
||||||
21, 11, 30)).select()), 1)
|
21, 11, 30)).count(), 1)
|
||||||
self.assertEqual(db(db.tt.aa.year() == 1971).count(), 2)
|
self.assertEqual(db(db.tt.aa.year() == 1971).count(), 2)
|
||||||
self.assertEqual(db(db.tt.aa.month() == 12).count(), 2)
|
self.assertEqual(db(db.tt.aa.month() == 12).count(), 2)
|
||||||
self.assertEqual(db(db.tt.aa.day() == 21).count(), 3)
|
self.assertEqual(db(db.tt.aa.day() == 21).count(), 3)
|
||||||
@@ -582,6 +583,32 @@ class TestComputedFields(unittest.TestCase):
|
|||||||
db.tt.drop()
|
db.tt.drop()
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
class TestCommonFilters(unittest.TestCase):
|
||||||
|
|
||||||
|
def testRun(self):
|
||||||
|
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
||||||
|
db.define_table('t1', Field('aa'))
|
||||||
|
db.define_table('t2', Field('aa'), Field('b', db.t1))
|
||||||
|
i1 = db.t1.insert(aa='1')
|
||||||
|
i2 = db.t1.insert(aa='2')
|
||||||
|
i3 = db.t1.insert(aa='3')
|
||||||
|
db.t2.insert(aa='4', b=i1)
|
||||||
|
db.t2.insert(aa='5', b=i2)
|
||||||
|
db.t2.insert(aa='6', b=i2)
|
||||||
|
db.t1._common_filter = lambda q: db.t1.aa>1
|
||||||
|
self.assertEqual(db(db.t1).count(),2)
|
||||||
|
self.assertEqual(db(db.t1).count(),2)
|
||||||
|
q = db.t2.b==db.t1.id
|
||||||
|
self.assertEqual(db(q).count(),2)
|
||||||
|
self.assertEqual(db(q).count(),2)
|
||||||
|
self.assertEqual(len(db(db.t1).select(left=db.t2.on(q))),3)
|
||||||
|
db.t2._common_filter = lambda q: db.t2.aa<6
|
||||||
|
self.assertEqual(db(q).count(),1)
|
||||||
|
self.assertEqual(db(q).count(),1)
|
||||||
|
self.assertEqual(len(db(db.t1).select(left=db.t2.on(q))),2)
|
||||||
|
db.t2.drop()
|
||||||
|
db.t1.drop()
|
||||||
|
|
||||||
class TestImportExportFields(unittest.TestCase):
|
class TestImportExportFields(unittest.TestCase):
|
||||||
|
|
||||||
def testRun(self):
|
def testRun(self):
|
||||||
|
|||||||
@@ -206,6 +206,12 @@ class TestBareHelpers(unittest.TestCase):
|
|||||||
self.assertEqual(UL('<>', _a='1', _b='2').xml(),
|
self.assertEqual(UL('<>', _a='1', _b='2').xml(),
|
||||||
'<ul a="1" b="2"><li><></li></ul>')
|
'<ul a="1" b="2"><li><></li></ul>')
|
||||||
|
|
||||||
|
class TestData(unittest.TestCase):
|
||||||
|
|
||||||
|
def testAdata(self):
|
||||||
|
self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),
|
||||||
|
'<a a="1" b="2" data-abc="<def?asd>" data-cde="standard"><></a>')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
+52
-6
@@ -11,11 +11,58 @@ else:
|
|||||||
sys.path.append(os.path.realpath('../'))
|
sys.path.append(os.path.realpath('../'))
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import signal
|
||||||
from contrib.webclient import WebClient
|
from contrib.webclient import WebClient
|
||||||
|
|
||||||
|
webserverprocess = None
|
||||||
|
|
||||||
class TestWeb(unittest.TestCase):
|
def startwebserver():
|
||||||
def testWebClient(self):
|
global webserverprocess
|
||||||
|
webserverprocess = subprocess.Popen([sys.executable, 'web2py.py', '-a', 'testpass'])
|
||||||
|
print 'Sleeping before web2py starts...'
|
||||||
|
for a in range(1,11):
|
||||||
|
time.sleep(1)
|
||||||
|
print a, '...'
|
||||||
|
print ''
|
||||||
|
|
||||||
|
def terminate_process(pid):
|
||||||
|
#Taken from http://stackoverflow.com/questions/1064335/in-python-2-5-how-do-i-kill-a-subprocess
|
||||||
|
# all this shit is because we are stuck with Python 2.5 and \
|
||||||
|
#we cannot use Popen.terminate()
|
||||||
|
if sys.platform.startswith('win'):
|
||||||
|
import ctypes
|
||||||
|
PROCESS_TERMINATE = 1
|
||||||
|
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, pid)
|
||||||
|
ctypes.windll.kernel32.TerminateProcess(handle, -1)
|
||||||
|
ctypes.windll.kernel32.CloseHandle(handle)
|
||||||
|
else:
|
||||||
|
os.kill(pid, signal.SIGKILL)
|
||||||
|
|
||||||
|
def stopwebserver():
|
||||||
|
global webserverprocess
|
||||||
|
print 'Killing webserver'
|
||||||
|
if sys.version_info < (2,6):
|
||||||
|
terminate_process(webserverprocess.pid)
|
||||||
|
else:
|
||||||
|
webserverprocess.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
class LiveTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
startwebserver()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
stopwebserver()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestWeb(LiveTest):
|
||||||
|
def testRegisterAndLogin(self):
|
||||||
client = WebClient('http://127.0.0.1:8000/welcome/default/')
|
client = WebClient('http://127.0.0.1:8000/welcome/default/')
|
||||||
|
|
||||||
client.get('index')
|
client.get('index')
|
||||||
@@ -40,7 +87,7 @@ class TestWeb(unittest.TestCase):
|
|||||||
|
|
||||||
# check registration and login were successful
|
# check registration and login were successful
|
||||||
client.get('index')
|
client.get('index')
|
||||||
print client.text
|
|
||||||
self.assertTrue('Welcome Homer' in client.text)
|
self.assertTrue('Welcome Homer' in client.text)
|
||||||
|
|
||||||
client = WebClient('http://127.0.0.1:8000/admin/default/')
|
client = WebClient('http://127.0.0.1:8000/admin/default/')
|
||||||
@@ -48,9 +95,7 @@ class TestWeb(unittest.TestCase):
|
|||||||
client.get('site')
|
client.get('site')
|
||||||
client.get('design/welcome')
|
client.get('design/welcome')
|
||||||
|
|
||||||
|
def testStaticCache(self):
|
||||||
class TestStaticCacheControl(unittest.TestCase):
|
|
||||||
def testWebClient(self):
|
|
||||||
s = WebClient('http://127.0.0.1:8000/welcome/')
|
s = WebClient('http://127.0.0.1:8000/welcome/')
|
||||||
s.get('static/js/web2py.js')
|
s.get('static/js/web2py.js')
|
||||||
assert('expires' not in s.headers)
|
assert('expires' not in s.headers)
|
||||||
@@ -61,5 +106,6 @@ class TestStaticCacheControl(unittest.TestCase):
|
|||||||
assert('expires' in s.headers)
|
assert('expires' in s.headers)
|
||||||
assert(s.headers['cache-control'].startswith('max-age'))
|
assert(s.headers['cache-control'].startswith('max-age'))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
+69
-37
@@ -266,8 +266,8 @@ class Mail(object):
|
|||||||
def send(
|
def send(
|
||||||
self,
|
self,
|
||||||
to,
|
to,
|
||||||
subject='None',
|
subject = '[no subject]',
|
||||||
message='None',
|
message = '[no message]',
|
||||||
attachments=None,
|
attachments=None,
|
||||||
cc=None,
|
cc=None,
|
||||||
bcc=None,
|
bcc=None,
|
||||||
@@ -347,10 +347,10 @@ class Mail(object):
|
|||||||
mail.send_mail() method
|
mail.send_mail() method
|
||||||
self.error: Exception message or None if above was successful
|
self.error: Exception message or None if above was successful
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# We don't want to use base64 encoding for unicode mail
|
# We don't want to use base64 encoding for unicode mail
|
||||||
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')
|
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')
|
||||||
|
|
||||||
def encode_header(key):
|
def encode_header(key):
|
||||||
if [c for c in key if 32 > ord(c) or ord(c) > 127]:
|
if [c for c in key if 32 > ord(c) or ord(c) > 127]:
|
||||||
return Header.Header(key.encode('utf-8'), 'utf-8')
|
return Header.Header(key.encode('utf-8'), 'utf-8')
|
||||||
@@ -374,10 +374,14 @@ class Mail(object):
|
|||||||
payload_in = MIMEMultipart.MIMEMultipart('mixed')
|
payload_in = MIMEMultipart.MIMEMultipart('mixed')
|
||||||
else:
|
else:
|
||||||
# no encoding configuration for raw messages
|
# no encoding configuration for raw messages
|
||||||
if isinstance(message, basestring):
|
if not isinstance(message, basestring):
|
||||||
|
message = message.read()
|
||||||
|
if isinstance(message, unicode):
|
||||||
|
text = message.encode('utf-8')
|
||||||
|
elif not encoding=='utf-8':
|
||||||
text = message.decode(encoding).encode('utf-8')
|
text = message.decode(encoding).encode('utf-8')
|
||||||
else:
|
else:
|
||||||
text = message.read().decode(encoding).encode('utf-8')
|
text = message
|
||||||
# No charset passed to avoid transport encoding
|
# No charset passed to avoid transport encoding
|
||||||
# NOTE: some unicode encoded strings will produce
|
# NOTE: some unicode encoded strings will produce
|
||||||
# unreadable mail contents.
|
# unreadable mail contents.
|
||||||
@@ -397,7 +401,8 @@ class Mail(object):
|
|||||||
text = html = None
|
text = html = None
|
||||||
elif isinstance(message, (list, tuple)):
|
elif isinstance(message, (list, tuple)):
|
||||||
text, html = message
|
text, html = message
|
||||||
elif message.strip().startswith('<html') and message.strip().endswith('</html>'):
|
elif message.strip().startswith('<html') and \
|
||||||
|
message.strip().endswith('</html>'):
|
||||||
text = self.settings.server == 'gae' and message or None
|
text = self.settings.server == 'gae' and message or None
|
||||||
html = message
|
html = message
|
||||||
else:
|
else:
|
||||||
@@ -1424,7 +1429,7 @@ class Auth(object):
|
|||||||
def represent(id, record=None, s=settings):
|
def represent(id, record=None, s=settings):
|
||||||
try:
|
try:
|
||||||
user = s.table_user(id)
|
user = s.table_user(id)
|
||||||
return '%s %s' % (user.get("first_name", user.get("email")),
|
return '%s %s' % (user.get("first_name", user.get("email")),
|
||||||
user.get("last_name", ''))
|
user.get("last_name", ''))
|
||||||
except:
|
except:
|
||||||
return id
|
return id
|
||||||
@@ -1764,14 +1769,14 @@ class Auth(object):
|
|||||||
|
|
||||||
reads current.request.env.http_authorization
|
reads current.request.env.http_authorization
|
||||||
and returns basic_allowed,basic_accepted,user.
|
and returns basic_allowed,basic_accepted,user.
|
||||||
|
|
||||||
if basic_auth_realm is defined is a callable it's return value
|
if basic_auth_realm is defined is a callable it's return value
|
||||||
is used to set the basic authentication realm, if it's a string
|
is used to set the basic authentication realm, if it's a string
|
||||||
its content is used instead. Otherwise basic authentication realm
|
its content is used instead. Otherwise basic authentication realm
|
||||||
is set to the application name.
|
is set to the application name.
|
||||||
If basic_auth_realm is None or False (the default) the behavior
|
If basic_auth_realm is None or False (the default) the behavior
|
||||||
is to skip sending any challenge.
|
is to skip sending any challenge.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not self.settings.allow_basic_login:
|
if not self.settings.allow_basic_login:
|
||||||
return (False, False, False)
|
return (False, False, False)
|
||||||
@@ -1783,7 +1788,7 @@ class Auth(object):
|
|||||||
basic_realm = unicode(basic_auth_realm)
|
basic_realm = unicode(basic_auth_realm)
|
||||||
elif basic_auth_realm is True:
|
elif basic_auth_realm is True:
|
||||||
basic_realm = u'' + current.request.application
|
basic_realm = u'' + current.request.application
|
||||||
http_401 = HTTP(401, u'Not Authorized',
|
http_401 = HTTP(401, u'Not Authorized',
|
||||||
**{'WWW-Authenticate': u'Basic realm="' + basic_realm + '"'})
|
**{'WWW-Authenticate': u'Basic realm="' + basic_realm + '"'})
|
||||||
if not basic or not basic[:6].lower() == 'basic ':
|
if not basic or not basic[:6].lower() == 'basic ':
|
||||||
if basic_auth_realm:
|
if basic_auth_realm:
|
||||||
@@ -4325,7 +4330,7 @@ class Service(object):
|
|||||||
|
|
||||||
# jsonrpc 2.0 error types. records the following structure {code: (message,meaning)}
|
# jsonrpc 2.0 error types. records the following structure {code: (message,meaning)}
|
||||||
jsonrpc_errors = {
|
jsonrpc_errors = {
|
||||||
-32700: ("Parse error. Invalid JSON was received by the server.", "An error occurred on the server while parsing the JSON text."),
|
-32700: ("Parse error. Invalid JSON was received by the server.", "An error occurred on the server while parsing the JSON text."),
|
||||||
-32600: ("Invalid Request", "The JSON sent is not a valid Request object."),
|
-32600: ("Invalid Request", "The JSON sent is not a valid Request object."),
|
||||||
-32601: ("Method not found", "The method does not exist / is not available."),
|
-32601: ("Method not found", "The method does not exist / is not available."),
|
||||||
-32602: ("Invalid params", "Invalid method parameter(s)."),
|
-32602: ("Invalid params", "Invalid method parameter(s)."),
|
||||||
@@ -4380,7 +4385,7 @@ class Service(object):
|
|||||||
return return_error(id, 100, 'Exception %s: %s' % (etype, eval))
|
return return_error(id, 100, 'Exception %s: %s' % (etype, eval))
|
||||||
|
|
||||||
def serve_jsonrpc2(self, data=None, batch_element=False):
|
def serve_jsonrpc2(self, data=None, batch_element=False):
|
||||||
|
|
||||||
def return_response(id, result):
|
def return_response(id, result):
|
||||||
if not must_respond:
|
if not must_respond:
|
||||||
return None
|
return None
|
||||||
@@ -4411,9 +4416,9 @@ class Service(object):
|
|||||||
:returns:
|
:returns:
|
||||||
- True -- if successful
|
- True -- if successful
|
||||||
- False -- if no error should be reported (i.e. data is missing 'id' member)
|
- False -- if no error should be reported (i.e. data is missing 'id' member)
|
||||||
|
|
||||||
:raises: JsonRPCException
|
:raises: JsonRPCException
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
iparms = set(data.keys())
|
iparms = set(data.keys())
|
||||||
@@ -4429,8 +4434,8 @@ class Service(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
request = current.request
|
request = current.request
|
||||||
response = current.response
|
response = current.response
|
||||||
if not data:
|
if not data:
|
||||||
@@ -4439,7 +4444,7 @@ class Service(object):
|
|||||||
data = json_parser.loads(request.body.read())
|
data = json_parser.loads(request.body.read())
|
||||||
except ValueError: # decoding error in json lib
|
except ValueError: # decoding error in json lib
|
||||||
return return_error(None, -32700)
|
return return_error(None, -32700)
|
||||||
except json_parser.JSONDecodeError: # decoding error in simplejson lib
|
except json_parser.JSONDecodeError: # decoding error in simplejson lib
|
||||||
return return_error(None, -32700)
|
return return_error(None, -32700)
|
||||||
|
|
||||||
# Batch handling
|
# Batch handling
|
||||||
@@ -4455,12 +4460,12 @@ class Service(object):
|
|||||||
return "[" + ','.join(retlist) + "]"
|
return "[" + ','.join(retlist) + "]"
|
||||||
methods = self.jsonrpc2_procedures
|
methods = self.jsonrpc2_procedures
|
||||||
methods.update(self.jsonrpc_procedures)
|
methods.update(self.jsonrpc_procedures)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
must_respond = validate(data)
|
must_respond = validate(data)
|
||||||
except Service.JsonRpcException, e:
|
except Service.JsonRpcException, e:
|
||||||
return return_error(None, e.code, e.info)
|
return return_error(None, e.code, e.info)
|
||||||
|
|
||||||
id, method, params = data.get('id'), data['method'], data.get('params', '')
|
id, method, params = data.get('id'), data['method'], data.get('params', '')
|
||||||
if not method in methods:
|
if not method in methods:
|
||||||
return return_error(id, -32601, data='Method "%s" does not exist' % method)
|
return return_error(id, -32601, data='Method "%s" does not exist' % method)
|
||||||
@@ -4487,7 +4492,7 @@ class Service(object):
|
|||||||
except:
|
except:
|
||||||
etype, eval, etb = sys.exc_info()
|
etype, eval, etb = sys.exc_info()
|
||||||
return return_error(id, -32099, data='Exception %s: %s' % (etype, eval))
|
return return_error(id, -32099, data='Exception %s: %s' % (etype, eval))
|
||||||
|
|
||||||
|
|
||||||
def serve_xmlrpc(self):
|
def serve_xmlrpc(self):
|
||||||
request = current.request
|
request = current.request
|
||||||
@@ -4828,14 +4833,27 @@ class PluginManager(object):
|
|||||||
|
|
||||||
|
|
||||||
class Expose(object):
|
class Expose(object):
|
||||||
def __init__(self, base=None, basename='base', extensions=None, allow_download=True):
|
def __init__(self, base=None, basename=None, extensions=None, allow_download=True):
|
||||||
"""
|
"""
|
||||||
extensions: an optional list of file extensions for filtering displayed files:
|
Usage:
|
||||||
|
|
||||||
|
def static():
|
||||||
|
return dict(files=Expose())
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
def static():
|
||||||
|
path = os.path.join(request.folder,'static','public')
|
||||||
|
return dict(files=Expose(path,basename='public'))
|
||||||
|
|
||||||
|
extensions:
|
||||||
|
an optional list of file extensions for filtering displayed files:
|
||||||
['.py', '.jpg']
|
['.py', '.jpg']
|
||||||
allow_download: whether to allow downloading selected files
|
allow_download: whether to allow downloading selected files
|
||||||
"""
|
"""
|
||||||
current.session.forget()
|
current.session.forget()
|
||||||
base = base or os.path.join(current.request.folder, 'static')
|
base = base or os.path.join(current.request.folder, 'static')
|
||||||
|
basename = basename or current.request.function
|
||||||
self.basename = basename
|
self.basename = basename
|
||||||
self.args = current.request.raw_args and \
|
self.args = current.request.raw_args and \
|
||||||
[arg for arg in current.request.raw_args.split('/') if arg] or []
|
[arg for arg in current.request.raw_args.split('/') if arg] or []
|
||||||
@@ -4852,8 +4870,14 @@ class Expose(object):
|
|||||||
if os.path.isdir(f) and not self.isprivate(f)]
|
if os.path.isdir(f) and not self.isprivate(f)]
|
||||||
self.filenames = [f[len(path) - 1:] for f in sorted(glob.glob(path))
|
self.filenames = [f[len(path) - 1:] for f in sorted(glob.glob(path))
|
||||||
if not os.path.isdir(f) and not self.isprivate(f)]
|
if not os.path.isdir(f) and not self.isprivate(f)]
|
||||||
|
if 'README' in self.filenames:
|
||||||
|
readme = open(os.path.join(filename,'README')).read()
|
||||||
|
self.paragraph = MARKMIN(readme)
|
||||||
|
else:
|
||||||
|
self.paragraph = None
|
||||||
if extensions:
|
if extensions:
|
||||||
self.filenames = [f for f in self.filenames if os.path.splitext(f)[-1] in extensions]
|
self.filenames = [f for f in self.filenames
|
||||||
|
if os.path.splitext(f)[-1] in extensions]
|
||||||
|
|
||||||
def breadcrumbs(self, basename):
|
def breadcrumbs(self, basename):
|
||||||
path = []
|
path = []
|
||||||
@@ -4867,8 +4891,10 @@ class Expose(object):
|
|||||||
|
|
||||||
def table_folders(self):
|
def table_folders(self):
|
||||||
if self.folders:
|
if self.folders:
|
||||||
return SPAN(H3('Folders'), TABLE(*[TR(TD(A(folder, _href=URL(args=self.args + [folder]))))
|
return SPAN(H3('Folders'), TABLE(
|
||||||
for folder in self.folders]))
|
*[TR(TD(A(folder, _href=URL(args=self.args + [folder]))))
|
||||||
|
for folder in self.folders],
|
||||||
|
**dict(_class="table")))
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -4877,20 +4903,24 @@ class Expose(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isimage(f):
|
def isimage(f):
|
||||||
return os.path.splitext(f)[-1].lower() in ('.png', '.jpg', '.jpeg', '.gif', '.tiff')
|
return os.path.splitext(f)[-1].lower() in (
|
||||||
|
'.png', '.jpg', '.jpeg', '.gif', '.tiff')
|
||||||
|
|
||||||
def table_files(self, width=160):
|
def table_files(self, width=160):
|
||||||
if self.filenames:
|
if self.filenames:
|
||||||
return SPAN(H3('Files'), TABLE(*[TR(TD(A(f, _href=URL(args=self.args + [f]))),
|
return SPAN(H3('Files'),
|
||||||
TD(IMG(_src=URL(args=self.args + [f]),
|
TABLE(*[TR(TD(A(f, _href=URL(args=self.args + [f]))),
|
||||||
_style='max-width:%spx' % width)
|
TD(IMG(_src=URL(args=self.args + [f]),
|
||||||
if width and self.isimage(f) else ''))
|
_style='max-width:%spx' % width)
|
||||||
for f in self.filenames]))
|
if width and self.isimage(f) else ''))
|
||||||
|
for f in self.filenames],
|
||||||
|
**dict(_class="table")))
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def xml(self):
|
def xml(self):
|
||||||
return DIV(
|
return DIV(
|
||||||
H2(self.breadcrumbs(self.basename)),
|
H2(self.breadcrumbs(self.basename)),
|
||||||
|
self.paragraph or '',
|
||||||
self.table_folders(),
|
self.table_folders(),
|
||||||
self.table_files()).xml()
|
self.table_files()).xml()
|
||||||
|
|
||||||
@@ -5043,8 +5073,10 @@ class Wiki(object):
|
|||||||
db.wiki_tag.insert(name=tag, wiki_page=page.id)
|
db.wiki_tag.insert(name=tag, wiki_page=page.id)
|
||||||
db.wiki_page._after_insert.append(update_tags_insert)
|
db.wiki_page._after_insert.append(update_tags_insert)
|
||||||
db.wiki_page._after_update.append(update_tags_update)
|
db.wiki_page._after_update.append(update_tags_update)
|
||||||
if auth.user and check_credentials(current.request) and \
|
|
||||||
not 'wiki_editor' in auth.user_groups.values():
|
if (auth.user and
|
||||||
|
check_credentials(current.request, gae_login=False) and
|
||||||
|
not 'wiki_editor' in auth.user_groups.values()):
|
||||||
group = db.auth_group(role='wiki_editor')
|
group = db.auth_group(role='wiki_editor')
|
||||||
gid = group.id if group else db.auth_group.insert(
|
gid = group.id if group else db.auth_group.insert(
|
||||||
role='wiki_editor')
|
role='wiki_editor')
|
||||||
@@ -5304,7 +5336,7 @@ class Wiki(object):
|
|||||||
slugs=db(db.wiki_page.id>0).select(db.wiki_page.id,db.wiki_page.slug)
|
slugs=db(db.wiki_page.id>0).select(db.wiki_page.id,db.wiki_page.slug)
|
||||||
options=[OPTION(row.slug,_value=row.id) for row in slugs]
|
options=[OPTION(row.slug,_value=row.id) for row in slugs]
|
||||||
options.insert(0, OPTION('',_value=''))
|
options.insert(0, OPTION('',_value=''))
|
||||||
fields = [Field("slug", default=current.request.args(1) or
|
fields = [Field("slug", default=current.request.args(1) or
|
||||||
self.settings.force_prefix,
|
self.settings.force_prefix,
|
||||||
requires=(IS_SLUG(), IS_NOT_IN_DB(db,db.wiki_page.slug))),]
|
requires=(IS_SLUG(), IS_NOT_IN_DB(db,db.wiki_page.slug))),]
|
||||||
if self.settings.templates:
|
if self.settings.templates:
|
||||||
@@ -5337,7 +5369,7 @@ class Wiki(object):
|
|||||||
content = SQLFORM.grid(
|
content = SQLFORM.grid(
|
||||||
wiki_table,
|
wiki_table,
|
||||||
fields = [wiki_table.slug,
|
fields = [wiki_table.slug,
|
||||||
wiki_table.title, wiki_table.tags,
|
wiki_table.title, wiki_table.tags,
|
||||||
wiki_table.can_read, wiki_table.can_edit],
|
wiki_table.can_read, wiki_table.can_edit],
|
||||||
links=[
|
links=[
|
||||||
lambda row:
|
lambda row:
|
||||||
|
|||||||
+201
-10
@@ -31,8 +31,8 @@ except ImportError:
|
|||||||
from gluon.contrib.simplejson.decoder import JSONDecodeError
|
from gluon.contrib.simplejson.decoder import JSONDecodeError
|
||||||
JSONErrors += (JSONDecodeError,)
|
JSONErrors += (JSONDecodeError,)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'ANY_OF',
|
||||||
'CLEANUP',
|
'CLEANUP',
|
||||||
'CRYPT',
|
'CRYPT',
|
||||||
'IS_ALPHANUMERIC',
|
'IS_ALPHANUMERIC',
|
||||||
@@ -50,6 +50,7 @@ __all__ = [
|
|||||||
'IS_IN_SET',
|
'IS_IN_SET',
|
||||||
'IS_INT_IN_RANGE',
|
'IS_INT_IN_RANGE',
|
||||||
'IS_IPV4',
|
'IS_IPV4',
|
||||||
|
'IS_IPV6',
|
||||||
'IS_LENGTH',
|
'IS_LENGTH',
|
||||||
'IS_LIST_OF',
|
'IS_LIST_OF',
|
||||||
'IS_LOWER',
|
'IS_LOWER',
|
||||||
@@ -332,7 +333,7 @@ class IS_JSON(Validator):
|
|||||||
requires=IS_JSON(error_message="This is not a valid json input")
|
requires=IS_JSON(error_message="This is not a valid json input")
|
||||||
|
|
||||||
>>> IS_JSON()('{"a": 100}')
|
>>> IS_JSON()('{"a": 100}')
|
||||||
('{"a": 100}', None)
|
({u'a': 100}, None)
|
||||||
|
|
||||||
>>> IS_JSON()('spam1234')
|
>>> IS_JSON()('spam1234')
|
||||||
('spam1234', 'invalid json')
|
('spam1234', 'invalid json')
|
||||||
@@ -518,7 +519,7 @@ class IS_IN_DB(Validator):
|
|||||||
if self.fields == 'all':
|
if self.fields == 'all':
|
||||||
fields = [f for f in table]
|
fields = [f for f in table]
|
||||||
else:
|
else:
|
||||||
fields = [table[k] for k in self.fields]
|
fields = [table[k] for k in self.fields]
|
||||||
ignore = (FieldVirtual,FieldMethod)
|
ignore = (FieldVirtual,FieldMethod)
|
||||||
fields = filter(lambda f:not isinstance(f,ignore), fields)
|
fields = filter(lambda f:not isinstance(f,ignore), fields)
|
||||||
if self.dbset.db._dbname != 'gae':
|
if self.dbset.db._dbname != 'gae':
|
||||||
@@ -651,7 +652,7 @@ class IS_NOT_IN_DB(Validator):
|
|||||||
if row and any(str(row[f]) != str(id[f]) for f in id):
|
if row and any(str(row[f]) != str(id[f]) for f in id):
|
||||||
return (value, translate(self.error_message))
|
return (value, translate(self.error_message))
|
||||||
else:
|
else:
|
||||||
row = subset.select(table._id, limitby=(0, 1)).first()
|
row = subset.select(table._id, field, limitby=(0, 1)).first()
|
||||||
if row and str(row.id) != str(id):
|
if row and str(row.id) != str(id):
|
||||||
return (value, translate(self.error_message))
|
return (value, translate(self.error_message))
|
||||||
return (value, None)
|
return (value, None)
|
||||||
@@ -2208,6 +2209,17 @@ class IS_TIME(Validator):
|
|||||||
pass
|
pass
|
||||||
return (ivalue, translate(self.error_message))
|
return (ivalue, translate(self.error_message))
|
||||||
|
|
||||||
|
# A UTC class.
|
||||||
|
class UTC(datetime.tzinfo):
|
||||||
|
"""UTC"""
|
||||||
|
ZERO = datetime.timedelta(0)
|
||||||
|
def utcoffset(self, dt):
|
||||||
|
return UTC.ZERO
|
||||||
|
def tzname(self, dt):
|
||||||
|
return "UTC"
|
||||||
|
def dst(self, dt):
|
||||||
|
return UTC.ZERO
|
||||||
|
utc = UTC()
|
||||||
|
|
||||||
class IS_DATE(Validator):
|
class IS_DATE(Validator):
|
||||||
"""
|
"""
|
||||||
@@ -2221,6 +2233,9 @@ class IS_DATE(Validator):
|
|||||||
def __init__(self, format='%Y-%m-%d',
|
def __init__(self, format='%Y-%m-%d',
|
||||||
error_message='enter date as %(format)s',
|
error_message='enter date as %(format)s',
|
||||||
timezone = None):
|
timezone = None):
|
||||||
|
"""
|
||||||
|
timezome must be None or a pytz.timezone("America/Chicago") object
|
||||||
|
"""
|
||||||
self.format = translate(format)
|
self.format = translate(format)
|
||||||
self.error_message = str(error_message)
|
self.error_message = str(error_message)
|
||||||
self.timezone = timezone
|
self.timezone = timezone
|
||||||
@@ -2237,7 +2252,7 @@ class IS_DATE(Validator):
|
|||||||
time.strptime(value, str(self.format))
|
time.strptime(value, str(self.format))
|
||||||
value = datetime.date(y, m, d)
|
value = datetime.date(y, m, d)
|
||||||
if self.timezone is not None:
|
if self.timezone is not None:
|
||||||
value = value - datetime.timedelta(seconds=self.timezone*3600)
|
value = self.timezone.localize(value).astimezone(utc)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
except:
|
except:
|
||||||
self.extremes.update(IS_DATETIME.nice(self.format))
|
self.extremes.update(IS_DATETIME.nice(self.format))
|
||||||
@@ -2255,7 +2270,7 @@ class IS_DATE(Validator):
|
|||||||
year = 2000
|
year = 2000
|
||||||
d = datetime.date(year, value.month, value.day)
|
d = datetime.date(year, value.month, value.day)
|
||||||
if self.timezone is not None:
|
if self.timezone is not None:
|
||||||
d = d + datetime.timedelta(seconds=self.timezone*3600)
|
d = d.replace(tzinfo=utc).astimezone(self.timezone)
|
||||||
return d.strftime(format)
|
return d.strftime(format)
|
||||||
|
|
||||||
|
|
||||||
@@ -2290,6 +2305,9 @@ class IS_DATETIME(Validator):
|
|||||||
def __init__(self, format='%Y-%m-%d %H:%M:%S',
|
def __init__(self, format='%Y-%m-%d %H:%M:%S',
|
||||||
error_message='enter date and time as %(format)s',
|
error_message='enter date and time as %(format)s',
|
||||||
timezone=None):
|
timezone=None):
|
||||||
|
"""
|
||||||
|
timezome must be None or a pytz.timezone("America/Chicago") object
|
||||||
|
"""
|
||||||
self.format = translate(format)
|
self.format = translate(format)
|
||||||
self.error_message = str(error_message)
|
self.error_message = str(error_message)
|
||||||
self.extremes = {}
|
self.extremes = {}
|
||||||
@@ -2304,7 +2322,7 @@ class IS_DATETIME(Validator):
|
|||||||
time.strptime(value, str(self.format))
|
time.strptime(value, str(self.format))
|
||||||
value = datetime.datetime(y, m, d, hh, mm, ss)
|
value = datetime.datetime(y, m, d, hh, mm, ss)
|
||||||
if self.timezone is not None:
|
if self.timezone is not None:
|
||||||
value = value - datetime.timedelta(seconds=self.timezone*3600)
|
value = self.timezone.localize(value).astimezone(utc)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
except:
|
except:
|
||||||
self.extremes.update(IS_DATETIME.nice(self.format))
|
self.extremes.update(IS_DATETIME.nice(self.format))
|
||||||
@@ -2323,7 +2341,7 @@ class IS_DATETIME(Validator):
|
|||||||
d = datetime.datetime(year, value.month, value.day,
|
d = datetime.datetime(year, value.month, value.day,
|
||||||
value.hour, value.minute, value.second)
|
value.hour, value.minute, value.second)
|
||||||
if self.timezone is not None:
|
if self.timezone is not None:
|
||||||
d = d + datetime.timedelta(seconds=self.timezone*3600)
|
d = d.replace(tzinfo=utc).astimezone(self.timezone)
|
||||||
return d.strftime(format)
|
return d.strftime(format)
|
||||||
|
|
||||||
|
|
||||||
@@ -2339,7 +2357,7 @@ class IS_DATE_IN_RANGE(IS_DATE):
|
|||||||
(datetime.date(2008, 3, 3), None)
|
(datetime.date(2008, 3, 3), None)
|
||||||
|
|
||||||
>>> v('03/03/2010')
|
>>> v('03/03/2010')
|
||||||
(datetime.date(2010, 3, 3), 'oops')
|
('03/03/2010', 'oops')
|
||||||
|
|
||||||
>>> v(datetime.date(2008,3,3))
|
>>> v(datetime.date(2008,3,3))
|
||||||
(datetime.date(2008, 3, 3), None)
|
(datetime.date(2008, 3, 3), None)
|
||||||
@@ -2393,7 +2411,7 @@ class IS_DATETIME_IN_RANGE(IS_DATETIME):
|
|||||||
(datetime.datetime(2008, 3, 3, 12, 40), None)
|
(datetime.datetime(2008, 3, 3, 12, 40), None)
|
||||||
|
|
||||||
>>> v('03/03/2010 10:34')
|
>>> v('03/03/2010 10:34')
|
||||||
(datetime.datetime(2010, 3, 3, 10, 34), 'oops')
|
('03/03/2010 10:34', 'oops')
|
||||||
|
|
||||||
>>> v(datetime.datetime(2008,3,3,0,0))
|
>>> v(datetime.datetime(2008,3,3,0,0))
|
||||||
(datetime.datetime(2008, 3, 3, 0, 0), None)
|
(datetime.datetime(2008, 3, 3, 0, 0), None)
|
||||||
@@ -2575,6 +2593,38 @@ class IS_SLUG(Validator):
|
|||||||
return (urlify(value, self.maxlen, self.keep_underscores), None)
|
return (urlify(value, self.maxlen, self.keep_underscores), None)
|
||||||
|
|
||||||
|
|
||||||
|
class ANY_OF(Validator):
|
||||||
|
"""
|
||||||
|
test if any of the validators in a list return successfully
|
||||||
|
|
||||||
|
>>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('a@b.co')
|
||||||
|
('a@b.co', None)
|
||||||
|
>>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('abco')
|
||||||
|
('abco', None)
|
||||||
|
>>> ANY_OF([IS_EMAIL(),IS_ALPHANUMERIC()])('@ab.co')
|
||||||
|
('@ab.co', 'enter only letters, numbers, and underscore')
|
||||||
|
>>> ANY_OF([IS_ALPHANUMERIC(),IS_EMAIL()])('@ab.co')
|
||||||
|
('@ab.co', 'enter a valid email address')
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, subs):
|
||||||
|
self.subs = subs
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
for validator in self.subs:
|
||||||
|
value, error = validator(value)
|
||||||
|
if error == None:
|
||||||
|
break
|
||||||
|
return value, error
|
||||||
|
|
||||||
|
def formatter(self, value):
|
||||||
|
# Use the formatter of the first subvalidator
|
||||||
|
# that validates the value and has a formatter
|
||||||
|
for validator in self.subs:
|
||||||
|
if hasattr(validator, 'formatter') and validator(value)[1] != None:
|
||||||
|
return validator.formatter(value)
|
||||||
|
|
||||||
|
|
||||||
class IS_EMPTY_OR(Validator):
|
class IS_EMPTY_OR(Validator):
|
||||||
"""
|
"""
|
||||||
dummy class for testing IS_EMPTY_OR
|
dummy class for testing IS_EMPTY_OR
|
||||||
@@ -3371,6 +3421,147 @@ class IS_IPV4(Validator):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translate(self.error_message))
|
||||||
|
|
||||||
|
class IS_IPV6(Validator):
|
||||||
|
"""
|
||||||
|
Checks if field's value is an IP version 6 address. First attempts to
|
||||||
|
use the ipaddress library and falls back to contrib/ipaddr.py from Google
|
||||||
|
(https://code.google.com/p/ipaddr-py/)
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
is_private: None (default): indifferent
|
||||||
|
True (enforce): address must be in fc00::/7 range
|
||||||
|
False (forbid): address must NOT be in fc00::/7 range
|
||||||
|
is_link_local: Same as above but uses fe80::/10 range
|
||||||
|
is_reserved: Same as above but uses IETF reserved range
|
||||||
|
is_mulicast: Same as above but uses ff00::/8 range
|
||||||
|
is_routeable: Similar to above but enforces not private, link_local,
|
||||||
|
reserved or multicast
|
||||||
|
is_6to4: Same as above but uses 2002::/16 range
|
||||||
|
is_teredo: Same as above but uses 2001::/32 range
|
||||||
|
subnets: value must be a member of at least one from list of subnets
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
#Check for valid IPv6 address:
|
||||||
|
INPUT(_type='text', _name='name', requires=IS_IPV6())
|
||||||
|
|
||||||
|
#Check for valid IPv6 address is a link_local address:
|
||||||
|
INPUT(_type='text', _name='name', requires=IS_IPV6(is_link_local=True))
|
||||||
|
|
||||||
|
#Check for valid IPv6 address that is Internet routeable:
|
||||||
|
INPUT(_type='text', _name='name', requires=IS_IPV6(is_routeable=True))
|
||||||
|
|
||||||
|
#Check for valid IPv6 address in specified subnet:
|
||||||
|
INPUT(_type='text', _name='name', requires=IS_IPV6(subnets=['2001::/32'])
|
||||||
|
|
||||||
|
>>> IS_IPV6()('fe80::126c:8ffa:fe22:b3af')
|
||||||
|
('fe80::126c:8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6()('192.168.1.1')
|
||||||
|
('192.168.1.1', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(error_message='bad ip')('192.168.1.1')
|
||||||
|
('192.168.1.1', 'bad ip')
|
||||||
|
>>> IS_IPV6(is_link_local=True)('fe80::126c:8ffa:fe22:b3af')
|
||||||
|
('fe80::126c:8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6(is_link_local=False)('fe80::126c:8ffa:fe22:b3af')
|
||||||
|
('fe80::126c:8ffa:fe22:b3af', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(is_link_local=True)('2001::126c:8ffa:fe22:b3af')
|
||||||
|
('2001::126c:8ffa:fe22:b3af', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(is_multicast=True)('2001::126c:8ffa:fe22:b3af')
|
||||||
|
('2001::126c:8ffa:fe22:b3af', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(is_multicast=True)('ff00::126c:8ffa:fe22:b3af')
|
||||||
|
('ff00::126c:8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6(is_routeable=True)('2001::126c:8ffa:fe22:b3af')
|
||||||
|
('2001::126c:8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6(is_routeable=True)('ff00::126c:8ffa:fe22:b3af')
|
||||||
|
('ff00::126c:8ffa:fe22:b3af', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(subnets='2001::/32')('2001::8ffa:fe22:b3af')
|
||||||
|
('2001::8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6(subnets='fb00::/8')('2001::8ffa:fe22:b3af')
|
||||||
|
('2001::8ffa:fe22:b3af', 'enter valid IPv6 address')
|
||||||
|
>>> IS_IPV6(subnets=['fc00::/8','2001::/32'])('2001::8ffa:fe22:b3af')
|
||||||
|
('2001::8ffa:fe22:b3af', None)
|
||||||
|
>>> IS_IPV6(subnets='invalidsubnet')('2001::8ffa:fe22:b3af')
|
||||||
|
('2001::8ffa:fe22:b3af', 'invalid subnet provided')
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
is_private=None,
|
||||||
|
is_link_local=None,
|
||||||
|
is_reserved=None,
|
||||||
|
is_multicast=None,
|
||||||
|
is_routeable=None,
|
||||||
|
is_6to4=None,
|
||||||
|
is_teredo=None,
|
||||||
|
subnets=None,
|
||||||
|
error_message='enter valid IPv6 address'):
|
||||||
|
self.is_private = is_private
|
||||||
|
self.is_link_local = is_link_local
|
||||||
|
self.is_reserved = is_reserved
|
||||||
|
self.is_multicast = is_multicast
|
||||||
|
self.is_routeable = is_routeable
|
||||||
|
self.is_6to4 = is_6to4
|
||||||
|
self.is_teredo = is_teredo
|
||||||
|
self.subnets = subnets
|
||||||
|
self.error_message = error_message
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
try:
|
||||||
|
import ipaddress
|
||||||
|
except ImportError:
|
||||||
|
from contrib import ipaddr as ipaddress
|
||||||
|
|
||||||
|
try:
|
||||||
|
ip = ipaddress.IPv6Address(value)
|
||||||
|
ok = True
|
||||||
|
except ipaddress.AddressValueError:
|
||||||
|
return (value, translate(self.error_message))
|
||||||
|
|
||||||
|
if self.subnets:
|
||||||
|
# iterate through self.subnets to see if value is a member
|
||||||
|
ok = False
|
||||||
|
if isinstance(self.subnets, str):
|
||||||
|
self.subnets = [self.subnets]
|
||||||
|
for network in self.subnets:
|
||||||
|
try:
|
||||||
|
ipnet = ipaddress.IPv6Network(network)
|
||||||
|
except (ipaddress.NetmaskValueError, ipaddress.AddressValueError):
|
||||||
|
return (value, translate('invalid subnet provided'))
|
||||||
|
if ip in ipnet:
|
||||||
|
ok = True
|
||||||
|
|
||||||
|
if self.is_routeable:
|
||||||
|
self.is_private = False
|
||||||
|
self.is_link_local = False
|
||||||
|
self.is_reserved = False
|
||||||
|
self.is_multicast = False
|
||||||
|
|
||||||
|
if not (self.is_private is None or self.is_private ==
|
||||||
|
ip.is_private):
|
||||||
|
ok = False
|
||||||
|
if not (self.is_link_local is None or self.is_link_local ==
|
||||||
|
ip.is_link_local):
|
||||||
|
ok = False
|
||||||
|
if not (self.is_reserved is None or self.is_reserved ==
|
||||||
|
ip.is_reserved):
|
||||||
|
ok = False
|
||||||
|
if not (self.is_multicast is None or self.is_multicast ==
|
||||||
|
ip.is_multicast):
|
||||||
|
ok = False
|
||||||
|
if not (self.is_6to4 is None or self.is_6to4 ==
|
||||||
|
ip.is_6to4):
|
||||||
|
ok = False
|
||||||
|
if not (self.is_teredo is None or self.is_teredo ==
|
||||||
|
ip.is_teredo):
|
||||||
|
ok = False
|
||||||
|
|
||||||
|
if ok:
|
||||||
|
return (value, None)
|
||||||
|
|
||||||
|
return (value, translate(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod(
|
doctest.testmod(
|
||||||
|
|||||||
+1
-1
@@ -793,7 +793,7 @@ def console():
|
|||||||
default=None,
|
default=None,
|
||||||
help=msg)
|
help=msg)
|
||||||
|
|
||||||
msg = 'run schedulers alongside webserver'
|
msg = 'run schedulers alongside webserver, needs -K app1 and -a too'
|
||||||
parser.add_option('-X',
|
parser.add_option('-X',
|
||||||
'--with-scheduler',
|
'--with-scheduler',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
|
|||||||
+2
-2
@@ -19,8 +19,8 @@ password = '<recycle>' # ## <recycle> means use the previous password
|
|||||||
pid_filename = 'httpserver.pid'
|
pid_filename = 'httpserver.pid'
|
||||||
log_filename = 'httpserver.log'
|
log_filename = 'httpserver.log'
|
||||||
profiler_filename = None
|
profiler_filename = None
|
||||||
ssl_certificate = None # 'ssl_certificate.pem' # ## path to certificate file
|
ssl_certificate = '' # 'ssl_certificate.pem' # ## path to certificate file
|
||||||
ssl_private_key = None # 'ssl_private_key.pem' # ## path to private key file
|
ssl_private_key = '' # 'ssl_private_key.pem' # ## path to private key file
|
||||||
#numthreads = 50 # ## deprecated; remove
|
#numthreads = 50 # ## deprecated; remove
|
||||||
minthreads = None
|
minthreads = None
|
||||||
maxthreads = None
|
maxthreads = None
|
||||||
|
|||||||
+4
-5
@@ -46,9 +46,9 @@ def allow_access(environ,host):
|
|||||||
filename = os.path.join(os.path.dirname(__file__),'access.wsgi.log')
|
filename = os.path.join(os.path.dirname(__file__),'access.wsgi.log')
|
||||||
f = open(filename,'a')
|
f = open(filename,'a')
|
||||||
try:
|
try:
|
||||||
f.write('\n'+header+'\n'+pprint+'\n')
|
f.write('\n'+header+'\n'+pprint+'\n')
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
app = environ['REQUEST_URI'].split('/')[1]
|
app = environ['REQUEST_URI'].split('/')[1]
|
||||||
keys = [key for key in environ if key.startswith('HTTP_')]
|
keys = [key for key in environ if key.startswith('HTTP_')]
|
||||||
headers = {}
|
headers = {}
|
||||||
@@ -58,8 +58,7 @@ def allow_access(environ,host):
|
|||||||
try:
|
try:
|
||||||
data = urllib.urlencode({'request_uri':environ['REQUEST_URI']})
|
data = urllib.urlencode({'request_uri':environ['REQUEST_URI']})
|
||||||
request = urllib2.Request(URL_CHECK_ACCESS % dict(app=app),data,headers)
|
request = urllib2.Request(URL_CHECK_ACCESS % dict(app=app),data,headers)
|
||||||
response = urllib2.urlopen(request).read().strip().lower()
|
response = urllib2.urlopen(request).read().strip().lower()
|
||||||
if response.startswith('true'): return True
|
if response.startswith('true'): return True
|
||||||
except: pass
|
except: pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
+83
-83
@@ -4,112 +4,112 @@ worker_processes 1;
|
|||||||
error_log /var/log/nginx/error_log info;
|
error_log /var/log/nginx/error_log info;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
use epoll;
|
use epoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
log_format main
|
log_format main
|
||||||
'$remote_addr - $remote_user [$time_local] '
|
'$remote_addr - $remote_user [$time_local] '
|
||||||
'"$request" $status $bytes_sent '
|
'"$request" $status $bytes_sent '
|
||||||
'"$http_referer" "$http_user_agent" '
|
'"$http_referer" "$http_user_agent" '
|
||||||
'"$gzip_ratio"';
|
'"$gzip_ratio"';
|
||||||
|
|
||||||
client_header_timeout 10m;
|
client_header_timeout 10m;
|
||||||
client_body_timeout 10m;
|
client_body_timeout 10m;
|
||||||
send_timeout 10m;
|
send_timeout 10m;
|
||||||
|
|
||||||
connection_pool_size 256;
|
connection_pool_size 256;
|
||||||
client_header_buffer_size 1k;
|
client_header_buffer_size 1k;
|
||||||
large_client_header_buffers 4 2k;
|
large_client_header_buffers 4 2k;
|
||||||
request_pool_size 4k;
|
request_pool_size 4k;
|
||||||
|
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_min_length 1100;
|
gzip_min_length 1100;
|
||||||
gzip_buffers 4 8k;
|
gzip_buffers 4 8k;
|
||||||
gzip_types text/plain;
|
gzip_types text/plain;
|
||||||
|
|
||||||
output_buffers 1 32k;
|
output_buffers 1 32k;
|
||||||
postpone_output 1460;
|
postpone_output 1460;
|
||||||
|
|
||||||
sendfile on;
|
sendfile on;
|
||||||
tcp_nopush on;
|
tcp_nopush on;
|
||||||
tcp_nodelay on;
|
tcp_nodelay on;
|
||||||
|
|
||||||
keepalive_timeout 75 20;
|
keepalive_timeout 75 20;
|
||||||
|
|
||||||
ignore_invalid_headers on;
|
ignore_invalid_headers on;
|
||||||
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 127.0.0.1;
|
listen 127.0.0.1;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
access_log /var/log/nginx/localhost.access_log main;
|
access_log /var/log/nginx/localhost.access_log main;
|
||||||
error_log /var/log/nginx/localhost.error_log info;
|
error_log /var/log/nginx/localhost.error_log info;
|
||||||
|
|
||||||
root /var/www/localhost/htdocs;
|
root /var/www/localhost/htdocs;
|
||||||
}
|
}
|
||||||
|
|
||||||
# SSL example
|
# SSL example
|
||||||
server {
|
server {
|
||||||
listen 127.0.0.1:443;
|
listen 127.0.0.1:443;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
ssl on;
|
ssl on;
|
||||||
ssl_certificate /etc/ssl/nginx/nginx-server.pem;
|
ssl_certificate /etc/ssl/nginx/nginx-server.pem;
|
||||||
ssl_client_certificate /etc/ssl/nginx/cacert.pem;
|
ssl_client_certificate /etc/ssl/nginx/cacert.pem;
|
||||||
ssl_certificate_key /etc/ssl/nginx/nginx.key;
|
ssl_certificate_key /etc/ssl/nginx/nginx.key;
|
||||||
ssl_verify_client optional;
|
ssl_verify_client optional;
|
||||||
|
|
||||||
access_log /var/log/nginx/localhost.ssl_access_log main;
|
access_log /var/log/nginx/localhost.ssl_access_log main;
|
||||||
error_log /var/log/nginx/localhost.ssl_error_log info;
|
error_log /var/log/nginx/localhost.ssl_error_log info;
|
||||||
|
|
||||||
root /var/www/localhost/htdocs;
|
root /var/www/localhost/htdocs;
|
||||||
|
|
||||||
set $web2pyroot /home/Desktop/source/michelecomitini-facebookaccess;
|
set $web2pyroot /home/Desktop/source/michelecomitini-facebookaccess;
|
||||||
|
|
||||||
|
|
||||||
location /pki/ {
|
|
||||||
root /var/www/localhost/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
location ^/(.*)/static/(.*) {
|
location /pki/ {
|
||||||
alias $web2pyroot/applications/$1/static/$2;
|
root /var/www/localhost/html;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
|
||||||
include /etc/nginx/scgi_params;
|
|
||||||
scgi_pass 127.0.0.1:4000;
|
|
||||||
|
|
||||||
#Module ngx_http_ssl_module supports the following built-in variables:
|
|
||||||
|
|
||||||
#$ssl_cipher returns the cipher suite being used for the currently established SSL/TLS connection
|
location ^/(.*)/static/(.*) {
|
||||||
#$ssl_client_serial returns the serial number of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
alias $web2pyroot/applications/$1/static/$2;
|
||||||
#$ssl_client_s_dn returns the subject Distinguished Name (DN) of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
}
|
||||||
#$ssl_client_i_dn returns the issuer DN of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
|
||||||
#$ssl_protocol returns the protocol of the currently established SSL/TLS connection — depending on the configuration and client available options it's one of SSLv2, SSLv3 or TLSv1
|
location / {
|
||||||
#$ssl_session_id the Session ID of the established secure connection — requires Nginx version greater or equal to 0.8.20
|
include /etc/nginx/scgi_params;
|
||||||
#$ssl_client_cert
|
scgi_pass 127.0.0.1:4000;
|
||||||
#$ssl_client_raw_cert
|
|
||||||
#$ssl_client_verify takes the value "SUCCESS" when the client certificate is successfully verified
|
#Module ngx_http_ssl_module supports the following built-in variables:
|
||||||
scgi_param SSL_PROTOCOL $ssl_protocol;
|
|
||||||
scgi_param HTTPS on;
|
#$ssl_cipher returns the cipher suite being used for the currently established SSL/TLS connection
|
||||||
scgi_param SSL_CIPHER $ssl_cipher;
|
#$ssl_client_serial returns the serial number of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
||||||
scgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
|
#$ssl_client_s_dn returns the subject Distinguished Name (DN) of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
||||||
scgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
|
#$ssl_client_i_dn returns the issuer DN of the client certificate for the currently established SSL/TLS connection — if applicable, i.e., if client authentication is activated in the connection
|
||||||
scgi_param SSL_CLIENT_I_DN $ssl_client_i_dn;
|
#$ssl_protocol returns the protocol of the currently established SSL/TLS connection — depending on the configuration and client available options it's one of SSLv2, SSLv3 or TLSv1
|
||||||
scgi_param SSL_SESSION_ID $ssl_session_id;
|
#$ssl_session_id the Session ID of the established secure connection — requires Nginx version greater or equal to 0.8.20
|
||||||
scgi_param SSL_CLIENT_CERT $ssl_client_cert;
|
#$ssl_client_cert
|
||||||
scgi_param SSL_CLIENT_RAW_CERT $ssl_client_raw_cert;
|
#$ssl_client_raw_cert
|
||||||
scgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
|
#$ssl_client_verify takes the value "SUCCESS" when the client certificate is successfully verified
|
||||||
}
|
scgi_param SSL_PROTOCOL $ssl_protocol;
|
||||||
}
|
scgi_param HTTPS on;
|
||||||
|
scgi_param SSL_CIPHER $ssl_cipher;
|
||||||
|
scgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
|
||||||
|
scgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
|
||||||
|
scgi_param SSL_CLIENT_I_DN $ssl_client_i_dn;
|
||||||
|
scgi_param SSL_SESSION_ID $ssl_session_id;
|
||||||
|
scgi_param SSL_CLIENT_CERT $ssl_client_cert;
|
||||||
|
scgi_param SSL_CLIENT_RAW_CERT $ssl_client_raw_cert;
|
||||||
|
scgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@
|
|||||||
# # chkconfig: 2345 90 10
|
# # chkconfig: 2345 90 10
|
||||||
# # description: web2py-scheduler
|
# # description: web2py-scheduler
|
||||||
#
|
#
|
||||||
# 4) make it executable with
|
# 4) make it executable with
|
||||||
#
|
#
|
||||||
# chmod 755 web2py-scheduler
|
# chmod 755 web2py-scheduler
|
||||||
#
|
#
|
||||||
# 5) add it to startup with
|
# 5) add it to startup with
|
||||||
#
|
#
|
||||||
# chkconfig --add web2py-scheduler
|
# chkconfig --add web2py-scheduler
|
||||||
#
|
#
|
||||||
@@ -64,4 +64,3 @@ case "$1" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
|||||||
@@ -9,4 +9,3 @@ unzip web2py_src.zip
|
|||||||
cd web2py
|
cd web2py
|
||||||
# start web2py using command-line script
|
# start web2py using command-line script
|
||||||
w2env/bin/python web2py.py -i 0.0.0.0 -p 8123 -a 'adminpasswd'
|
w2env/bin/python web2py.py -i 0.0.0.0 -p 8123 -a 'adminpasswd'
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Description : Installation and basic configuration of web2py, uWSGI, Redmine,
|
# Description : Installation and basic configuration of web2py, uWSGI, Redmine,
|
||||||
# Unicorn, Nginx and PostgreSQL.
|
# Unicorn, Nginx and PostgreSQL.
|
||||||
# Usage : Copy the script in /home/username and run it as root, you may
|
# Usage : Copy the script in /home/username and run it as root, you may
|
||||||
# need to allow exectuion (chmod +x). Ex.:
|
# need to allow exectuion (chmod +x). Ex.:
|
||||||
# sudo ./setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
|
# sudo ./setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
|
||||||
# File : setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
|
# File : setup-ubuntu-12-04-redmine-unicorn-web2py-uwsgi-nginx.sh
|
||||||
# Author : Richard V?zina
|
# Author : Richard V?zina
|
||||||
@@ -58,8 +58,8 @@ wget http://rubyforge.org/frs/download.php/76628/redmine-2.2.0.tar.gz.md5
|
|||||||
md5sum --check redmine-2.2.0.tar.gz.md5 > redmine_md5_checked_successfully
|
md5sum --check redmine-2.2.0.tar.gz.md5 > redmine_md5_checked_successfully
|
||||||
if [ -f redmine_md5_checked_successfully ]
|
if [ -f redmine_md5_checked_successfully ]
|
||||||
then
|
then
|
||||||
tar xvfz redmine-2.2.0.tar.gz
|
tar xvfz redmine-2.2.0.tar.gz
|
||||||
rm redmine_md5_checked_successfully
|
rm redmine_md5_checked_successfully
|
||||||
else
|
else
|
||||||
echo "Redmine md5 check sum failed..."
|
echo "Redmine md5 check sum failed..."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -98,9 +98,9 @@ echo 'production:
|
|||||||
rake generate_secret_token
|
rake generate_secret_token
|
||||||
RAILS_ENV=production rake db:migrate
|
RAILS_ENV=production rake db:migrate
|
||||||
RAILS_ENV=production rake redmine:load_default_data
|
RAILS_ENV=production rake redmine:load_default_data
|
||||||
mkdir /opt/redmine-2.2.0/tmp/pids
|
mkdir /opt/redmine-2.2.0/tmp/pids
|
||||||
#mkdir /opt/redmine-2.2.0/log # if not there
|
#mkdir /opt/redmine-2.2.0/log # if not there
|
||||||
cd /opt/redmine-2.2.0/config
|
cd /opt/redmine-2.2.0/config
|
||||||
# Create Unicorn specific Redmine config in /opt/redmine-2.2.0/config/unicorn.rb
|
# Create Unicorn specific Redmine config in /opt/redmine-2.2.0/config/unicorn.rb
|
||||||
echo '#unicorn.rb Starts here
|
echo '#unicorn.rb Starts here
|
||||||
worker_processes 1
|
worker_processes 1
|
||||||
@@ -115,8 +115,8 @@ timeout 45
|
|||||||
|
|
||||||
# This is where we specify the socket.
|
# This is where we specify the socket.
|
||||||
# We will point the upstream Nginx module to this socket later on
|
# We will point the upstream Nginx module to this socket later on
|
||||||
listen "/tmp/unicorn_rails.socket", :backlog => 64 #directory structure needs to be created.
|
listen "/tmp/unicorn_rails.socket", :backlog => 64 #directory structure needs to be created.
|
||||||
pid "/opt/redmine-2.2.0/tmp/pids/unicorn_rails.pid" # make sure this points to a valid directory. Make sure it is named the same as the real process name in order to allow init.d script start-stop-daemon command to kill unicorn process properly
|
pid "/opt/redmine-2.2.0/tmp/pids/unicorn_rails.pid" # make sure this points to a valid directory. Make sure it is named the same as the real process name in order to allow init.d script start-stop-daemon command to kill unicorn process properly
|
||||||
|
|
||||||
# Set the path of the log files inside the log folder of the testapp
|
# Set the path of the log files inside the log folder of the testapp
|
||||||
stderr_path "/opt/redmine-2.2.0/log/unicorn_rails.stderr.log"
|
stderr_path "/opt/redmine-2.2.0/log/unicorn_rails.stderr.log"
|
||||||
@@ -139,7 +139,7 @@ ActiveRecord::Base.establish_connection
|
|||||||
worker.user('\''www-data'\'', '\''www-data'\'') if Process.euid == 0
|
worker.user('\''www-data'\'', '\''www-data'\'') if Process.euid == 0
|
||||||
end
|
end
|
||||||
#unicorn.rb Ends here' > unicorn.rb
|
#unicorn.rb Ends here' > unicorn.rb
|
||||||
chown www-data:www-data unicorn.rb
|
chown www-data:www-data unicorn.rb
|
||||||
chown -R www-data:www-data /opt/redmine-2.2.0/tmp
|
chown -R www-data:www-data /opt/redmine-2.2.0/tmp
|
||||||
mkdir /etc/unicorn
|
mkdir /etc/unicorn
|
||||||
# Set some config for Unicorn in /etc/unicorn/redmine
|
# Set some config for Unicorn in /etc/unicorn/redmine
|
||||||
@@ -161,7 +161,7 @@ echo '#! /bin/sh
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Author: Richard V?zina <ml.richard.vezina@gmail.com>
|
# Author: Richard V?zina <ml.richard.vezina@gmail.com>
|
||||||
# Base on Ubuntu 12.04 : /etc/init.d/skeleton
|
# Base on Ubuntu 12.04 : /etc/init.d/skeleton
|
||||||
# ven 21 d?c 2012 11:08:31 EST
|
# ven 21 d?c 2012 11:08:31 EST
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# Do NOT "set -e"
|
# Do NOT "set -e"
|
||||||
@@ -195,18 +195,18 @@ SCRIPTNAME=/etc/init.d/redmine
|
|||||||
#
|
#
|
||||||
do_start()
|
do_start()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been started
|
# 0 if daemon has been started
|
||||||
# 1 if daemon was already running
|
# 1 if daemon was already running
|
||||||
# 2 if daemon could not be started
|
# 2 if daemon could not be started
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||||
|| return 1
|
|| return 1
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||||
$DAEMON_ARGS \
|
$DAEMON_ARGS \
|
||||||
|| return 2
|
|| return 2
|
||||||
# Add code here, if necessary, that waits for the process to be ready
|
# Add code here, if necessary, that waits for the process to be ready
|
||||||
# to handle requests from services started subsequently which depend
|
# to handle requests from services started subsequently which depend
|
||||||
# on this one. As a last resort, sleep for some time.
|
# on this one. As a last resort, sleep for some time.
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -214,108 +214,108 @@ do_start()
|
|||||||
#
|
#
|
||||||
do_stop()
|
do_stop()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been stopped
|
# 0 if daemon has been stopped
|
||||||
# 1 if daemon was already stopped
|
# 1 if daemon was already stopped
|
||||||
# 2 if daemon could not be stopped
|
# 2 if daemon could not be stopped
|
||||||
# other if a failure occurred
|
# other if a failure occurred
|
||||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
|
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
|
||||||
RETVAL="$?"
|
RETVAL="$?"
|
||||||
[ "$RETVAL" = 2 ] && return 2
|
[ "$RETVAL" = 2 ] && return 2
|
||||||
# Wait for children to finish too if this is a daemon that forks
|
# Wait for children to finish too if this is a daemon that forks
|
||||||
# and if the daemon is only ever run from this initscript.
|
# and if the daemon is only ever run from this initscript.
|
||||||
# If the above conditions are not satisfied then add some other code
|
# If the above conditions are not satisfied then add some other code
|
||||||
# that waits for the process to drop all resources that could be
|
# that waits for the process to drop all resources that could be
|
||||||
# needed by services started subsequently. A last resort is to
|
# needed by services started subsequently. A last resort is to
|
||||||
# sleep for some time.
|
# sleep for some time.
|
||||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||||
[ "$?" = 2 ] && return 2
|
[ "$?" = 2 ] && return 2
|
||||||
# Many daemons don'\''t delete their pidfiles when they exit.
|
# Many daemons don'\''t delete their pidfiles when they exit.
|
||||||
rm -f $PIDFILE
|
rm -f $PIDFILE
|
||||||
return "$RETVAL"
|
return "$RETVAL"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Function that sends a SIGHUP to the daemon/service
|
# Function that sends a SIGHUP to the daemon/service
|
||||||
#
|
#
|
||||||
do_reload() {
|
do_reload() {
|
||||||
#
|
#
|
||||||
# If the daemon can reload its configuration without
|
# If the daemon can reload its configuration without
|
||||||
# restarting (for example, when it is sent a SIGHUP),
|
# restarting (for example, when it is sent a SIGHUP),
|
||||||
# then implement that here.
|
# then implement that here.
|
||||||
#
|
#
|
||||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||||
do_start
|
do_start
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||||
do_stop
|
do_stop
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||||
;;
|
;;
|
||||||
#reload|force-reload)
|
#reload|force-reload)
|
||||||
#
|
#
|
||||||
# If do_reload() is not implemented then leave this commented out
|
# If do_reload() is not implemented then leave this commented out
|
||||||
# and leave '\''force-reload'\'' as an alias for '\''restart'\''.
|
# and leave '\''force-reload'\'' as an alias for '\''restart'\''.
|
||||||
#
|
#
|
||||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||||
#do_reload
|
#do_reload
|
||||||
#log_end_msg $?
|
#log_end_msg $?
|
||||||
#;;
|
#;;
|
||||||
restart|force-reload)
|
restart|force-reload)
|
||||||
#
|
#
|
||||||
# If the "reload" option is implemented then remove the
|
# If the "reload" option is implemented then remove the
|
||||||
# '\''force-reload'\'' alias
|
# '\''force-reload'\'' alias
|
||||||
#
|
#
|
||||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||||
do_stop
|
do_stop
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0|1)
|
0|1)
|
||||||
do_start
|
do_start
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0) log_end_msg 0 ;;
|
0) log_end_msg 0 ;;
|
||||||
1) log_end_msg 1 ;; # Old process is still running
|
1) log_end_msg 1 ;; # Old process is still running
|
||||||
*) log_end_msg 1 ;; # Failed to start
|
*) log_end_msg 1 ;; # Failed to start
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# Failed to stop
|
# Failed to stop
|
||||||
log_end_msg 1
|
log_end_msg 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||||
exit 3
|
exit 3
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
:' > /etc/init.d/redmine
|
:' > /etc/init.d/redmine
|
||||||
chmod +x /etc/init.d/redmine
|
chmod +x /etc/init.d/redmine
|
||||||
# Backup default Nginx site and replace it
|
# Backup default Nginx site and replace it
|
||||||
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_original
|
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_original
|
||||||
rm /etc/nginx/sites-available/default
|
rm /etc/nginx/sites-available/default
|
||||||
# Create configuration file /etc/nginx/sites-available/default
|
# Create configuration file /etc/nginx/sites-available/default
|
||||||
echo 'upstream unicorn_server {
|
echo 'upstream unicorn_server {
|
||||||
# This is the socket we configured in unicorn.rb
|
# This is the socket we configured in unicorn.rb
|
||||||
server unix:/tmp/unicorn_rails.socket
|
server unix:/tmp/unicorn_rails.socket
|
||||||
fail_timeout=0;
|
fail_timeout=0;
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
@@ -323,8 +323,8 @@ server {
|
|||||||
charset utf-8;
|
charset utf-8;
|
||||||
server_name localhost; # $hostname;
|
server_name localhost; # $hostname;
|
||||||
root /var/www;
|
root /var/www;
|
||||||
access_log /var/log/nginx/yoursite.access.log;
|
access_log /var/log/nginx/yoursite.access.log;
|
||||||
error_log /var/log/nginx/yoursite.error.log;
|
error_log /var/log/nginx/yoursite.error.log;
|
||||||
#to enable correct use of response.static_version
|
#to enable correct use of response.static_version
|
||||||
#location ~* /(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$ {
|
#location ~* /(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$ {
|
||||||
# alias /home/www-data/web2py/applications/$1/static/$2;
|
# alias /home/www-data/web2py/applications/$1/static/$2;
|
||||||
@@ -342,16 +342,16 @@ server {
|
|||||||
uwsgi_param UWSGI_SCHEME $scheme;
|
uwsgi_param UWSGI_SCHEME $scheme;
|
||||||
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
}
|
}
|
||||||
location / {
|
location / {
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
|
|
||||||
if (!-f $request_filename) {
|
if (!-f $request_filename) {
|
||||||
proxy_pass http://unicorn_server;
|
proxy_pass http://unicorn_server;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
listen 443 default_server ssl;
|
listen 443 default_server ssl;
|
||||||
@@ -360,12 +360,12 @@ server {
|
|||||||
root /var/www;
|
root /var/www;
|
||||||
ssl_certificate /etc/nginx/ssl/self_signed.cert;
|
ssl_certificate /etc/nginx/ssl/self_signed.cert;
|
||||||
ssl_certificate_key /etc/nginx/ssl/self_signed.key;
|
ssl_certificate_key /etc/nginx/ssl/self_signed.key;
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
ssl_session_timeout 10m;
|
ssl_session_timeout 10m;
|
||||||
ssl_ciphers ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA;
|
ssl_ciphers ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA;
|
||||||
ssl_protocols SSLv3 TLSv1;
|
ssl_protocols SSLv3 TLSv1;
|
||||||
keepalive_timeout 70;
|
keepalive_timeout 70;
|
||||||
location ~^\/(?!redmine(.*)) {
|
location ~^\/(?!redmine(.*)) {
|
||||||
#uwsgi_pass 127.0.0.1:9001;
|
#uwsgi_pass 127.0.0.1:9001;
|
||||||
uwsgi_pass unix:///tmp/web2py.socket;
|
uwsgi_pass unix:///tmp/web2py.socket;
|
||||||
@@ -373,16 +373,16 @@ server {
|
|||||||
uwsgi_param UWSGI_SCHEME $scheme;
|
uwsgi_param UWSGI_SCHEME $scheme;
|
||||||
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
|
||||||
}
|
}
|
||||||
location / {
|
location / {
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
|
|
||||||
if (!-f $request_filename) {
|
if (!-f $request_filename) {
|
||||||
proxy_pass http://unicorn_server;
|
proxy_pass http://unicorn_server;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}' >/etc/nginx/sites-available/default
|
}' >/etc/nginx/sites-available/default
|
||||||
|
|
||||||
@@ -392,8 +392,8 @@ server {
|
|||||||
# We copy ssl files we previously created
|
# We copy ssl files we previously created
|
||||||
if [ -f /etc/nginx/ssl ]
|
if [ -f /etc/nginx/ssl ]
|
||||||
then
|
then
|
||||||
cp ~/self_signed.* /etc/nginx/ssl/
|
cp ~/self_signed.* /etc/nginx/ssl/
|
||||||
rm ~/self_signed.*
|
rm ~/self_signed.*
|
||||||
else
|
else
|
||||||
mkdir /etc/nginx/ssl
|
mkdir /etc/nginx/ssl
|
||||||
cp ~/self_signed.* /etc/nginx/ssl/
|
cp ~/self_signed.* /etc/nginx/ssl/
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#
|
#
|
||||||
# Author: Christopher Steel
|
# Author: Christopher Steel
|
||||||
# Organization: Voice of Access
|
# Organization: Voice of Access
|
||||||
# Date: 2010-11-24
|
# Date: 2010-11-24
|
||||||
# License: Same as Web2py, MIT / GNU
|
# License: Same as Web2py, MIT / GNU
|
||||||
# Email: Christopher DOT Steel AT Voice of Access DOT org
|
# Email: Christopher DOT Steel AT Voice of Access DOT org
|
||||||
#
|
#
|
||||||
# This script will :
|
# This script will :
|
||||||
# download and install virtualenv
|
# download and install virtualenv
|
||||||
# start a virtual environment
|
# start a virtual environment
|
||||||
# move into the virtual environment
|
# move into the virtual environment
|
||||||
# download and install latest stable version of web2py
|
# download and install latest stable version of web2py
|
||||||
# start web2py in the virtual environment
|
# start web2py in the virtual environment
|
||||||
#
|
#
|
||||||
# To disactivate the virtual environment, shut down web2py
|
# To disactivate the virtual environment, shut down web2py
|
||||||
# and type 'disactivate' at the command line.
|
# and type 'disactivate' at the command line.
|
||||||
#
|
#
|
||||||
# Testing:
|
# Testing:
|
||||||
# OS X
|
# OS X
|
||||||
# should work on POSIX systems
|
# should work on POSIX systems
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# create a directory to hold your virtual environments, for example
|
# create a directory to hold your virtual environments, for example
|
||||||
# /home/user_name/virtual_environments
|
# /home/user_name/virtual_environments
|
||||||
# place this script in the directory and make it executable
|
# place this script in the directory and make it executable
|
||||||
# chmod +x web2py-install-virtualenv.sh
|
# chmod +x web2py-install-virtualenv.sh
|
||||||
customize the variables below to meet your needs
|
customize the variables below to meet your needs
|
||||||
# execute from terminal
|
# execute from terminal
|
||||||
# ./web2py-install-virtualenv.sh
|
# ./web2py-install-virtualenv.sh
|
||||||
# relax...
|
# relax...
|
||||||
|
|
||||||
################ VARIABLES
|
################ VARIABLES
|
||||||
# Change to reflect version changes etc.
|
# Change to reflect version changes etc.
|
||||||
@@ -94,8 +94,3 @@ read -p "Press any key to start web2py…"
|
|||||||
echo 'starting web2py'
|
echo 'starting web2py'
|
||||||
echo '==============='
|
echo '==============='
|
||||||
../bin/python2.5 web2py.py
|
../bin/python2.5 web2py.py
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -398,4 +398,3 @@ cd ${current_directory}
|
|||||||
|
|
||||||
echo " - Complete!"
|
echo " - Complete!"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -346,5 +346,3 @@ reboot
|
|||||||
|
|
||||||
as superuser
|
as superuser
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ echo 'server {
|
|||||||
# expires max;
|
# expires max;
|
||||||
#}
|
#}
|
||||||
###
|
###
|
||||||
|
|
||||||
###if you use something like myapp = dict(languages=['en', 'it', 'jp'], default_language='en') in your routes.py
|
###if you use something like myapp = dict(languages=['en', 'it', 'jp'], default_language='en') in your routes.py
|
||||||
#location ~* /(\w+)/(en|it|jp)/static/(.*)$ {
|
#location ~* /(\w+)/(en|it|jp)/static/(.*)$ {
|
||||||
# alias /home/www-data/web2py/applications/$1/;
|
# alias /home/www-data/web2py/applications/$1/;
|
||||||
@@ -70,14 +70,14 @@ echo 'server {
|
|||||||
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;
|
||||||
|
|
||||||
###remove the comments to turn on if you want gzip compression of your pages
|
###remove the comments to turn on if you want gzip compression of your pages
|
||||||
# include /etc/nginx/conf.d/web2py/gzip.conf;
|
# include /etc/nginx/conf.d/web2py/gzip.conf;
|
||||||
### end gzip section
|
### end gzip section
|
||||||
|
|
||||||
### remove the comments if you use uploads (max 10 MB)
|
### remove the comments if you use uploads (max 10 MB)
|
||||||
#client_max_body_size 10m;
|
#client_max_body_size 10m;
|
||||||
###
|
###
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
@@ -102,28 +102,28 @@ server {
|
|||||||
### end gzip section
|
### end gzip section
|
||||||
### remove the comments if you want to enable uploads (max 10 MB)
|
### remove the comments if you want to enable uploads (max 10 MB)
|
||||||
#client_max_body_size 10m;
|
#client_max_body_size 10m;
|
||||||
###
|
###
|
||||||
}
|
}
|
||||||
## if you serve static files through https, copy here the section
|
## if you serve static files through https, copy here the section
|
||||||
## from the previous server instance to manage static files
|
## from the previous server instance to manage static files
|
||||||
|
|
||||||
}' >/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
|
mkdir /etc/nginx/ssl
|
||||||
cd /etc/nginx/ssl
|
cd /etc/nginx/ssl
|
||||||
|
|
||||||
openssl genrsa 1024 > web2py.key
|
openssl genrsa 1024 > web2py.key
|
||||||
chmod 400 web2py.key
|
chmod 400 web2py.key
|
||||||
openssl req -new -x509 -nodes -sha1 -days 1780 -key web2py.key > web2py.crt
|
openssl req -new -x509 -nodes -sha1 -days 1780 -key web2py.key > web2py.crt
|
||||||
openssl x509 -noout -fingerprint -text < web2py.crt > web2py.info
|
openssl x509 -noout -fingerprint -text < web2py.crt > web2py.info
|
||||||
|
|
||||||
|
|
||||||
# Prepare folders for uwsgi
|
# Prepare folders for uwsgi
|
||||||
sudo mkdir /etc/uwsgi
|
sudo mkdir /etc/uwsgi
|
||||||
sudo mkdir /var/log/uwsgi
|
sudo mkdir /var/log/uwsgi
|
||||||
|
|
||||||
# Create configuration file /etc/uwsgi/web2py.xml
|
# Create configuration file /etc/uwsgi/web2py.xml
|
||||||
echo '[uwsgi]
|
echo '[uwsgi]
|
||||||
|
|
||||||
@@ -145,11 +145,11 @@ gid = www-data
|
|||||||
cron = 0 0 -1 -1 -1 python /home/www-data/web2py/web2py.py -Q -S welcome -M -R scripts/sessions2trash.py -A -o
|
cron = 0 0 -1 -1 -1 python /home/www-data/web2py/web2py.py -Q -S welcome -M -R scripts/sessions2trash.py -A -o
|
||||||
no-orphans = true
|
no-orphans = true
|
||||||
' >/etc/uwsgi/web2py.ini
|
' >/etc/uwsgi/web2py.ini
|
||||||
|
|
||||||
#Create a configuration file for uwsgi in emperor-mode
|
#Create a configuration file for uwsgi in emperor-mode
|
||||||
#for Upstart in /etc/init/uwsgi-emperor.conf
|
#for Upstart in /etc/init/uwsgi-emperor.conf
|
||||||
echo '# Emperor uWSGI script
|
echo '# Emperor uWSGI script
|
||||||
|
|
||||||
description "uWSGI Emperor"
|
description "uWSGI Emperor"
|
||||||
start on runlevel [2345]
|
start on runlevel [2345]
|
||||||
stop on runlevel [06]
|
stop on runlevel [06]
|
||||||
@@ -177,7 +177,7 @@ cd /home/www-data/web2py
|
|||||||
sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)"
|
sudo -u www-data python -c "from gluon.main import save_password; save_password('$PW',443)"
|
||||||
start uwsgi-emperor
|
start uwsgi-emperor
|
||||||
/etc/init.d/nginx restart
|
/etc/init.d/nginx restart
|
||||||
|
|
||||||
## you can reload uwsgi with
|
## you can reload uwsgi with
|
||||||
# restart uwsgi-emperor
|
# restart uwsgi-emperor
|
||||||
## and stop it with
|
## and stop it with
|
||||||
|
|||||||
@@ -175,4 +175,3 @@ cd /home/www-data/web2py
|
|||||||
sudo -u www-data python -c "from gluon.widget import console; console();"
|
sudo -u www-data python -c "from gluon.widget import console; console();"
|
||||||
sudo -u www-data python -c "from gluon.main import save_password; save_password(raw_input('admin password: '),443)"
|
sudo -u www-data python -c "from gluon.main import save_password; save_password(raw_input('admin password: '),443)"
|
||||||
echo "done!"
|
echo "done!"
|
||||||
|
|
||||||
|
|||||||
+14
-15
@@ -13,13 +13,13 @@
|
|||||||
TARGET=web2py
|
TARGET=web2py
|
||||||
|
|
||||||
if [ ! -d $TARGET ]; then
|
if [ ! -d $TARGET ]; then
|
||||||
# in case we're in web2py/
|
# in case we're in web2py/
|
||||||
if [ -f ../$TARGET/VERSION ]; then
|
if [ -f ../$TARGET/VERSION ]; then
|
||||||
cd ..
|
cd ..
|
||||||
# in case we're in web2py/scripts
|
# in case we're in web2py/scripts
|
||||||
elif [ -f ../../$TARGET/VERSION ]; then
|
elif [ -f ../../$TARGET/VERSION ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
read a VERSION c < $TARGET/VERSION
|
read a VERSION c < $TARGET/VERSION
|
||||||
SAVE=$TARGET-$VERSION
|
SAVE=$TARGET-$VERSION
|
||||||
@@ -32,14 +32,14 @@ SAVED=""
|
|||||||
# but don't overwrite a previous save of the same version.
|
# but don't overwrite a previous save of the same version.
|
||||||
#
|
#
|
||||||
if [ -f $SAVE.zip ]; then
|
if [ -f $SAVE.zip ]; then
|
||||||
echo "Remove or rename $SAVE.zip first" >&2
|
echo "Remove or rename $SAVE.zip first" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ -d $TARGET ]; then
|
if [ -d $TARGET ]; then
|
||||||
echo -n ">>Save old version: " >&2
|
echo -n ">>Save old version: " >&2
|
||||||
cat $TARGET/VERSION >&2
|
cat $TARGET/VERSION >&2
|
||||||
zip -q -r $SAVE.zip $TARGET
|
zip -q -r $SAVE.zip $TARGET
|
||||||
SAVED=$SAVE.zip
|
SAVED=$SAVE.zip
|
||||||
fi
|
fi
|
||||||
#
|
#
|
||||||
# Download the new version.
|
# Download the new version.
|
||||||
@@ -54,6 +54,5 @@ rm $ZIP
|
|||||||
echo -n ">>New version: " >&2
|
echo -n ">>New version: " >&2
|
||||||
cat $TARGET/VERSION >&2
|
cat $TARGET/VERSION >&2
|
||||||
if [ "$SAVED" != "" ]; then
|
if [ "$SAVED" != "" ]; then
|
||||||
echo ">>Old version saved as $SAVED"
|
echo ">>Old version saved as $SAVED"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+26
-13
@@ -2,25 +2,39 @@
|
|||||||
# the script should be run
|
# the script should be run
|
||||||
# from WEB2PY root directory
|
# from WEB2PY root directory
|
||||||
|
|
||||||
prog=`basename $0`
|
prog="web2py.py"
|
||||||
|
|
||||||
cd `pwd`
|
|
||||||
chmod +x $prog
|
chmod +x $prog
|
||||||
|
|
||||||
function web2py_start {
|
function web2py_start {
|
||||||
nohup ./$prog -a "<recycle>" 2>/dev/null &
|
nohup python2 ./$prog -a "<recycle>" >>/dev/null 2>/dev/null &
|
||||||
pid=`pgrep $prog | tail -1`
|
pid=`pgrep -f $prog | tail -1`
|
||||||
if [ $pid -ne $$ ]
|
if [ "x$pid" != "x$$" ]
|
||||||
then
|
then
|
||||||
echo "WEB2PY has been started."
|
echo "WEB2PY has been started (pid $pid). Stop it with '$0 stop'"
|
||||||
|
else
|
||||||
|
echo "Failed to start WEB2PY."
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function web2py_stop {
|
function web2py_stop {
|
||||||
kill -15 `pgrep $prog | grep -v $$` 2>/dev/null
|
pid="`pgrep -f $prog | grep -v $$`"
|
||||||
pid=`pgrep $prog | head -1`
|
if [ "x$pid" == "x" ]
|
||||||
if [ $pid -ne $$ ]
|
then
|
||||||
then
|
echo "No WEB2PY processes to stop."
|
||||||
echo "WEB2PY has been stopped."
|
else
|
||||||
|
kill -15 $pid
|
||||||
|
# Wait for web2py to shut down gracefully.
|
||||||
|
sleep 2
|
||||||
|
pid="`pgrep -f $prog | head -1`"
|
||||||
|
if [ "x$pid" == "x" ]
|
||||||
|
then
|
||||||
|
echo "WEB2PY has been stopped."
|
||||||
|
else
|
||||||
|
echo "Failed to stop WEB2PY. (Possibly, only one of several web2py processes was killed.)"
|
||||||
|
echo "Still running:"
|
||||||
|
pgrep -af $prog
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +50,8 @@ case "$1" in
|
|||||||
web2py_start
|
web2py_start
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $prog [start|stop|restart]"
|
echo "Usage: $0 [start|stop|restart]"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
|||||||
+36
-37
@@ -28,55 +28,54 @@ PYTHON=python
|
|||||||
cd $DAEMON_DIR
|
cd $DAEMON_DIR
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
echo -n $"Starting $DESC ($NAME): "
|
echo -n $"Starting $DESC ($NAME): "
|
||||||
daemon --check $NAME $PYTHON $DAEMON_DIR/web2py.py -Q --nogui -a $ADMINPASS -d $PIDFILE -p $PORT &
|
daemon --check $NAME $PYTHON $DAEMON_DIR/web2py.py -Q --nogui -a $ADMINPASS -d $PIDFILE -p $PORT &
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
if [ $RETVAL -eq 0 ]; then
|
if [ $RETVAL -eq 0 ]; then
|
||||||
touch /var/lock/subsys/$NAME
|
touch /var/lock/subsys/$NAME
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
return $RETVAL
|
return $RETVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
echo -n $"Shutting down $DESC ($NAME): "
|
echo -n $"Shutting down $DESC ($NAME): "
|
||||||
killproc -p "$PIDFILE" -d 3 "$NAME"
|
killproc -p "$PIDFILE" -d 3 "$NAME"
|
||||||
echo
|
echo
|
||||||
if [ $RETVAL -eq 0 ]; then
|
if [ $RETVAL -eq 0 ]; then
|
||||||
rm -f /var/lock/subsys/$NAME
|
rm -f /var/lock/subsys/$NAME
|
||||||
rm -f $PIDFILE
|
rm -f $PIDFILE
|
||||||
fi
|
fi
|
||||||
return $RETVAL
|
return $RETVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
restart() {
|
restart() {
|
||||||
stop
|
stop
|
||||||
start
|
start
|
||||||
}
|
}
|
||||||
|
|
||||||
status() {
|
status() {
|
||||||
if [ -r "$PIDFILE" ]; then
|
if [ -r "$PIDFILE" ]; then
|
||||||
pid=`cat $PIDFILE`
|
pid=`cat $PIDFILE`
|
||||||
fi
|
fi
|
||||||
if [ $pid ]; then
|
if [ $pid ]; then
|
||||||
echo "$NAME (pid $pid) is running..."
|
echo "$NAME (pid $pid) is running..."
|
||||||
else
|
else
|
||||||
echo "$NAME is stopped"
|
echo "$NAME is stopped"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start) start;;
|
start) start;;
|
||||||
stop) stop;;
|
stop) stop;;
|
||||||
status) status;;
|
status) status;;
|
||||||
restart) restart;;
|
restart) restart;;
|
||||||
condrestart) [ -e /var/lock/subsys/$NAME ] && restart
|
condrestart) [ -e /var/lock/subsys/$NAME ] && restart
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
;;
|
;;
|
||||||
*) echo $"Usage: $0 {start|stop|restart|condrestart|status}"
|
*) echo $"Usage: $0 {start|stop|restart|condrestart|status}"
|
||||||
RETVAL=1
|
RETVAL=1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
exit $RETVAL
|
exit $RETVAL
|
||||||
|
|
||||||
|
|||||||
+108
-109
@@ -48,26 +48,26 @@ DAEMON_USER=web2py
|
|||||||
#
|
#
|
||||||
do_start()
|
do_start()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been started
|
# 0 if daemon has been started
|
||||||
# 1 if daemon was already running
|
# 1 if daemon was already running
|
||||||
# 2 if daemon could not be started
|
# 2 if daemon could not be started
|
||||||
|
|
||||||
# The PIDDIR should normally be created during installation. This
|
# The PIDDIR should normally be created during installation. This
|
||||||
# fixes things just in case.
|
# fixes things just in case.
|
||||||
[ -d $PIDDIR ] || mkdir -p $PIDDIR
|
[ -d $PIDDIR ] || mkdir -p $PIDDIR
|
||||||
[ -n "$DAEMON_USER" ] && chown --recursive $DAEMON_USER $PIDDIR
|
[ -n "$DAEMON_USER" ] && chown --recursive $DAEMON_USER $PIDDIR
|
||||||
|
|
||||||
# Check to see if the daemon is already running.
|
# Check to see if the daemon is already running.
|
||||||
start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \
|
start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \
|
||||||
&& return 1
|
&& return 1
|
||||||
|
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
||||||
${DAEMON_USER:+--chuid $DAEMON_USER} --chdir $DAEMON_DIR \
|
${DAEMON_USER:+--chuid $DAEMON_USER} --chdir $DAEMON_DIR \
|
||||||
--background --exec $DAEMON -- $DAEMON_ARGS \
|
--background --exec $DAEMON -- $DAEMON_ARGS \
|
||||||
|| return 2
|
|| return 2
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -75,17 +75,17 @@ do_start()
|
|||||||
#
|
#
|
||||||
do_stop()
|
do_stop()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been stopped
|
# 0 if daemon has been stopped
|
||||||
# 1 if daemon was already stopped
|
# 1 if daemon was already stopped
|
||||||
# 2 if daemon could not be stopped
|
# 2 if daemon could not be stopped
|
||||||
# other if a failure occurred
|
# other if a failure occurred
|
||||||
|
|
||||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
|
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
# Many daemons don't delete their pidfiles when they exit.
|
# Many daemons don't delete their pidfiles when they exit.
|
||||||
rm -f $PIDFILE
|
rm -f $PIDFILE
|
||||||
return "$RETVAL"
|
return "$RETVAL"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -93,37 +93,37 @@ do_stop()
|
|||||||
#
|
#
|
||||||
do_restart()
|
do_restart()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon was (re-)started
|
# 0 if daemon was (re-)started
|
||||||
# 1 if daemon was not strated or re-started
|
# 1 if daemon was not strated or re-started
|
||||||
|
|
||||||
do_stop
|
do_stop
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0|1)
|
0|1)
|
||||||
do_start
|
do_start
|
||||||
case "$?" in
|
case "$?" in
|
||||||
0) RETVAL=0 ;;
|
0) RETVAL=0 ;;
|
||||||
1) RETVAL=1 ;; # Old process is still running
|
1) RETVAL=1 ;; # Old process is still running
|
||||||
*) RETVAL=1 ;; # Failed to start
|
*) RETVAL=1 ;; # Failed to start
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*) RETVAL=1 ;; # Failed to stop
|
*) RETVAL=1 ;; # Failed to stop
|
||||||
esac
|
esac
|
||||||
|
|
||||||
return "$RETVAL"
|
return "$RETVAL"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Function that sends a SIGHUP to the daemon/service
|
# Function that sends a SIGHUP to the daemon/service
|
||||||
#
|
#
|
||||||
do_reload() {
|
do_reload() {
|
||||||
#
|
#
|
||||||
# If the daemon can reload its configuration without
|
# If the daemon can reload its configuration without
|
||||||
# restarting (for example, when it is sent a SIGHUP),
|
# restarting (for example, when it is sent a SIGHUP),
|
||||||
# then implement that here.
|
# then implement that here.
|
||||||
#
|
#
|
||||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
|
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -131,79 +131,79 @@ do_reload() {
|
|||||||
#
|
#
|
||||||
do_status()
|
do_status()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon is responding and OK
|
# 0 if daemon is responding and OK
|
||||||
# 1 if daemon is not responding, but PIDFILE exists
|
# 1 if daemon is not responding, but PIDFILE exists
|
||||||
# 2 if daemon is not responding, but LOCKFILE exists
|
# 2 if daemon is not responding, but LOCKFILE exists
|
||||||
# 3 if deamon is not running
|
# 3 if deamon is not running
|
||||||
# 4 if daemon status is unknown
|
# 4 if daemon status is unknown
|
||||||
|
|
||||||
# Check to see if the daemon is already running.
|
# Check to see if the daemon is already running.
|
||||||
start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \
|
start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \
|
||||||
&& return 0
|
&& return 0
|
||||||
[ -f $PIDFILE ] && return 1
|
[ -f $PIDFILE ] && return 1
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||||
do_start
|
do_start
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
[ "$VERBOSE" != no ] &&
|
[ "$VERBOSE" != no ] &&
|
||||||
case "$RETVAL" in
|
case "$RETVAL" in
|
||||||
0|1) log_end_msg 0 ;;
|
0|1) log_end_msg 0 ;;
|
||||||
*) log_end_msg 1 ;;
|
*) log_end_msg 1 ;;
|
||||||
esac
|
esac
|
||||||
exit "$RETVAL"
|
exit "$RETVAL"
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||||
do_stop
|
do_stop
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
[ "$VERBOSE" != no ] &&
|
[ "$VERBOSE" != no ] &&
|
||||||
case "$RETVAL" in
|
case "$RETVAL" in
|
||||||
0|1) log_end_msg 0 ;;
|
0|1) log_end_msg 0 ;;
|
||||||
*) log_end_msg 1 ;;
|
*) log_end_msg 1 ;;
|
||||||
esac
|
esac
|
||||||
exit "$RETVAL"
|
exit "$RETVAL"
|
||||||
;;
|
;;
|
||||||
#reload|force-reload)
|
#reload|force-reload)
|
||||||
#
|
#
|
||||||
# If do_reload() is not implemented then leave this commented out
|
# If do_reload() is not implemented then leave this commented out
|
||||||
# and leave 'force-reload' as an alias for 'restart'.
|
# and leave 'force-reload' as an alias for 'restart'.
|
||||||
#
|
#
|
||||||
#[ "$VERBOSE" != no ] && log_daemon_msg "Reloading $DESC" "$NAME"
|
#[ "$VERBOSE" != no ] && log_daemon_msg "Reloading $DESC" "$NAME"
|
||||||
#do_reload
|
#do_reload
|
||||||
#RETVAL=$?
|
#RETVAL=$?
|
||||||
#[ "$VERBOSE" != no ] && log_end_msg $?
|
#[ "$VERBOSE" != no ] && log_end_msg $?
|
||||||
#exit "$RETVAL"
|
#exit "$RETVAL"
|
||||||
#;;
|
#;;
|
||||||
restart|force-reload)
|
restart|force-reload)
|
||||||
#
|
#
|
||||||
# If the "reload" option is implemented then remove the
|
# If the "reload" option is implemented then remove the
|
||||||
# 'force-reload' alias
|
# 'force-reload' alias
|
||||||
#
|
#
|
||||||
[ "$VERBOSE" != no ] && log_daemon_msg "Restarting $DESC" "$NAME"
|
[ "$VERBOSE" != no ] && log_daemon_msg "Restarting $DESC" "$NAME"
|
||||||
do_restart
|
do_restart
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
[ "$VERBOSE" != no ] && log_end_msg "$RETVAL"
|
[ "$VERBOSE" != no ] && log_end_msg "$RETVAL"
|
||||||
exit "$RETVAL"
|
exit "$RETVAL"
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
do_status
|
do_status
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
[ "$VERBOSE" != no ] &&
|
[ "$VERBOSE" != no ] &&
|
||||||
case "$RETVAL" in
|
case "$RETVAL" in
|
||||||
0) log_success_msg "$NAME is running" ;;
|
0) log_success_msg "$NAME is running" ;;
|
||||||
*) log_failure_msg "$NAME is not running" ;;
|
*) log_failure_msg "$NAME is not running" ;;
|
||||||
esac
|
esac
|
||||||
exit "$RETVAL"
|
exit "$RETVAL"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
|
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2
|
||||||
exit 3
|
exit 3
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
:
|
:
|
||||||
@@ -220,4 +220,3 @@ esac
|
|||||||
# http://refspecs.linux-foundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic.pdf
|
# http://refspecs.linux-foundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic.pdf
|
||||||
# Debian Policy SysV init: http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit
|
# Debian Policy SysV init: http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit
|
||||||
# Examine files in /usr/share/doc/sysv-rc/
|
# Examine files in /usr/share/doc/sysv-rc/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user