Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d93a13ca46 | |||
| 7216003eb6 | |||
| e16becb6a9 | |||
| ca6014e6e2 | |||
| 64315dac4a | |||
| fed82e0007 | |||
| 174c1fb31d | |||
| 089013c40e | |||
| 5e0f6c19bf | |||
| 1fff3fc237 | |||
| 32a8a15187 | |||
| b42a3a968f | |||
| d3666ee79a | |||
| cfa0d742fc | |||
| b3d92e8c7d | |||
| e8860233a0 | |||
| 019cad9640 |
@@ -1,6 +1,3 @@
|
|||||||
[submodule "gluon/packages/dal"]
|
[submodule "gluon/packages/dal"]
|
||||||
path = gluon/packages/dal
|
path = gluon/packages/dal
|
||||||
url = https://github.com/web2py/pydal.git
|
url = https://github.com/web2py/pydal.git
|
||||||
[submodule "gluon/packages/yatl"]
|
|
||||||
path = gluon/packages/yatl
|
|
||||||
url = https://github.com/web2py/yatl
|
|
||||||
|
|||||||
+14
-8
@@ -4,22 +4,20 @@ sudo: required
|
|||||||
|
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
||||||
dist: "xenial"
|
dist: "trusty"
|
||||||
|
|
||||||
services:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
python:
|
python:
|
||||||
- '2.7'
|
- '2.7'
|
||||||
- '3.5'
|
- '3.5'
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.6-dev'
|
- '3.6-dev'
|
||||||
- '3.7'
|
|
||||||
- '3.7-dev'
|
- '3.7-dev'
|
||||||
- 'pypy3.5'
|
- 'pypy-5.3.1'
|
||||||
|
- 'pypy3.5-5.7.1-beta'
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
- python: 'pypy3.5-5.7.1-beta'
|
||||||
- python: '3.6-dev'
|
- python: '3.6-dev'
|
||||||
- python: '3.7-dev'
|
- python: '3.7-dev'
|
||||||
|
|
||||||
@@ -29,9 +27,11 @@ install:
|
|||||||
before_script:
|
before_script:
|
||||||
- pip install coverage
|
- pip install coverage
|
||||||
- pip install codecov
|
- pip install codecov
|
||||||
|
|
||||||
before_install:
|
|
||||||
- mysql -e 'create database pydal;'
|
- mysql -e 'create database pydal;'
|
||||||
|
- psql -c 'create database pydal;' -U postgres
|
||||||
|
- psql -c 'create extension postgis;' -U postgres -d pydal;
|
||||||
|
- psql -c 'SHOW SERVER_VERSION' -U postgres
|
||||||
|
|
||||||
|
|
||||||
script: export COVERAGE_PROCESS_START=gluon/tests/coverage.ini; ./web2py.py --run_system_tests --with_coverage
|
script: export COVERAGE_PROCESS_START=gluon/tests/coverage.ini; ./web2py.py --run_system_tests --with_coverage
|
||||||
|
|
||||||
@@ -41,3 +41,9 @@ after_success:
|
|||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: true
|
email: true
|
||||||
|
|
||||||
|
addons:
|
||||||
|
postgresql: "9.4"
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- postgresql-9.4-postgis-2.3
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
## 2.18.1-2.18.3
|
|
||||||
- pydal 19.02
|
|
||||||
- made template its own module (Yet Another Template Language)
|
|
||||||
- improved python 3.4-3.7 support
|
|
||||||
- bug fixes
|
|
||||||
|
|
||||||
## 2.17.1-2
|
## 2.17.1-2
|
||||||
- pydal 18.08
|
- pydal 18.08
|
||||||
- many small bug fixes
|
- many small bug fixes
|
||||||
|
|||||||
@@ -6,18 +6,17 @@ clean:
|
|||||||
rm -f httpserver.log
|
rm -f httpserver.log
|
||||||
rm -f parameters*.py
|
rm -f parameters*.py
|
||||||
rm -f -r applications/*/compiled
|
rm -f -r applications/*/compiled
|
||||||
find . -name '*~' -exec rm -f {} \;
|
find ./ -name '*~' -exec rm -f {} \;
|
||||||
find . -name '*.orig' -exec rm -f {} \;
|
find ./ -name '*.orig' -exec rm -f {} \;
|
||||||
find . -name '*.rej' -exec rm -f {} \;
|
find ./ -name '*.rej' -exec rm -f {} \;
|
||||||
find . -name '#*' -exec rm -f {} \;
|
find ./ -name '#*' -exec rm -f {} \;
|
||||||
find . -name 'Thumbs.db' -exec rm -f {} \;
|
find ./ -name 'Thumbs.db' -exec rm -f {} \;
|
||||||
find . -name '.tox' -exec rm -rf {} \;
|
# find ./gluon/ -name '.*' -exec rm -f {} \;
|
||||||
find . -name '__pycache__' -exec rm -rf {} \;
|
find ./gluon/ -name '*class' -exec rm -f {} \;
|
||||||
find gluon/ -name '*class' -exec rm -f {} \;
|
find ./applications/admin/ -name '.*' -exec rm -f {} \;
|
||||||
find applications/admin/ -name '.*' -exec rm -f {} \;
|
find ./applications/examples/ -name '.*' -exec rm -f {} \;
|
||||||
find applications/examples/ -name '.*' -exec rm -f {} \;
|
find ./applications/welcome/ -name '.*' -exec rm -f {} \;
|
||||||
find applications/welcome/ -name '.*' -exec rm -f {} \;
|
find ./ -name '*.pyc' -exec rm -f {} \;
|
||||||
find . -name '*.pyc' -exec rm -f {} \;
|
|
||||||
tests:
|
tests:
|
||||||
python web2py.py --run_system_tests
|
python web2py.py --run_system_tests
|
||||||
coverage:
|
coverage:
|
||||||
@@ -45,9 +44,9 @@ rmfiles:
|
|||||||
rm -rf applications/examples/uploads/*
|
rm -rf applications/examples/uploads/*
|
||||||
src:
|
src:
|
||||||
### Use semantic versioning
|
### Use semantic versioning
|
||||||
echo 'Version 2.18.3-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
echo 'Version 2.17.2-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||||
### rm -f all junk files
|
### rm -f all junk files
|
||||||
make clean
|
#make clean
|
||||||
# make rmfiles
|
# make rmfiles
|
||||||
### make welcome layout and appadmin the default
|
### make welcome layout and appadmin the default
|
||||||
cp applications/welcome/views/appadmin.html applications/admin/views
|
cp applications/welcome/views/appadmin.html applications/admin/views
|
||||||
@@ -57,7 +56,7 @@ src:
|
|||||||
### build web2py_src.zip
|
### build web2py_src.zip
|
||||||
echo '' > NEWINSTALL
|
echo '' > NEWINSTALL
|
||||||
mv web2py_src.zip web2py_src_old.zip | echo 'no old'
|
mv web2py_src.zip web2py_src_old.zip | echo 'no old'
|
||||||
cd ..; zip -r --exclude=**.git** --exclude=**.tox** --exclude=**_pycache__** web2py/web2py_src.zip web2py/web2py.py web2py/anyserver.py web2py/fabfile.py web2py/gluon/* web2py/extras/* web2py/handlers/* web2py/examples/* web2py/README.markdown web2py/LICENSE web2py/CHANGELOG web2py/NEWINSTALL web2py/VERSION web2py/MANIFEST.in web2py/scripts/*.sh web2py/scripts/*.py web2py/applications/admin web2py/applications/examples/ web2py/applications/welcome web2py/applications/__init__.py web2py/site-packages/__init__.py web2py/gluon/tests/*.sh web2py/gluon/tests/*.py
|
cd ..; zip -r --exclude=**.git** web2py/web2py_src.zip web2py/web2py.py web2py/anyserver.py web2py/fabfile.py web2py/gluon/* web2py/extras/* web2py/handlers/* web2py/examples/* web2py/README.markdown web2py/LICENSE web2py/CHANGELOG web2py/NEWINSTALL web2py/VERSION web2py/MANIFEST.in web2py/scripts/*.sh web2py/scripts/*.py web2py/applications/admin web2py/applications/examples/ web2py/applications/welcome web2py/applications/__init__.py web2py/site-packages/__init__.py web2py/gluon/tests/*.sh web2py/gluon/tests/*.py
|
||||||
|
|
||||||
mdp:
|
mdp:
|
||||||
make src
|
make src
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Version 2.18.3-stable+timestamp.2019.03.03.15.06.20
|
Version 2.17.2-stable+timestamp.2018.10.06.11.34.06
|
||||||
|
|||||||
@@ -185,9 +185,9 @@ def select():
|
|||||||
is_imap = db._uri.startswith("imap://")
|
is_imap = db._uri.startswith("imap://")
|
||||||
except (KeyError, AttributeError, TypeError):
|
except (KeyError, AttributeError, TypeError):
|
||||||
is_imap = False
|
is_imap = False
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||||
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
||||||
if request.vars.query:
|
if request.vars.query:
|
||||||
match = regex.match(request.vars.query)
|
match = regex.match(request.vars.query)
|
||||||
if match:
|
if match:
|
||||||
@@ -237,7 +237,7 @@ def select():
|
|||||||
|
|
||||||
tb = None
|
tb = None
|
||||||
if form.accepts(request.vars, formname=None):
|
if form.accepts(request.vars, formname=None):
|
||||||
regex = re.compile(request.args[0] + r'\.(?P<table>\w+)\..+')
|
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
|
||||||
match = regex.match(form.vars.query.strip())
|
match = regex.match(form.vars.query.strip())
|
||||||
if match:
|
if match:
|
||||||
table = match.group('table')
|
table = match.group('table')
|
||||||
|
|||||||
Regular → Executable
+267
-267
@@ -2,92 +2,92 @@
|
|||||||
{
|
{
|
||||||
'!langcode!': 'de',
|
'!langcode!': 'de',
|
||||||
'!langname!': 'Deutsch',
|
'!langname!': 'Deutsch',
|
||||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "feld1=\'newvalue\'". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden',
|
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "Feld1 = \'newvalue". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden',
|
||||||
'"User Exception" debug mode. ': '"Benutzerausnahme" Debug-Modus.',
|
'"User Exception" debug mode. ': '"User Exception" debug mode. ',
|
||||||
'%s': '%s',
|
'%s': '%s',
|
||||||
'%s %%{row} deleted': '%s %%{Reihe} gelöscht',
|
'%s %%{row} deleted': '%s %%{row} Zeilen gelöscht',
|
||||||
'%s %%{row} updated': '%s %%{Reihe} aktualisiert',
|
'%s %%{row} updated': '%s %%{row} Zeilen aktualisiert',
|
||||||
'%s selected': '%s ausgewählt',
|
'%s selected': '%s selected',
|
||||||
'%s students registered': '%s Studenten registriert',
|
'%s students registered': '%s students registered',
|
||||||
'%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)': '(Erfordert Internetzugang)',
|
'(requires internet access)': '(Benötigt Internetzugang)',
|
||||||
'(requires internet access, experimental)': '(Erfordert Internetzugang, experimentell)',
|
'(requires internet access, experimental)': '(Benötigt Internetzugang)',
|
||||||
'(something like "it-it")': '(so etwas wie "it-it")',
|
'(something like "it-it")': '(so etwas wie "it-it")',
|
||||||
'(version %s)': '(version %s)',
|
'(version %s)': '(version %s)',
|
||||||
'?': '?',
|
'?': '?',
|
||||||
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(Datei **gluon/contrib/plural_rules/%s.py** wurde nicht gefunden)',
|
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(Datei **gluon/contrib/plural_rules/%s.py** wurde nicht gefunden)',
|
||||||
'@markmin\x01An error occured, please [[reload %s]] the page': 'Ein Fehler ist aufgetreten, bitte [[laden %s]] Sie die Seite neu',
|
'@markmin\x01An error occured, please [[reload %s]] the page': 'Ein Fehler ist aufgetreten, bitte [[reload %s]] sie die Seite erneut',
|
||||||
'@markmin\x01Searching: **%s** %%{file}': 'Suche: **% s ** %% {Datei}',
|
'@markmin\x01Searching: **%s** %%{file}': '@markmin\x01Suche: **%s** Dateien',
|
||||||
'A new version of web2py is available': 'Eine neue Version von web2py ist verfügbar',
|
'A new version of web2py is available': 'Eine neue Version von web2py ist verfügbar',
|
||||||
'A new version of web2py is available: %s': 'Eine neue Version von web2py ist verfügbar: %s',
|
'A new version of web2py is available: %s': 'Eine neue Version von web2py ist verfügbar: %s',
|
||||||
'Abort': 'Verwerfen',
|
'Abort': 'Abbrechen',
|
||||||
'About': 'Über',
|
'About': 'Über',
|
||||||
'About application': 'Über die Anwendung',
|
'About application': 'Über die Anwendung',
|
||||||
'Accept Terms': 'Nutzerbedingungen akzeptieren',
|
'Accept Terms': 'Accept Terms',
|
||||||
'Add breakpoint': 'Breakpoint hinzufügen',
|
'Add breakpoint': 'Add breakpoint',
|
||||||
'Additional code for your application': 'Zusätzlicher Code für Ihre Anwendung',
|
'Additional code for your application': 'Zusätzlicher Code für Ihre Anwendung',
|
||||||
'Admin design page': 'Admin-Design-Seite',
|
'Admin design page': 'Admin design page',
|
||||||
'admin disabled because no admin password': 'Admin ist deaktiviert, da kein Admin-Passwort gesetzt ist',
|
'admin disabled because no admin password': 'admin ist deaktiviert, weil kein Admin-Passwort gesetzt ist',
|
||||||
'admin disabled because not supported on google app engine': 'Admin deaktiviert, da auf Google App Engine nicht unterstützt',
|
'admin disabled because not supported on google app engine': 'admin disabled because not supported on google app engine',
|
||||||
'admin disabled because not supported on google apps engine': 'Admin deaktiviert, da es auf Google Apps Engine nicht unterstützt wird.',
|
'admin disabled because not supported on google apps engine': 'admin ist deaktiviert, es existiert dafür keine Unterstützung auf der google apps engine',
|
||||||
'admin disabled because too many invalid login attempts': 'Admin deaktiviert, weil zu viele ungültige Anmeldeversuche',
|
'admin disabled because too many invalid login attempts': 'admin disabled because too many invalid login attempts',
|
||||||
'admin disabled because unable to access password file': 'Admin deaktiviert, da der Zugriff auf die Kennwortdatei nicht möglich ist',
|
'admin disabled because unable to access password file': 'admin ist deaktiviert, weil kein Zugriff auf die Passwortdatei besteht',
|
||||||
'Admin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
'Admin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||||
'Admin is disabled because unsecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
'Admin is disabled because unsecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||||
'Admin language': 'Admin-Sprache',
|
'Admin language': 'Admin-Sprache',
|
||||||
'Admin versioning page': 'Admin-Versionierungsseite',
|
'Admin versioning page': 'Admin versioning page',
|
||||||
'administrative interface': 'Administratives Interface',
|
'administrative interface': 'Administrative Schnittstelle',
|
||||||
'Administrator Password:': 'Administrator Passwort:',
|
'Administrator Password:': 'Administrator Passwort:',
|
||||||
'An error occured, please %s the page': 'Ein Fehler ist aufgetereten, bitte %s die Seite',
|
'An error occured, please %s the page': 'Ein Fehler ist aufgetereten, bitte %s die Seite',
|
||||||
'and rename it (required):': 'und benenne sie se um (erforderlich):',
|
'and rename it (required):': 'und benenne sie um (erforderlich):',
|
||||||
'and rename it:': ' und benenne sie es um:',
|
'and rename it:': ' und benenne sie um:',
|
||||||
'App does not exist or you are not authorized': 'App existiert nicht oder Sie sind nicht autorisiert',
|
'App does not exist or you are not authorized': 'App does not exist or you are not authorized',
|
||||||
'appadmin': 'appadmin',
|
'appadmin': 'appadmin',
|
||||||
'appadmin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
'appadmin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||||
'Application': 'Anwendung',
|
'Application': 'Anwendung',
|
||||||
'application "%s" uninstalled': 'Anwendung "%s" deinstalliert',
|
'application "%s" uninstalled': 'Anwendung "%s" deinstalliert',
|
||||||
'Application cannot be generated in demo mode': 'Anwendung kann nicht im Demo-Modus erstellt werden',
|
'Application cannot be generated in demo mode': 'Application cannot be generated in demo mode',
|
||||||
'application compiled': 'Anwendung kompiliert',
|
'application compiled': 'Anwendung kompiliert',
|
||||||
'Application exists already': 'Anwendung existiert bereits',
|
'Application exists already': 'Application exists already',
|
||||||
'application is compiled and cannot be designed': 'Die Anwendung ist kompiliert und kann deswegen nicht mehr geändert werden',
|
'application is compiled and cannot be designed': 'Die Anwendung ist kompiliert und kann deswegen nicht mehr geändert werden',
|
||||||
'Application name:': 'Anwendungsname:',
|
'Application name:': 'Name der Anwendung:',
|
||||||
'Application updated via git pull': 'Die Anwendung wurde über Git Pull updated',
|
'Application updated via git pull': 'Application updated via git pull',
|
||||||
'are not used': 'werden nicht verwendet',
|
'are not used': 'werden nicht verwendet',
|
||||||
'are not used yet': 'werden bisher nicht verwendet',
|
'are not used yet': 'werden bisher nicht verwendet',
|
||||||
'Are you sure you want to delete file "%s"?': 'Sind Sie sich sicher, dass Sie die Datei "%s" löschen wollen?',
|
'Are you sure you want to delete file "%s"?': 'Sind Sie sich sicher, dass Sie diese Datei löschen wollen "%s"?',
|
||||||
'Are you sure you want to delete plugin "%s"?': 'Möchten Sie das Plugin "%s" wirklich löschen?',
|
'Are you sure you want to delete plugin "%s"?': 'Are you sure you want to delete plugin "%s"?',
|
||||||
'Are you sure you want to delete this object?': 'Sind Sie sich sicher, dass Sie dieses Objekt löschen wollen?',
|
'Are you sure you want to delete this object?': 'Sind Sie sich sicher, dass Sie dieses Objekt löschen wollen?',
|
||||||
'Are you sure you want to uninstall application "%s"': 'Sind Sie sich sicher, dass Sie die Anwendung "%s" deinstallieren wollen',
|
'Are you sure you want to uninstall application "%s"': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"',
|
||||||
'Are you sure you want to uninstall application "%s"?': 'Sind Sie sich sicher, dass Sie die Anwendung "%s" deinstallieren wollen?',
|
'Are you sure you want to uninstall application "%s"?': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"?',
|
||||||
'Are you sure you want to upgrade web2py now?': 'Sind Sie sich sicher, dass Sie web2py jetzt upgraden möchten?',
|
'Are you sure you want to upgrade web2py now?': 'Sind Sie sich sicher, dass Sie web2py jetzt upgraden möchten?',
|
||||||
'Are you sure?': 'Bist du sicher?',
|
'Are you sure?': 'Are you sure?',
|
||||||
'arguments': 'Argumente',
|
'arguments': 'arguments',
|
||||||
'at char %s': 'bei Zeichen %s',
|
'at char %s': 'bei Zeichen %s',
|
||||||
'at line %s': 'in Linie %s',
|
'at line %s': 'in Linie %s',
|
||||||
'ATTENTION:': 'BEACHTUNG:',
|
'ATTENTION:': 'ATTENTION:',
|
||||||
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ACHTUNG: Die Einwahl benötigt eine sichere (HTTPS) Verbindung. Es sei denn sie läuft Lokal (localhost).',
|
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ACHTUNG: Die Einwahl benötigt eine sichere (HTTPS) Verbindung. Es sei denn sie läuft Lokal (localhost).',
|
||||||
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ACHTUNG: Testen ist nicht threadsicher. Führen Sie also nicht mehrere Tests gleichzeitig aus.',
|
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ACHTUNG: Testen ist nicht threadsicher. Führen Sie also nicht mehrere Tests gleichzeitig aus.',
|
||||||
'ATTENTION: This is an experimental feature and it needs more testing.': 'ACHTUNG: Dies ist eine experimentelle Funktion und benötigt noch weitere Tests.',
|
'ATTENTION: This is an experimental feature and it needs more testing.': 'ACHTUNG: Dies ist eine experimentelle Funktion und benötigt noch weitere Tests.',
|
||||||
'ATTENTION: you cannot edit the running application!': 'ACHTUNG: Eine laufende Anwendung kann nicht editiert werden!',
|
'ATTENTION: you cannot edit the running application!': 'ACHTUNG: Eine laufende Anwendung kann nicht editiert werden!',
|
||||||
'Authentication': 'Authentifizierung',
|
'Authentication': 'Authentifizierung',
|
||||||
'Autocomplete Python Code': 'Python-Code automatisch vervollständigen',
|
'Autocomplete Python Code': 'Autocomplete Python Code',
|
||||||
'Available databases and tables': 'Verfügbare Datenbanken und Tabellen',
|
'Available databases and tables': 'Verfügbare Datenbanken und Tabellen',
|
||||||
'Available Databases and Tables': 'Verfügbare Datenbanken und Tabellen',
|
'Available Databases and Tables': 'Available Databases and Tables',
|
||||||
'back': 'Zurück',
|
'back': 'Zurück',
|
||||||
'Back to the plugins list': 'Zurück zur Plugin-Liste',
|
'Back to the plugins list': 'Back to the plugins list',
|
||||||
'Back to wizard': 'Zurück zum Wizard',
|
'Back to wizard': 'Back to wizard',
|
||||||
'Basics': 'Basics',
|
'Basics': 'Basics',
|
||||||
'beautify': 'Verschönern',
|
'beautify': 'Verschönern',
|
||||||
'Begin': 'Start',
|
'Begin': 'Begin',
|
||||||
'breakpoint': 'breakpoint',
|
'breakpoint': 'breakpoint',
|
||||||
'Breakpoints': 'Breakpoints',
|
'Breakpoints': 'Breakpoints',
|
||||||
'breakpoints': 'breakpoints',
|
'breakpoints': 'breakpoints',
|
||||||
'Bulk Register': 'Masse-registrierung',
|
'Bulk Register': 'Bulk Register',
|
||||||
'Bulk Student Registration': 'Massen-Studenten registrierung',
|
'Bulk Student Registration': 'Bulk Student Registration',
|
||||||
'Cache': 'Zwischenspeicher',
|
'Cache': 'Cache',
|
||||||
'cache': 'Zwischenspeicher',
|
'cache': 'Zwischenspeicher',
|
||||||
'Cache Cleared': 'Cache geleert',
|
'Cache Cleared': 'Cache Cleared',
|
||||||
'Cache Keys': 'Cache Keys',
|
'Cache Keys': 'Cache Keys',
|
||||||
'cache, errors and sessions cleaned': 'Zwischenspeicher (cache), Fehler und Sitzungen (sessions) gelöscht',
|
'cache, errors and sessions cleaned': 'Zwischenspeicher (cache), Fehler und Sitzungen (sessions) gelöscht',
|
||||||
'call': 'Aufruf',
|
'call': 'Aufruf',
|
||||||
@@ -95,10 +95,10 @@
|
|||||||
'Cancel': 'Abbrechen',
|
'Cancel': 'Abbrechen',
|
||||||
'Cannot be empty': 'Darf nicht leer sein',
|
'Cannot be empty': 'Darf nicht leer sein',
|
||||||
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Nicht Kompilierbar: Es sind Fehler in der Anwendung. Beseitigen Sie die Fehler und versuchen Sie es erneut.',
|
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Nicht Kompilierbar: Es sind Fehler in der Anwendung. Beseitigen Sie die Fehler und versuchen Sie es erneut.',
|
||||||
'Cannot compile: there are errors in your app:': 'Kompilieren nicht möglich: Es gibt Fehler in Ihrer App:',
|
'Cannot compile: there are errors in your app:': 'Cannot compile: there are errors in your app:',
|
||||||
'cannot create file': 'Kann Datei nicht erstellen',
|
'cannot create file': 'Kann Datei nicht erstellen',
|
||||||
'cannot upload file "%(filename)s"': 'Kann Datei nicht Hochladen "%(filename)s"',
|
'cannot upload file "%(filename)s"': 'Kann Datei nicht Hochladen "%(filename)s"',
|
||||||
'Change Admin Password': 'Admin-Passwort ändern',
|
'Change Admin Password': 'Change Admin Password',
|
||||||
'Change admin password': 'Administrator-Passwort ändern',
|
'Change admin password': 'Administrator-Passwort ändern',
|
||||||
'change editor settings': 'Editoreinstellungen ändern',
|
'change editor settings': 'Editoreinstellungen ändern',
|
||||||
'Change Password': 'Passwort ändern',
|
'Change Password': 'Passwort ändern',
|
||||||
@@ -109,30 +109,30 @@
|
|||||||
'Check to delete': 'Markiere zum löschen',
|
'Check to delete': 'Markiere zum löschen',
|
||||||
'Checking for upgrades...': 'Überprüfe auf Updates...',
|
'Checking for upgrades...': 'Überprüfe auf Updates...',
|
||||||
'Clean': 'Leeren',
|
'Clean': 'Leeren',
|
||||||
'Clear': 'Leeren',
|
'Clear': 'Clear',
|
||||||
'Clear CACHE?': 'CACHE leeren?',
|
'Clear CACHE?': 'Clear CACHE?',
|
||||||
'Clear DISK': 'DISK leeren',
|
'Clear DISK': 'Clear DISK',
|
||||||
'Clear RAM': 'RAM leeren',
|
'Clear RAM': 'Clear RAM',
|
||||||
'click here for online examples': 'hier klicken für online Beispiele',
|
'click here for online examples': 'hier klicken für online Beispiele',
|
||||||
'click here for the administrative interface': 'hier klicken für die Administrationsoberfläche ',
|
'click here for the administrative interface': 'hier klicken für die Administrationsoberfläche ',
|
||||||
'Click row to expand traceback': 'Klicke auf die Zeile für Fehlerverfolgung',
|
'Click row to expand traceback': 'Klicke auf die Zeile für Fehlerverfolgung',
|
||||||
'Click row to view a ticket': 'Klicke auf eine Zeile, um ein Ticket anzusehen',
|
'Click row to view a ticket': 'Click row to view a ticket',
|
||||||
'click to check for upgrades': 'hier klicken um nach Upgrades zu suchen',
|
'click to check for upgrades': 'hier klicken um nach Upgrades zu suchen',
|
||||||
'Client IP': 'Client IP',
|
'Client IP': 'Client IP',
|
||||||
'code': 'Code',
|
'code': 'code',
|
||||||
'Code listing': 'Codeauflistung',
|
'Code listing': 'Code listing',
|
||||||
'collapse/expand all': 'alles zu- bzw. aufklappen',
|
'collapse/expand all': 'alles zu- bzw. aufklappen',
|
||||||
'Command': 'Befehl',
|
'Command': 'Command',
|
||||||
'Comment:': 'Kommentar:',
|
'Comment:': 'Comment:',
|
||||||
'Commit': 'Commit',
|
'Commit': 'Commit',
|
||||||
'Commit form': 'Formular ausfüllen',
|
'Commit form': 'Commit form',
|
||||||
'Committed files': 'Festgelegte Dateien',
|
'Committed files': 'Committed files',
|
||||||
'Compile': 'kompilieren',
|
'Compile': 'kompilieren',
|
||||||
'Compile (all or nothing)': 'Kompilieren (alles oder nichts)',
|
'Compile (all or nothing)': 'Compile (all or nothing)',
|
||||||
'Compile (skip failed views)': 'Kompilieren (Fehlgeschlagene Ansichten überspringen)',
|
'Compile (skip failed views)': 'Compile (skip failed views)',
|
||||||
'compiled application removed': 'kompilierte Anwendung gelöscht',
|
'compiled application removed': 'kompilierte Anwendung gelöscht',
|
||||||
'Condition': 'Bedingung',
|
'Condition': 'Condition',
|
||||||
'continue': 'fortsetzen',
|
'continue': 'continue',
|
||||||
'Controller': 'Controller',
|
'Controller': 'Controller',
|
||||||
'Controllers': 'Controllers',
|
'Controllers': 'Controllers',
|
||||||
'controllers': 'controllers',
|
'controllers': 'controllers',
|
||||||
@@ -142,11 +142,11 @@
|
|||||||
'create file with filename:': 'Erzeuge Datei mit Dateinamen:',
|
'create file with filename:': 'Erzeuge Datei mit Dateinamen:',
|
||||||
'create new application:': 'Erzeuge neue Anwendung:',
|
'create new application:': 'Erzeuge neue Anwendung:',
|
||||||
'Create new simple application': 'Erzeuge neue Anwendung',
|
'Create new simple application': 'Erzeuge neue Anwendung',
|
||||||
'Create/Upload': 'Erstellen/Uploaden',
|
'Create/Upload': 'Create/Upload',
|
||||||
'created by': 'Erstellt von',
|
'created by': 'Erstellt von',
|
||||||
'Created by:': 'Erstellt von:',
|
'Created by:': 'Created by:',
|
||||||
'Created On': 'Erstellt am',
|
'Created On': 'Created On',
|
||||||
'Created on:': 'Erstellt am:',
|
'Created on:': 'Created on:',
|
||||||
'crontab': 'crontab',
|
'crontab': 'crontab',
|
||||||
'Current request': 'Aktuelle Anfrage (request)',
|
'Current request': 'Aktuelle Anfrage (request)',
|
||||||
'Current response': 'Aktuelle Antwort (response)',
|
'Current response': 'Aktuelle Antwort (response)',
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
'data uploaded': 'Daten hochgeladen',
|
'data uploaded': 'Daten hochgeladen',
|
||||||
'Database': 'Datenbank',
|
'Database': 'Datenbank',
|
||||||
'database': 'Datenbank',
|
'database': 'Datenbank',
|
||||||
'Database %s select': 'Database %s ausgewählt',
|
'Database %s select': 'Database %s select',
|
||||||
'database %s select': 'Datenbank %s ausgewählt',
|
'database %s select': 'Datenbank %s ausgewählt',
|
||||||
'Database administration': 'Database administration',
|
'Database administration': 'Database administration',
|
||||||
'database administration': 'Datenbankadministration',
|
'database administration': 'Datenbankadministration',
|
||||||
@@ -173,49 +173,49 @@
|
|||||||
'delete plugin': 'Plugin löschen',
|
'delete plugin': 'Plugin löschen',
|
||||||
'Delete this file (you will be asked to confirm deletion)': 'Diese Datei löschen (mit Bestätigungsdialog)',
|
'Delete this file (you will be asked to confirm deletion)': 'Diese Datei löschen (mit Bestätigungsdialog)',
|
||||||
'Delete:': 'Löschen:',
|
'Delete:': 'Löschen:',
|
||||||
'deleted after first hit': 'nach dem ersten Treffer gelöscht',
|
'deleted after first hit': 'deleted after first hit',
|
||||||
'Demo': 'Demo',
|
'Demo': 'Demo',
|
||||||
'Deploy': 'Installieren',
|
'Deploy': 'Installieren',
|
||||||
'Deploy on Google App Engine': 'Auf Google App Engine installieren',
|
'Deploy on Google App Engine': 'Auf Google App Engine installieren',
|
||||||
'Deploy to OpenShift': 'Auf OpenShift installieren',
|
'Deploy to OpenShift': 'Auf OpenShift installieren',
|
||||||
'Deploy to pythonanywhere': 'Bereitstellen für pythonanywhere',
|
'Deploy to pythonanywhere': 'Deploy to pythonanywhere',
|
||||||
'Deploy to PythonAnywhere': 'Bereitstellen für PythonAnywhere',
|
'Deploy to PythonAnywhere': 'Deploy to PythonAnywhere',
|
||||||
'Deployment form': 'Deployment form',
|
'Deployment form': 'Deployment form',
|
||||||
'Deployment Interface': 'Deployment Interface',
|
'Deployment Interface': 'Deployment Interface',
|
||||||
'Description': 'Beschreibung',
|
'Description': 'Beschreibung',
|
||||||
'Description:': 'Beschreibung:',
|
'Description:': 'Description:',
|
||||||
'design': 'design',
|
'design': 'design',
|
||||||
'DESIGN': 'DESIGN',
|
'DESIGN': 'DESIGN',
|
||||||
'Design for': 'Design für',
|
'Design for': 'Design für',
|
||||||
'Detailed traceback description': 'Detaillierte traceback Beschreibung',
|
'Detailed traceback description': 'Detaillierte traceback Beschreibung',
|
||||||
'details': 'Details',
|
'details': 'details',
|
||||||
'direction: ltr': 'Richtung: ltr',
|
'direction: ltr': 'direction: ltr',
|
||||||
'directory not found': 'Verzeichnis nicht gefunden',
|
'directory not found': 'directory not found',
|
||||||
'Disable': 'Deaktivieren',
|
'Disable': 'Deaktivieren',
|
||||||
'Disabled': 'Deaktiviert',
|
'Disabled': 'Disabled',
|
||||||
'disabled in demo mode': 'Im Demo Modus deaktiviert',
|
'disabled in demo mode': 'disabled in demo mode',
|
||||||
'disabled in GAE mode': 'Im GAE Modus deaktiviert',
|
'disabled in GAE mode': 'disabled in GAE mode',
|
||||||
'disabled in multi user mode': 'Im Multi-User-Modus deaktiviert',
|
'disabled in multi user mode': 'disabled in multi user mode',
|
||||||
'DISK': 'DISK',
|
'DISK': 'DISK',
|
||||||
'Disk Cache Keys': 'Disk Cache Keys',
|
'Disk Cache Keys': 'Disk Cache Keys',
|
||||||
'Disk Cleared': 'Disk geleert',
|
'Disk Cleared': 'Disk Cleared',
|
||||||
'Display line numbers': 'Zeilennummern anzeigen',
|
'Display line numbers': 'Display line numbers',
|
||||||
'DO NOT use the "Pack compiled" feature.': 'Verwenden Sie NICHT die Funktion "Pack kompiliert".',
|
'DO NOT use the "Pack compiled" feature.': 'DO NOT use the "Pack compiled" feature.',
|
||||||
'docs': 'docs',
|
'docs': 'docs',
|
||||||
'Docs': 'Docs',
|
'Docs': 'Docs',
|
||||||
'documentation': 'Dokumentation',
|
'documentation': 'Dokumentation',
|
||||||
'done!': 'fertig!',
|
'done!': 'fertig!',
|
||||||
'Downgrade': 'Downgrade',
|
'Downgrade': 'Downgrade',
|
||||||
'Download .w2p': 'Download .w2p',
|
'Download .w2p': 'Download .w2p',
|
||||||
'Download as .exe': 'Downloade als .exe',
|
'Download as .exe': 'Download as .exe',
|
||||||
'download layouts': 'Layouts herunterladen',
|
'download layouts': 'Layouts herunterladen',
|
||||||
'Download layouts from repository': 'Layouts aus dem Repository herunterladen',
|
'Download layouts from repository': 'Download layouts from repository',
|
||||||
'download plugins': 'Plugins herunterladen',
|
'download plugins': 'Plugins herunterladen',
|
||||||
'Download plugins from repository': 'Plugins aus dem Repository herunterladen',
|
'Download plugins from repository': 'Download plugins from repository',
|
||||||
'E-mail': 'E-mail',
|
'E-mail': 'E-mail',
|
||||||
'EDIT': 'BEARBEITEN',
|
'EDIT': 'BEARBEITEN',
|
||||||
'Edit': 'Bearbeiten',
|
'Edit': 'Bearbeiten',
|
||||||
'edit all': 'Alles bearbeiten',
|
'edit all': 'edit all',
|
||||||
'Edit application': 'Bearbeite Anwendung',
|
'Edit application': 'Bearbeite Anwendung',
|
||||||
'edit controller': 'Bearbeite Controller',
|
'edit controller': 'Bearbeite Controller',
|
||||||
'edit controller:': 'bearbeite Controller:',
|
'edit controller:': 'bearbeite Controller:',
|
||||||
@@ -228,12 +228,12 @@
|
|||||||
'Editing file': 'Bearbeite Datei',
|
'Editing file': 'Bearbeite Datei',
|
||||||
'Editing file "%s"': 'Bearbeite Datei "%s"',
|
'Editing file "%s"': 'Bearbeite Datei "%s"',
|
||||||
'Editing Language file': 'Sprachdatei bearbeiten',
|
'Editing Language file': 'Sprachdatei bearbeiten',
|
||||||
'Editing Plural Forms File': 'Bearbeiten von Plural formen Datei',
|
'Editing Plural Forms File': 'Editing Plural Forms File',
|
||||||
'Editor': 'Editor',
|
'Editor': 'Editor',
|
||||||
'Email Address': 'Email Address',
|
'Email Address': 'Email Address',
|
||||||
'Enable': 'Aktivieren',
|
'Enable': 'Aktivieren',
|
||||||
'Enable Close-Tag': 'Aktiviere Close-Tag',
|
'Enable Close-Tag': 'Enable Close-Tag',
|
||||||
'Enable Code Folding': 'Aktiviere Code Folding',
|
'Enable Code Folding': 'Enable Code Folding',
|
||||||
'Enterprise Web Framework': 'Enterprise Web Framework',
|
'Enterprise Web Framework': 'Enterprise Web Framework',
|
||||||
'Error': 'Fehler',
|
'Error': 'Fehler',
|
||||||
'Error logs for "%(app)s"': 'Fehlerprotokoll für "%(app)s"',
|
'Error logs for "%(app)s"': 'Fehlerprotokoll für "%(app)s"',
|
||||||
@@ -241,8 +241,8 @@
|
|||||||
'Error ticket': 'Error ticket',
|
'Error ticket': 'Error ticket',
|
||||||
'Errors': 'Fehlermeldungen',
|
'Errors': 'Fehlermeldungen',
|
||||||
'escape': 'escape',
|
'escape': 'escape',
|
||||||
'Exception %(extype)s: %(exvalue)s': 'Ausnahme %(extype)s: %(exvalue)s',
|
'Exception %(extype)s: %(exvalue)s': 'Exception %(extype)s: %(exvalue)s',
|
||||||
'Exception %s': 'Ausnahme %s',
|
'Exception %s': 'Exception %s',
|
||||||
'Exception instance attributes': 'Attribute der Ausnahmeinstanz',
|
'Exception instance attributes': 'Attribute der Ausnahmeinstanz',
|
||||||
'Exit Fullscreen': 'Vollbild beenden',
|
'Exit Fullscreen': 'Vollbild beenden',
|
||||||
'Expand Abbreviation': 'Kürzel erweitern',
|
'Expand Abbreviation': 'Kürzel erweitern',
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
'extends': 'erweitert',
|
'extends': 'erweitert',
|
||||||
'failed to compile file because:': 'Datei konnte nicht kompiliert werden, da:',
|
'failed to compile file because:': 'Datei konnte nicht kompiliert werden, da:',
|
||||||
'failed to reload module': 'neu laden des Moduls fehlgeschlagen',
|
'failed to reload module': 'neu laden des Moduls fehlgeschlagen',
|
||||||
'failed to reload module because:': 'Modul konnte nicht geladen werden, weil:',
|
'failed to reload module because:': 'failed to reload module because:',
|
||||||
'File': 'Datei',
|
'File': 'Datei',
|
||||||
'file "%(filename)s" created': 'Datei "%(filename)s" erstellt',
|
'file "%(filename)s" created': 'Datei "%(filename)s" erstellt',
|
||||||
'file "%(filename)s" deleted': 'Datei "%(filename)s" gelöscht',
|
'file "%(filename)s" deleted': 'Datei "%(filename)s" gelöscht',
|
||||||
@@ -263,166 +263,166 @@
|
|||||||
'file "%s" of %s restored': 'Datei "%s" von %s wiederhergestellt',
|
'file "%s" of %s restored': 'Datei "%s" von %s wiederhergestellt',
|
||||||
'file changed on disk': 'Datei auf Festplatte geändert',
|
'file changed on disk': 'Datei auf Festplatte geändert',
|
||||||
'file does not exist': 'Datei existiert nicht',
|
'file does not exist': 'Datei existiert nicht',
|
||||||
'file not found': 'Datei nicht gefunden',
|
'file not found': 'file not found',
|
||||||
'file saved on %(time)s': 'Datei gespeichert am %(time)s',
|
'file saved on %(time)s': 'Datei gespeichert am %(time)s',
|
||||||
'file saved on %s': 'Datei gespeichert auf %s',
|
'file saved on %s': 'Datei gespeichert auf %s',
|
||||||
'filename': 'dateiname',
|
'filename': 'filename',
|
||||||
'Filename': 'Dateiname',
|
'Filename': 'Filename',
|
||||||
'Files added': 'Dateien hinzugefügt',
|
'Files added': 'Files added',
|
||||||
'filter': 'Filter',
|
'filter': 'Filter',
|
||||||
'Find Next': 'Nächster',
|
'Find Next': 'Nächster',
|
||||||
'Find Previous': 'Vorheriger',
|
'Find Previous': 'Vorheriger',
|
||||||
'First name': 'Vorname',
|
'First name': 'Vorname',
|
||||||
'Form has errors': 'Das Formular hat Fehler',
|
'Form has errors': 'Form has errors',
|
||||||
'Frames': 'Frames',
|
'Frames': 'Frames',
|
||||||
'Functions with no doctests will result in [passed] tests.': 'Funktionen ohne doctests erzeugen [passed] in Tests',
|
'Functions with no doctests will result in [passed] tests.': 'Funktionen ohne doctests erzeugen [passed] in Tests',
|
||||||
'GAE Email': 'GAE Email',
|
'GAE Email': 'GAE Email',
|
||||||
'GAE Output': 'GAE Output',
|
'GAE Output': 'GAE Output',
|
||||||
'GAE Password': 'GAE Passwort',
|
'GAE Password': 'GAE Password',
|
||||||
'Generate': 'Generieren',
|
'Generate': 'Generate',
|
||||||
'Get from URL:': 'Von URL abrufen:',
|
'Get from URL:': 'Get from URL:',
|
||||||
'Git Pull': 'Git Pull',
|
'Git Pull': 'Git Pull',
|
||||||
'Git Push': 'Git Push',
|
'Git Push': 'Git Push',
|
||||||
'Globals##debug': 'Globales##debug',
|
'Globals##debug': 'Globals##debug',
|
||||||
'Go to Matching Pair': 'Gehe zum übereinstimmenden Paar',
|
'Go to Matching Pair': 'Gehe zum übereinstimmenden Paar',
|
||||||
'go!': 'go!',
|
'go!': 'go!',
|
||||||
'Google App Engine Deployment Interface': 'Google App Engine Deployment Interface',
|
'Google App Engine Deployment Interface': 'Google App Engine Deployment Interface',
|
||||||
'Google Application Id': 'Google-Anwendungs-ID',
|
'Google Application Id': 'Google Application Id',
|
||||||
'Goto': 'Gehe zu',
|
'Goto': 'Goto',
|
||||||
'graph model': 'graph model',
|
'graph model': 'graph model',
|
||||||
'Graph Model': 'Graph Model',
|
'Graph Model': 'Graph Model',
|
||||||
'Group ID': 'Gruppen ID',
|
'Group ID': 'Gruppen ID',
|
||||||
'Hello World': 'Hallo Welt',
|
'Hello World': 'Hallo Welt',
|
||||||
'Help': 'Hilfe',
|
'Help': 'Hilfe',
|
||||||
'here': 'Hier',
|
'here': 'here',
|
||||||
'Hide/Show Translated strings': 'Zeige/Verstecke übersetzte Strings',
|
'Hide/Show Translated strings': 'Zeige/Verstecke übersetzte Strings',
|
||||||
'Highlight current line': 'Aktuelle Zeile markieren',
|
'Highlight current line': 'Highlight current line',
|
||||||
'Hits': 'Treffer',
|
'Hits': 'Hits',
|
||||||
'Home': 'Startseite',
|
'Home': 'Startseite',
|
||||||
'honored only if the expression evaluates to true': 'Wird nur berücksichtigt, wenn der Ausdruck als true ausgewertet wird',
|
'honored only if the expression evaluates to true': 'honored only if the expression evaluates to true',
|
||||||
'htmledit': 'htmledit',
|
'htmledit': 'htmledit',
|
||||||
'If start the downgrade, be patient, it may take a while to rollback': 'Wenn Sie das Downgrade starten, haben Sie etwas Geduld. Das Rollback kann einige Zeit dauern',
|
'If start the downgrade, be patient, it may take a while to rollback': 'If start the downgrade, be patient, it may take a while to rollback',
|
||||||
'If start the upgrade, be patient, it may take a while to download': 'Wenn Sie das Upgrade starten, haben Sie etwas Geduld. Das Herunterladen kann einige Zeit dauern',
|
'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.\n\t\tA 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.\r\n\t\tA 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.\n\t\tA 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.\n\t\tA 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.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich Führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.',
|
'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.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich Führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.',
|
||||||
'If you answer "yes", be patient, it may take a while to download': 'Wenn Sie mit "Ja" antworten, seien Sie bitte geduldig. Der Download könnte eine Weile dauern.',
|
'If you answer "yes", be patient, it may take a while to download': 'Wenn Sie mit "Ja" antworten, seien Sie bitte geduldig. Der Download könnte eine Weile dauern.',
|
||||||
'If you answer yes, be patient, it may take a while to download': 'Wenn Sie mit Ja antworten, seien Sie bitte geduldig. Der Download könnte eine Weile dauern.',
|
'If you answer yes, be patient, it may take a while to download': 'Wenn Sie mit Ja antworten, seien Sie bitte geduldig. Der Download könnte eine Weile dauern.',
|
||||||
'if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.': 'Wenn Ihre Anwendung eine andere Datenbank als sqlite verwendet, müssen Sie ihre DAL in pythonanywhere konfigurieren.',
|
'if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.': 'if your application uses a database other than sqlite you will then have to configure its DAL in pythonanywhere.',
|
||||||
'import': 'Import',
|
'import': 'import',
|
||||||
'Import/Export': 'Importieren/Exportieren',
|
'Import/Export': 'Importieren/Exportieren',
|
||||||
'In development, use the default Rocket webserver that is currently supported by this debugger.': 'Verwenden Sie in der Entwicklung den Standard-Rocket-Webserver, der derzeit von diesem Debugger unterstützt wird.',
|
'In development, use the default Rocket webserver that is currently supported by this debugger.': 'In development, use the default Rocket webserver that is currently supported by this debugger.',
|
||||||
'includes': 'Einfügen',
|
'includes': 'Einfügen',
|
||||||
'Indent with tabs': 'Einrücken mit Tabulatoren',
|
'Indent with tabs': 'Indent with tabs',
|
||||||
'Index': 'Index',
|
'Index': 'Index',
|
||||||
'index': 'index',
|
'index': 'index',
|
||||||
'insert new': 'neu Einfügen',
|
'insert new': 'neu Einfügen',
|
||||||
'insert new %s': 'neu Einfügen %s',
|
'insert new %s': 'neu Einfügen %s',
|
||||||
'inspect attributes': 'Attribute inspizieren',
|
'inspect attributes': 'Attribute inspizieren',
|
||||||
'Install': 'Installieren',
|
'Install': 'Installieren',
|
||||||
'Installation of %(plugin)s for %(app)s': 'Installation von %(Plugin)s für %(App)s',
|
'Installation of %(plugin)s for %(app)s': 'Installation of %(plugin)s for %(app)s',
|
||||||
'Installed applications': 'Installierte Anwendungen',
|
'Installed applications': 'Installierte Anwendungen',
|
||||||
'Interaction at %s line %s': 'Interaktion bei %s Zeile %s',
|
'Interaction at %s line %s': 'Interaction at %s line %s',
|
||||||
'Interactive console': 'Interaktive Konsole',
|
'Interactive console': 'Interactive console',
|
||||||
'internal error': 'Interner Fehler',
|
'internal error': 'Interner Fehler',
|
||||||
'internal error: %s': 'interner Error: %s',
|
'internal error: %s': 'internal error: %s',
|
||||||
'Internal State': 'Interner Status',
|
'Internal State': 'Interner Status',
|
||||||
'Invalid action': 'Ungültige Aktion',
|
'Invalid action': 'Ungültige Aktion',
|
||||||
'Invalid application name': 'Ungültiger Anwendungsname',
|
'Invalid application name': 'Invalid application name',
|
||||||
'invalid circular reference': 'ungültiger Zirkelverweis',
|
'invalid circular reference': 'invalid circular reference',
|
||||||
'Invalid email': 'Ungültige Email',
|
'Invalid email': 'Ungültige Email',
|
||||||
'Invalid git repository specified.': 'Ungültiges git-Repository angegeben.',
|
'Invalid git repository specified.': 'Invalid git repository specified.',
|
||||||
'invalid password': 'Ungültiges Passwort',
|
'invalid password': 'Ungültiges Passwort',
|
||||||
'invalid password.': 'Ungültiges Passwort.',
|
'invalid password.': 'invalid password.',
|
||||||
'Invalid Query': 'Ungültige Abfrage',
|
'Invalid Query': 'Ungültige Abfrage',
|
||||||
'invalid request': 'Ungültige Anfrage',
|
'invalid request': 'Ungültige Anfrage',
|
||||||
'Invalid request': 'Ungültige Anfrage',
|
'Invalid request': 'Invalid request',
|
||||||
'invalid table names (auth_* tables already defined)': 'Ungültige Tabellennamen (auth_* Tabellen bereits definiert)',
|
'invalid table names (auth_* tables already defined)': 'invalid table names (auth_* tables already defined)',
|
||||||
'invalid ticket': 'Ungültiges Ticket',
|
'invalid ticket': 'Ungültiges Ticket',
|
||||||
'Key': 'Key',
|
'Key': 'Key',
|
||||||
'Key bindings': 'Tastenbelegungen',
|
'Key bindings': 'Tastenbelegungen',
|
||||||
'Key bindings for ZenCoding Plugin': 'Tastenbelegungen für das ZenCoding Plugin',
|
'Key bindings for ZenCoding Plugin': 'Key bindings for ZenCoding Plugin',
|
||||||
'Key bindings for ZenConding Plugin': 'Tastenbelegungen für das ZenConding Plugin',
|
'Key bindings for ZenConding Plugin': 'Tastenbelegungen für das ZenConding Plugin',
|
||||||
'Keyboard shortcuts': 'Tastenkombination',
|
'Keyboard shortcuts': 'Tastenkombination',
|
||||||
'kill process': 'Prozess zu töten',
|
'kill process': 'kill process',
|
||||||
'language file "%(filename)s" created/updated': 'Sprachdatei "%(filename)s" erstellt/aktualisiert',
|
'language file "%(filename)s" created/updated': 'Sprachdatei "%(filename)s" erstellt/aktualisiert',
|
||||||
'Language files (static strings) updated': 'Sprachdatei (statisch Strings) aktualisiert',
|
'Language files (static strings) updated': 'Sprachdatei (statisch Strings) aktualisiert',
|
||||||
'languages': 'Sprachen',
|
'languages': 'Sprachen',
|
||||||
'Languages': 'Sprachen',
|
'Languages': 'Sprachen',
|
||||||
'languages updated': 'Sprachen aktualisiert',
|
'languages updated': 'Sprachen aktualisiert',
|
||||||
'Last name': 'Nachname',
|
'Last name': 'Nachname',
|
||||||
'Last Revision': 'Letzete Revision',
|
'Last Revision': 'Last Revision',
|
||||||
'Last saved on:': 'Zuletzt gespeichert am:',
|
'Last saved on:': 'Zuletzt gespeichert am:',
|
||||||
'Layout': 'Layout',
|
'Layout': 'Layout',
|
||||||
'License for': 'Lizenz für',
|
'License for': 'Lizenz für',
|
||||||
'License:': 'Lizenz:',
|
'License:': 'License:',
|
||||||
'Line Nr': 'Zeilen Nr',
|
'Line Nr': 'Line Nr',
|
||||||
'Line number': 'Zeilennummer',
|
'Line number': 'Line number',
|
||||||
'lists by exception': 'Listen nach Ausnahme',
|
'lists by exception': 'lists by exception',
|
||||||
'lists by ticket': 'nach Ticket aufgelistet',
|
'lists by ticket': 'nach Ticket aufgelistet',
|
||||||
'Loading...': 'Laden...',
|
'Loading...': 'Loading...',
|
||||||
'loading...': 'lade...',
|
'loading...': 'lade...',
|
||||||
'Local Apps': 'Lokale Apps',
|
'Local Apps': 'Local Apps',
|
||||||
'locals': 'lokales',
|
'locals': 'locals',
|
||||||
'Locals##debug': 'Lokales##debug',
|
'Locals##debug': 'Locals##debug',
|
||||||
'located in the file': 'befindet sich in der Datei',
|
'located in the file': 'befindet sich in der Datei',
|
||||||
'login': 'anmelden',
|
'login': 'anmelden',
|
||||||
'Login': 'Anmelden',
|
'Login': 'Anmelden',
|
||||||
'Login successful': 'Login erfolgreich',
|
'Login successful': 'Login successful',
|
||||||
'Login to the Administrative Interface': 'An das Administrations-Interface anmelden',
|
'Login to the Administrative Interface': 'An das Administrations-Interface anmelden',
|
||||||
'Login/Register': 'Login/Registrieren',
|
'Login/Register': 'Login/Register',
|
||||||
'Logout': 'Abmelden',
|
'Logout': 'Abmelden',
|
||||||
'lost password': 'Passwort vergessen',
|
'lost password': 'lost password',
|
||||||
'Lost Password': 'Passwort vergessen',
|
'Lost Password': 'Passwort vergessen',
|
||||||
'lost password?': 'Passwort vergessen?',
|
'lost password?': 'Passwort vergessen?',
|
||||||
'Main Menu': 'Hauptmenü',
|
'Main Menu': 'Hauptmenü',
|
||||||
'Manage': 'Verwalten',
|
'Manage': 'Verwalten',
|
||||||
'Manage %(action)s': '%(action)s verwalten',
|
'Manage %(action)s': 'Manage %(action)s',
|
||||||
'Manage Access Control': 'Zugriffskontrolle verwalten',
|
'Manage Access Control': 'Manage Access Control',
|
||||||
'Manage Admin Users/Students': 'Admin-User/Studenten verwalten',
|
'Manage Admin Users/Students': 'Manage Admin Users/Students',
|
||||||
'Manage Cache': 'Cache verwalten',
|
'Manage Cache': 'Manage Cache',
|
||||||
'Manage Students': 'Studenten verwalten',
|
'Manage Students': 'Manage Students',
|
||||||
'Match Pair': 'Paare finden',
|
'Match Pair': 'Paare finden',
|
||||||
'Memberships': 'Mitgliedschaften',
|
'Memberships': 'Memberships',
|
||||||
'Menu Model': 'Menü Modell',
|
'Menu Model': 'Menü Modell',
|
||||||
'merge': 'verbinden',
|
'merge': 'verbinden',
|
||||||
'Merge Lines': 'Zeilen zusammenfügen',
|
'Merge Lines': 'Zeilen zusammenfügen',
|
||||||
'Models': 'Modelle',
|
'Models': 'Modelle',
|
||||||
'models': 'Modelle',
|
'models': 'Modelle',
|
||||||
'Modified On': 'Geändert am',
|
'Modified On': 'Modified On',
|
||||||
'Modules': 'Module',
|
'Modules': 'Module',
|
||||||
'modules': 'Module',
|
'modules': 'Module',
|
||||||
'Multi User Mode': 'Multi-User-Modus',
|
'Multi User Mode': 'Multi User Mode',
|
||||||
'Name': 'Name',
|
'Name': 'Name',
|
||||||
'new application "%s" created': 'neue Anwendung "%s" erzeugt',
|
'new application "%s" created': 'neue Anwendung "%s" erzeugt',
|
||||||
'new application "%s" imported': 'Neue Anwendung "%s" importiert',
|
'new application "%s" imported': 'new application "%s" imported',
|
||||||
'New Application Wizard': 'Neuer Anwendungs Assistent',
|
'New Application Wizard': 'New Application Wizard',
|
||||||
'New application wizard': 'Neue Anwendung per Assistent',
|
'New application wizard': 'Neue Anwendung per Assistent',
|
||||||
'new plugin installed': 'Neues Plugin wurde installiert',
|
'new plugin installed': 'Neues Plugin wurde installiert',
|
||||||
'New plugin installed: %s': 'Neues Plugin installiert: %s',
|
'New plugin installed: %s': 'New plugin installed: %s',
|
||||||
'New Record': 'Neuer Datensatz',
|
'New Record': 'Neuer Datensatz',
|
||||||
'new record inserted': 'Neuer wurde Datensatz eingefügt',
|
'new record inserted': 'Neuer wurde Datensatz eingefügt',
|
||||||
'New simple application': 'Neue einfache Anwendung',
|
'New simple application': 'Neue einfache Anwendung',
|
||||||
'next': 'Nächste',
|
'next': 'next',
|
||||||
'next %s rows': 'nächste %s Zeilen',
|
'next %s rows': 'next %s rows',
|
||||||
'next 100 rows': 'nächsten 100 Zeilen',
|
'next 100 rows': 'nächsten 100 Zeilen',
|
||||||
'Next Edit Point': 'nächster Bearbeitungsschritt',
|
'Next Edit Point': 'nächster Bearbeitungsschritt',
|
||||||
'NO': 'NEIN',
|
'NO': 'NEIN',
|
||||||
'no changes': 'keine Änderungen',
|
'no changes': 'no changes',
|
||||||
'No databases in this application': 'Keine Datenbank in dieser Anwendung',
|
'No databases in this application': 'Keine Datenbank in dieser Anwendung',
|
||||||
'No Interaction yet': 'Noch keine Interaktion',
|
'No Interaction yet': 'No Interaction yet',
|
||||||
'no match': 'keine Übereinstimmung',
|
'no match': 'no match',
|
||||||
'no package selected': 'Kein Paket ausgewählt',
|
'no package selected': 'Kein Paket ausgewählt',
|
||||||
'no permission to uninstall "%s"': 'Keine Berechtigung zum Deinstallieren von "%s"',
|
'no permission to uninstall "%s"': 'no permission to uninstall "%s"',
|
||||||
'No ticket_storage.txt found under /private folder': 'Kein ticket_storage.txt unter /private folder gefunden',
|
'No ticket_storage.txt found under /private folder': 'Kein ticket_storage.txt unter /private folder gefunden',
|
||||||
'Node:': 'Hinweis:',
|
'Node:': 'Node:',
|
||||||
'Not Authorized': 'Nicht berechtigt',
|
'Not Authorized': 'Not Authorized',
|
||||||
'Not supported': 'Nicht unterstützt',
|
'Not supported': 'Not supported',
|
||||||
'Note: If you receive an error with github status code of 128, ensure the system and account you are deploying from has a cooresponding ssh key configured in the openshift account.': 'Hinweis: Wenn Sie einen Fehler mit dem Github-Statuscode 128 erhalten, stellen Sie sicher, dass das System und der Account, von dem Sie das Deployment durchführen, über einen entsprechenden ssh-Schlüssel im Account "openshift" verfügen.',
|
'Note: If you receive an error with github status code of 128, ensure the system and account you are deploying from has a cooresponding ssh key configured in the openshift account.': 'Note: If you receive an error with github status code of 128, ensure the system and account you are deploying from has a cooresponding ssh key configured in the openshift account.',
|
||||||
"On production, you'll have to configure your webserver to use one process and multiple threads to use this debugger.": 'In der Produktion müssen Sie Ihren Webserver so konfigurieren, dass er einen Prozess und mehrere Threads verwendet, um diesen Debugger zu verwenden.',
|
"On production, you'll have to configure your webserver to use one process and multiple threads to use this debugger.": "On production, you'll have to configure your webserver to use one process and multiple threads to use this debugger.",
|
||||||
'online designer': 'Online Designer',
|
'online designer': 'Online Designer',
|
||||||
'Open new app in new window': 'Neue App in neuem Fenster öffnen',
|
'Open new app in new window': 'Open new app in new window',
|
||||||
'OpenShift Deployment Interface': 'OpenShift Deployment Interface',
|
'OpenShift Deployment Interface': 'OpenShift Deployment Interface',
|
||||||
'OpenShift Output': 'OpenShift Ausgabe',
|
'OpenShift Output': 'OpenShift Output',
|
||||||
'or alternatively': 'oder Alternativ',
|
'or alternatively': 'oder Alternativ',
|
||||||
'Or Get from URL:': 'oder von folgender URL herunterladen:',
|
'Or Get from URL:': 'oder von folgender URL herunterladen:',
|
||||||
'or import from csv file': 'oder importieren von cvs Datei',
|
'or import from csv file': 'oder importieren von cvs Datei',
|
||||||
@@ -430,52 +430,52 @@
|
|||||||
'or provide application url:': 'oder geben Sie eine Anwendungs-URL an:',
|
'or provide application url:': 'oder geben Sie eine Anwendungs-URL an:',
|
||||||
'Origin': 'Herkunft',
|
'Origin': 'Herkunft',
|
||||||
'Original/Translation': 'Original/übersetzung',
|
'Original/Translation': 'Original/übersetzung',
|
||||||
'Overview': 'Übersicht',
|
'Overview': 'Overview',
|
||||||
'Overwrite installed app': 'Installierte Anwendungen überschreiben',
|
'Overwrite installed app': 'Installierte Anwendungen überschreiben',
|
||||||
'Pack all': 'Verpacke alles',
|
'Pack all': 'Verpacke alles',
|
||||||
'Pack compiled': 'Verpacke kompiliert',
|
'Pack compiled': 'Verpacke kompiliert',
|
||||||
'Pack custom': 'Verpacke individuell',
|
'Pack custom': 'Verpacke individuell',
|
||||||
'pack plugin': 'Plugin verpacken',
|
'pack plugin': 'Plugin verpacken',
|
||||||
'Password': 'Passwort',
|
'Password': 'Passwort',
|
||||||
'password changed': 'passwort geändert',
|
'password changed': 'password changed',
|
||||||
'Past revisions': 'Vergangene Revisionen',
|
'Past revisions': 'Past revisions',
|
||||||
'Path to appcfg.py': 'Pfad zu appcfg.py',
|
'Path to appcfg.py': 'Path to appcfg.py',
|
||||||
'Path to local openshift repo root.': 'Pfad zum lokalen OpenShift-Repo-root.',
|
'Path to local openshift repo root.': 'Path to local openshift repo root.',
|
||||||
'Peeking at file': 'Dateiansicht',
|
'Peeking at file': 'Dateiansicht',
|
||||||
'Permission': 'Berechtigung',
|
'Permission': 'Permission',
|
||||||
'Permissions': 'Berechtigungen',
|
'Permissions': 'Permissions',
|
||||||
'Please': 'Bitte',
|
'Please': 'Please',
|
||||||
'please wait!': 'Bitte warten!',
|
'please wait!': 'Bitte warten!',
|
||||||
'Please wait, giving pythonanywhere a moment...': 'Bitte warten Sie, und geben Sie pythonanywhere einen Moment Zeit...',
|
'Please wait, giving pythonanywhere a moment...': 'Please wait, giving pythonanywhere a moment...',
|
||||||
'plugin "%(plugin)s" deleted': 'Plugin "%(plugin) s" wurde gelöscht',
|
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" deleted',
|
||||||
'Plugin "%s" in application': 'Plugin "%s" in Anwendung',
|
'Plugin "%s" in application': 'Plugin "%s" in Anwendung',
|
||||||
'plugin not specified': 'Plugin nicht angegeben',
|
'plugin not specified': 'plugin not specified',
|
||||||
'Plugin page': 'Plugin seite',
|
'Plugin page': 'Plugin page',
|
||||||
'plugins': 'plugins',
|
'plugins': 'plugins',
|
||||||
'Plugins': 'Plugins',
|
'Plugins': 'Plugins',
|
||||||
'Plural Form #%s': 'Plural Formen #%s',
|
'Plural Form #%s': 'Plural Form #%s',
|
||||||
'Plural-Forms:': 'Plural Formen:',
|
'Plural-Forms:': 'Plural-Forms:',
|
||||||
'Powered by': 'Unterstützt von',
|
'Powered by': 'Unterstützt von',
|
||||||
'Preferences saved correctly': 'Einstellungen korrekt gespeichert',
|
'Preferences saved correctly': 'Preferences saved correctly',
|
||||||
'Preferences saved on session only': 'Einstellungen nur in der Sitzung gespeichert',
|
'Preferences saved on session only': 'Preferences saved on session only',
|
||||||
'previous %s rows': 'vorherige %s Zeilen',
|
'previous %s rows': 'previous %s rows',
|
||||||
'previous 100 rows': 'vorherige 100 zeilen',
|
'previous 100 rows': 'vorherige 100 zeilen',
|
||||||
'Previous Edit Point': 'vorheriger Bearbeitungsschritt',
|
'Previous Edit Point': 'vorheriger Bearbeitungsschritt',
|
||||||
'Private files': 'Private Dateien',
|
'Private files': 'Private files',
|
||||||
'private files': 'private Dateien',
|
'private files': 'private files',
|
||||||
'Project Progress': 'Projekt Fortschritt',
|
'Project Progress': 'Projekt Fortschritt',
|
||||||
'Pull': 'Pull',
|
'Pull': 'Pull',
|
||||||
'Pull failed, certain files could not be checked out. Check logs for details.': 'Pull fehlgeschlagen, bestimmte Dateien konnten nicht ausgecheckt werden. Überprüfen Sie die Protokolle für Details.',
|
'Pull failed, certain files could not be checked out. Check logs for details.': 'Pull failed, certain files could not be checked out. Check logs for details.',
|
||||||
'Pull is not possible because you have unmerged files. Fix them up in the work tree, and then try again.': 'Pull ist nicht möglich, weil Sie nicht gespeicherte Dateien haben. Reparieren Sie sie im Arbeitsbaum und versuchen Sie es erneut.',
|
'Pull is not possible because you have unmerged files. Fix them up in the work tree, and then try again.': 'Pull is not possible because you have unmerged files. Fix them up in the work tree, and then try again.',
|
||||||
'Push': 'Push',
|
'Push': 'Push',
|
||||||
'Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.': 'Push fehlgeschlagen, es sind nicht fusionierte Einträge im Cache. Beheben Sie fusionierungsprobleme manuell und versuchen Sie es erneut.',
|
'Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.': 'Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.',
|
||||||
'pygraphviz library not found': 'pygraphviz Bibliothek nicht gefunden',
|
'pygraphviz library not found': 'pygraphviz library not found',
|
||||||
'PythonAnywhere Apps': 'PythonAnywhere Apps',
|
'PythonAnywhere Apps': 'PythonAnywhere Apps',
|
||||||
'PythonAnywhere Password': 'PythonAnywhere Passwort',
|
'PythonAnywhere Password': 'PythonAnywhere Password',
|
||||||
'Query:': 'Abfrage:',
|
'Query:': 'Abfrage:',
|
||||||
'RAM': 'RAM',
|
'RAM': 'RAM',
|
||||||
'RAM Cache Keys': 'RAM Cache Keys',
|
'RAM Cache Keys': 'RAM Cache Keys',
|
||||||
'Ram Cleared': 'Ram geleert',
|
'Ram Cleared': 'Ram Cleared',
|
||||||
'Rapid Search': 'Schnelle Suche',
|
'Rapid Search': 'Schnelle Suche',
|
||||||
'Record': 'Record',
|
'Record': 'Record',
|
||||||
'record': 'Datensatz',
|
'record': 'Datensatz',
|
||||||
@@ -483,91 +483,91 @@
|
|||||||
'record id': 'Datensatz id',
|
'record id': 'Datensatz id',
|
||||||
'Record ID': 'Datensatz ID',
|
'Record ID': 'Datensatz ID',
|
||||||
'Record id': 'Record id',
|
'Record id': 'Record id',
|
||||||
'refresh': 'Aktualisieren',
|
'refresh': 'refresh',
|
||||||
'Register': 'Registrieren',
|
'Register': 'Registrieren',
|
||||||
'register': 'Registrierung',
|
'register': 'Registrierung',
|
||||||
'Registration key': 'Registrierungsschlüssel',
|
'Registration key': 'Registrierungsschlüssel',
|
||||||
'reload': 'Neu laden',
|
'reload': 'Neu laden',
|
||||||
'Reload routes': 'Routen neu laden',
|
'Reload routes': 'Routen neu laden',
|
||||||
'Remove compiled': 'Bytecode löschen',
|
'Remove compiled': 'Bytecode löschen',
|
||||||
'Removed Breakpoint on %s at line %s': 'Breakpoint entfernt an %s auf Zeile %s',
|
'Removed Breakpoint on %s at line %s': 'Removed Breakpoint on %s at line %s',
|
||||||
'Replace': 'Ersetzen',
|
'Replace': 'Ersetzen',
|
||||||
'Replace All': 'Alle Ersetzen',
|
'Replace All': 'Alle Ersetzen',
|
||||||
'Repository (%s)': 'Speiche-Archiv (%s)',
|
'Repository (%s)': 'Repository (%s)',
|
||||||
'request': 'Anfrage',
|
'request': 'Anfrage',
|
||||||
'requires distutils, but not installed': 'erfordert distutils, aber nicht installiert',
|
'requires distutils, but not installed': 'requires distutils, but not installed',
|
||||||
'requires python-git, but not installed': 'rfordert Python-Git, aber nicht installiert',
|
'requires python-git, but not installed': 'requires python-git, but not installed',
|
||||||
'Reset Password key': 'Passwortschlüssel zurücksetzen',
|
'Reset Password key': 'Passwortschlüssel zurücksetzen',
|
||||||
'Resolve Conflict file': 'bereinige Konflikt-Datei',
|
'Resolve Conflict file': 'bereinige Konflikt-Datei',
|
||||||
'response': 'Antwort',
|
'response': 'Antwort',
|
||||||
'restart': 'Neustart',
|
'restart': 'restart',
|
||||||
'restore': 'wiederherstellen',
|
'restore': 'wiederherstellen',
|
||||||
'return': 'Zurück',
|
'return': 'return',
|
||||||
'Revert': 'Zurückkehren',
|
'Revert': 'Revert',
|
||||||
'revert': 'zurückkehren',
|
'revert': 'zurückkehren',
|
||||||
'reverted to revision %s': 'Zurück zur revision %s',
|
'reverted to revision %s': 'reverted to revision %s',
|
||||||
'Revision %s': 'Revision %s',
|
'Revision %s': 'Revision %s',
|
||||||
'Revision:': 'Revision:',
|
'Revision:': 'Revision:',
|
||||||
'Role': 'Rolle',
|
'Role': 'Rolle',
|
||||||
'Roles': 'Rollen',
|
'Roles': 'Roles',
|
||||||
'Rows in table': 'Zeilen in Tabelle',
|
'Rows in table': 'Zeilen in Tabelle',
|
||||||
'Rows in Table': 'Zeilen in der Tabelle',
|
'Rows in Table': 'Rows in Table',
|
||||||
'Rows selected': 'Zeilen ausgewählt',
|
'Rows selected': 'Zeilen ausgewählt',
|
||||||
'rules are not defined': 'Regeln sind nicht definiert',
|
'rules are not defined': 'Regeln sind nicht definiert',
|
||||||
'Run tests': 'Tests ausführen',
|
'Run tests': 'Run tests',
|
||||||
'Run tests in this file': 'Führen Sie Tests in dieser Datei aus',
|
'Run tests in this file': 'Run tests in this file',
|
||||||
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Tests in dieser Datei ausführen (um alle Dateien auszuführen, kann auch der Button 'test' genutzt werden)",
|
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Tests in dieser Datei ausführen (um alle Dateien auszuführen, kann auch der Button 'test' genutzt werden)",
|
||||||
'Running on %s': 'läuft auf %s',
|
'Running on %s': 'läuft auf %s',
|
||||||
'Save': 'Speichern',
|
'Save': 'Speichern',
|
||||||
'save': 'Speichern',
|
'save': 'Speichern',
|
||||||
'Save file:': 'Speichere Datei:',
|
'Save file:': 'Speichere Datei:',
|
||||||
'Save file: %s': 'Speichere Datei: %s',
|
'Save file: %s': 'Speichere Datei: %s',
|
||||||
'Save model as...': 'Modell speichern als...',
|
'Save model as...': 'Save model as...',
|
||||||
'Save via Ajax': 'via Ajax speichern',
|
'Save via Ajax': 'via Ajax speichern',
|
||||||
'Saved file hash:': 'Gespeicherter Datei-Hash:',
|
'Saved file hash:': 'Gespeicherter Datei-Hash:',
|
||||||
'Screenshot %s': 'Bildschirmfoto %s',
|
'Screenshot %s': 'Screenshot %s',
|
||||||
'Search': 'Suche',
|
'Search': 'Search',
|
||||||
'Select Files to Package': 'Dateien zum Paketieren wählen',
|
'Select Files to Package': 'Dateien zum Paketieren wählen',
|
||||||
'selected': 'ausgewählt(e)',
|
'selected': 'ausgewählt(e)',
|
||||||
'session': 'Sitzung',
|
'session': 'Sitzung',
|
||||||
'session expired': 'Sitzung abgelaufen',
|
'session expired': 'Sitzung abgelaufen',
|
||||||
'Session saved correctly': 'Sitzung korrekt gespeichert',
|
'Session saved correctly': 'Session saved correctly',
|
||||||
'Session saved on session only': 'Sitzung gespeichert auf Nur Sitzung',
|
'Session saved on session only': 'Session saved on session only',
|
||||||
'Set Breakpoint on %s at line %s: %s': 'Setze Breakpoint auf %s an Linie %s: %s',
|
'Set Breakpoint on %s at line %s: %s': 'Set Breakpoint on %s at line %s: %s',
|
||||||
'shell': 'Shell',
|
'shell': 'Shell',
|
||||||
'Showing %s to %s of %s %s found': 'Showing %s to %s of %s %s found',
|
'Showing %s to %s of %s %s found': 'Showing %s to %s of %s %s found',
|
||||||
'Singular Form': 'Einzahl',
|
'Singular Form': 'Singular Form',
|
||||||
'Site': 'Seite',
|
'Site': 'Seite',
|
||||||
'Size of cache:': 'Größe des Caches:',
|
'Size of cache:': 'Size of cache:',
|
||||||
'skip to generate': 'überspringen, um zu generieren',
|
'skip to generate': 'skip to generate',
|
||||||
'some files could not be removed': 'einige Dateien konnten nicht gelöscht werden',
|
'some files could not be removed': 'einige Dateien konnten nicht gelöscht werden',
|
||||||
'Something went wrong please wait a few minutes before retrying': 'Es ist ein Fehler aufgetreten. Bitte warten Sie einige Minuten, bevor Sie es erneut versuchen',
|
'Something went wrong please wait a few minutes before retrying': 'Something went wrong please wait a few minutes before retrying',
|
||||||
'Sorry, could not find mercurial installed': 'Leider konnte mercurial nicht installiert werden',
|
'Sorry, could not find mercurial installed': 'Sorry, could not find mercurial installed',
|
||||||
'source : db': 'Quelle : db',
|
'source : db': 'source : db',
|
||||||
'source : filesystem': 'Quelle : Dateisystem',
|
'source : filesystem': 'Quelle : Dateisystem',
|
||||||
'Start a new app': 'Starten Sie eine neue App',
|
'Start a new app': 'Start a new app',
|
||||||
'Start searching': 'Suche beginnen',
|
'Start searching': 'Suche beginnen',
|
||||||
'Start wizard': 'Assistent starten',
|
'Start wizard': 'Assistent starten',
|
||||||
'state': 'Status',
|
'state': 'Status',
|
||||||
'Static': 'Statisch',
|
'Static': 'Statisch',
|
||||||
'static': 'statische Dateien',
|
'static': 'statische Dateien',
|
||||||
'Static files': 'statische Dateien',
|
'Static files': 'statische Dateien',
|
||||||
'Statistics': 'Statistiken',
|
'Statistics': 'Statistics',
|
||||||
'Step': 'Schritt',
|
'Step': 'Step',
|
||||||
'step': 'schritt',
|
'step': 'step',
|
||||||
'stop': 'Halt',
|
'stop': 'stop',
|
||||||
'Stylesheet': 'Stylesheet',
|
'Stylesheet': 'Stylesheet',
|
||||||
'submit': 'Absenden',
|
'submit': 'Absenden',
|
||||||
'Submit': 'Einreichen',
|
'Submit': 'Submit',
|
||||||
'successful': 'erfolgreich',
|
'successful': 'successful',
|
||||||
'Sure you want to delete this object?': 'Wollen Sie das Objekt wirklich löschen?',
|
'Sure you want to delete this object?': 'Wollen Sie das Objekt wirklich löschen?',
|
||||||
'switch to : db': 'wechsel zu : db',
|
'switch to : db': 'wechsel zu : db',
|
||||||
'switch to : filesystem': 'wechseln zu : filesystem',
|
'switch to : filesystem': 'switch to : filesystem',
|
||||||
'Tab width (# characters)': 'Tabulatorbreite (# characters)',
|
'Tab width (# characters)': 'Tab width (# characters)',
|
||||||
'table': 'Tabelle',
|
'table': 'Tabelle',
|
||||||
'Table': 'Tabelle',
|
'Table': 'Table',
|
||||||
'Table name': 'Tabellen Name',
|
'Table name': 'Tabellen Name',
|
||||||
'Temporary': 'Temporär',
|
'Temporary': 'Temporary',
|
||||||
'test': 'Test',
|
'test': 'Test',
|
||||||
'test_def': 'test_def',
|
'test_def': 'test_def',
|
||||||
'test_for': 'test_for',
|
'test_for': 'test_for',
|
||||||
@@ -576,8 +576,8 @@
|
|||||||
'Testing application': 'Teste die Anwendung',
|
'Testing application': 'Teste die Anwendung',
|
||||||
'Testing controller': 'Teste Controller',
|
'Testing controller': 'Teste Controller',
|
||||||
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'Die "query" ist eine Bedingung wie "db.table1.field1 == \'Wert\'". Etwas wie "db.table1.field1 db.table2.field2 ==" führt zu einem 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.': 'Die "query" ist eine Bedingung wie "db.table1.field1 == \'Wert\'". Etwas wie "db.table1.field1 db.table2.field2 ==" führt zu einem SQL JOIN.',
|
||||||
'The app exists, was created by wizard, continue to overwrite!': 'Die App existiert, wurde von Wizard erstellt, weiter überschreiben!',
|
'The app exists, was created by wizard, continue to overwrite!': 'The app exists, was created by wizard, continue to overwrite!',
|
||||||
'The app exists, was NOT created by wizard, continue to overwrite!': 'Die App existiert, wurde NICHT vom Assistenten erstellt, weiter überschreiben!',
|
'The app exists, was NOT created by wizard, continue to overwrite!': 'The app exists, was NOT created by wizard, continue to overwrite!',
|
||||||
'the application logic, each URL path is mapped in one exposed function in the controller': 'Die Logik der Anwendung, jeder URL-Pfad wird auf eine Funktion abgebildet die der Controller zur Verfügung stellt',
|
'the application logic, each URL path is mapped in one exposed function in the controller': 'Die Logik der Anwendung, jeder URL-Pfad wird auf eine Funktion abgebildet die der Controller zur Verfügung stellt',
|
||||||
'The application logic, each URL path is mapped in one exposed function in the controller': 'Die Logik der Anwendung, jeder URL-Pfad wird auf eine Funktion abgebildet die der Controller zur Verfügung stellt',
|
'The application logic, each URL path is mapped in one exposed function in the controller': 'Die Logik der Anwendung, jeder URL-Pfad wird auf eine Funktion abgebildet die der Controller zur Verfügung stellt',
|
||||||
'the data representation, define database tables and sets': 'Die Datenrepräsentation definiert Mengen von Tabellen und Datenbanken',
|
'the data representation, define database tables and sets': 'Die Datenrepräsentation definiert Mengen von Tabellen und Datenbanken',
|
||||||
@@ -585,39 +585,39 @@
|
|||||||
'The output of the file is a dictionary that was rendered by the view': 'Die Ausgabe der Datei ist ein "dictionary" und wurde vom "view" gerendert',
|
'The output of the file is a dictionary that was rendered by the view': 'Die Ausgabe der Datei ist ein "dictionary" und wurde vom "view" gerendert',
|
||||||
'The presentations layer, views are also known as templates': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
'The presentations layer, views are also known as templates': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
||||||
'the presentations layer, views are also known as templates': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
'the presentations layer, views are also known as templates': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
||||||
'Theme': 'Thema',
|
'Theme': 'Theme',
|
||||||
'There are no controllers': 'Keine Controller vorhanden',
|
'There are no controllers': 'Keine Controller vorhanden',
|
||||||
'There are no models': 'Keine Modelle vorhanden',
|
'There are no models': 'Keine Modelle vorhanden',
|
||||||
'There are no modules': 'Keine Module vorhanden',
|
'There are no modules': 'Keine Module vorhanden',
|
||||||
'There are no plugins': 'Keine Plugins vorhanden',
|
'There are no plugins': 'Keine Plugins vorhanden',
|
||||||
'There are no private files': 'Keine privaten Dateien vorhanden',
|
'There are no private files': 'Keine privaten Dateien vorhanden',
|
||||||
'There are no static files': 'Keine statischen Dateien vorhanden',
|
'There are no static files': 'Keine statischen Dateien vorhanden',
|
||||||
'There are no translators': 'Es gibt keine Übersetzer',
|
'There are no translators': 'There are no translators',
|
||||||
'There are no translators, only default language is supported': 'Keine übersetzungen vorhanden, nur die voreingestellte Sprache wird Unterstützt',
|
'There are no translators, only default language is supported': 'Keine übersetzungen vorhanden, nur die voreingestellte Sprache wird Unterstützt',
|
||||||
'There are no views': 'Keine Views vorhanden',
|
'There are no views': 'Keine Views vorhanden',
|
||||||
'These files are not served, they are only available from within your app': 'Diese Dateien werden nicht ausgeliefert, sie sind nur innerhalb Ihrer App verfügbar',
|
'These files are not served, they are only available from within your app': 'Diese Dateien werden nicht ausgeliefert, sie sind nur innerhalb Ihrer App verfügbar',
|
||||||
'These files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
'These files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
||||||
'these files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
'these files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
||||||
"This debugger may not work properly if you don't have a threaded webserver or you're using multiple daemon processes.": 'Dieser Debugger funktioniert möglicherweise nicht ordnungsgemäß, wenn Sie keinen Thread-Webserver haben oder mehrere Daemon-Prozesse verwenden.',
|
"This debugger may not work properly if you don't have a threaded webserver or you're using multiple daemon processes.": "This debugger may not work properly if you don't have a threaded webserver or you're using multiple daemon processes.",
|
||||||
'This is a copy of the scaffolding application': 'Dies ist eine Kopie einer Grundgerüst-Anwendung',
|
'This is a copy of the scaffolding application': 'Dies ist eine Kopie einer Grundgerüst-Anwendung',
|
||||||
'This is an experimental feature and it needs more testing. If you decide to downgrade you do it at your own risk': 'Dies ist eine experimentelle Funktion und muss noch getestet werden. Wenn Sie sich für ein Downgrade entscheiden, tun Sie dies auf eigene Gefahr',
|
'This is an experimental feature and it needs more testing. If you decide to downgrade you do it at your own risk': 'This is an experimental feature and it needs more testing. If you decide to downgrade 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': 'Dies ist eine experimentelle Funktion und muss noch getestet werden. Wenn Sie sich für ein Upgrade entscheiden, tun Sie dies auf eigene Gefahr',
|
'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': 'Dies ist das Template %(filename)s',
|
'This is the %(filename)s template': 'Dies ist das Template %(filename)s',
|
||||||
"This page can commit your changes to an openshift app repo and push them to your cloud instance. This assumes that you've already created the application instance using the web2py skeleton and have that repo somewhere on a filesystem that this web2py instance can access. This functionality requires GitPython installed and on the python path of the runtime that web2py is operating in.": 'Auf dieser Seite können Sie Ihre Änderungen in ein OpenShift-App-Repo übernehmen und in Ihre Cloud-Instanz verschieben. Dies setzt voraus, dass Sie die Anwendungsinstanz bereits mit dem web2py-Skelett erstellt haben und dieses Repo auf einem Dateisystem haben, auf das diese web2py-Instanz zugreifen kann. Für diese Funktionalität muss GitPython installiert sein und sich auf dem Python-Pfad der Runtime befinden, in der web2py ausgeführt wird.',
|
"This page can commit your changes to an openshift app repo and push them to your cloud instance. This assumes that you've already created the application instance using the web2py skeleton and have that repo somewhere on a filesystem that this web2py instance can access. This functionality requires GitPython installed and on the python path of the runtime that web2py is operating in.": "This page can commit your changes to an openshift app repo and push them to your cloud instance. This assumes that you've already created the application instance using the web2py skeleton and have that repo somewhere on a filesystem that this web2py instance can access. This functionality requires GitPython installed and on the python path of the runtime that web2py is operating in.",
|
||||||
'This page can upload your application to the Google App Engine computing cloud. Mind that you must first create indexes locally and this is done by installing the Google appserver and running the app locally with it once, or there will be errors when selecting records. Attention: deployment may take long time, depending on the network speed. Attention: it will overwrite your app.yaml. DO NOT SUBMIT TWICE.': 'Diese Seite kann Ihre Anwendung in die Cloud der Google App Engine Computing hochladen. Beachten Sie, dass Sie zunächst Indexe lokal erstellen müssen. Dies geschieht, indem Sie den Google Appserver installieren und die App einmalig lokal ausführen. Andernfalls treten Fehler bei der Auswahl von Datensätzen auf. Achtung: Die Bereitstellung kann abhängig von der Netzwerkgeschwindigkeit sehr lange dauern. Achtung: Ihre app.yaml wird überschrieben. SENDEN SIE NICHT ZWEIMAL EIN.',
|
'This page can upload your application to the Google App Engine computing cloud. Mind that you must first create indexes locally and this is done by installing the Google appserver and running the app locally with it once, or there will be errors when selecting records. Attention: deployment may take long time, depending on the network speed. Attention: it will overwrite your app.yaml. DO NOT SUBMIT TWICE.': 'This page can upload your application to the Google App Engine computing cloud. Mind that you must first create indexes locally and this is done by installing the Google appserver and running the app locally with it once, or there will be errors when selecting records. Attention: deployment may take long time, depending on the network speed. Attention: it will overwrite your app.yaml. DO NOT SUBMIT TWICE.',
|
||||||
'this page to see if a breakpoint was hit and debug interaction is required.': 'Auf dieser Seite können Sie sehen, ob ein breakpoint getroffen wurde und eine Debug-Interaktion erforderlich ist.',
|
'this page to see if a breakpoint was hit and debug interaction is required.': 'this page to see if a breakpoint was hit and debug interaction is required.',
|
||||||
'This will pull changes from the remote repo for application "%s"?': 'Dadurch werden Änderungen vom Remote-Repo für die Anwendung "% s" übernommen?',
|
'This will pull changes from the remote repo for application "%s"?': 'This will pull changes from the remote repo for application "%s"?',
|
||||||
'This will push changes to the remote repo for application "%s".': 'Dadurch werden Änderungen an das Remote-Repo für die Anwendung "% s" übertragen.',
|
'This will push changes to the remote repo for application "%s".': 'This will push changes to the remote repo for application "%s".',
|
||||||
'Ticket': 'Ticket',
|
'Ticket': 'Ticket',
|
||||||
'Ticket ID': 'Ticket ID',
|
'Ticket ID': 'Ticket ID',
|
||||||
'Ticket Missing': 'Ticket fehlt',
|
'Ticket Missing': 'Ticket Missing',
|
||||||
'Time in Cache (h:m:s)': 'Zeit im Cache (h:m:s)',
|
'Time in Cache (h:m:s)': 'Time in Cache (h:m:s)',
|
||||||
'Timestamp': 'Zeitstempel',
|
'Timestamp': 'Zeitstempel',
|
||||||
'TM': 'TM',
|
'TM': 'TM',
|
||||||
'to previous version.': 'zu einer früheren Version.',
|
'to previous version.': 'zu einer früheren Version.',
|
||||||
'To create a plugin, name a file/folder plugin_[name]': 'Um ein Plugin zu erstellen benennen Sie eine(n) Datei/Ordner plugin_[Name]',
|
'To create a plugin, name a file/folder plugin_[name]': 'Um ein Plugin zu erstellen benennen Sie eine(n) Datei/Ordner plugin_[Name]',
|
||||||
'To emulate a breakpoint programatically, write:': 'Um einen breapoint programmatisch zu emulieren, schreiben Sie:',
|
'To emulate a breakpoint programatically, write:': 'To emulate a breakpoint programatically, write:',
|
||||||
'to use the debugger!': 'um den Debugger zuverwenden!',
|
'to use the debugger!': 'to use the debugger!',
|
||||||
'toggle breakpoint': 'Breakpoint aktivieren/deaktivieren',
|
'toggle breakpoint': 'Breakpoint aktivieren/deaktivieren',
|
||||||
'Toggle comment': ' Kommentar ein-/ausblenden',
|
'Toggle comment': ' Kommentar ein-/ausblenden',
|
||||||
'Toggle Fullscreen': 'Vollbild ein-/ausschalten',
|
'Toggle Fullscreen': 'Vollbild ein-/ausschalten',
|
||||||
@@ -628,31 +628,31 @@
|
|||||||
'try something like': 'Versuchen Sie so etwas wie',
|
'try something like': 'Versuchen Sie so etwas wie',
|
||||||
'Try the mobile interface': 'Testen Sie das Interface für Handys',
|
'Try the mobile interface': 'Testen Sie das Interface für Handys',
|
||||||
'try view': 'Versuche view',
|
'try view': 'Versuche view',
|
||||||
'Type PDB debugger command in here and hit Return (Enter) to execute it.': 'Geben Sie den PDB-Debuggerbefehl hier ein und drücken Sie die Eingabetaste, um ihn auszuführen.',
|
'Type PDB debugger command in here and hit Return (Enter) to execute it.': 'Type PDB debugger command in here and hit Return (Enter) to execute it.',
|
||||||
'Type some Python code in here and hit Return (Enter) to execute it.': 'Geben Sie hier einen Python-Code ein und drücken Sie die Eingabetaste, um ihn auszuführen.',
|
'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': 'Überprüfen von Upgrades nicht möglich',
|
'Unable to check for upgrades': 'Überprüfen von Upgrades nicht möglich',
|
||||||
'unable to create application "%s"': 'Erzeugen von Anwendung "%s" nicht möglich',
|
'unable to create application "%s"': 'Erzeugen von Anwendung "%s" nicht möglich',
|
||||||
'unable to delete file "%(filename)s"': 'Löschen von Dateien "%(filename)s" nicht möglich',
|
'unable to delete file "%(filename)s"': 'Löschen von Dateien "%(filename)s" nicht möglich',
|
||||||
'unable to delete file plugin "%(plugin)s"': 'Datei-Plugin "%(plugin)s" kann nicht gelöscht werden',
|
'unable to delete file plugin "%(plugin)s"': 'unable to delete file plugin "%(plugin)s"',
|
||||||
'Unable to determine the line number!': 'Die Zeilennummer kann nicht ermittelt werden!',
|
'Unable to determine the line number!': 'Unable to determine the line number!',
|
||||||
'Unable to download': 'Herunterladen nicht möglich',
|
'Unable to download': 'Herunterladen nicht möglich',
|
||||||
'Unable to download app': 'Herunterladen der Anwendung nicht möglich',
|
'Unable to download app': 'Herunterladen der Anwendung nicht möglich',
|
||||||
'Unable to download app because:': 'App kann nicht heruntergeladen werden, weil:',
|
'Unable to download app because:': 'Unable to download app because:',
|
||||||
'unable to download layout': 'Layout kann nicht heruntergeladen werden',
|
'unable to download layout': 'unable to download layout',
|
||||||
'unable to download plugin: %s': 'Folgendes Plugin konnte nicht heruntergeladen werden: %s',
|
'unable to download plugin: %s': 'unable to download plugin: %s',
|
||||||
'Unable to download the list of plugins': 'Die Liste der Plugins kann nicht heruntergeladen werden',
|
'Unable to download the list of plugins': 'Unable to download the list of plugins',
|
||||||
'unable to install plugin "%s"': 'Plugin "%s" kann nicht installiert werden',
|
'unable to install plugin "%s"': 'unable to install plugin "%s"',
|
||||||
'unable to parse csv file': 'Analysieren der cvs Datei nicht möglich',
|
'unable to parse csv file': 'Analysieren der cvs Datei nicht möglich',
|
||||||
'unable to uninstall "%s"': 'Deinstallieren von "%s" nicht möglich',
|
'unable to uninstall "%s"': 'Deinstallieren von "%s" nicht möglich',
|
||||||
'unable to upgrade because "%s"': 'Upgrade wegen "%s" nicht möglich',
|
'unable to upgrade because "%s"': 'unable to upgrade because "%s"',
|
||||||
'uncheck all': 'Auswahl entfernen',
|
'uncheck all': 'Auswahl entfernen',
|
||||||
'Uninstall': 'Deinstallieren',
|
'Uninstall': 'Deinstallieren',
|
||||||
'Unsupported webserver working mode: %s': 'Nicht unterstützte Webserver-Arbeitsmodell: %s',
|
'Unsupported webserver working mode: %s': 'Unsupported webserver working mode: %s',
|
||||||
'update': 'Aktualisieren',
|
'update': 'Aktualisieren',
|
||||||
'update all languages': 'Aktualisiere alle Sprachen',
|
'update all languages': 'Aktualisiere alle Sprachen',
|
||||||
'Update:': 'Aktualisiere:',
|
'Update:': 'Aktualisiere:',
|
||||||
'Upgrade': 'Upgrade',
|
'Upgrade': 'Upgrade',
|
||||||
'upgrade now to %s': 'Upgrade jetzt zu %s',
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
'upgrade web2py now': 'web2py jetzt upgraden',
|
'upgrade web2py now': 'web2py jetzt upgraden',
|
||||||
'upload': 'upload',
|
'upload': 'upload',
|
||||||
'Upload': 'Upload',
|
'Upload': 'Upload',
|
||||||
@@ -670,7 +670,7 @@
|
|||||||
'User ID': 'Benutzer ID',
|
'User ID': 'Benutzer ID',
|
||||||
'Username': 'Username',
|
'Username': 'Username',
|
||||||
'Users': 'Users',
|
'Users': 'Users',
|
||||||
'Using the shell may lock the database to other users of this app.': 'Durch die Verwendung des Shell kann die Datenbank für andere Benutzer dieser App gesperrt werden.',
|
'Using the shell may lock the database to other users of this app.': 'Using the shell may lock the database to other users of this app.',
|
||||||
'variables': 'Variablen',
|
'variables': 'Variablen',
|
||||||
'Version': 'Version',
|
'Version': 'Version',
|
||||||
'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s',
|
'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s',
|
||||||
@@ -680,35 +680,35 @@
|
|||||||
'view': 'Ansicht',
|
'view': 'Ansicht',
|
||||||
'Views': 'Ansichten',
|
'Views': 'Ansichten',
|
||||||
'views': 'Ansichten',
|
'views': 'Ansichten',
|
||||||
'Warning!': 'Warnung!',
|
'Warning!': 'Warning!',
|
||||||
'WARNING:': 'WARNUNG:',
|
'WARNING:': 'WARNING:',
|
||||||
'WARNING: The following views could not be compiled:': 'WARNUNG: Die folgenden Ansichten konnten nicht kompiliert werden:',
|
'WARNING: The following views could not be compiled:': 'WARNING: The following views could not be compiled:',
|
||||||
'Web Framework': 'Web Framework',
|
'Web Framework': 'Web Framework',
|
||||||
'web2py Admin Password': 'Administratorkennwort für web2py',
|
'web2py Admin Password': 'web2py Admin Password',
|
||||||
'web2py apps to deploy': 'Web2py-Apps zur Bereitstellung',
|
'web2py apps to deploy': 'web2py apps to deploy',
|
||||||
'web2py Debugger': 'web2py Debugger',
|
'web2py Debugger': 'web2py Debugger',
|
||||||
'web2py downgrade': 'web2py Downgrade',
|
'web2py downgrade': 'web2py downgrade',
|
||||||
'web2py is up to date': 'web2py ist aktuell',
|
'web2py is up to date': 'web2py ist aktuell',
|
||||||
'web2py online debugger': 'web2py Online-Debugger',
|
'web2py online debugger': 'web2py online debugger',
|
||||||
'web2py Recent Tweets': 'Neuste Tweets von web2py',
|
'web2py Recent Tweets': 'Neuste Tweets von web2py',
|
||||||
'web2py upgrade': 'web2py-Upgrade',
|
'web2py upgrade': 'web2py upgrade',
|
||||||
'web2py upgraded; please restart it': 'web2py aktualisiert bitte neu starten',
|
'web2py upgraded; please restart it': 'web2py upgraded; please restart it',
|
||||||
'Welcome %s': 'Willkommen %s',
|
'Welcome %s': 'Willkommen %s',
|
||||||
'Welcome to web2py': 'Willkommen zu web2py',
|
'Welcome to web2py': 'Willkommen zu web2py',
|
||||||
'Which called the function': 'welche die Funktion aufrief',
|
'Which called the function': 'welche die Funktion aufrief',
|
||||||
'Working...': 'Arbeitet...',
|
'Working...': 'Working...',
|
||||||
'Wrap with Abbreviation': 'mit Kürzel einhüllen',
|
'Wrap with Abbreviation': 'mit Kürzel einhüllen',
|
||||||
'WSGI reference name': 'WSGI Referenzname',
|
'WSGI reference name': 'WSGI reference name',
|
||||||
'xml': 'xml',
|
'xml': 'xml',
|
||||||
'YES': 'JA',
|
'YES': 'JA',
|
||||||
'Yes': 'JA',
|
'Yes': 'Yes',
|
||||||
'You are successfully running web2py': 'web2by wird erfolgreich ausgeführt',
|
'You are successfully running web2py': 'web2by wird erfolgreich ausgeführt',
|
||||||
'You can also set and remove breakpoint in the edit window, using the Toggle Breakpoint button': 'Sie können Breakpoint auch im Bearbeitungsfenster festlegen und entfernen, indem Sie die Schaltfläche Breakpoint umschalten verwenden',
|
'You can also set and remove breakpoint in the edit window, using the Toggle Breakpoint button': 'You can also set and remove breakpoint in the edit window, using the Toggle Breakpoint button',
|
||||||
'You can inspect variables using the console below': 'Sie können Variablen mit der folgenden Konsole überprüfen',
|
'You can inspect variables using the console below': 'You can inspect variables using the console below',
|
||||||
'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen',
|
'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen',
|
||||||
'You have one more login attempt before you are locked out': 'Sie haben einen weiteren Anmeldeversuch, bevor Sie gesperrt werden',
|
'You have one more login attempt before you are locked out': 'You have one more login attempt before you are locked out',
|
||||||
'You need to set up and reach a': 'You need to set up and reach a',
|
'You need to set up and reach a': 'You need to set up and reach a',
|
||||||
'You only need these if you have already registered': 'Sie benötigen diese nur, wenn Sie sich bereits registriert haben.',
|
'You only need these if you have already registered': 'You only need these if you have already registered',
|
||||||
'You visited the url': 'Sie besuchten die URL',
|
'You visited the url': 'Sie besuchten die URL',
|
||||||
'Your application will be blocked until you click an action button (next, step, continue, etc.)': 'Ihre Bewerbung wird blockiert, bis Sie auf eine Aktionsschaltfläche klicken (next, step, continue usw.).',
|
'Your application will be blocked until you click an action button (next, step, continue, etc.)': 'Your application will be blocked until you click an action button (next, step, continue, etc.)',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,6 @@
|
|||||||
'Enable': 'Enable',
|
'Enable': 'Enable',
|
||||||
'Enable Close-Tag': 'Enable Close-Tag',
|
'Enable Close-Tag': 'Enable Close-Tag',
|
||||||
'Enable Code Folding': 'Enable Code Folding',
|
'Enable Code Folding': 'Enable Code Folding',
|
||||||
'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g',
|
|
||||||
'Enterprise Web Framework': 'Enterprise Web Framework',
|
'Enterprise Web Framework': 'Enterprise Web Framework',
|
||||||
'Error': 'Error',
|
'Error': 'Error',
|
||||||
'Error logs for "%(app)s"': 'Log degli errori per "%(app)s"',
|
'Error logs for "%(app)s"': 'Log degli errori per "%(app)s"',
|
||||||
|
|||||||
@@ -63,12 +63,12 @@
|
|||||||
<h3 class="not_paused">{{=T("No Interaction yet")}}</h3>
|
<h3 class="not_paused">{{=T("No Interaction yet")}}</h3>
|
||||||
<div class="help span7 alert alert-block alert-info">
|
<div class="help span7 alert alert-block alert-info">
|
||||||
<ul class="unstyled">
|
<ul class="unstyled">
|
||||||
<li>{{=T.M("You need to set up and reach a [[breakpoint %s]] to use the debugger!') %URL('breakpoints')}}</li>
|
<li>{{=T("You need to set up and reach a")}} {{=A(T("breakpoint"), _href=URL('breakpoints'))}} {{=T('to use the debugger!')}}</li>
|
||||||
<li>{{=T('To emulate a breakpoint programatically, write:')}}
|
<li>{{=T('To emulate a breakpoint programatically, write:')}}
|
||||||
{{=CODE("from gluon.debug import dbg\n"
|
{{=CODE("from gluon.debug import dbg\n"
|
||||||
"dbg.set_trace() # stop here!\n",
|
"dbg.set_trace() # stop here!\n",
|
||||||
counter=None)}}</li>
|
counter=None)}}</li>
|
||||||
<li>{{=T.M('Please [[refresh %s]] this page to see if a breakpoint was hit and debug interaction is required.') %URL('interact')}}</li>
|
<li>{{=T('Please')}} {{=A(T("refresh"), _href=URL('interact'))}} {{=T('this page to see if a breakpoint was hit and debug interaction is required.')}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{{pass}}
|
{{pass}}
|
||||||
|
|||||||
@@ -185,9 +185,9 @@ def select():
|
|||||||
is_imap = db._uri.startswith("imap://")
|
is_imap = db._uri.startswith("imap://")
|
||||||
except (KeyError, AttributeError, TypeError):
|
except (KeyError, AttributeError, TypeError):
|
||||||
is_imap = False
|
is_imap = False
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||||
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
||||||
if request.vars.query:
|
if request.vars.query:
|
||||||
match = regex.match(request.vars.query)
|
match = regex.match(request.vars.query)
|
||||||
if match:
|
if match:
|
||||||
@@ -237,7 +237,7 @@ def select():
|
|||||||
|
|
||||||
tb = None
|
tb = None
|
||||||
if form.accepts(request.vars, formname=None):
|
if form.accepts(request.vars, formname=None):
|
||||||
regex = re.compile(request.args[0] + r'\.(?P<table>\w+)\..+')
|
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
|
||||||
match = regex.match(form.vars.query.strip())
|
match = regex.match(form.vars.query.strip())
|
||||||
if match:
|
if match:
|
||||||
table = match.group('table')
|
table = match.group('table')
|
||||||
|
|||||||
@@ -185,9 +185,9 @@ def select():
|
|||||||
is_imap = db._uri.startswith("imap://")
|
is_imap = db._uri.startswith("imap://")
|
||||||
except (KeyError, AttributeError, TypeError):
|
except (KeyError, AttributeError, TypeError):
|
||||||
is_imap = False
|
is_imap = False
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
|
||||||
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
|
||||||
regex = re.compile(r'(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
|
||||||
if request.vars.query:
|
if request.vars.query:
|
||||||
match = regex.match(request.vars.query)
|
match = regex.match(request.vars.query)
|
||||||
if match:
|
if match:
|
||||||
@@ -237,7 +237,7 @@ def select():
|
|||||||
|
|
||||||
tb = None
|
tb = None
|
||||||
if form.accepts(request.vars, formname=None):
|
if form.accepts(request.vars, formname=None):
|
||||||
regex = re.compile(request.args[0] + r'\.(?P<table>\w+)\..+')
|
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
|
||||||
match = regex.match(form.vars.query.strip())
|
match = regex.match(form.vars.query.strip())
|
||||||
if match:
|
if match:
|
||||||
table = match.group('table')
|
table = match.group('table')
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#crontab
|
||||||
Regular → Executable
+8
-8
@@ -5,17 +5,17 @@
|
|||||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "feld1=\'newvalue\'". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden',
|
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "feld1=\'newvalue\'". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden',
|
||||||
'%s %%(shop)': '%s %%(shop)',
|
'%s %%(shop)': '%s %%(shop)',
|
||||||
'%s %%(shop[0])': '%s %%(shop[0])',
|
'%s %%(shop[0])': '%s %%(shop[0])',
|
||||||
'%s %%{quark[0]}': '%s %%{Quark[0]}',
|
'%s %%{quark[0]}': '%s %%{quark[0]}',
|
||||||
'%s %%{row} deleted': '%s %%{row} gelöscht',
|
'%s %%{row} deleted': '%s %%{row} gelöscht',
|
||||||
'%s %%{row} updated': '%s %%{row} aktualisiert',
|
'%s %%{row} updated': '%s %%{row} aktualisiert',
|
||||||
'%s %%{shop[0]}': '%s %%{Shop[0]}',
|
'%s %%{shop[0]}': '%s %%{shop[0]}',
|
||||||
'%s %%{shop}': '%s %%{Shop}',
|
'%s %%{shop}': '%s %%{shop}',
|
||||||
'%s selected': '%s ausgewählt',
|
'%s selected': '%s ausgewählt',
|
||||||
'%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',
|
||||||
'(**%.0d MB**)': '(**%.0d MB**)',
|
'(**%.0d MB**)': '(**%.0d MB**)',
|
||||||
'**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{Item(Items)}, **%(bytes)s** %%{Byte(Bytes)}',
|
'**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}',
|
||||||
'**%(items)s** items, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** Items, **%(bytes)s** %%{byte(bytes)}',
|
'**%(items)s** items, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** items, **%(bytes)s** %%{byte(bytes)}',
|
||||||
'**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**nicht verfügbar** (benötigt die Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] Bibliothek)',
|
'**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**nicht verfügbar** (benötigt die Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] Bibliothek)',
|
||||||
'?': '?',
|
'?': '?',
|
||||||
'@markmin\x01**Hello World**': '**Hallo Welt**',
|
'@markmin\x01**Hello World**': '**Hallo Welt**',
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
'Hello World': 'Hallo Welt',
|
'Hello World': 'Hallo Welt',
|
||||||
'Hello World ## Kommentar': 'Hallo Welt ',
|
'Hello World ## Kommentar': 'Hallo Welt ',
|
||||||
'Hello World## Kommentar': 'Hallo Welt',
|
'Hello World## Kommentar': 'Hallo Welt',
|
||||||
'Helping web2py': 'web2py Helfen',
|
'Helping web2py': 'Helping web2py',
|
||||||
'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Trefferquote: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} und **%(misses)s** %%{miss(misses)})',
|
'Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses)})': 'Trefferquote: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} und **%(misses)s** %%{miss(misses)})',
|
||||||
'Home': 'Startseite',
|
'Home': 'Startseite',
|
||||||
'How did you get here?': 'Wie sind Sie hier her gelangt?',
|
'How did you get here?': 'Wie sind Sie hier her gelangt?',
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
'record does not exist': 'Eintrag existiert nicht',
|
'record does not exist': 'Eintrag existiert nicht',
|
||||||
'Record ID': 'ID des Eintrags',
|
'Record ID': 'ID des Eintrags',
|
||||||
'Record id': 'id des Eintrags',
|
'Record id': 'id des Eintrags',
|
||||||
'Register': 'Registrieren',
|
'Register': 'Register',
|
||||||
'Registration identifier': 'Registrierungsbezeichnung',
|
'Registration identifier': 'Registrierungsbezeichnung',
|
||||||
'Registration key': 'Registierungsschlüssel',
|
'Registration key': 'Registierungsschlüssel',
|
||||||
'Registration successful': 'Registrierung erfolgreich',
|
'Registration successful': 'Registrierung erfolgreich',
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
'Welcome': 'Willkommen',
|
'Welcome': 'Willkommen',
|
||||||
'Welcome to web2py!': 'Willkommen bei web2py!',
|
'Welcome to web2py!': 'Willkommen bei web2py!',
|
||||||
'Which called the function %s located in the file %s': 'Welche die Funktion %s in der Datei %s aufrief',
|
'Which called the function %s located in the file %s': 'Welche die Funktion %s in der Datei %s aufrief',
|
||||||
'Working...': 'Arbeitet...',
|
'Working...': 'Arbeite...',
|
||||||
'You are successfully running web2py': 'web2py wird erfolgreich ausgeführt',
|
'You are successfully running web2py': 'web2py wird erfolgreich ausgeführt',
|
||||||
'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen',
|
'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen',
|
||||||
'You visited the url %s': 'Sie haben die URL %s besucht',
|
'You visited the url %s': 'Sie haben die URL %s besucht',
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
'Cannot be empty': 'Non può essere vuoto',
|
'Cannot be empty': 'Non può essere vuoto',
|
||||||
'Change password': 'Cambia Password',
|
'Change password': 'Cambia Password',
|
||||||
'change password': 'Cambia password',
|
'change password': 'Cambia password',
|
||||||
'Change Password': 'Change Password',
|
|
||||||
'Check to delete': 'Seleziona per cancellare',
|
'Check to delete': 'Seleziona per cancellare',
|
||||||
'Clear': 'Resetta',
|
'Clear': 'Resetta',
|
||||||
'Clear CACHE?': 'Resetta CACHE?',
|
'Clear CACHE?': 'Resetta CACHE?',
|
||||||
@@ -61,7 +60,6 @@
|
|||||||
'Community': 'Community',
|
'Community': 'Community',
|
||||||
'Components and Plugins': 'Componenti and Plugin',
|
'Components and Plugins': 'Componenti and Plugin',
|
||||||
'Config.ini': 'Config.ini',
|
'Config.ini': 'Config.ini',
|
||||||
'Confirm Password': 'Confirm Password',
|
|
||||||
'contains': 'contiene',
|
'contains': 'contiene',
|
||||||
'Controller': 'Controller',
|
'Controller': 'Controller',
|
||||||
'Copyright': 'Copyright',
|
'Copyright': 'Copyright',
|
||||||
@@ -104,7 +102,6 @@
|
|||||||
'enter a number between %(min)g and %(max)g': 'enter a number between %(min)g and %(max)g',
|
'enter a number between %(min)g and %(max)g': 'enter a number between %(min)g and %(max)g',
|
||||||
'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g',
|
'Enter an integer between %(min)g and %(max)g': 'Enter an integer between %(min)g and %(max)g',
|
||||||
'enter an integer between %(min)g and %(max)g': 'inserisci un intero tra %(min)g e %(max)g',
|
'enter an integer between %(min)g and %(max)g': 'inserisci un intero tra %(min)g e %(max)g',
|
||||||
'Enter an integer greater than or equal to %(min)g': 'Enter an integer greater than or equal to %(min)g',
|
|
||||||
'Errors': 'Errori',
|
'Errors': 'Errori',
|
||||||
'Errors in form, please check it out.': 'Errori nel form, ricontrollalo',
|
'Errors in form, please check it out.': 'Errori nel form, ricontrollalo',
|
||||||
'export as csv file': 'esporta come file CSV',
|
'export as csv file': 'esporta come file CSV',
|
||||||
@@ -157,7 +154,6 @@
|
|||||||
'Lost Password': 'Password Smarrita',
|
'Lost Password': 'Password Smarrita',
|
||||||
'Lost password?': 'Password smarrita?',
|
'Lost password?': 'Password smarrita?',
|
||||||
'lost password?': 'dimenticato la password?',
|
'lost password?': 'dimenticato la password?',
|
||||||
'Lost your password?': 'Lost your password?',
|
|
||||||
'Main Menu': 'Menu principale',
|
'Main Menu': 'Menu principale',
|
||||||
'Manage %(action)s': 'Manage %(action)s',
|
'Manage %(action)s': 'Manage %(action)s',
|
||||||
'Manage Access Control': 'Manage Access Control',
|
'Manage Access Control': 'Manage Access Control',
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
label, th {
|
label, th {
|
||||||
font-weigth: bold;
|
font-weigth: bold;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -19,9 +20,6 @@ div.w2p_flash {
|
|||||||
margin: 0 0 20px;
|
margin: 0 0 20px;
|
||||||
padding: 15px 35px 15px 15px;
|
padding: 15px 35px 15px 15px;
|
||||||
}
|
}
|
||||||
.nav-item a {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
div.w2p_flash.alert:hover {
|
div.w2p_flash.alert:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ environment:
|
|||||||
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
||||||
PYTHON_ARCH: "64"
|
PYTHON_ARCH: "64"
|
||||||
|
|
||||||
- PYTHON: "C:/Python37"
|
|
||||||
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
|
||||||
PYTHON_ARCH: "64"
|
|
||||||
|
|
||||||
clone_depth: 50
|
clone_depth: 50
|
||||||
|
|
||||||
init:
|
init:
|
||||||
|
|||||||
+16
-18
@@ -10,29 +10,27 @@ Web2Py framework modules
|
|||||||
========================
|
========================
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ['A', 'B', 'BEAUTIFY', 'BODY', 'BR', 'CAT', 'CENTER', 'CLEANUP', 'CODE', 'CRYPT', 'DAL', 'DIV', 'EM', 'EMBED', 'FIELDSET', 'FORM', 'Field', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEAD', 'HR', 'HTML', 'HTTP', 'I', 'IFRAME', 'IMG', 'INPUT', 'IS_ALPHANUMERIC', 'IS_DATE', 'IS_DATETIME', 'IS_DATETIME_IN_RANGE', 'IS_DATE_IN_RANGE', 'IS_DECIMAL_IN_RANGE', 'IS_EMAIL', 'IS_LIST_OF_EMAILS', 'IS_EMPTY_OR', 'IS_EQUAL_TO', 'IS_EXPR', 'IS_FILE', 'IS_FLOAT_IN_RANGE', 'IS_IMAGE', 'IS_JSON', 'IS_INT_IN_RANGE', 'IS_IN_DB', 'IS_IN_SET', 'IS_IPV4', 'IS_LENGTH', 'IS_LIST_OF', 'IS_LOWER', 'IS_MATCH', 'IS_NOT_EMPTY', 'IS_NOT_IN_DB', 'IS_NULL_OR', 'IS_SLUG', 'IS_STRONG', 'IS_TIME', 'IS_UPLOAD_FILENAME', 'IS_UPPER', 'IS_URL', 'LABEL', 'LEGEND', 'LI', 'LINK', 'LOAD', 'MARKMIN', 'MENU', 'META', 'OBJECT', 'OL', 'ON', 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SCRIPT', 'SELECT', 'SPAN', 'SQLFORM', 'SQLTABLE', 'STRONG', 'STYLE', 'TABLE', 'TAG', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TITLE', 'TR', 'TT', 'UL', 'URL', 'XHTML', 'XML', 'redirect', 'current', 'embed64']
|
__all__ = ['A', 'B', 'BEAUTIFY', 'BODY', 'BR', 'CAT', 'CENTER', 'CLEANUP', 'CODE', 'CRYPT', 'DAL', 'DIV', 'EM', 'EMBED', 'FIELDSET', 'FORM', 'Field', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEAD', 'HR', 'HTML', 'HTTP', 'I', 'IFRAME', 'IMG', 'INPUT', 'IS_ALPHANUMERIC', 'IS_DATE', 'IS_DATETIME', 'IS_DATETIME_IN_RANGE', 'IS_DATE_IN_RANGE', 'IS_DECIMAL_IN_RANGE', 'IS_EMAIL', 'IS_LIST_OF_EMAILS', 'IS_EMPTY_OR', 'IS_EQUAL_TO', 'IS_EXPR', 'IS_FLOAT_IN_RANGE', 'IS_IMAGE', 'IS_JSON', 'IS_INT_IN_RANGE', 'IS_IN_DB', 'IS_IN_SET', 'IS_IPV4', 'IS_LENGTH', 'IS_LIST_OF', 'IS_LOWER', 'IS_MATCH', 'IS_NOT_EMPTY', 'IS_NOT_IN_DB', 'IS_NULL_OR', 'IS_SLUG', 'IS_STRONG', 'IS_TIME', 'IS_UPLOAD_FILENAME', 'IS_UPPER', 'IS_URL', 'LABEL', 'LEGEND', 'LI', 'LINK', 'LOAD', 'MARKMIN', 'MENU', 'META', 'OBJECT', 'OL', 'ON', 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SCRIPT', 'SELECT', 'SPAN', 'SQLFORM', 'SQLTABLE', 'STRONG', 'STYLE', 'TABLE', 'TAG', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TITLE', 'TR', 'TT', 'UL', 'URL', 'XHTML', 'XML', 'redirect', 'current', 'embed64']
|
||||||
|
|
||||||
#: add pydal to sys.modules
|
#: add pydal to sys.modules
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
try:
|
||||||
|
pydalpath = os.path.join(
|
||||||
|
os.path.dirname(os.path.abspath(__file__)), "packages", "dal")
|
||||||
|
if pydalpath not in sys.path:
|
||||||
|
sys.path.append(pydalpath)
|
||||||
|
import pydal
|
||||||
|
sys.modules['pydal'] = pydal
|
||||||
|
except ImportError:
|
||||||
|
raise RuntimeError(
|
||||||
|
"web2py depends on pydal, which apparently you have not installed.\n" +
|
||||||
|
"Probably you cloned the repository using git without '--recursive'" +
|
||||||
|
"\nTo fix this, please run (from inside your web2py folder):\n\n" +
|
||||||
|
" git submodule update --init --recursive\n\n" +
|
||||||
|
"You can also download a complete copy from http://www.web2py.com."
|
||||||
|
)
|
||||||
|
|
||||||
MESSAGE = ("web2py depends on %s, which apparently you have not installed.\n" +
|
|
||||||
"Probably you cloned the repository using git without '--recursive'" +
|
|
||||||
"\nTo fix this, please run (from inside your web2py folder):\n\n" +
|
|
||||||
" git submodule update --init --recursive\n\n" +
|
|
||||||
"You can also download a complete copy from http://www.web2py.com.")
|
|
||||||
|
|
||||||
def import_packages():
|
|
||||||
for package, location in [('pydal', 'dal'), ('yatl', 'yatl')]:
|
|
||||||
try:
|
|
||||||
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", location)
|
|
||||||
if path not in sys.path:
|
|
||||||
sys.path.insert(0, path)
|
|
||||||
sys.modules[package] = __import__(package)
|
|
||||||
except ImportError:
|
|
||||||
raise RuntimeError(MESSAGE % package)
|
|
||||||
|
|
||||||
import_packages()
|
|
||||||
|
|
||||||
from .globals import current
|
from .globals import current
|
||||||
from .html import *
|
from .html import *
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ if PY2:
|
|||||||
from gluon.contrib import ipaddress
|
from gluon.contrib import ipaddress
|
||||||
else:
|
else:
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -9,7 +9,7 @@
|
|||||||
Utility functions for the Admin application
|
Utility functions for the Admin application
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
@@ -436,8 +436,7 @@ def add_path_first(path):
|
|||||||
sys.path = [path] + [p for p in sys.path if (
|
sys.path = [path] + [p for p in sys.path if (
|
||||||
not p == path and not p == (path + '/'))]
|
not p == path and not p == (path + '/'))]
|
||||||
if not global_settings.web2py_runtime_gae:
|
if not global_settings.web2py_runtime_gae:
|
||||||
if not path in sys.path:
|
site.addsitedir(path)
|
||||||
site.addsitedir(path)
|
|
||||||
|
|
||||||
|
|
||||||
def try_mkdir(path):
|
def try_mkdir(path):
|
||||||
|
|||||||
+1
-1
@@ -988,7 +988,7 @@ class AuthAPI(object):
|
|||||||
requires = table_user[passfield].requires
|
requires = table_user[passfield].requires
|
||||||
if not isinstance(requires, (list, tuple)):
|
if not isinstance(requires, (list, tuple)):
|
||||||
requires = [requires]
|
requires = [requires]
|
||||||
requires = [t for t in requires if isinstance(t, CRYPT)]
|
requires = list(filter(lambda t: isinstance(t, CRYPT), requires))
|
||||||
if requires:
|
if requires:
|
||||||
requires[0] = CRYPT(**requires[0].__dict__) # Copy the existing CRYPT attributes
|
requires[0] = CRYPT(**requires[0].__dict__) # Copy the existing CRYPT attributes
|
||||||
requires[0].min_length = 0 # But do not enforce minimum length for the old password
|
requires[0].min_length = 0 # But do not enforce minimum length for the old password
|
||||||
|
|||||||
+8
-7
@@ -600,14 +600,15 @@ class Cache(object):
|
|||||||
(session_, vars_, lang_, user_agent_, public_) = \
|
(session_, vars_, lang_, user_agent_, public_) = \
|
||||||
(session, vars, lang, user_agent, public)
|
(session, vars, lang, user_agent, public)
|
||||||
|
|
||||||
expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
|
||||||
if time_expire:
|
if time_expire:
|
||||||
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
cache_control = 'max-age=%(time_expire)s, s-maxage=%(time_expire)s' % dict(time_expire=time_expire)
|
||||||
expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)).strftime(
|
if not session_ and public_:
|
||||||
'%a, %d %b %Y %H:%M:%S GMT')
|
cache_control += ', public'
|
||||||
else:
|
expires = (current.request.utcnow + datetime.timedelta(seconds=time_expire)
|
||||||
cache_control = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
|
).strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||||
cache_control += ', public' if not session_ and public_ else ', private'
|
else:
|
||||||
|
cache_control += ', private'
|
||||||
|
expires = 'Fri, 01 Jan 1990 00:00:00 GMT'
|
||||||
|
|
||||||
if cache_model:
|
if cache_model:
|
||||||
# figure out the correct cache key
|
# figure out the correct cache key
|
||||||
@@ -618,7 +619,7 @@ class Cache(object):
|
|||||||
if user_agent_ is True:
|
if user_agent_ is True:
|
||||||
cache_key.append("%(is_mobile)s_%(is_tablet)s" % current.request.user_agent())
|
cache_key.append("%(is_mobile)s_%(is_tablet)s" % current.request.user_agent())
|
||||||
else:
|
else:
|
||||||
cache_key.append(str(list(user_agent_.items())))
|
cache_key.append(str(user_agent_.items()))
|
||||||
if vars_:
|
if vars_:
|
||||||
cache_key.append(current.request.env.query_string)
|
cache_key.append(current.request.env.query_string)
|
||||||
if lang_:
|
if lang_:
|
||||||
|
|||||||
+9
-13
@@ -18,15 +18,14 @@ import fnmatch
|
|||||||
import os, sys
|
import os, sys
|
||||||
import copy
|
import copy
|
||||||
import random
|
import random
|
||||||
from gluon._compat import builtin, PY2, unicodeT, to_native, to_bytes, iteritems, integer_types, basestring, reduce, xrange, long, reload
|
from gluon._compat import builtin, PY2, unicodeT, to_native, to_bytes, iteritems, basestring, reduce, xrange, long, reload
|
||||||
from gluon.storage import Storage, List
|
from gluon.storage import Storage, List
|
||||||
from gluon.template import parse_template
|
from gluon.template import parse_template
|
||||||
from gluon.restricted import restricted, compile2
|
from gluon.restricted import restricted, compile2
|
||||||
from gluon.fileutils import mktree, listdir, read_file, write_file
|
from gluon.fileutils import mktree, listdir, read_file, write_file
|
||||||
from gluon.myregex import regex_expose, regex_longcomments
|
from gluon.myregex import regex_expose, regex_longcomments
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.dal import DAL, Field
|
from gluon.dal import DAL, Field
|
||||||
from gluon.validators import Validator
|
|
||||||
from pydal.base import BaseAdapter
|
from pydal.base import BaseAdapter
|
||||||
from gluon.sqlhtml import SQLFORM, SQLTABLE
|
from gluon.sqlhtml import SQLFORM, SQLTABLE
|
||||||
from gluon.cache import Cache
|
from gluon.cache import Cache
|
||||||
@@ -178,7 +177,7 @@ def LOAD(c=None, f='index', args=None, vars=None,
|
|||||||
else:
|
else:
|
||||||
raise TypeError("Unsupported times argument type %s" % type(times))
|
raise TypeError("Unsupported times argument type %s" % type(times))
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
if not isinstance(timeout, integer_types):
|
if not isinstance(timeout, (int, long)):
|
||||||
raise ValueError("Timeout argument must be an integer or None")
|
raise ValueError("Timeout argument must be an integer or None")
|
||||||
elif timeout <= 0:
|
elif timeout <= 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@@ -262,7 +261,7 @@ class LoadFactory(object):
|
|||||||
if args is None:
|
if args is None:
|
||||||
args = []
|
args = []
|
||||||
vars = Storage(vars or {})
|
vars = Storage(vars or {})
|
||||||
from . import globals
|
import globals
|
||||||
target = target or 'c' + str(random.random())[2:]
|
target = target or 'c' + str(random.random())[2:]
|
||||||
attr['_id'] = target
|
attr['_id'] = target
|
||||||
request = current.request
|
request = current.request
|
||||||
@@ -424,19 +423,16 @@ def build_environment(request, response, session, store_current=True):
|
|||||||
r'^%s/%s/\w+\.py$' % (request.controller, request.function)
|
r'^%s/%s/\w+\.py$' % (request.controller, request.function)
|
||||||
]
|
]
|
||||||
|
|
||||||
T = environment['T'] = TranslatorFactory(os.path.join(request.folder, 'languages'),
|
t = environment['T'] = translator(os.path.join(request.folder, 'languages'),
|
||||||
request.env.http_accept_language)
|
request.env.http_accept_language)
|
||||||
c = environment['cache'] = Cache(request)
|
c = environment['cache'] = Cache(request)
|
||||||
|
|
||||||
# configure the validator to use the t translator
|
|
||||||
Validator.translator = staticmethod(lambda text: None if text is None else str(T(text)))
|
|
||||||
|
|
||||||
if store_current:
|
if store_current:
|
||||||
current.globalenv = environment
|
current.globalenv = environment
|
||||||
current.request = request
|
current.request = request
|
||||||
current.response = response
|
current.response = response
|
||||||
current.session = session
|
current.session = session
|
||||||
current.T = T
|
current.T = t
|
||||||
current.cache = c
|
current.cache = c
|
||||||
|
|
||||||
if is_jython: # jython hack
|
if is_jython: # jython hack
|
||||||
@@ -635,7 +631,7 @@ def run_controller_in(controller, function, environment):
|
|||||||
raise HTTP(404,
|
raise HTTP(404,
|
||||||
rewrite.THREAD_LOCAL.routes.error_message % badc,
|
rewrite.THREAD_LOCAL.routes.error_message % badc,
|
||||||
web2py_error=badc)
|
web2py_error=badc)
|
||||||
environment['__symbols__'] = list(environment.keys())
|
environment['__symbols__'] = environment.keys()
|
||||||
code = read_file(filename)
|
code = read_file(filename)
|
||||||
code += TEST_CODE
|
code += TEST_CODE
|
||||||
ccode = compile2(code, filename)
|
ccode = compile2(code, filename)
|
||||||
@@ -731,7 +727,7 @@ def run_view_in(environment):
|
|||||||
context=environment)
|
context=environment)
|
||||||
# Compile template
|
# Compile template
|
||||||
ccode = compile2(scode, filename)
|
ccode = compile2(scode, filename)
|
||||||
layer = filename
|
layer = filename
|
||||||
restricted(ccode, environment, layer=layer, scode=scode)
|
restricted(ccode, environment, layer=layer, scode=scode)
|
||||||
# parse_template saves everything in response body
|
# parse_template saves everything in response body
|
||||||
return environment['response'].body.getvalue()
|
return environment['response'].body.getvalue()
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ def saml2_handler(session, request, config_filename = None, entityid = None):
|
|||||||
config_filename = config_filename or os.path.join(request.folder,'private','sp_conf')
|
config_filename = config_filename or os.path.join(request.folder,'private','sp_conf')
|
||||||
client = Saml2Client(config_file = config_filename)
|
client = Saml2Client(config_file = config_filename)
|
||||||
if not entityid:
|
if not entityid:
|
||||||
idps = client.metadata.with_descriptor("idpsso")
|
idps = client.metadata.with_descriptor("idpsso")
|
||||||
entityid = idps.keys()[0]
|
entityid = idps.keys()[0]
|
||||||
bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
|
bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
|
||||||
binding, destination = client.pick_binding(
|
binding, destination = client.pick_binding(
|
||||||
"single_sign_on_service", bindings, "idpsso", entity_id=entityid)
|
"single_sign_on_service", bindings, "idpsso", entity_id=entityid)
|
||||||
@@ -120,7 +120,7 @@ def saml2_handler(session, request, config_filename = None, entityid = None):
|
|||||||
if not request.vars.SAMLResponse:
|
if not request.vars.SAMLResponse:
|
||||||
req_id, req = client.create_authn_request(destination, binding=binding)
|
req_id, req = client.create_authn_request(destination, binding=binding)
|
||||||
relay_state = web2py_uuid().replace('-','')
|
relay_state = web2py_uuid().replace('-','')
|
||||||
session.saml_outstanding_queries = {req_id: request.url}
|
session.saml_outstanding_queries = {req_id: request.url}
|
||||||
session.saml_req_id = req_id
|
session.saml_req_id = req_id
|
||||||
http_args = client.apply_binding(binding, str(req), destination,
|
http_args = client.apply_binding(binding, str(req), destination,
|
||||||
relay_state=relay_state)
|
relay_state=relay_state)
|
||||||
@@ -150,14 +150,14 @@ class Saml2Auth(object):
|
|||||||
self.config_file = config_file
|
self.config_file = config_file
|
||||||
self.maps = maps
|
self.maps = maps
|
||||||
|
|
||||||
# URL for redirecting users to when they sign out
|
# URL for redirecting users to when they sign out
|
||||||
self.saml_logout_url = logout_url
|
self.saml_logout_url = logout_url
|
||||||
|
|
||||||
# URL to let users change their password in the IDP system
|
# URL to let users change their password in the IDP system
|
||||||
self.saml_change_password_url = change_password_url
|
self.saml_change_password_url = change_password_url
|
||||||
|
|
||||||
# URL to specify an IDP if using federation metadata or an MDQ
|
# URL to specify an IDP if using federation metadata or an MDQ
|
||||||
self.entityid = entityid
|
self.entityid = entityid
|
||||||
|
|
||||||
def login_url(self, next="/"):
|
def login_url(self, next="/"):
|
||||||
d = saml2_handler(current.session, current.request, entityid=self.entityid)
|
d = saml2_handler(current.session, current.request, entityid=self.entityid)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from .markdown2 import *
|
from .markdown2 import *
|
||||||
from gluon.html import XML
|
from gluon.html import XML
|
||||||
from gluon._compat import to_unicode
|
|
||||||
|
|
||||||
def WIKI(text, encoding="utf8", safe_mode='escape', html4tags=False, **attributes):
|
def WIKI(text, encoding="utf8", safe_mode='escape', html4tags=False, **attributes):
|
||||||
if not text:
|
if not text:
|
||||||
@@ -10,7 +9,7 @@ def WIKI(text, encoding="utf8", safe_mode='escape', html4tags=False, **attribute
|
|||||||
del attributes['extras']
|
del attributes['extras']
|
||||||
else:
|
else:
|
||||||
extras=None
|
extras=None
|
||||||
text = to_unicode(text, encoding, 'replace')
|
text = text.decode(encoding,'replace')
|
||||||
|
|
||||||
return XML(markdown(text,extras=extras,
|
return XML(markdown(text,extras=extras,
|
||||||
safe_mode=safe_mode, html4tags=html4tags)\
|
safe_mode=safe_mode, html4tags=html4tags)\
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ def test():
|
|||||||
def check(data, salt, iterations, keylen, expected):
|
def check(data, salt, iterations, keylen, expected):
|
||||||
rv = pbkdf2_hex(data, salt, iterations, keylen)
|
rv = pbkdf2_hex(data, salt, iterations, keylen)
|
||||||
if rv != expected:
|
if rv != expected:
|
||||||
print('Test failed:')
|
print 'Test failed:'
|
||||||
print(' Expected: %s' % expected)
|
print ' Expected: %s' % expected
|
||||||
print(' Got: %s' % rv)
|
print ' Got: %s' % rv
|
||||||
print(' Parameters:')
|
print ' Parameters:'
|
||||||
print(' data=%s' % data)
|
print ' data=%s' % data
|
||||||
print(' salt=%s' % salt)
|
print ' salt=%s' % salt
|
||||||
print(' iterations=%d' % iterations)
|
print ' iterations=%d' % iterations
|
||||||
print()
|
print
|
||||||
failed.append(1)
|
failed.append(1)
|
||||||
|
|
||||||
# From RFC 6070
|
# From RFC 6070
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ def RedisCache(redis_conn=None, debug=False, with_lock=False, fail_gracefully=Fa
|
|||||||
|
|
||||||
locker.acquire()
|
locker.acquire()
|
||||||
try:
|
try:
|
||||||
if application is None:
|
if not application:
|
||||||
application = current.request.application
|
application = current.request.application
|
||||||
instance_name = 'redis_instance_' + application
|
instance_name = 'redis_instance_' + application
|
||||||
if not hasattr(RedisCache, instance_name):
|
if not hasattr(RedisCache, instance_name):
|
||||||
@@ -110,10 +110,10 @@ class RedisClient(object):
|
|||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.with_lock = with_lock
|
self.with_lock = with_lock
|
||||||
self.fail_gracefully = fail_gracefully
|
self.fail_gracefully = fail_gracefully
|
||||||
self.application = application or current.request.application
|
self.application = application
|
||||||
self.prefix = "w2p:cache:%s:" % self.application
|
self.prefix = "w2p:cache:%s:" % application
|
||||||
if self.request:
|
if self.request:
|
||||||
app = self.application
|
app = application
|
||||||
else:
|
else:
|
||||||
app = ''
|
app = ''
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ class RedisClient(object):
|
|||||||
else:
|
else:
|
||||||
self.storage = self.meta_storage[app]
|
self.storage = self.meta_storage[app]
|
||||||
|
|
||||||
self.cache_set_key = 'w2p:%s:___cache_set' % self.application
|
self.cache_set_key = 'w2p:%s:___cache_set' % application
|
||||||
|
|
||||||
self.r_server = redis_conn
|
self.r_server = redis_conn
|
||||||
self._release_script = register_release_lock(self.r_server)
|
self._release_script = register_release_lock(self.r_server)
|
||||||
|
|||||||
@@ -29,16 +29,14 @@ except ImportError:
|
|||||||
locker = Lock()
|
locker = Lock()
|
||||||
|
|
||||||
|
|
||||||
def RConn(application=None, *args, **vars):
|
def RConn(*args, **vars):
|
||||||
"""
|
"""
|
||||||
Istantiates a StrictRedis connection with parameters, at the first time
|
Istantiates a StrictRedis connection with parameters, at the first time
|
||||||
only
|
only
|
||||||
"""
|
"""
|
||||||
locker.acquire()
|
locker.acquire()
|
||||||
try:
|
try:
|
||||||
if application is None:
|
instance_name = 'redis_conn_' + current.request.application
|
||||||
application = current.request.application
|
|
||||||
instance_name = 'redis_conn_' + application
|
|
||||||
if not hasattr(RConn, instance_name):
|
if not hasattr(RConn, instance_name):
|
||||||
setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))
|
setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))
|
||||||
return getattr(RConn, instance_name)
|
return getattr(RConn, instance_name)
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class WebClient(object):
|
|||||||
self.method = 'POST' if method=='auto' else method
|
self.method = 'POST' if method=='auto' else method
|
||||||
# if there is only one form, set _formname automatically
|
# if there is only one form, set _formname automatically
|
||||||
if not '_formname' in data and len(self.forms) == 1:
|
if not '_formname' in data and len(self.forms) == 1:
|
||||||
data['_formname'] = next(iter(self.forms.keys())) # Use the first key
|
data['_formname'] = self.forms.keys()[0]
|
||||||
|
|
||||||
# if there is no formkey but it is known, set it
|
# if there is no formkey but it is known, set it
|
||||||
if '_formname' in data and not '_formkey' in data and \
|
if '_formname' in data and not '_formkey' in data and \
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ def _default_validators(db, field):
|
|||||||
requires._and = validators.IS_NOT_IN_DB(db, field)
|
requires._and = validators.IS_NOT_IN_DB(db, field)
|
||||||
if not field.notnull:
|
if not field.notnull:
|
||||||
requires = validators.IS_EMPTY_OR(requires)
|
requires = validators.IS_EMPTY_OR(requires)
|
||||||
return requires
|
return requires
|
||||||
# does not get here for reference and list:reference
|
# does not get here for reference and list:reference
|
||||||
if isinstance(requires, list):
|
if isinstance(requires, list):
|
||||||
if field.unique:
|
if field.unique:
|
||||||
|
|||||||
+2
-2
@@ -57,8 +57,8 @@ def autoDetectXMLEncoding(buffer):
|
|||||||
secret_decoder_ring = codecs.lookup(encoding)[1]
|
secret_decoder_ring = codecs.lookup(encoding)[1]
|
||||||
(decoded, length) = secret_decoder_ring(buffer)
|
(decoded, length) = secret_decoder_ring(buffer)
|
||||||
first_line = decoded.split("\n")[0]
|
first_line = decoded.split("\n")[0]
|
||||||
if first_line and first_line.startswith("<?xml"):
|
if first_line and first_line.startswith(u"<?xml"):
|
||||||
encoding_pos = first_line.find("encoding")
|
encoding_pos = first_line.find(u"encoding")
|
||||||
if encoding_pos != -1:
|
if encoding_pos != -1:
|
||||||
# look for double quote
|
# look for double quote
|
||||||
quote_pos = first_line.find('"', encoding_pos)
|
quote_pos = first_line.find('"', encoding_pos)
|
||||||
|
|||||||
+1
-1
@@ -1078,7 +1078,7 @@ class Session(Storage):
|
|||||||
if self._same_site is None:
|
if self._same_site is None:
|
||||||
# Using SameSite Lax Mode is the default
|
# Using SameSite Lax Mode is the default
|
||||||
# You actually have to call session.samesite(False) if you really
|
# You actually have to call session.samesite(False) if you really
|
||||||
# dont want the extra protection provided by the SameSite header
|
# dont want the extra protection provided by the SameSite header
|
||||||
self._same_site = 'Lax'
|
self._same_site = 'Lax'
|
||||||
if self._same_site:
|
if self._same_site:
|
||||||
if 'samesite' not in Cookie.Morsel._reserved:
|
if 'samesite' not in Cookie.Morsel._reserved:
|
||||||
|
|||||||
+10
-10
@@ -6,9 +6,9 @@
|
|||||||
| Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
|
| Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
|
||||||
| License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
| License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
from pydal._compat import xrange
|
from gluon._compat import xrange
|
||||||
from yatl.sanitizer import xmlescape
|
from gluon.utils import local_html_escape
|
||||||
import re
|
import re
|
||||||
|
|
||||||
__all__ = ['highlight']
|
__all__ = ['highlight']
|
||||||
@@ -63,7 +63,7 @@ class Highlighter(object):
|
|||||||
Callback for C specific highlighting.
|
Callback for C specific highlighting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
value = xmlescape(match.group(), quote=False)
|
value = local_html_escape(match.group(), quote=False)
|
||||||
self.change_style(token, style)
|
self.change_style(token, style)
|
||||||
self.output.append(value)
|
self.output.append(value)
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ class Highlighter(object):
|
|||||||
Callback for python specific highlighting.
|
Callback for python specific highlighting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
value = xmlescape(match.group(), quote=False)
|
value = local_html_escape(match.group(), quote=False)
|
||||||
if token == 'MULTILINESTRING':
|
if token == 'MULTILINESTRING':
|
||||||
self.change_style(token, style)
|
self.change_style(token, style)
|
||||||
self.output.append(value)
|
self.output.append(value)
|
||||||
@@ -114,7 +114,7 @@ class Highlighter(object):
|
|||||||
Callback for HTML specific highlighting.
|
Callback for HTML specific highlighting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
value = xmlescape(match.group(), quote=False)
|
value = local_html_escape(match.group(), quote=False)
|
||||||
self.change_style(token, style)
|
self.change_style(token, style)
|
||||||
self.output.append(value)
|
self.output.append(value)
|
||||||
if token == 'GOTOPYTHON':
|
if token == 'GOTOPYTHON':
|
||||||
@@ -166,7 +166,7 @@ class Highlighter(object):
|
|||||||
+ r'from|True|False)(?![a-zA-Z0-9_])'),
|
+ r'from|True|False)(?![a-zA-Z0-9_])'),
|
||||||
'color:#185369; font-weight: bold'),
|
'color:#185369; font-weight: bold'),
|
||||||
('WEB2PY',
|
('WEB2PY',
|
||||||
re.compile(r'(request|response|session|cache|redirect|local_import|HTTP|TR|XML|URL|BEAUTIFY|A|BODY|BR|B|CAT|CENTER|CODE|COL|COLGROUP|DIV|EM|EMBED|FIELDSET|LEGEND|FORM|H1|H2|H3|H4|H5|H6|IFRAME|HEAD|HR|HTML|I|IMG|INPUT|LABEL|LI|LINK|MARKMIN|MENU|META|OBJECT|OL|ON|OPTION|P|PRE|SCRIPT|SELECT|SPAN|STYLE|TABLE|THEAD|TBODY|TFOOT|TAG|TD|TEXTAREA|TH|TITLE|TT|T|UL|XHTML|IS_SLUG|IS_STRONG|IS_LOWER|IS_UPPER|IS_ALPHANUMERIC|IS_DATETIME|IS_DATETIME_IN_RANGE|IS_DATE|IS_DATE_IN_RANGE|IS_DECIMAL_IN_RANGE|IS_EMAIL|IS_EXPR|IS_FILE|IS_FLOAT_IN_RANGE|IS_IMAGE|IS_INT_IN_RANGE|IS_IN_SET|IS_IPV4|IS_LIST_OF|IS_LENGTH|IS_MATCH|IS_EQUAL_TO|IS_EMPTY_OR|IS_NULL_OR|IS_NOT_EMPTY|IS_TIME|IS_UPLOAD_FILENAME|IS_URL|CLEANUP|CRYPT|IS_IN_DB|IS_NOT_IN_DB|DAL|Field|SQLFORM|SQLTABLE|xmlescape|embed64)(?![a-zA-Z0-9_])'
|
re.compile(r'(request|response|session|cache|redirect|local_import|HTTP|TR|XML|URL|BEAUTIFY|A|BODY|BR|B|CAT|CENTER|CODE|COL|COLGROUP|DIV|EM|EMBED|FIELDSET|LEGEND|FORM|H1|H2|H3|H4|H5|H6|IFRAME|HEAD|HR|HTML|I|IMG|INPUT|LABEL|LI|LINK|MARKMIN|MENU|META|OBJECT|OL|ON|OPTION|P|PRE|SCRIPT|SELECT|SPAN|STYLE|TABLE|THEAD|TBODY|TFOOT|TAG|TD|TEXTAREA|TH|TITLE|TT|T|UL|XHTML|IS_SLUG|IS_STRONG|IS_LOWER|IS_UPPER|IS_ALPHANUMERIC|IS_DATETIME|IS_DATETIME_IN_RANGE|IS_DATE|IS_DATE_IN_RANGE|IS_DECIMAL_IN_RANGE|IS_EMAIL|IS_EXPR|IS_FLOAT_IN_RANGE|IS_IMAGE|IS_INT_IN_RANGE|IS_IN_SET|IS_IPV4|IS_LIST_OF|IS_LENGTH|IS_MATCH|IS_EQUAL_TO|IS_EMPTY_OR|IS_NULL_OR|IS_NOT_EMPTY|IS_TIME|IS_UPLOAD_FILENAME|IS_URL|CLEANUP|CRYPT|IS_IN_DB|IS_NOT_IN_DB|DAL|Field|SQLFORM|SQLTABLE|xmlescape|embed64)(?![a-zA-Z0-9_])'
|
||||||
), 'link:%(link)s;text-decoration:None;color:#FF5C1F;'),
|
), 'link:%(link)s;text-decoration:None;color:#FF5C1F;'),
|
||||||
('MAGIC', re.compile(r'self|None'),
|
('MAGIC', re.compile(r'self|None'),
|
||||||
'color:#185369; font-weight: bold'),
|
'color:#185369; font-weight: bold'),
|
||||||
@@ -286,13 +286,13 @@ color: #A0A0A0;
|
|||||||
'WEB2PY']:
|
'WEB2PY']:
|
||||||
code = Highlighter(language, link, styles).highlight(code)
|
code = Highlighter(language, link, styles).highlight(code)
|
||||||
else:
|
else:
|
||||||
code = xmlescape(code, quote=False)
|
code = local_html_escape(code, quote=False)
|
||||||
lines = code.split('\n')
|
lines = code.split('\n')
|
||||||
|
|
||||||
if counter is None:
|
if counter is None:
|
||||||
linenumbers = [''] * len(lines)
|
linenumbers = [''] * len(lines)
|
||||||
elif isinstance(counter, str):
|
elif isinstance(counter, str):
|
||||||
linenumbers = [xmlescape(counter, quote=False)] * len(lines)
|
linenumbers = [local_html_escape(counter, quote=False)] * len(lines)
|
||||||
else:
|
else:
|
||||||
linenumbers = [str(i + counter) + '.' for i in
|
linenumbers = [str(i + counter) + '.' for i in
|
||||||
xrange(len(lines))]
|
xrange(len(lines))]
|
||||||
@@ -325,7 +325,7 @@ color: #A0A0A0;
|
|||||||
fa = ' '.join([key[1:].lower() for (key, value) in items if key[:1]
|
fa = ' '.join([key[1:].lower() for (key, value) in items if key[:1]
|
||||||
== '_' and value is None] + ['%s="%s"'
|
== '_' and value is None] + ['%s="%s"'
|
||||||
% (key[1:].lower(), str(value).replace('"', "'"))
|
% (key[1:].lower(), str(value).replace('"', "'"))
|
||||||
for (key, value) in items if key[:1]
|
for (key, value) in attributes.items() if key[:1]
|
||||||
== '_' and value])
|
== '_' and value])
|
||||||
if fa:
|
if fa:
|
||||||
fa = ' ' + fa
|
fa = ' ' + fa
|
||||||
|
|||||||
+6
-29
@@ -9,6 +9,7 @@
|
|||||||
Template helpers
|
Template helpers
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import cgi
|
import cgi
|
||||||
import os
|
import os
|
||||||
@@ -17,49 +18,25 @@ import copy
|
|||||||
import types
|
import types
|
||||||
import urllib
|
import urllib
|
||||||
import base64
|
import base64
|
||||||
|
from gluon import sanitizer, decoder
|
||||||
import itertools
|
import itertools
|
||||||
from pydal._compat import PY2, reduce, pickle, copyreg, HTMLParser, name2codepoint, iteritems, unichr, unicodeT, \
|
from gluon._compat import reduce, pickle, copyreg, HTMLParser, name2codepoint, iteritems, unichr, unicodeT, \
|
||||||
urllib_quote, to_bytes, to_native, to_unicode, basestring, urlencode, implements_bool, text_type, long
|
urllib_quote, to_bytes, to_native, to_unicode, basestring, urlencode, implements_bool, text_type, long
|
||||||
from yatl import sanitizer
|
from gluon.utils import local_html_escape
|
||||||
import marshal
|
import marshal
|
||||||
|
|
||||||
from gluon import decoder
|
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.utils import web2py_uuid, simple_hash, compare
|
from gluon.utils import web2py_uuid, simple_hash, compare
|
||||||
from gluon.highlight import highlight
|
from gluon.highlight import highlight
|
||||||
|
|
||||||
|
|
||||||
def local_html_escape(data, quote=False):
|
|
||||||
"""
|
|
||||||
Works with bytes.
|
|
||||||
Replace special characters "&", "<" and ">" to HTML-safe sequences.
|
|
||||||
If the optional flag quote is true (the default), the quotation mark
|
|
||||||
characters, both double quote (") and single quote (') characters are also
|
|
||||||
translated.
|
|
||||||
"""
|
|
||||||
if PY2:
|
|
||||||
import cgi
|
|
||||||
data = cgi.escape(data, quote)
|
|
||||||
return data.replace("'", "'") if quote else data
|
|
||||||
else:
|
|
||||||
import html
|
|
||||||
if isinstance(data, str):
|
|
||||||
return html.escape(data, quote=quote)
|
|
||||||
data = data.replace(b"&", b"&") # Must be done first!
|
|
||||||
data = data.replace(b"<", b"<")
|
|
||||||
data = data.replace(b">", b">")
|
|
||||||
if quote:
|
|
||||||
data = data.replace(b'"', b""")
|
|
||||||
data = data.replace(b'\'', b"'")
|
|
||||||
return data
|
|
||||||
|
|
||||||
regex_crlf = re.compile('\r|\n')
|
regex_crlf = re.compile('\r|\n')
|
||||||
|
|
||||||
join = ''.join
|
join = ''.join
|
||||||
|
|
||||||
# name2codepoint is incomplete respect to xhtml (and xml): 'apos' is missing.
|
# name2codepoint is incomplete respect to xhtml (and xml): 'apos' is missing.
|
||||||
entitydefs = dict([(k_v[0], to_bytes(unichr(k_v[1]))) for k_v in iteritems(name2codepoint)])
|
entitydefs = dict(map(lambda k_v: (k_v[0], unichr(k_v[1]).encode('utf-8')), iteritems(name2codepoint)))
|
||||||
entitydefs.setdefault('apos', to_bytes("'"))
|
entitydefs.setdefault('apos', u"'".encode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
+9
-8
@@ -19,10 +19,11 @@ import logging
|
|||||||
from cgi import escape
|
from cgi import escape
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
|
||||||
from pydal._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin
|
from gluon.utils import local_html_escape
|
||||||
from pydal.contrib.portalocker import read_locked, LockedFile
|
|
||||||
|
|
||||||
from yatl.sanitizer import xmlescape
|
from gluon._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin
|
||||||
|
|
||||||
|
from pydal.contrib.portalocker import read_locked, LockedFile
|
||||||
|
|
||||||
from gluon.fileutils import listdir
|
from gluon.fileutils import listdir
|
||||||
from gluon.cfs import getcfs
|
from gluon.cfs import getcfs
|
||||||
@@ -325,7 +326,7 @@ def write_plural_dict(filename, contents):
|
|||||||
|
|
||||||
|
|
||||||
def sort_function(x):
|
def sort_function(x):
|
||||||
return to_unicode(x, 'utf-8').lower()
|
return unicode(x, 'utf-8').lower()
|
||||||
|
|
||||||
|
|
||||||
def write_dict(filename, contents):
|
def write_dict(filename, contents):
|
||||||
@@ -427,7 +428,7 @@ class lazyT(object):
|
|||||||
return len(str(self))
|
return len(str(self))
|
||||||
|
|
||||||
def xml(self):
|
def xml(self):
|
||||||
return str(self) if self.M else xmlescape(str(self), quote=False)
|
return str(self) if self.M else local_html_escape(str(self), quote=False)
|
||||||
|
|
||||||
def encode(self, *a, **b):
|
def encode(self, *a, **b):
|
||||||
if PY2 and a[0] != 'utf8':
|
if PY2 and a[0] != 'utf8':
|
||||||
@@ -456,7 +457,7 @@ def pickle_lazyT(c):
|
|||||||
copyreg.pickle(lazyT, pickle_lazyT)
|
copyreg.pickle(lazyT, pickle_lazyT)
|
||||||
|
|
||||||
|
|
||||||
class TranslatorFactory(object):
|
class translator(object):
|
||||||
"""
|
"""
|
||||||
This class is instantiated by gluon.compileapp.build_environment
|
This class is instantiated by gluon.compileapp.build_environment
|
||||||
as the T object
|
as the T object
|
||||||
@@ -741,8 +742,8 @@ class TranslatorFactory(object):
|
|||||||
try:
|
try:
|
||||||
otherT = self.otherTs[index]
|
otherT = self.otherTs[index]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
otherT = self.otherTs[index] = TranslatorFactory(self.langpath,
|
otherT = self.otherTs[index] = translator(self.langpath,
|
||||||
self.http_accept_language)
|
self.http_accept_language)
|
||||||
if language:
|
if language:
|
||||||
otherT.force(language)
|
otherT.force(language)
|
||||||
return otherT
|
return otherT
|
||||||
|
|||||||
+8
-7
@@ -9,9 +9,10 @@
|
|||||||
The gluon wsgi application
|
The gluon wsgi application
|
||||||
---------------------------
|
---------------------------
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from . import import_all # DO NOT REMOVE PART OF FREEZE PROCESS
|
import import_all # DO NOT REMOVE PART OF FREEZE PROCESS
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -25,7 +26,7 @@ import socket
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from gluon._compat import Cookie, urllib_quote
|
from gluon._compat import Cookie, urllib2
|
||||||
# from thread import allocate_lock
|
# from thread import allocate_lock
|
||||||
|
|
||||||
from gluon.fileutils import abspath, write_file
|
from gluon.fileutils import abspath, write_file
|
||||||
@@ -248,7 +249,7 @@ class LazyWSGI(object):
|
|||||||
def app(environ, start_response):
|
def app(environ, start_response):
|
||||||
data = f()
|
data = f()
|
||||||
start_response(self.response.status,
|
start_response(self.response.status,
|
||||||
list(self.response.headers.items()))
|
self.response.headers.items())
|
||||||
if isinstance(data, list):
|
if isinstance(data, list):
|
||||||
return data
|
return data
|
||||||
return [data]
|
return [data]
|
||||||
@@ -485,10 +486,10 @@ def wsgibase(environ, responder):
|
|||||||
if request.ajax:
|
if request.ajax:
|
||||||
if response.flash:
|
if response.flash:
|
||||||
http_response.headers['web2py-component-flash'] = \
|
http_response.headers['web2py-component-flash'] = \
|
||||||
urllib_quote(xmlescape(response.flash).replace(b'\n', b''))
|
urllib2.quote(xmlescape(response.flash).replace(b'\n', b''))
|
||||||
if response.js:
|
if response.js:
|
||||||
http_response.headers['web2py-component-command'] = \
|
http_response.headers['web2py-component-command'] = \
|
||||||
urllib_quote(response.js.replace('\n', ''))
|
urllib2.quote(response.js.replace('\n', ''))
|
||||||
|
|
||||||
# ##################################################
|
# ##################################################
|
||||||
# store cookies in headers
|
# store cookies in headers
|
||||||
@@ -716,9 +717,9 @@ class HttpServer(object):
|
|||||||
if isinstance(interfaces, list):
|
if isinstance(interfaces, list):
|
||||||
for i in interfaces:
|
for i in interfaces:
|
||||||
if not isinstance(i, tuple):
|
if not isinstance(i, tuple):
|
||||||
raise AttributeError("Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/")
|
raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"
|
||||||
else:
|
else:
|
||||||
raise AttributeError("Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/")
|
raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"
|
||||||
|
|
||||||
if path:
|
if path:
|
||||||
# if a path is specified change the global variables so that web2py
|
# if a path is specified change the global variables so that web2py
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if sys.version_info[0] == 2:
|
import Tkinter
|
||||||
import Tkinter as tkinter
|
except:
|
||||||
else:
|
|
||||||
import tkinter
|
|
||||||
except ImportError:
|
|
||||||
Tkinter = None
|
Tkinter = None
|
||||||
|
|
||||||
|
|
||||||
@@ -16,15 +12,15 @@ class MessageBoxHandler(logging.Handler):
|
|||||||
logging.Handler.__init__(self)
|
logging.Handler.__init__(self)
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
if tkinter:
|
if Tkinter:
|
||||||
msg = self.format(record)
|
msg = self.format(record)
|
||||||
root = tkinter.Tk()
|
root = Tkinter.Tk()
|
||||||
root.wm_title("web2py logger message")
|
root.wm_title("web2py logger message")
|
||||||
text = tkinter.Text()
|
text = Tkinter.Text()
|
||||||
text["height"] = 12
|
text["height"] = 12
|
||||||
text.insert(0.1, msg)
|
text.insert(0.1, msg)
|
||||||
text.pack()
|
text.pack()
|
||||||
button = tkinter.Button(root, text="OK", command=root.destroy)
|
button = Tkinter.Button(root, text="OK", command=root.destroy)
|
||||||
button.pack()
|
button.pack()
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
@@ -34,6 +30,6 @@ class NotifySendHandler(logging.Handler):
|
|||||||
logging.Handler.__init__(self)
|
logging.Handler.__init__(self)
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
if tkinter:
|
if Tkinter:
|
||||||
msg = self.format(record)
|
msg = self.format(record)
|
||||||
os.system("notify-send '%s'" % msg)
|
os.system("notify-send '%s'" % msg)
|
||||||
|
|||||||
+5
-1
@@ -20,9 +20,13 @@ import re
|
|||||||
import datetime
|
import datetime
|
||||||
import platform
|
import platform
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
try:
|
||||||
|
import cPickle as pickle
|
||||||
|
except:
|
||||||
|
import pickle
|
||||||
from gluon.settings import global_settings
|
from gluon.settings import global_settings
|
||||||
from gluon import fileutils
|
from gluon import fileutils
|
||||||
from gluon._compat import to_bytes, pickle
|
from gluon._compat import to_bytes
|
||||||
from pydal.contrib import portalocker
|
from pydal.contrib import portalocker
|
||||||
|
|
||||||
logger = logging.getLogger("web2py.cron")
|
logger = logging.getLogger("web2py.cron")
|
||||||
|
|||||||
+1
-1
Submodule gluon/packages/dal updated: 48adca66cf...d9d880a719
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Submodule gluon/packages/yatl deleted from 7e905158ff
@@ -15,6 +15,7 @@ routes.py supports two styles of URL rewriting, depending on whether 'routers' i
|
|||||||
Refer to router.example.py and routes.example.py for additional documentation.
|
Refer to router.example.py and routes.example.py for additional documentation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|||||||
+39
-8
@@ -5,14 +5,14 @@
|
|||||||
# Modified by Massimo Di Pierro
|
# Modified by Massimo Di Pierro
|
||||||
|
|
||||||
# Import System Modules
|
# Import System Modules
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import errno
|
import errno
|
||||||
import socket
|
import socket
|
||||||
import logging
|
import logging
|
||||||
import platform
|
import platform
|
||||||
from gluon._compat import iteritems, to_bytes, to_unicode, StringIO
|
from gluon._compat import iteritems, to_bytes, StringIO
|
||||||
from gluon._compat import urllib_unquote, to_native, PY2
|
from gluon._compat import urllib_unquote, to_native
|
||||||
|
|
||||||
# Define Constants
|
# Define Constants
|
||||||
VERSION = '1.2.6'
|
VERSION = '1.2.6'
|
||||||
@@ -32,7 +32,7 @@ DEFAULTS = dict(LISTEN_QUEUE_SIZE=DEFAULT_LISTEN_QUEUE_SIZE,
|
|||||||
MIN_THREADS=DEFAULT_MIN_THREADS,
|
MIN_THREADS=DEFAULT_MIN_THREADS,
|
||||||
MAX_THREADS=DEFAULT_MAX_THREADS)
|
MAX_THREADS=DEFAULT_MAX_THREADS)
|
||||||
|
|
||||||
PY3K = not PY2
|
PY3K = sys.version_info[0] > 2
|
||||||
|
|
||||||
|
|
||||||
class NullHandler(logging.Handler):
|
class NullHandler(logging.Handler):
|
||||||
@@ -40,8 +40,39 @@ class NullHandler(logging.Handler):
|
|||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
b = to_bytes
|
if PY3K:
|
||||||
u = to_unicode
|
def b(val):
|
||||||
|
""" Convert string/unicode/bytes literals into bytes. This allows for
|
||||||
|
the same code to run on Python 2.x and 3.x. """
|
||||||
|
if isinstance(val, str):
|
||||||
|
return val.encode()
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
def u(val, encoding="us-ascii"):
|
||||||
|
""" Convert bytes into string/unicode. This allows for the
|
||||||
|
same code to run on Python 2.x and 3.x. """
|
||||||
|
if isinstance(val, bytes):
|
||||||
|
return val.decode(encoding)
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
else:
|
||||||
|
def b(val):
|
||||||
|
""" Convert string/unicode/bytes literals into bytes. This allows for
|
||||||
|
the same code to run on Python 2.x and 3.x. """
|
||||||
|
if isinstance(val, unicode):
|
||||||
|
return val.encode()
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
def u(val, encoding="us-ascii"):
|
||||||
|
""" Convert bytes into string/unicode. This allows for the
|
||||||
|
same code to run on Python 2.x and 3.x. """
|
||||||
|
if isinstance(val, str):
|
||||||
|
return val.decode(encoding)
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
# Import Package Modules
|
# Import Package Modules
|
||||||
# package imports removed in monolithic build
|
# package imports removed in monolithic build
|
||||||
@@ -582,9 +613,9 @@ import socket
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
if PY3K:
|
try:
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
else:
|
except ImportError:
|
||||||
from Queue import Queue
|
from Queue import Queue
|
||||||
|
|
||||||
# Import Package Modules
|
# Import Package Modules
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from __future__ import print_function
|
||||||
# The following code is not part of Rocket but was added to
|
# The following code is not part of Rocket but was added to
|
||||||
# web2py for testing purposes.
|
# web2py for testing purposes.
|
||||||
|
|
||||||
|
|||||||
+219
-1
@@ -1 +1,219 @@
|
|||||||
from yatl.sanitizer import sanitize
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
| From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496942
|
||||||
|
| Submitter: Josh Goldfoot (other recipes)
|
||||||
|
| Last Updated: 2006/08/05
|
||||||
|
| Version: 1.0
|
||||||
|
|
||||||
|
Cross-site scripting (XSS) defense
|
||||||
|
-----------------------------------
|
||||||
|
"""
|
||||||
|
|
||||||
|
from gluon._compat import HTMLParser, urlparse, entitydefs, basestring
|
||||||
|
from gluon.utils import local_html_escape
|
||||||
|
from formatter import AbstractFormatter
|
||||||
|
from xml.sax.saxutils import quoteattr
|
||||||
|
|
||||||
|
__all__ = ['sanitize']
|
||||||
|
|
||||||
|
|
||||||
|
def xssescape(text):
|
||||||
|
"""Gets rid of < and > and & and, for good measure, :"""
|
||||||
|
|
||||||
|
return local_html_escape(text, quote=True).replace(':', ':')
|
||||||
|
|
||||||
|
|
||||||
|
class XssCleaner(HTMLParser):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
permitted_tags=[
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'blockquote',
|
||||||
|
'br/',
|
||||||
|
'i',
|
||||||
|
'li',
|
||||||
|
'ol',
|
||||||
|
'ul',
|
||||||
|
'p',
|
||||||
|
'cite',
|
||||||
|
'code',
|
||||||
|
'pre',
|
||||||
|
'img/',
|
||||||
|
],
|
||||||
|
allowed_attributes={'a': ['href', 'title'], 'img': ['src', 'alt'
|
||||||
|
], 'blockquote': ['type']},
|
||||||
|
strip_disallowed=False
|
||||||
|
):
|
||||||
|
|
||||||
|
HTMLParser.__init__(self)
|
||||||
|
self.result = ''
|
||||||
|
self.open_tags = []
|
||||||
|
self.permitted_tags = [i for i in permitted_tags if i[-1] != '/']
|
||||||
|
self.requires_no_close = [i[:-1] for i in permitted_tags
|
||||||
|
if i[-1] == '/']
|
||||||
|
self.permitted_tags += self.requires_no_close
|
||||||
|
self.allowed_attributes = allowed_attributes
|
||||||
|
|
||||||
|
# The only schemes allowed in URLs (for href and src attributes).
|
||||||
|
# Adding "javascript" or "vbscript" to this list would not be smart.
|
||||||
|
|
||||||
|
self.allowed_schemes = ['http', 'https', 'ftp', 'mailto']
|
||||||
|
|
||||||
|
#to strip or escape disallowed tags?
|
||||||
|
self.strip_disallowed = strip_disallowed
|
||||||
|
# there might be data after final closing tag, that is to be ignored
|
||||||
|
self.in_disallowed = [False]
|
||||||
|
|
||||||
|
def handle_data(self, data):
|
||||||
|
if data and not self.in_disallowed[-1]:
|
||||||
|
self.result += xssescape(data)
|
||||||
|
|
||||||
|
def handle_charref(self, ref):
|
||||||
|
if self.in_disallowed[-1]:
|
||||||
|
return
|
||||||
|
elif len(ref) < 7 and (ref.isdigit() or ref == 'x27'): # x27 is a special case for apostrophe
|
||||||
|
self.result += '&#%s;' % ref
|
||||||
|
else:
|
||||||
|
self.result += xssescape('&#%s' % ref)
|
||||||
|
|
||||||
|
def handle_entityref(self, ref):
|
||||||
|
if self.in_disallowed[-1]:
|
||||||
|
return
|
||||||
|
elif ref in entitydefs:
|
||||||
|
self.result += '&%s;' % ref
|
||||||
|
else:
|
||||||
|
self.result += xssescape('&%s' % ref)
|
||||||
|
|
||||||
|
def handle_comment(self, comment):
|
||||||
|
if self.in_disallowed[-1]:
|
||||||
|
return
|
||||||
|
elif comment:
|
||||||
|
self.result += xssescape('<!--%s-->' % comment)
|
||||||
|
|
||||||
|
def handle_starttag(
|
||||||
|
self,
|
||||||
|
tag,
|
||||||
|
attrs
|
||||||
|
):
|
||||||
|
if tag not in self.permitted_tags:
|
||||||
|
self.in_disallowed.append(True)
|
||||||
|
if (not self.strip_disallowed):
|
||||||
|
self.result += xssescape('<%s>' % tag)
|
||||||
|
else:
|
||||||
|
self.in_disallowed.append(False)
|
||||||
|
bt = '<' + tag
|
||||||
|
if tag in self.allowed_attributes:
|
||||||
|
attrs = dict(attrs)
|
||||||
|
self.allowed_attributes_here = [x for x in
|
||||||
|
self.allowed_attributes[tag] if x in attrs
|
||||||
|
and len(attrs[x]) > 0]
|
||||||
|
for attribute in self.allowed_attributes_here:
|
||||||
|
if attribute in ['href', 'src', 'background']:
|
||||||
|
if self.url_is_acceptable(attrs[attribute]):
|
||||||
|
bt += ' %s="%s"' % (attribute,
|
||||||
|
attrs[attribute])
|
||||||
|
else:
|
||||||
|
bt += ' %s=%s' % (xssescape(attribute),
|
||||||
|
quoteattr(attrs[attribute]))
|
||||||
|
# deal with <a> without href and <img> without src
|
||||||
|
if bt == '<a' or bt == '<img':
|
||||||
|
return
|
||||||
|
if tag in self.requires_no_close:
|
||||||
|
bt += ' /'
|
||||||
|
bt += '>'
|
||||||
|
self.result += bt
|
||||||
|
if tag not in self.requires_no_close: self.open_tags.insert(0, tag)
|
||||||
|
|
||||||
|
def handle_endtag(self, tag):
|
||||||
|
bracketed = '</%s>' % tag
|
||||||
|
self.in_disallowed and self.in_disallowed.pop()
|
||||||
|
if tag not in self.permitted_tags:
|
||||||
|
if (not self.strip_disallowed):
|
||||||
|
self.result += xssescape(bracketed)
|
||||||
|
elif tag in self.open_tags:
|
||||||
|
self.result += bracketed
|
||||||
|
self.open_tags.remove(tag)
|
||||||
|
|
||||||
|
def url_is_acceptable(self, url):
|
||||||
|
"""
|
||||||
|
Accepts relative, absolute, and mailto urls
|
||||||
|
"""
|
||||||
|
|
||||||
|
if url.startswith('#'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
parsed = urlparse.urlparse(url)
|
||||||
|
return ((parsed[0] in self.allowed_schemes and '.' in parsed[1]) or
|
||||||
|
(parsed[0] in self.allowed_schemes and '@' in parsed[2]) or
|
||||||
|
(parsed[0] == '' and parsed[2].startswith('/')))
|
||||||
|
|
||||||
|
def strip(self, rawstring, escape=True):
|
||||||
|
"""
|
||||||
|
Returns the argument stripped of potentially harmful
|
||||||
|
HTML or Javascript code
|
||||||
|
|
||||||
|
@type escape: boolean
|
||||||
|
@param escape: If True (default) it escapes the potentially harmful
|
||||||
|
content, otherwise remove it
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not isinstance(rawstring, str):
|
||||||
|
return str(rawstring)
|
||||||
|
for tag in self.requires_no_close:
|
||||||
|
rawstring = rawstring.replace("<%s/>" % tag, "<%s />" % tag)
|
||||||
|
if not escape:
|
||||||
|
self.strip_disallowed = True
|
||||||
|
self.result = ''
|
||||||
|
self.feed(rawstring)
|
||||||
|
for endtag in self.open_tags:
|
||||||
|
if endtag not in self.requires_no_close:
|
||||||
|
self.result += '</%s>' % endtag
|
||||||
|
return self.result
|
||||||
|
|
||||||
|
def xtags(self):
|
||||||
|
"""
|
||||||
|
Returns a printable string informing the user which tags are allowed
|
||||||
|
"""
|
||||||
|
|
||||||
|
tg = ''
|
||||||
|
for x in sorted(self.permitted_tags):
|
||||||
|
tg += '<' + x
|
||||||
|
if x in self.allowed_attributes:
|
||||||
|
for y in self.allowed_attributes[x]:
|
||||||
|
tg += ' %s=""' % y
|
||||||
|
tg += '> '
|
||||||
|
return xssescape(tg.strip())
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize(text, permitted_tags=[
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'blockquote',
|
||||||
|
'br/',
|
||||||
|
'i',
|
||||||
|
'li',
|
||||||
|
'ol',
|
||||||
|
'ul',
|
||||||
|
'p',
|
||||||
|
'cite',
|
||||||
|
'code',
|
||||||
|
'pre',
|
||||||
|
'img/',
|
||||||
|
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||||
|
'table', 'tbody', 'thead', 'tfoot', 'tr', 'td', 'div',
|
||||||
|
'strong', 'span',
|
||||||
|
],
|
||||||
|
allowed_attributes={
|
||||||
|
'a': ['href', 'title'],
|
||||||
|
'img': ['src', 'alt'],
|
||||||
|
'blockquote': ['type'],
|
||||||
|
'td': ['colspan'],
|
||||||
|
},
|
||||||
|
escape=True):
|
||||||
|
if not isinstance(text, basestring):
|
||||||
|
return str(text)
|
||||||
|
return XssCleaner(permitted_tags=permitted_tags,
|
||||||
|
allowed_attributes=allowed_attributes).strip(text, escape)
|
||||||
|
|||||||
+1
-1746
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ from gluon.html import TAG, XmlComponent, xmlescape
|
|||||||
from gluon.languages import lazyT
|
from gluon.languages import lazyT
|
||||||
import gluon.contrib.rss2 as rss2
|
import gluon.contrib.rss2 as rss2
|
||||||
import json as json_parser
|
import json as json_parser
|
||||||
from gluon._compat import long, to_native, unicodeT, integer_types
|
from gluon._compat import long, to_native, unicodeT
|
||||||
|
|
||||||
have_yaml = True
|
have_yaml = True
|
||||||
try:
|
try:
|
||||||
@@ -79,7 +79,7 @@ def custom_json(o):
|
|||||||
datetime.datetime,
|
datetime.datetime,
|
||||||
datetime.time)):
|
datetime.time)):
|
||||||
return o.isoformat()[:19].replace('T', ' ')
|
return o.isoformat()[:19].replace('T', ' ')
|
||||||
elif isinstance(o, integer_types):
|
elif isinstance(o, (int, long)):
|
||||||
return int(o)
|
return int(o)
|
||||||
elif isinstance(o, decimal.Decimal):
|
elif isinstance(o, decimal.Decimal):
|
||||||
return str(o)
|
return str(o)
|
||||||
|
|||||||
+2
-3
@@ -10,7 +10,6 @@
|
|||||||
Web2py environment in the shell
|
Web2py environment in the shell
|
||||||
--------------------------------
|
--------------------------------
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -96,7 +95,7 @@ def exec_environment(
|
|||||||
if pyfile:
|
if pyfile:
|
||||||
pycfile = pyfile + 'c'
|
pycfile = pyfile + 'c'
|
||||||
if os.path.isfile(pycfile):
|
if os.path.isfile(pycfile):
|
||||||
exec(read_pyc(pycfile), env)
|
exec (read_pyc(pycfile), env)
|
||||||
else:
|
else:
|
||||||
execfile(pyfile, env)
|
execfile(pyfile, env)
|
||||||
return Storage(env)
|
return Storage(env)
|
||||||
@@ -211,7 +210,7 @@ def run(
|
|||||||
- a/c : exec the controller c into the application environment
|
- a/c : exec the controller c into the application environment
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(a, c, f, args, vars) = parse_path_info(appname, av=True)
|
(a, c, f, args, vars) = parse_path_info(appname, av=True)
|
||||||
errmsg = 'invalid application name: %s' % appname
|
errmsg = 'invalid application name: %s' % appname
|
||||||
if not a:
|
if not a:
|
||||||
die(errmsg)
|
die(errmsg)
|
||||||
|
|||||||
+51
-64
@@ -717,7 +717,7 @@ class AutocompleteWidget(object):
|
|||||||
compact=table_rows.compact)
|
compact=table_rows.compact)
|
||||||
elif settings and settings.global_settings.web2py_runtime_gae:
|
elif settings and settings.global_settings.web2py_runtime_gae:
|
||||||
rows = self.db(field.__ge__(kword) &
|
rows = self.db(field.__ge__(kword) &
|
||||||
field.__lt__(kword + '\ufffd')
|
field.__lt__(kword + u'\ufffd')
|
||||||
).select(orderby=self.orderby,
|
).select(orderby=self.orderby,
|
||||||
limitby=self.limitby,
|
limitby=self.limitby,
|
||||||
*(self.fields + self.help_fields))
|
*(self.fields + self.help_fields))
|
||||||
@@ -1966,7 +1966,7 @@ class SQLFORM(FORM):
|
|||||||
|
|
||||||
AUTOTYPES = {
|
AUTOTYPES = {
|
||||||
type(''): ('string', None),
|
type(''): ('string', None),
|
||||||
type(''): ('string',None),
|
type(u''): ('string',None),
|
||||||
type(True): ('boolean', None),
|
type(True): ('boolean', None),
|
||||||
type(1): ('integer', IS_INT_IN_RANGE(-1e12, +1e12)),
|
type(1): ('integer', IS_INT_IN_RANGE(-1e12, +1e12)),
|
||||||
type(1.0): ('double', IS_FLOAT_IN_RANGE()),
|
type(1.0): ('double', IS_FLOAT_IN_RANGE()),
|
||||||
@@ -2322,7 +2322,7 @@ class SQLFORM(FORM):
|
|||||||
create = wenabled and create
|
create = wenabled and create
|
||||||
editable = wenabled and editable
|
editable = wenabled and editable
|
||||||
deletable = wenabled and deletable
|
deletable = wenabled and deletable
|
||||||
details = not groupby and details
|
details = details and not groupby
|
||||||
rows = None
|
rows = None
|
||||||
|
|
||||||
# see issue 1980. Basically we can have keywords in get_vars
|
# see issue 1980. Basically we can have keywords in get_vars
|
||||||
@@ -2385,12 +2385,6 @@ class SQLFORM(FORM):
|
|||||||
b['args'] = args + b.get('args', [])
|
b['args'] = args + b.get('args', [])
|
||||||
localvars = request.get_vars.copy()
|
localvars = request.get_vars.copy()
|
||||||
localvars.update(b.get('vars', {}))
|
localvars.update(b.get('vars', {}))
|
||||||
# avoid empty keywords in vars
|
|
||||||
if localvars.get('keywords') == '':
|
|
||||||
del localvars['keywords']
|
|
||||||
# avoid propagating order=None in vars
|
|
||||||
if localvars.get('order') == 'None':
|
|
||||||
del localvars['order']
|
|
||||||
b['vars'] = localvars
|
b['vars'] = localvars
|
||||||
b['hash_vars'] = False
|
b['hash_vars'] = False
|
||||||
b['user_signature'] = user_signature
|
b['user_signature'] = user_signature
|
||||||
@@ -2420,7 +2414,7 @@ class SQLFORM(FORM):
|
|||||||
|
|
||||||
def gridbutton(buttonclass='buttonadd', buttontext=T('Add'),
|
def gridbutton(buttonclass='buttonadd', buttontext=T('Add'),
|
||||||
buttonurl=url(args=[]), callback=None,
|
buttonurl=url(args=[]), callback=None,
|
||||||
delete=None, noconfirm=None, title=None):
|
delete=None, trap=True, noconfirm=None, title=None):
|
||||||
if showbuttontext:
|
if showbuttontext:
|
||||||
return A(SPAN(_class=ui.get(buttonclass)), CAT(' '),
|
return A(SPAN(_class=ui.get(buttonclass)), CAT(' '),
|
||||||
SPAN(T(buttontext), _title=title or T(buttontext),
|
SPAN(T(buttontext), _title=title or T(buttontext),
|
||||||
@@ -2450,6 +2444,11 @@ class SQLFORM(FORM):
|
|||||||
tablenames = merge_tablemaps(tablenames, db._adapter.tables(join))
|
tablenames = merge_tablemaps(tablenames, db._adapter.tables(join))
|
||||||
tables = [db[tablename] for tablename in tablenames]
|
tables = [db[tablename] for tablename in tablenames]
|
||||||
if fields:
|
if fields:
|
||||||
|
# add missing tablename to virtual fields
|
||||||
|
for table in tables:
|
||||||
|
for k, f in iteritems(table):
|
||||||
|
if isinstance(f, Field.Virtual):
|
||||||
|
f.tablename = table._tablename
|
||||||
columns = [f for f in fields if f.tablename in tablenames and f.listable]
|
columns = [f for f in fields if f.tablename in tablenames and f.listable]
|
||||||
else:
|
else:
|
||||||
fields = []
|
fields = []
|
||||||
@@ -2457,8 +2456,8 @@ class SQLFORM(FORM):
|
|||||||
filter1 = lambda f: isinstance(f, Field) and (f.type!='blob' or showblobs)
|
filter1 = lambda f: isinstance(f, Field) and (f.type!='blob' or showblobs)
|
||||||
filter2 = lambda f: isinstance(f, Field) and f.readable and f.listable
|
filter2 = lambda f: isinstance(f, Field) and f.readable and f.listable
|
||||||
for table in tables:
|
for table in tables:
|
||||||
fields += list(filter(filter1, table))
|
fields += filter(filter1, table)
|
||||||
columns += list(filter(filter2, table))
|
columns += filter(filter2, table)
|
||||||
for k, f in iteritems(table):
|
for k, f in iteritems(table):
|
||||||
if not k.startswith('_'):
|
if not k.startswith('_'):
|
||||||
if isinstance(f, Field.Virtual) and f.readable:
|
if isinstance(f, Field.Virtual) and f.readable:
|
||||||
@@ -2544,7 +2543,7 @@ class SQLFORM(FORM):
|
|||||||
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)
|
||||||
if represent_none is not None:
|
if represent_none is not None:
|
||||||
for field in record.keys():
|
for field in record.iterkeys():
|
||||||
if record[field] is None:
|
if record[field] is None:
|
||||||
record[field] = represent_none
|
record[field] = represent_none
|
||||||
sqlformargs = dict(upload=upload, ignore_rw=ignore_rw,
|
sqlformargs = dict(upload=upload, ignore_rw=ignore_rw,
|
||||||
@@ -2646,18 +2645,20 @@ class SQLFORM(FORM):
|
|||||||
|
|
||||||
orderby = fix_orderby(orderby)
|
orderby = fix_orderby(orderby)
|
||||||
|
|
||||||
# expcolumns start with the visible columns, which
|
|
||||||
# includes visible virtual fields
|
|
||||||
expcolumns = [str(f) for f in columns]
|
expcolumns = [str(f) for f in columns]
|
||||||
selectable_columns = [str(f) for f in columns if not isinstance(f, Field.Virtual)]
|
selectable_columns = [str(f) for f in columns if not isinstance(f, Field.Virtual)]
|
||||||
if export_type.endswith('with_hidden_cols'):
|
if export_type.endswith('with_hidden_cols'):
|
||||||
|
# expcolumns = [] start with the visible columns, which
|
||||||
|
# includes visible virtual fields
|
||||||
|
selectable_columns = []
|
||||||
|
# like expcolumns but excluding virtual
|
||||||
for table in tables:
|
for table in tables:
|
||||||
for field in table:
|
for field in table:
|
||||||
if field.readable and field.tablename in tablenames:
|
if field.readable and field.tablename in tablenames:
|
||||||
if not str(field) in expcolumns:
|
if not str(field) in expcolumns:
|
||||||
expcolumns.append(str(field))
|
expcolumns.append(str(field))
|
||||||
if not(isinstance(field, Field.Virtual)):
|
if not(isinstance(field, Field.Virtual)):
|
||||||
selectable_columns.append(str(field))
|
selectable_columns.append(str(field))
|
||||||
# look for virtual fields not displayed (and virtual method
|
# look for virtual fields not displayed (and virtual method
|
||||||
# fields to be added here?)
|
# fields to be added here?)
|
||||||
for (field_name, field) in iteritems(table):
|
for (field_name, field) in iteritems(table):
|
||||||
@@ -2671,7 +2672,7 @@ class SQLFORM(FORM):
|
|||||||
# the query should be constructed using searchable
|
# the query should be constructed using searchable
|
||||||
# fields but not virtual fields
|
# fields but not virtual fields
|
||||||
is_searchable = lambda f: f.readable and not isinstance(f, Field.Virtual) and f.searchable
|
is_searchable = lambda f: f.readable and not isinstance(f, Field.Virtual) and f.searchable
|
||||||
sfields = reduce(lambda a, b: a + b, [list(filter(is_searchable, t)) for t in tables])
|
sfields = reduce(lambda a, b: a + b, [filter(is_searchable, t) for t in tables])
|
||||||
# use custom_query using searchable
|
# use custom_query using searchable
|
||||||
if callable(searchable):
|
if callable(searchable):
|
||||||
dbset = dbset(searchable(sfields, keywords))
|
dbset = dbset(searchable(sfields, keywords))
|
||||||
@@ -2679,13 +2680,13 @@ class SQLFORM(FORM):
|
|||||||
dbset = dbset(SQLFORM.build_query(
|
dbset = dbset(SQLFORM.build_query(
|
||||||
sfields, keywords))
|
sfields, keywords))
|
||||||
rows = dbset.select(left=left, orderby=orderby,
|
rows = dbset.select(left=left, orderby=orderby,
|
||||||
cacheable=True, *selectable_columns)
|
cacheable=True, *expcolumns)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
response.flash = T('Internal Error')
|
response.flash = T('Internal Error')
|
||||||
rows = []
|
rows = []
|
||||||
else:
|
else:
|
||||||
rows = dbset.select(left=left, orderby=orderby,
|
rows = dbset.select(left=left, orderby=orderby,
|
||||||
cacheable=True, *selectable_columns)
|
cacheable=True, *expcolumns)
|
||||||
|
|
||||||
value = exportManager[export_type]
|
value = exportManager[export_type]
|
||||||
clazz = value[0] if hasattr(value, '__getitem__') else value
|
clazz = value[0] if hasattr(value, '__getitem__') else value
|
||||||
@@ -2722,7 +2723,7 @@ class SQLFORM(FORM):
|
|||||||
|
|
||||||
if searchable:
|
if searchable:
|
||||||
sfields = reduce(lambda a, b: a + b,
|
sfields = reduce(lambda a, b: a + b,
|
||||||
[[f for f in t if f.readable and f.searchable] for t in tables])
|
[[f for f in t if f.readable] for t in tables])
|
||||||
if isinstance(search_widget, dict):
|
if isinstance(search_widget, dict):
|
||||||
search_widget = search_widget[tablename]
|
search_widget = search_widget[tablename]
|
||||||
if search_widget == 'default':
|
if search_widget == 'default':
|
||||||
@@ -2731,7 +2732,7 @@ class SQLFORM(FORM):
|
|||||||
spanel_id = '%s_query_fields' % prefix
|
spanel_id = '%s_query_fields' % prefix
|
||||||
sfields_id = '%s_query_panel' % prefix
|
sfields_id = '%s_query_panel' % prefix
|
||||||
skeywords_id = '%s_keywords' % prefix
|
skeywords_id = '%s_keywords' % prefix
|
||||||
# hidden fields to preserve keywords in url after the submit
|
# hidden fields to presever keywords in url after the submit
|
||||||
hidden_fields = [INPUT(_type='hidden', _value=v, _name=k) for k, v in request.get_vars.items() if k not in ['keywords', 'page']]
|
hidden_fields = [INPUT(_type='hidden', _value=v, _name=k) for k, v in request.get_vars.items() if k not in ['keywords', 'page']]
|
||||||
search_widget = lambda sfield, url: CAT(FORM(
|
search_widget = lambda sfield, url: CAT(FORM(
|
||||||
INPUT(_name='keywords', _value=keywords,
|
INPUT(_name='keywords', _value=keywords,
|
||||||
@@ -2747,17 +2748,14 @@ class SQLFORM(FORM):
|
|||||||
form = search_widget and search_widget(sfields, url()) or ''
|
form = search_widget and search_widget(sfields, url()) or ''
|
||||||
console.append(add)
|
console.append(add)
|
||||||
console.append(form)
|
console.append(form)
|
||||||
if keywords:
|
try:
|
||||||
try:
|
if callable(searchable):
|
||||||
if callable(searchable):
|
subquery = searchable(sfields, keywords)
|
||||||
subquery = searchable(sfields, keywords)
|
else:
|
||||||
else:
|
subquery = SQLFORM.build_query(sfields, keywords)
|
||||||
subquery = SQLFORM.build_query(sfields, keywords)
|
except RuntimeError:
|
||||||
except RuntimeError:
|
|
||||||
subquery = None
|
|
||||||
error = T('Invalid query')
|
|
||||||
else:
|
|
||||||
subquery = None
|
subquery = None
|
||||||
|
error = T('Invalid query')
|
||||||
else:
|
else:
|
||||||
subquery = None
|
subquery = None
|
||||||
|
|
||||||
@@ -2770,15 +2768,12 @@ class SQLFORM(FORM):
|
|||||||
error = T('Unsupported query')
|
error = T('Unsupported query')
|
||||||
|
|
||||||
order = request.vars.order or ''
|
order = request.vars.order or ''
|
||||||
asc_icon, desc_icon = sorter_icons
|
|
||||||
if sortable:
|
if sortable:
|
||||||
if order and not order == 'None':
|
if order and not order == 'None':
|
||||||
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
||||||
sort_field = db[otablename][ofieldname]
|
sort_field = db[otablename][ofieldname]
|
||||||
# invert order direction on date/time fields
|
|
||||||
exception = sort_field.type in ('date', 'datetime', 'time')
|
exception = sort_field.type in ('date', 'datetime', 'time')
|
||||||
if exception:
|
if exception:
|
||||||
desc_icon, asc_icon = sorter_icons
|
|
||||||
orderby = (order[:1] == '~' and sort_field) or ~sort_field
|
orderby = (order[:1] == '~' and sort_field) or ~sort_field
|
||||||
else:
|
else:
|
||||||
orderby = (order[:1] == '~' and ~sort_field) or sort_field
|
orderby = (order[:1] == '~' and ~sort_field) or sort_field
|
||||||
@@ -2787,30 +2782,30 @@ class SQLFORM(FORM):
|
|||||||
if selectable:
|
if selectable:
|
||||||
headcols.append(TH(_class=ui.get('default')))
|
headcols.append(TH(_class=ui.get('default')))
|
||||||
|
|
||||||
ordermatch = orderby; marker = ''
|
ordermatch, marker = orderby, ''
|
||||||
if orderby:
|
if orderby:
|
||||||
# if orderby is a single column, remember to put the marker
|
# if orderby is a single column, remember to put the marker
|
||||||
if isinstance(orderby, Expression):
|
if isinstance(orderby, Expression):
|
||||||
if orderby.first and not orderby.second:
|
if orderby.first and not orderby.second:
|
||||||
ordermatch = orderby.first; marker = '~'
|
ordermatch, marker = orderby.first, '~'
|
||||||
ordermatch = marker + str(ordermatch)
|
ordermatch = marker + str(ordermatch)
|
||||||
for field in columns:
|
for field in columns:
|
||||||
if not field.readable:
|
if not field.readable:
|
||||||
continue
|
continue
|
||||||
key = str(field)
|
key = str(field)
|
||||||
header = headers.get(key, field.label or key)
|
header = headers.get(str(field), field.label or key)
|
||||||
if sortable and not isinstance(field, Field.Virtual):
|
if sortable and not isinstance(field, Field.Virtual):
|
||||||
marker = ''
|
marker = ''
|
||||||
if order:
|
if order:
|
||||||
if key == order:
|
if key == order:
|
||||||
key = '~' + order; marker = asc_icon
|
key, marker = '~' + order, sorter_icons[0]
|
||||||
elif key == order[1:]:
|
elif key == order[1:]:
|
||||||
key = 'None'; marker = desc_icon
|
marker = sorter_icons[1]
|
||||||
else:
|
else:
|
||||||
if key == ordermatch:
|
if key == ordermatch:
|
||||||
key = '~' + ordermatch; marker = asc_icon
|
key, marker = '~' + ordermatch, sorter_icons[0]
|
||||||
elif key == ordermatch[1:]:
|
elif key == ordermatch[1:]:
|
||||||
marker = desc_icon
|
marker = sorter_icons[1]
|
||||||
header = A(header, marker, _href=url(vars=dict(
|
header = A(header, marker, _href=url(vars=dict(
|
||||||
keywords=keywords,
|
keywords=keywords,
|
||||||
order=key)), cid=request.cid)
|
order=key)), cid=request.cid)
|
||||||
@@ -2932,7 +2927,7 @@ class SQLFORM(FORM):
|
|||||||
paginator.append(LI(self_link('<<', 0)))
|
paginator.append(LI(self_link('<<', 0)))
|
||||||
if page > NPAGES:
|
if page > NPAGES:
|
||||||
paginator.append(LI(self_link('<', page - 1)))
|
paginator.append(LI(self_link('<', page - 1)))
|
||||||
pages = list(range(max(0, page - NPAGES), min(page + NPAGES, npages)))
|
pages = range(max(0, page - NPAGES), min(page + NPAGES, npages))
|
||||||
for p in pages:
|
for p in pages:
|
||||||
if p == page:
|
if p == page:
|
||||||
paginator.append(LI(A(p + 1, _onclick='return false'),
|
paginator.append(LI(A(p + 1, _onclick='return false'),
|
||||||
@@ -3119,7 +3114,7 @@ class SQLFORM(FORM):
|
|||||||
link = url2(vars=dict(
|
link = url2(vars=dict(
|
||||||
order=request.vars.order or '',
|
order=request.vars.order or '',
|
||||||
_export_type=k,
|
_export_type=k,
|
||||||
keywords=keywords))
|
keywords=keywords or ''))
|
||||||
export_links.append(A(T(label), _href=link, _title=title, _class='btn btn-default btn-secondary'))
|
export_links.append(A(T(label), _href=link, _title=title, _class='btn btn-default btn-secondary'))
|
||||||
export_menu = \
|
export_menu = \
|
||||||
DIV(T('Export:'), _class="w2p_export_menu", *export_links)
|
DIV(T('Export:'), _class="w2p_export_menu", *export_links)
|
||||||
@@ -3284,8 +3279,6 @@ class SQLFORM(FORM):
|
|||||||
if isinstance(kwargs.get(key, None), dict):
|
if isinstance(kwargs.get(key, None), dict):
|
||||||
if table._tablename in kwargs[key]:
|
if table._tablename in kwargs[key]:
|
||||||
kwargs[key] = kwargs[key][table._tablename]
|
kwargs[key] = kwargs[key][table._tablename]
|
||||||
elif '*' in kwargs[key]:
|
|
||||||
kwargs[key] = kwargs[key]['*']
|
|
||||||
else:
|
else:
|
||||||
del kwargs[key]
|
del kwargs[key]
|
||||||
check = {}
|
check = {}
|
||||||
@@ -3422,22 +3415,16 @@ class SQLTABLE(TABLE):
|
|||||||
(components, row) = (self.components, [])
|
(components, row) = (self.components, [])
|
||||||
if not sqlrows:
|
if not sqlrows:
|
||||||
return
|
return
|
||||||
fieldlist = sqlrows.colnames_fields
|
REGEX_TABLE_DOT_FIELD = sqlrows.db._adapter.REGEX_TABLE_DOT_FIELD
|
||||||
fieldmap = dict(zip(sqlrows.colnames, fieldlist))
|
fieldmap = dict(zip(sqlrows.colnames, sqlrows.fields))
|
||||||
if columns:
|
tablemap = dict(((f.tablename, f.table) if isinstance(f, Field) else (f._table._tablename, f._table) for f in fieldmap.values()))
|
||||||
tablenames = []
|
for table in tablemap.values():
|
||||||
for colname, field in fieldmap.items():
|
pref = table._tablename + '.'
|
||||||
if isinstance(field, (Field, Field.Virtual)):
|
fieldmap.update(((pref+f.name, f) for f in table._virtual_fields))
|
||||||
tablenames.append(field.tablename)
|
fieldmap.update(((pref+f.name, f) for f in table._virtual_methods))
|
||||||
elif isinstance(field, Expression):
|
|
||||||
tablenames.append(field._table._tablename)
|
|
||||||
for tablename in set(tablenames):
|
|
||||||
table = sqlrows.db[tablename]
|
|
||||||
fieldmap.update((("%s.%s" % (tablename, f.name), f) for f in table._virtual_fields + table._virtual_methods))
|
|
||||||
else:
|
|
||||||
columns = list(sqlrows.colnames)
|
|
||||||
field_types = (Field, Field.Virtual, Field.Method)
|
field_types = (Field, Field.Virtual, Field.Method)
|
||||||
|
if not columns:
|
||||||
|
columns = list(sqlrows.colnames)
|
||||||
header_func = {
|
header_func = {
|
||||||
'fieldname:capitalize': lambda f: f.name.replace('_', ' ').title(),
|
'fieldname:capitalize': lambda f: f.name.replace('_', ' ').title(),
|
||||||
'labels': lambda f: f.label
|
'labels': lambda f: f.label
|
||||||
@@ -3710,7 +3697,7 @@ class ExporterTSV(ExportClass):
|
|||||||
def __init__(self, rows):
|
def __init__(self, rows):
|
||||||
ExportClass.__init__(self, rows)
|
ExportClass.__init__(self, rows)
|
||||||
|
|
||||||
def export(self): # export TSV with field.represent
|
def export(self): # export TSV with rows.represent
|
||||||
if self.rows:
|
if self.rows:
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
self.rows.export_to_csv_file(s, represent=True,delimiter='\t',newline='\n')
|
self.rows.export_to_csv_file(s, represent=True,delimiter='\t',newline='\n')
|
||||||
@@ -3727,7 +3714,7 @@ class ExporterTSV_hidden(ExportClass):
|
|||||||
def __init__(self, rows):
|
def __init__(self, rows):
|
||||||
ExportClass.__init__(self, rows)
|
ExportClass.__init__(self, rows)
|
||||||
|
|
||||||
def export(self):
|
def export(self): # export TSV with rows.represent
|
||||||
if self.rows:
|
if self.rows:
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
self.rows.export_to_csv_file(s,delimiter='\t',newline='\n')
|
self.rows.export_to_csv_file(s,delimiter='\t',newline='\n')
|
||||||
@@ -3745,7 +3732,7 @@ class ExporterCSV(ExportClass):
|
|||||||
def __init__(self, rows):
|
def __init__(self, rows):
|
||||||
ExportClass.__init__(self, rows)
|
ExportClass.__init__(self, rows)
|
||||||
|
|
||||||
def export(self): # export CSV with field.represent
|
def export(self): # export CSV with rows.represent
|
||||||
if self.rows:
|
if self.rows:
|
||||||
s = StringIO()
|
s = StringIO()
|
||||||
self.rows.export_to_csv_file(s, represent=True)
|
self.rows.export_to_csv_file(s, represent=True)
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from yatl.template import render, parse_template
|
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
packages/template/template.py
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
from .test_http import *
|
from .test_http import *
|
||||||
from .test_contenttype import *
|
from .test_contenttype import *
|
||||||
from .test_fileutils import *
|
from .test_fileutils import *
|
||||||
@@ -6,6 +7,7 @@ from .test_recfile import *
|
|||||||
from .test_storage import *
|
from .test_storage import *
|
||||||
from .test_dal import *
|
from .test_dal import *
|
||||||
from .test_cache import *
|
from .test_cache import *
|
||||||
|
from .test_template import *
|
||||||
from .test_html import *
|
from .test_html import *
|
||||||
from .test_contribs import *
|
from .test_contribs import *
|
||||||
from .test_routes import *
|
from .test_routes import *
|
||||||
@@ -20,9 +22,9 @@ from .test_compileapp import *
|
|||||||
from .test_appadmin import *
|
from .test_appadmin import *
|
||||||
from .test_web import *
|
from .test_web import *
|
||||||
from .test_sqlhtml import *
|
from .test_sqlhtml import *
|
||||||
|
from .test_scheduler import *
|
||||||
from .test_cron import *
|
from .test_cron import *
|
||||||
from .test_is_url import *
|
from .test_is_url import *
|
||||||
from .test_scheduler import *
|
|
||||||
|
|
||||||
if sys.version[:3] == '2.7':
|
if sys.version[:3] == '2.7':
|
||||||
from .test_old_doctests import *
|
from .test_old_doctests import *
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for gluon.sqlhtml
|
Unit tests for gluon.sqlhtml
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
from gluon.compileapp import run_controller_in, run_view_in, compile_application, remove_compiled_application
|
from gluon.compileapp import run_controller_in, run_view_in, compile_application, remove_compiled_application
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.storage import Storage, List
|
from gluon.storage import Storage, List
|
||||||
from gluon import fileutils
|
from gluon import fileutils
|
||||||
from gluon.dal import DAL, Field, Table
|
from gluon.dal import DAL, Field, Table
|
||||||
@@ -50,7 +50,7 @@ class TestAppAdmin(unittest.TestCase):
|
|||||||
request.env.remote_addr = '127.0.0.1'
|
request.env.remote_addr = '127.0.0.1'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
current.request = request
|
current.request = request
|
||||||
current.response = response
|
current.response = response
|
||||||
@@ -196,3 +196,4 @@ class TestAppAdmin(unittest.TestCase):
|
|||||||
data['id'] = '1'
|
data['id'] = '1'
|
||||||
request._vars = data
|
request._vars = data
|
||||||
self.assertRaises(HTTP, self.run_function)
|
self.assertRaises(HTTP, self.run_function)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.dal import DAL, Field
|
from gluon.dal import DAL, Field
|
||||||
from gluon.authapi import AuthAPI
|
from gluon.authapi import AuthAPI
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
@@ -24,7 +24,7 @@ class TestAuthAPI(unittest.TestCase):
|
|||||||
self.request.folder = 'applications/admin'
|
self.request.folder = 'applications/admin'
|
||||||
self.response = Response()
|
self.response = Response()
|
||||||
self.session = Session()
|
self.session = Session()
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
self.session.connect(self.request, self.response)
|
self.session.connect(self.request, self.response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
self.current = current
|
self.current = current
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class TestCache(unittest.TestCase):
|
|||||||
s = Storage({'application': 'admin',
|
s = Storage({'application': 'admin',
|
||||||
'folder': 'applications/admin'})
|
'folder': 'applications/admin'})
|
||||||
cache = Cache(s)
|
cache = Cache(s)
|
||||||
db = DAL('sqlite:memory', check_reserved=['all'])
|
db = DAL(check_reserved=['all'])
|
||||||
db.define_table('t_a', Field('f_a'))
|
db.define_table('t_a', Field('f_a'))
|
||||||
db.t_a.insert(f_a='test')
|
db.t_a.insert(f_a='test')
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -142,3 +142,4 @@ class TestCache(unittest.TestCase):
|
|||||||
self.assertEqual(a.as_csv(), h.as_csv())
|
self.assertEqual(a.as_csv(), h.as_csv())
|
||||||
db.t_a.drop()
|
db.t_a.drop()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ class TestCron(unittest.TestCase):
|
|||||||
def test_Token(self):
|
def test_Token(self):
|
||||||
appname_path = os.path.join(os.getcwd(), 'applications', 'welcome')
|
appname_path = os.path.join(os.getcwd(), 'applications', 'welcome')
|
||||||
t = Token(path=appname_path)
|
t = Token(path=appname_path)
|
||||||
self.assertNotEqual(t.acquire(), None)
|
self.assertNotEqual(t.acquire(startup=True), None)
|
||||||
self.assertFalse(t.release())
|
self.assertFalse(t.release())
|
||||||
self.assertEqual(t.acquire(), None)
|
self.assertEqual(t.acquire(), None)
|
||||||
self.assertTrue(t.release())
|
self.assertTrue(t.release())
|
||||||
return
|
return
|
||||||
|
|
||||||
def test_crondance(self):
|
def test_crondance(self):
|
||||||
#TODO update crondance to return something
|
#TODO update crondance to return something
|
||||||
crondance(os.getcwd())
|
crondance(os.getcwd())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class TestDALSubclass(unittest.TestCase):
|
|||||||
|
|
||||||
def testSerialization(self):
|
def testSerialization(self):
|
||||||
from gluon._compat import pickle
|
from gluon._compat import pickle
|
||||||
db = DAL('sqlite:memory', check_reserved=['all'])
|
db = DAL(check_reserved=['all'])
|
||||||
db.define_table('t_a', Field('f_a'))
|
db.define_table('t_a', Field('f_a'))
|
||||||
db.t_a.insert(f_a='test')
|
db.t_a.insert(f_a='test')
|
||||||
a = db(db.t_a.id > 0).select(cacheable=True)
|
a = db(db.t_a.id > 0).select(cacheable=True)
|
||||||
@@ -56,7 +56,7 @@ def _prepare_exec_for_file(filename):
|
|||||||
elif os.path.split(filename)[1] == '__init__.py':
|
elif os.path.split(filename)[1] == '__init__.py':
|
||||||
filename = os.path.dirname(filename)
|
filename = os.path.dirname(filename)
|
||||||
else:
|
else:
|
||||||
raise IOError('The file provided (%s) is not a valid Python file.')
|
raise 'The file provided (%s) does is not a valid Python file.'
|
||||||
filename = os.path.realpath(filename)
|
filename = os.path.realpath(filename)
|
||||||
dirpath = filename
|
dirpath = filename
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ class TestFileUtils(unittest.TestCase):
|
|||||||
# Semantic Beta
|
# Semantic Beta
|
||||||
rtn = parse_version('Version 2.14.1-beta+timestamp.2016.03.21.22.35.26')
|
rtn = parse_version('Version 2.14.1-beta+timestamp.2016.03.21.22.35.26')
|
||||||
self.assertEqual(rtn, (2, 14, 1, 'beta', datetime.datetime(2016, 3, 21, 22, 35, 26)))
|
self.assertEqual(rtn, (2, 14, 1, 'beta', datetime.datetime(2016, 3, 21, 22, 35, 26)))
|
||||||
|
|
||||||
def test_fix_newlines(self):
|
def test_fix_newlines(self):
|
||||||
fix_newlines(os.path.dirname(os.path.abspath(__file__)))
|
fix_newlines(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|||||||
@@ -252,10 +252,11 @@ class testResponse(unittest.TestCase):
|
|||||||
|
|
||||||
def test_include_meta(self):
|
def test_include_meta(self):
|
||||||
response = Response()
|
response = Response()
|
||||||
response.meta['web2py'] = 'web2py'
|
response.meta[u'web2py'] = 'web2py'
|
||||||
response.include_meta()
|
response.include_meta()
|
||||||
self.assertEqual(response.body.getvalue(), '\n<meta name="web2py" content="web2py" />\n')
|
self.assertEqual(response.body.getvalue(), '\n<meta name="web2py" content="web2py" />\n')
|
||||||
response = Response()
|
response = Response()
|
||||||
response.meta['meta_dict'] = {'tag_name':'tag_value'}
|
response.meta[u'meta_dict'] = {u'tag_name':'tag_value'}
|
||||||
response.include_meta()
|
response.include_meta()
|
||||||
self.assertEqual(response.body.getvalue(), '\n<meta tag_name="tag_value" />\n')
|
self.assertEqual(response.body.getvalue(), '\n<meta tag_name="tag_value" />\n')
|
||||||
|
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ class TestBareHelpers(unittest.TestCase):
|
|||||||
<>
|
<>
|
||||||
//--></script>''')
|
//--></script>''')
|
||||||
self.assertEqual(SCRIPT().xml(), b'<script></script>')
|
self.assertEqual(SCRIPT().xml(), b'<script></script>')
|
||||||
self.assertEqual(SCRIPT(';').xml() + DIV().xml(),
|
self.assertEqual(SCRIPT(';').xml() + DIV().xml(),
|
||||||
b'<script><!--\n;\n//--></script><div></div>')
|
b'<script><!--\n;\n//--></script><div></div>')
|
||||||
|
|
||||||
def test_STYLE(self):
|
def test_STYLE(self):
|
||||||
|
|||||||
@@ -88,14 +88,14 @@ class TestTranslations(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_plain(self):
|
def test_plain(self):
|
||||||
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
T = languages.translator(self.langpath, self.http_accept_language)
|
||||||
self.assertEqual(str(T('Hello World')),
|
self.assertEqual(str(T('Hello World')),
|
||||||
'Hello World')
|
'Hello World')
|
||||||
self.assertEqual(str(T('Hello World## comment')),
|
self.assertEqual(str(T('Hello World## comment')),
|
||||||
'Hello World')
|
'Hello World')
|
||||||
self.assertEqual(str(T.M('**Hello World**')),
|
self.assertEqual(str(T.M('**Hello World**')),
|
||||||
'<strong>Hello World</strong>')
|
'<strong>Hello World</strong>')
|
||||||
# sub_tuple testing
|
# sub_tuple testing
|
||||||
self.assertEqual(str(T('%s %%{shop}', 1)),
|
self.assertEqual(str(T('%s %%{shop}', 1)),
|
||||||
'1 shop')
|
'1 shop')
|
||||||
self.assertEqual(str(T('%s %%{shop}', 2)),
|
self.assertEqual(str(T('%s %%{shop}', 2)),
|
||||||
@@ -192,7 +192,7 @@ class TestTranslations(unittest.TestCase):
|
|||||||
'2')
|
'2')
|
||||||
self.assertEqual(str(T('%i%%{?st?[0]}', 0)),
|
self.assertEqual(str(T('%i%%{?st?[0]}', 0)),
|
||||||
'0')
|
'0')
|
||||||
# sub_dict testing
|
# sub_dict testing
|
||||||
self.assertEqual(str(T('%(key)s %%{is(key)}', dict(key=1))),
|
self.assertEqual(str(T('%(key)s %%{is(key)}', dict(key=1))),
|
||||||
'1 is')
|
'1 is')
|
||||||
self.assertEqual(str(T('%(key)i %%{is(key)}', dict(key=2))),
|
self.assertEqual(str(T('%(key)i %%{is(key)}', dict(key=2))),
|
||||||
@@ -340,7 +340,7 @@ class TestMessages(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_decode(self):
|
def test_decode(self):
|
||||||
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
T = languages.translator(self.langpath, self.http_accept_language)
|
||||||
messages = Messages(T)
|
messages = Messages(T)
|
||||||
messages.update({'email_sent':'Email sent', 'test': "ä"})
|
messages.update({'email_sent':'Email sent', 'test': "ä"})
|
||||||
self.assertEqual(to_unicode(messages.email_sent, 'utf-8'), 'Email sent')
|
self.assertEqual(to_unicode(messages.email_sent, 'utf-8'), 'Email sent')
|
||||||
@@ -359,7 +359,7 @@ class TestHTMLTag(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_decode(self):
|
def test_decode(self):
|
||||||
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
T = languages.translator(self.langpath, self.http_accept_language)
|
||||||
elem = SPAN(T("Complete"))
|
elem = SPAN(T("Complete"))
|
||||||
self.assertEqual(elem.flatten(), "Complete")
|
self.assertEqual(elem.flatten(), "Complete")
|
||||||
elem = SPAN(T("Cannot be empty", language="ru"))
|
elem = SPAN(T("Cannot be empty", language="ru"))
|
||||||
|
|||||||
@@ -71,3 +71,4 @@ class TestRecfile(unittest.TestCase):
|
|||||||
self.assertFalse(recfile.exists(filename))
|
self.assertFalse(recfile.exists(filename))
|
||||||
self.assertRaises(IOError, recfile.remove, filename)
|
self.assertRaises(IOError, recfile.remove, filename)
|
||||||
self.assertRaises(IOError, recfile.open, filename, "r")
|
self.assertRaises(IOError, recfile.open, filename, "r")
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# TODO : I think we should continue to use pathoc (http://pathod.net/docs/pathoc) for tests but integrate the call in
|
# TODO : I think we should continue to use pathoc (http://pathod.net/docs/pathoc) for tests but integrate the call in
|
||||||
# gluon/tests so they run automatically. No need to make our own tests.
|
# gluon/tests so they run automatically. No need to make our own tests.
|
||||||
# ref: https://groups.google.com/d/msg/web2py-developers/Cjye8_hXZk8/AXbftS3sCgAJ
|
# ref: https://groups.google.com/d/msg/web2py-developers/Cjye8_hXZk8/AXbftS3sCgAJ
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""Unit tests for rewrite.py routers option"""
|
"""Unit tests for rewrite.py routers option"""
|
||||||
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -1555,3 +1555,4 @@ class TestRouter(unittest.TestCase):
|
|||||||
load(rdict=router_collide)
|
load(rdict=router_collide)
|
||||||
self.assertEqual(filter_url('http://welcome.com/welcome/admin/index',
|
self.assertEqual(filter_url('http://welcome.com/welcome/admin/index',
|
||||||
domain='welcome', out=True), "/welcome/admin")
|
domain='welcome', out=True), "/welcome/admin")
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import datetime
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.scheduler import JobGraph, Scheduler, CronParser
|
from gluon.scheduler import JobGraph, Scheduler, CronParser
|
||||||
from gluon.dal import DAL
|
from gluon.dal import DAL
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class BaseTestScheduler(unittest.TestCase):
|
|||||||
'folder': 'applications/welcome',
|
'folder': 'applications/welcome',
|
||||||
'controller': 'default'})
|
'controller': 'default'})
|
||||||
current.request = s
|
current.request = s
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
current.T = T
|
current.T = T
|
||||||
self.db = DAL('sqlite://dummy2.db', check_reserved=['all'])
|
self.db = DAL('sqlite://dummy2.db', check_reserved=['all'])
|
||||||
|
|
||||||
@@ -551,12 +551,12 @@ class TestsForSchedulerAPIs(BaseTestScheduler):
|
|||||||
def isnotqueued(result):
|
def isnotqueued(result):
|
||||||
self.assertEqual(result.id, None)
|
self.assertEqual(result.id, None)
|
||||||
self.assertEqual(result.uuid, None)
|
self.assertEqual(result.uuid, None)
|
||||||
self.assertEqual(len(list(result.errors.keys())) > 0, True)
|
self.assertEqual(len(result.errors.keys()) > 0, True)
|
||||||
|
|
||||||
def isqueued(result):
|
def isqueued(result):
|
||||||
self.assertNotEqual(result.id, None)
|
self.assertNotEqual(result.id, None)
|
||||||
self.assertNotEqual(result.uuid, None)
|
self.assertNotEqual(result.uuid, None)
|
||||||
self.assertEqual(len(list(result.errors.keys())), 0)
|
self.assertEqual(len(result.errors.keys()), 0)
|
||||||
|
|
||||||
s = Scheduler(self.db)
|
s = Scheduler(self.db)
|
||||||
fname = 'foo'
|
fname = 'foo'
|
||||||
@@ -629,6 +629,7 @@ sched_dal = DAL('sqlite://%s' % db_dal, folder=os.path.dirname(db_dal))
|
|||||||
sched = Scheduler(sched_dal, max_empty_runs=15, migrate=False, heartbeat=1)
|
sched = Scheduler(sched_dal, max_empty_runs=15, migrate=False, heartbeat=1)
|
||||||
def termination():
|
def termination():
|
||||||
sched.terminate()
|
sched.terminate()
|
||||||
|
sched_dal.commit()
|
||||||
"""
|
"""
|
||||||
with open(fdest, 'w') as q:
|
with open(fdest, 'w') as q:
|
||||||
q.write(initlines)
|
q.write(initlines)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import decimal
|
|||||||
from gluon.serializers import *
|
from gluon.serializers import *
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
# careful with the import path 'cause of isinstance() checks
|
# careful with the import path 'cause of isinstance() checks
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.html import SPAN
|
from gluon.html import SPAN
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ class TestSerializers(unittest.TestCase):
|
|||||||
obj = {'a': decimal.Decimal('4.312312312312')}
|
obj = {'a': decimal.Decimal('4.312312312312')}
|
||||||
self.assertEqual(json(obj), u'{"a": "4.312312312312"}')
|
self.assertEqual(json(obj), u'{"a": "4.312312312312"}')
|
||||||
# lazyT translated
|
# lazyT translated
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
lazy_translation = T('abc')
|
lazy_translation = T('abc')
|
||||||
self.assertEqual(json(lazy_translation), u'"abc"')
|
self.assertEqual(json(lazy_translation), u'"abc"')
|
||||||
# html helpers are xml()ed before too
|
# html helpers are xml()ed before too
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from pydal.objects import Table
|
|||||||
from gluon.tools import Auth, Mail
|
from gluon.tools import Auth, Mail
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.http import HTTP
|
from gluon.http import HTTP
|
||||||
from gluon.validators import *
|
from gluon.validators import *
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ class TestSQLFORM(unittest.TestCase):
|
|||||||
request.folder = 'applications/admin'
|
request.folder = 'applications/admin'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
current.request = request
|
current.request = request
|
||||||
@@ -277,7 +277,7 @@ class TestSQLFORM(unittest.TestCase):
|
|||||||
|
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
|
|
||||||
def test_SQLFORM(self):
|
def test_SQLFORM(self):
|
||||||
form = SQLFORM(self.db.auth_user)
|
form = SQLFORM(self.db.auth_user)
|
||||||
self.assertEqual(form.xml()[:5], b'<form')
|
self.assertEqual(form.xml()[:5], b'<form')
|
||||||
@@ -337,7 +337,7 @@ class TestSQLFORM(unittest.TestCase):
|
|||||||
|
|
||||||
# def test_search_menu(self):
|
# def test_search_menu(self):
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
def test_grid(self):
|
def test_grid(self):
|
||||||
grid_form = SQLFORM.grid(self.db.auth_user)
|
grid_form = SQLFORM.grid(self.db.auth_user)
|
||||||
self.assertEqual(grid_form.xml()[:4], b'<div')
|
self.assertEqual(grid_form.xml()[:4], b'<div')
|
||||||
@@ -355,7 +355,7 @@ class TestSQLTABLE(unittest.TestCase):
|
|||||||
request.folder = 'applications/admin'
|
request.folder = 'applications/admin'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
current.request = request
|
current.request = request
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Unit tests for gluon.template
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from gluon import template
|
||||||
|
from gluon.template import render
|
||||||
|
|
||||||
|
|
||||||
|
class TestTemplate(unittest.TestCase):
|
||||||
|
|
||||||
|
def testRun(self):
|
||||||
|
self.assertEqual(render(content='{{for i in range(n):}}{{=i}}{{pass}}',
|
||||||
|
context=dict(n=3)), '012')
|
||||||
|
self.assertEqual(render(content='{{if n>2:}}ok{{pass}}',
|
||||||
|
context=dict(n=3)), 'ok')
|
||||||
|
self.assertEqual(
|
||||||
|
render(content='{{try:}}{{n/0}}{{except:}}fail{{pass}}',
|
||||||
|
context=dict(n=3)), 'fail')
|
||||||
|
self.assertEqual(render(content='{{="<&>"}}'), '<&>')
|
||||||
|
self.assertEqual(render(content='"abc"'), '"abc"')
|
||||||
|
self.assertEqual(render(content='"a\'bc"'), '"a\'bc"')
|
||||||
|
self.assertEqual(render(content='"a\"bc"'), '"a\"bc"')
|
||||||
|
self.assertEqual(render(content=r'"a\"bc"'), r'"a\"bc"')
|
||||||
|
self.assertEqual(render(content=r'"""abc\""""'), r'"""abc\""""')
|
||||||
|
|
||||||
|
def testEqualWrite(self):
|
||||||
|
"test generation of response.write"
|
||||||
|
self.assertEqual(render(content='{{=2+2}}'), '4')
|
||||||
|
self.assertEqual(render(content='{{="abc"}}'), 'abc')
|
||||||
|
# whitespace is stripped
|
||||||
|
self.assertEqual(render(content='{{ ="abc"}}'), 'abc')
|
||||||
|
self.assertEqual(render(content='{{ ="abc" }}'), 'abc')
|
||||||
|
self.assertEqual(render(content='{{pass\n="abc" }}'), 'abc')
|
||||||
|
# = recognized only at the beginning of a physical line
|
||||||
|
self.assertEqual(render(
|
||||||
|
content='{{xyz = "xyz"\n="abc"\n="def"\n=xyz }}'), 'abcdefxyz')
|
||||||
|
# = in python blocks
|
||||||
|
self.assertEqual(render(content='{{if True:\n="abc"\npass }}'), 'abc')
|
||||||
|
self.assertEqual(
|
||||||
|
render(content='{{if True:\n="abc"\npass\n="def" }}'), 'abcdef')
|
||||||
|
self.assertEqual(
|
||||||
|
render(content='{{if False:\n="abc"\npass\n="def" }}'), 'def')
|
||||||
|
self.assertEqual(render(
|
||||||
|
content='{{if True:\n="abc"\nelse:\n="def"\npass }}'), 'abc')
|
||||||
|
self.assertEqual(render(
|
||||||
|
content='{{if False:\n="abc"\nelse:\n="def"\npass }}'), 'def')
|
||||||
|
# codeblock-leading = handles internal newlines, escaped or not
|
||||||
|
self.assertEqual(render(content='{{=list((1,2,3))}}'), '[1, 2, 3]')
|
||||||
|
self.assertEqual(render(content='{{=list((1,2,\\\n3))}}'), '[1, 2, 3]')
|
||||||
|
self.assertEqual(render(content='{{=list((1,2,\n3))}}'), '[1, 2, 3]')
|
||||||
|
# ...but that means no more = operators in the codeblock
|
||||||
|
self.assertRaises(SyntaxError, render, content='{{="abc"\n="def" }}')
|
||||||
|
# = embedded in codeblock won't handle newlines in its argument
|
||||||
|
self.assertEqual(
|
||||||
|
render(content='{{pass\n=list((1,2,\\\n3))}}'), '[1, 2, 3]')
|
||||||
|
self.assertRaises(
|
||||||
|
SyntaxError, render, content='{{pass\n=list((1,2,\n3))}}')
|
||||||
|
|
||||||
|
def testWithDummyFileSystem(self):
|
||||||
|
from os.path import join as pjoin
|
||||||
|
import contextlib
|
||||||
|
from gluon._compat import StringIO
|
||||||
|
from gluon.restricted import RestrictedError
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def monkey_patch(module, fn_name, patch):
|
||||||
|
try:
|
||||||
|
unpatch = getattr(module, fn_name)
|
||||||
|
except AttributeError:
|
||||||
|
unpatch = None
|
||||||
|
setattr(module, fn_name, patch)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
if unpatch is None:
|
||||||
|
delattr(module, fn_name)
|
||||||
|
else:
|
||||||
|
setattr(module, fn_name, unpatch)
|
||||||
|
|
||||||
|
def dummy_open(path):
|
||||||
|
if path == pjoin('views', 'layout.html'):
|
||||||
|
return ("{{block left_sidebar}}left{{end}}"
|
||||||
|
"{{include}}"
|
||||||
|
"{{block right_sidebar}}right{{end}}")
|
||||||
|
elif path == pjoin('views', 'layoutbrackets.html'):
|
||||||
|
return ("[[block left_sidebar]]left[[end]]"
|
||||||
|
"[[include]]"
|
||||||
|
"[[block right_sidebar]]right[[end]]")
|
||||||
|
elif path == pjoin('views', 'default', 'index.html'):
|
||||||
|
return ("{{extend 'layout.html'}}"
|
||||||
|
"{{block left_sidebar}}{{super}} {{end}}"
|
||||||
|
"to"
|
||||||
|
"{{block right_sidebar}} {{super}}{{end}}")
|
||||||
|
elif path == pjoin('views', 'default', 'indexbrackets.html'):
|
||||||
|
return ("[[extend 'layoutbrackets.html']]"
|
||||||
|
"[[block left_sidebar]][[super]] [[end]]"
|
||||||
|
"to"
|
||||||
|
"[[block right_sidebar]] [[super]][[end]]")
|
||||||
|
elif path == pjoin('views', 'default', 'missing.html'):
|
||||||
|
return ("{{extend 'wut'}}"
|
||||||
|
"{{block left_sidebar}}{{super}} {{end}}"
|
||||||
|
"to"
|
||||||
|
"{{block right_sidebar}} {{super}}{{end}}")
|
||||||
|
elif path == pjoin('views', 'default', 'noescape.html'):
|
||||||
|
return "{{=NOESCAPE('<script></script>')}}"
|
||||||
|
raise IOError
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
render(filename=pjoin('views', 'default', 'index.html'),
|
||||||
|
path='views', reader=dummy_open),
|
||||||
|
'left to right')
|
||||||
|
self.assertEqual(
|
||||||
|
render(filename=pjoin('views', 'default', 'indexbrackets.html'),
|
||||||
|
path='views', delimiters='[[ ]]', reader=dummy_open),
|
||||||
|
'left to right')
|
||||||
|
self.assertRaises(
|
||||||
|
RestrictedError,
|
||||||
|
render,
|
||||||
|
filename=pjoin('views', 'default', 'missing.html'),
|
||||||
|
path='views',
|
||||||
|
reader=dummy_open)
|
||||||
|
response = template.DummyResponse()
|
||||||
|
response.delimiters = ('[[', ']]')
|
||||||
|
self.assertEqual(
|
||||||
|
render(filename=pjoin('views', 'default', 'indexbrackets.html'),
|
||||||
|
path='views', context={'response': response}, reader=dummy_open),
|
||||||
|
'left to right')
|
||||||
|
self.assertEqual(
|
||||||
|
render(filename=pjoin('views', 'default', 'noescape.html'),
|
||||||
|
context={'NOESCAPE': template.NOESCAPE}, reader=dummy_open),
|
||||||
|
'<script></script>')
|
||||||
@@ -18,10 +18,10 @@ from gluon.dal import DAL, Field
|
|||||||
from pydal.objects import Table
|
from pydal.objects import Table
|
||||||
from gluon import tools
|
from gluon import tools
|
||||||
from gluon.tools import Auth, Mail, Recaptcha2, prettydate, Expose
|
from gluon.tools import Auth, Mail, Recaptcha2, prettydate, Expose
|
||||||
from gluon._compat import PY2, to_bytes
|
from gluon._compat import PY2
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import TranslatorFactory
|
from gluon.languages import translator
|
||||||
from gluon.http import HTTP
|
from gluon.http import HTTP
|
||||||
from gluon import SPAN, H3, TABLE, TR, TD, A, URL, current
|
from gluon import SPAN, H3, TABLE, TR, TD, A, URL, current
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ class TestMail(unittest.TestCase):
|
|||||||
message = TestMail.DummySMTP.inbox.pop()
|
message = TestMail.DummySMTP.inbox.pop()
|
||||||
attachment = message.parsed_payload.get_payload(1).get_payload(decode=True)
|
attachment = message.parsed_payload.get_payload(1).get_payload(decode=True)
|
||||||
with open(module_file, 'rb') as mf:
|
with open(module_file, 'rb') as mf:
|
||||||
self.assertEqual(to_bytes(attachment), to_bytes(mf.read()))
|
self.assertEqual(attachment, mf.read())
|
||||||
# Test missing attachment name error
|
# Test missing attachment name error
|
||||||
stream = open(module_file)
|
stream = open(module_file)
|
||||||
self.assertRaises(Exception, lambda *args, **kwargs: Mail.Attachment(*args, **kwargs), stream)
|
self.assertRaises(Exception, lambda *args, **kwargs: Mail.Attachment(*args, **kwargs), stream)
|
||||||
@@ -208,6 +208,13 @@ class TestMail(unittest.TestCase):
|
|||||||
self.assertTrue('Content-Id: <trololo>' in message.payload)
|
self.assertTrue('Content-Id: <trololo>' in message.payload)
|
||||||
|
|
||||||
|
|
||||||
|
# class TestRecaptcha2(unittest.TestCase):
|
||||||
|
# def test_Recaptcha2(self):
|
||||||
|
# from html import FORM
|
||||||
|
# form = FORM(Recaptcha2(public_key='public_key', private_key='private_key'))
|
||||||
|
# rtn = '<form action="#" enctype="multipart/form-data" method="post"><div><script async="" defer="" src="https://www.google.com/recaptcha/api.js"></script><div class="g-recaptcha" data-sitekey="public_key"></div><noscript>\n<div style="width: 302px; height: 352px;">\n<div style="width: 302px; height: 352px; position: relative;">\n <div style="width: 302px; height: 352px; position: absolute;">\n <iframe src="https://www.google.com/recaptcha/api/fallback?k=public_key"\n frameborder="0" scrolling="no"\n style="width: 302px; height:352px; border-style: none;">\n </iframe>\n </div>\n <div style="width: 250px; height: 80px; position: absolute; border-style: none;\n bottom: 21px; left: 25px; margin: 0px; padding: 0px; right: 25px;">\n <textarea id="g-recaptcha-response" name="g-recaptcha-response"\n class="g-recaptcha-response"\n style="width: 250px; height: 80px; border: 1px solid #c1c1c1;\n margin: 0px; padding: 0px; resize: none;" value="">\n </textarea>\n </div>\n</div>\n</div></noscript></div></form>'
|
||||||
|
# self.assertEqual(form.xml(), rtn)
|
||||||
|
|
||||||
# TODO: class TestAuthJWT(unittest.TestCase):
|
# TODO: class TestAuthJWT(unittest.TestCase):
|
||||||
class TestAuthJWT(unittest.TestCase):
|
class TestAuthJWT(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -271,7 +278,7 @@ class TestAuthJWT(unittest.TestCase):
|
|||||||
# request.folder = 'applications/admin'
|
# request.folder = 'applications/admin'
|
||||||
# response = Response()
|
# response = Response()
|
||||||
# session = Session()
|
# session = Session()
|
||||||
# T = TranslatorFactory('', 'en')
|
# T = translator('', 'en')
|
||||||
# session.connect(request, response)
|
# session.connect(request, response)
|
||||||
# from gluon.globals import current
|
# from gluon.globals import current
|
||||||
# current.request = request
|
# current.request = request
|
||||||
@@ -434,7 +441,7 @@ class TestAuthJWT(unittest.TestCase):
|
|||||||
# # request.folder = 'applications/admin'
|
# # request.folder = 'applications/admin'
|
||||||
# # response = Response()
|
# # response = Response()
|
||||||
# # session = Session()
|
# # session = Session()
|
||||||
# # T = TranslatorFactory('', 'en')
|
# # T = translator('', 'en')
|
||||||
# # session.connect(request, response)
|
# # session.connect(request, response)
|
||||||
# # from gluon.globals import current
|
# # from gluon.globals import current
|
||||||
# # current.request = request
|
# # current.request = request
|
||||||
@@ -495,7 +502,7 @@ class TestAuth(unittest.TestCase):
|
|||||||
self.request.folder = 'applications/admin'
|
self.request.folder = 'applications/admin'
|
||||||
self.response = Response()
|
self.response = Response()
|
||||||
self.session = Session()
|
self.session = Session()
|
||||||
T = TranslatorFactory('', 'en')
|
T = translator('', 'en')
|
||||||
self.session.connect(self.request, self.response)
|
self.session.connect(self.request, self.response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
self.current = current
|
self.current = current
|
||||||
@@ -1380,3 +1387,4 @@ class TestExpose(unittest.TestCase):
|
|||||||
def test_not_authorized(self):
|
def test_not_authorized(self):
|
||||||
with self.assertRaises(HTTP):
|
with self.assertRaises(HTTP):
|
||||||
self.make_expose(base='inside', show='link_to_file3')
|
self.make_expose(base='inside', show='link_to_file3')
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ class TestValidators(unittest.TestCase):
|
|||||||
|
|
||||||
def test_MISC(self):
|
def test_MISC(self):
|
||||||
""" Test miscelaneous utility functions and some general behavior guarantees """
|
""" Test miscelaneous utility functions and some general behavior guarantees """
|
||||||
from gluon.validators import options_sorter, Validator, UTC
|
from gluon.validators import translate, options_sorter, Validator, UTC
|
||||||
|
self.assertEqual(translate(None), None)
|
||||||
self.assertEqual(options_sorter(('a', 'a'), ('a', 'a')), -1)
|
self.assertEqual(options_sorter(('a', 'a'), ('a', 'a')), -1)
|
||||||
self.assertEqual(options_sorter(('A', 'A'), ('a', 'a')), -1)
|
self.assertEqual(options_sorter(('A', 'A'), ('a', 'a')), -1)
|
||||||
self.assertEqual(options_sorter(('b', 'b'), ('a', 'a')), 1)
|
self.assertEqual(options_sorter(('b', 'b'), ('a', 'a')), 1)
|
||||||
@@ -942,14 +943,6 @@ class TestValidators(unittest.TestCase):
|
|||||||
'May not include any lowercase letters',
|
'May not include any lowercase letters',
|
||||||
'May not include any numbers']))
|
'May not include any numbers']))
|
||||||
)
|
)
|
||||||
rtn = IS_STRONG(special=0, es=True)('Abcde1!')
|
|
||||||
self.assertEqual(rtn,
|
|
||||||
('Abcde1!',
|
|
||||||
'|'.join(['Minimum length is 8',
|
|
||||||
'May not contain any of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|']))
|
|
||||||
)
|
|
||||||
rtn = IS_STRONG(upper=False, number=False, special=False, es=True)('Abcde1!')
|
|
||||||
self.assertEqual(rtn, ('Abcde1!', 'Minimum length is 8'))
|
|
||||||
|
|
||||||
def test_IS_IMAGE(self):
|
def test_IS_IMAGE(self):
|
||||||
class DummyImageFile(object):
|
class DummyImageFile(object):
|
||||||
@@ -1021,65 +1014,6 @@ class TestValidators(unittest.TestCase):
|
|||||||
rtn = IS_IMAGE(error_message='oops')(img)
|
rtn = IS_IMAGE(error_message='oops')(img)
|
||||||
self.assertEqual(rtn, (img, 'oops'))
|
self.assertEqual(rtn, (img, 'oops'))
|
||||||
|
|
||||||
def test_IS_FILE(self):
|
|
||||||
import cgi
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
def gen_fake(filename):
|
|
||||||
formdata_file_data = """
|
|
||||||
---123
|
|
||||||
Content-Disposition: form-data; name="key2"
|
|
||||||
|
|
||||||
value2y
|
|
||||||
---123
|
|
||||||
Content-Disposition: form-data; name="file_attach"; filename="%s"
|
|
||||||
Content-Type: text/plain
|
|
||||||
|
|
||||||
this is the content of the fake file
|
|
||||||
|
|
||||||
---123--
|
|
||||||
""" % filename
|
|
||||||
formdata_file_environ = {
|
|
||||||
'CONTENT_LENGTH': str(len(formdata_file_data)),
|
|
||||||
'CONTENT_TYPE': 'multipart/form-data; boundary=-123',
|
|
||||||
'QUERY_STRING': 'key1=value1&key2=value2x',
|
|
||||||
'REQUEST_METHOD': 'POST',
|
|
||||||
}
|
|
||||||
return cgi.FieldStorage(fp=BytesIO(to_bytes(formdata_file_data)), environ=formdata_file_environ)['file_attach']
|
|
||||||
|
|
||||||
fake = gen_fake('example.pdf')
|
|
||||||
rtn = IS_FILE(extension='pdf')(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('example.gif')
|
|
||||||
rtn = IS_FILE(extension='pdf')(fake)
|
|
||||||
self.assertEqual(rtn, (fake, 'Enter valid filename'))
|
|
||||||
fake = gen_fake('multiple.pdf')
|
|
||||||
rtn = IS_FILE(extension=['pdf', 'png'])(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('multiple.png')
|
|
||||||
rtn = IS_FILE(extension=['pdf', 'png'])(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('multiple.gif')
|
|
||||||
rtn = IS_FILE(extension=['pdf', 'png'])(fake)
|
|
||||||
self.assertEqual(rtn, (fake, 'Enter valid filename'))
|
|
||||||
fake = gen_fake('backup2014.tar.gz')
|
|
||||||
rtn = IS_FILE(filename=re.compile('backup.*'), extension='tar.gz', lastdot=False)(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('README')
|
|
||||||
rtn = IS_FILE(filename='README', extension='', case=0)(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('readme')
|
|
||||||
rtn = IS_FILE(filename='README', extension='', case=0)(fake)
|
|
||||||
self.assertEqual(rtn, (fake, 'Enter valid filename'))
|
|
||||||
fake = gen_fake('readme')
|
|
||||||
rtn = IS_FILE(filename='README', case=2)(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
fake = gen_fake('README')
|
|
||||||
rtn = IS_FILE(filename='README', case=2)(fake)
|
|
||||||
self.assertEqual(rtn, (fake, None))
|
|
||||||
rtn = IS_FILE(extension='pdf')('example.pdf')
|
|
||||||
self.assertEqual(rtn, ('example.pdf', 'Enter valid filename'))
|
|
||||||
|
|
||||||
def test_IS_UPLOAD_FILENAME(self):
|
def test_IS_UPLOAD_FILENAME(self):
|
||||||
import cgi
|
import cgi
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for running web2py
|
Unit tests for running web2py
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|||||||
+32
-32
@@ -15,9 +15,8 @@ from functools import reduce
|
|||||||
from gluon._compat import pickle, thread, urllib2, Cookie, StringIO, urlencode
|
from gluon._compat import pickle, thread, urllib2, Cookie, StringIO, urlencode
|
||||||
from gluon._compat import configparser, MIMEBase, MIMEMultipart, MIMEText, Header
|
from gluon._compat import configparser, MIMEBase, MIMEMultipart, MIMEText, Header
|
||||||
from gluon._compat import Encoders, Charset, long, urllib_quote, iteritems
|
from gluon._compat import Encoders, Charset, long, urllib_quote, iteritems
|
||||||
from gluon._compat import to_bytes, to_native, add_charset, string_types
|
from gluon._compat import to_bytes, to_native, add_charset
|
||||||
from gluon._compat import charset_QP, basestring, unicodeT, to_unicode
|
from gluon._compat import charset_QP, basestring, unicodeT, to_unicode
|
||||||
from gluon._compat import urllib2, urlopen
|
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
@@ -903,13 +902,13 @@ class Recaptcha2(DIV):
|
|||||||
'secret': self.private_key,
|
'secret': self.private_key,
|
||||||
'remoteip': remoteip,
|
'remoteip': remoteip,
|
||||||
'response': recaptcha_response_field,
|
'response': recaptcha_response_field,
|
||||||
}).encode('utf-8')
|
})
|
||||||
request = urllib2.Request(
|
request = urllib2.Request(
|
||||||
url=self.VERIFY_SERVER,
|
url=self.VERIFY_SERVER,
|
||||||
data=to_bytes(params),
|
data=to_bytes(params),
|
||||||
headers={'Content-type': 'application/x-www-form-urlencoded',
|
headers={'Content-type': 'application/x-www-form-urlencoded',
|
||||||
'User-agent': 'reCAPTCHA Python'})
|
'User-agent': 'reCAPTCHA Python'})
|
||||||
httpresp = urlopen(request)
|
httpresp = urllib2.urlopen(request)
|
||||||
content = httpresp.read()
|
content = httpresp.read()
|
||||||
httpresp.close()
|
httpresp.close()
|
||||||
try:
|
try:
|
||||||
@@ -1038,7 +1037,7 @@ class AuthJWT(object):
|
|||||||
Example:
|
Example:
|
||||||
def mybefore_authorization(tokend):
|
def mybefore_authorization(tokend):
|
||||||
if not tokend['my_name_is'] == 'bond,james bond':
|
if not tokend['my_name_is'] == 'bond,james bond':
|
||||||
raise HTTP(400, 'Invalid JWT my_name_is claim')
|
raise HTTP(400, u'Invalid JWT my_name_is claim')
|
||||||
- max_header_length: check max length to avoid load()ing unusually large tokens (could mean crafted, e.g. in a DDoS.)
|
- max_header_length: check max length to avoid load()ing unusually large tokens (could mean crafted, e.g. in a DDoS.)
|
||||||
|
|
||||||
Basic Usage:
|
Basic Usage:
|
||||||
@@ -1162,7 +1161,7 @@ class AuthJWT(object):
|
|||||||
b64h, b64b = body.split(b'.', 1)
|
b64h, b64b = body.split(b'.', 1)
|
||||||
if b64h != self.cached_b64h:
|
if b64h != self.cached_b64h:
|
||||||
# header not the same
|
# header not the same
|
||||||
raise HTTP(400, 'Invalid JWT Header')
|
raise HTTP(400, u'Invalid JWT Header')
|
||||||
secret = self.secret_key
|
secret = self.secret_key
|
||||||
tokend = serializers.loads_json(to_native(self.jwt_b64d(b64b)))
|
tokend = serializers.loads_json(to_native(self.jwt_b64d(b64b)))
|
||||||
if self.salt:
|
if self.salt:
|
||||||
@@ -1173,11 +1172,11 @@ class AuthJWT(object):
|
|||||||
secret = to_bytes(secret, 'ascii', 'ignore')
|
secret = to_bytes(secret, 'ascii', 'ignore')
|
||||||
if not self.verify_signature(body, sig, secret):
|
if not self.verify_signature(body, sig, secret):
|
||||||
# signature verification failed
|
# signature verification failed
|
||||||
raise HTTP(400, 'Token signature is invalid')
|
raise HTTP(400, u'Token signature is invalid')
|
||||||
if self.verify_expiration:
|
if self.verify_expiration:
|
||||||
now = time.mktime(datetime.datetime.utcnow().timetuple())
|
now = time.mktime(datetime.datetime.utcnow().timetuple())
|
||||||
if tokend['exp'] + self.leeway < now:
|
if tokend['exp'] + self.leeway < now:
|
||||||
raise HTTP(400, 'Token is expired')
|
raise HTTP(400, u'Token is expired')
|
||||||
if callable(self.before_authorization):
|
if callable(self.before_authorization):
|
||||||
self.before_authorization(tokend)
|
self.before_authorization(tokend)
|
||||||
return tokend
|
return tokend
|
||||||
@@ -1210,11 +1209,11 @@ class AuthJWT(object):
|
|||||||
orig_exp = orig_payload['exp']
|
orig_exp = orig_payload['exp']
|
||||||
if orig_exp + self.leeway < now:
|
if orig_exp + self.leeway < now:
|
||||||
# token already expired, can't be used for refresh
|
# token already expired, can't be used for refresh
|
||||||
raise HTTP(400, 'Token already expired')
|
raise HTTP(400, u'Token already expired')
|
||||||
orig_iat = orig_payload.get('orig_iat') or orig_payload['iat']
|
orig_iat = orig_payload.get('orig_iat') or orig_payload['iat']
|
||||||
if orig_iat + self.refresh_expiration_delta < now:
|
if orig_iat + self.refresh_expiration_delta < now:
|
||||||
# refreshed too long ago
|
# refreshed too long ago
|
||||||
raise HTTP(400, 'Token issued too long ago')
|
raise HTTP(400, u'Token issued too long ago')
|
||||||
expires = now + self.expiration
|
expires = now + self.expiration
|
||||||
orig_payload.update(
|
orig_payload.update(
|
||||||
orig_iat=orig_iat,
|
orig_iat=orig_iat,
|
||||||
@@ -1260,7 +1259,7 @@ class AuthJWT(object):
|
|||||||
pass
|
pass
|
||||||
if token:
|
if token:
|
||||||
if not self.allow_refresh:
|
if not self.allow_refresh:
|
||||||
raise HTTP(403, 'Refreshing token is not allowed')
|
raise HTTP(403, u'Refreshing token is not allowed')
|
||||||
tokend = self.load_token(token)
|
tokend = self.load_token(token)
|
||||||
# verification can fail here
|
# verification can fail here
|
||||||
refreshed = self.refresh_token(tokend)
|
refreshed = self.refresh_token(tokend)
|
||||||
@@ -1278,9 +1277,9 @@ class AuthJWT(object):
|
|||||||
ret = {'token': self.generate_token(payload)}
|
ret = {'token': self.generate_token(payload)}
|
||||||
elif ret is None:
|
elif ret is None:
|
||||||
raise HTTP(401,
|
raise HTTP(401,
|
||||||
'Not Authorized - need to be logged in, to pass a token '
|
u'Not Authorized - need to be logged in, to pass a token '
|
||||||
'for refresh or username and password for login',
|
u'for refresh or username and password for login',
|
||||||
**{'WWW-Authenticate': 'JWT realm="%s"' % self.realm})
|
**{'WWW-Authenticate': u'JWT realm="%s"' % self.realm})
|
||||||
response.headers['Content-Type'] = 'application/json'
|
response.headers['Content-Type'] = 'application/json'
|
||||||
return serializers.json(ret)
|
return serializers.json(ret)
|
||||||
|
|
||||||
@@ -1304,9 +1303,9 @@ class AuthJWT(object):
|
|||||||
if token_in_header:
|
if token_in_header:
|
||||||
parts = token_in_header.split()
|
parts = token_in_header.split()
|
||||||
if parts[0].lower() != self.header_prefix.lower():
|
if parts[0].lower() != self.header_prefix.lower():
|
||||||
raise HTTP(400, 'Invalid JWT header')
|
raise HTTP(400, u'Invalid JWT header')
|
||||||
elif len(parts) == 1:
|
elif len(parts) == 1:
|
||||||
raise HTTP(400, 'Invalid JWT header, missing token')
|
raise HTTP(400, u'Invalid JWT header, missing token')
|
||||||
elif len(parts) > 2:
|
elif len(parts) > 2:
|
||||||
raise HTTP(400, 'Invalid JWT header, token contains spaces')
|
raise HTTP(400, 'Invalid JWT header, token contains spaces')
|
||||||
token = parts[1]
|
token = parts[1]
|
||||||
@@ -2244,11 +2243,11 @@ class Auth(AuthAPI):
|
|||||||
if basic_auth_realm:
|
if basic_auth_realm:
|
||||||
if callable(basic_auth_realm):
|
if callable(basic_auth_realm):
|
||||||
basic_auth_realm = basic_auth_realm()
|
basic_auth_realm = basic_auth_realm()
|
||||||
elif isinstance(basic_auth_realm, string_types):
|
elif isinstance(basic_auth_realm, (unicode, str)):
|
||||||
basic_realm = to_unicode(basic_auth_realm)
|
basic_realm = unicode(basic_auth_realm) # Warning python 3.5 does not have method unicod
|
||||||
elif basic_auth_realm is True:
|
elif basic_auth_realm is True:
|
||||||
basic_realm = '' + current.request.application
|
basic_realm = u'' + current.request.application
|
||||||
http_401 = HTTP(401, 'Not Authorized', **{'WWW-Authenticate': 'Basic realm="' + basic_realm + '"'})
|
http_401 = HTTP(401, u'Not Authorized', **{'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:
|
||||||
raise http_401
|
raise http_401
|
||||||
@@ -2261,9 +2260,9 @@ class Auth(AuthAPI):
|
|||||||
|
|
||||||
def _get_login_settings(self):
|
def _get_login_settings(self):
|
||||||
table_user = self.table_user()
|
table_user = self.table_user()
|
||||||
userfield = self.settings.login_userfield or ('username' \
|
userfield = self.settings.login_userfield or 'username' \
|
||||||
if self.settings.login_userfield or 'username' \
|
if self.settings.login_userfield or 'username' \
|
||||||
in table_user.fields else 'email')
|
in table_user.fields else 'email'
|
||||||
passfield = self.settings.password_field
|
passfield = self.settings.password_field
|
||||||
return Storage({'table_user': table_user,
|
return Storage({'table_user': table_user,
|
||||||
'userfield': userfield,
|
'userfield': userfield,
|
||||||
@@ -2638,9 +2637,9 @@ class Auth(AuthAPI):
|
|||||||
# invalid login
|
# invalid login
|
||||||
session.flash = specific_error if self.settings.login_specify_error else self.messages.invalid_login
|
session.flash = specific_error if self.settings.login_specify_error else self.messages.invalid_login
|
||||||
callback(onfail, None)
|
callback(onfail, None)
|
||||||
if 'password' in request.post_vars:
|
redirect(
|
||||||
del request.post_vars['password']
|
self.url(args=request.args, vars=request.get_vars),
|
||||||
redirect(self.url(args=request.args, vars=request.vars),client_side=settings.client_side)
|
client_side=settings.client_side)
|
||||||
|
|
||||||
else: # use a central authentication server
|
else: # use a central authentication server
|
||||||
cas = settings.login_form
|
cas = settings.login_form
|
||||||
@@ -3575,7 +3574,7 @@ class Auth(AuthAPI):
|
|||||||
requires = table_user[passfield].requires
|
requires = table_user[passfield].requires
|
||||||
if not isinstance(requires, (list, tuple)):
|
if not isinstance(requires, (list, tuple)):
|
||||||
requires = [requires]
|
requires = [requires]
|
||||||
requires = [t for t in requires if isinstance(t, CRYPT)]
|
requires = list(filter(lambda t: isinstance(t, CRYPT), requires))
|
||||||
if requires:
|
if requires:
|
||||||
requires[0] = CRYPT(**requires[0].__dict__) # Copy the existing CRYPT attributes
|
requires[0] = CRYPT(**requires[0].__dict__) # Copy the existing CRYPT attributes
|
||||||
requires[0].min_length = 0 # But do not enforce minimum length for the old password
|
requires[0].min_length = 0 # But do not enforce minimum length for the old password
|
||||||
@@ -4615,6 +4614,7 @@ class Crud(object): # pragma: no cover
|
|||||||
results = None
|
results = None
|
||||||
return form, results
|
return form, results
|
||||||
|
|
||||||
|
|
||||||
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor()))
|
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor()))
|
||||||
|
|
||||||
|
|
||||||
@@ -4632,7 +4632,7 @@ def fetch(url, data=None, headers=None,
|
|||||||
from google.appengine.api import urlfetch
|
from google.appengine.api import urlfetch
|
||||||
except ImportError:
|
except ImportError:
|
||||||
req = urllib2.Request(url, data, headers)
|
req = urllib2.Request(url, data, headers)
|
||||||
html = urlopen(req).read()
|
html = urllib2.urlopen(req).read()
|
||||||
else:
|
else:
|
||||||
method = ((data is None) and urlfetch.GET) or urlfetch.POST
|
method = ((data is None) and urlfetch.GET) or urlfetch.POST
|
||||||
while url is not None:
|
while url is not None:
|
||||||
@@ -5000,7 +5000,7 @@ class Service(object):
|
|||||||
elif r and not isinstance(r, types.GeneratorType) and isinstance(r[0], (dict, Storage)):
|
elif r and not isinstance(r, types.GeneratorType) and isinstance(r[0], (dict, Storage)):
|
||||||
import csv
|
import csv
|
||||||
writer = csv.writer(s)
|
writer = csv.writer(s)
|
||||||
writer.writerow(list(r[0].keys()))
|
writer.writerow(r[0].keys())
|
||||||
for line in r:
|
for line in r:
|
||||||
writer.writerow([none_exception(v)
|
writer.writerow([none_exception(v)
|
||||||
for v in line.values()])
|
for v in line.values()])
|
||||||
@@ -5217,7 +5217,7 @@ class Service(object):
|
|||||||
def serve_xmlrpc(self):
|
def serve_xmlrpc(self):
|
||||||
request = current.request
|
request = current.request
|
||||||
response = current.response
|
response = current.response
|
||||||
services = list(self.xmlrpc_procedures.values())
|
services = self.xmlrpc_procedures.values()
|
||||||
return response.xmlrpc(request, services)
|
return response.xmlrpc(request, services)
|
||||||
|
|
||||||
def serve_amfrpc(self, version=0):
|
def serve_amfrpc(self, version=0):
|
||||||
@@ -5572,7 +5572,7 @@ class PluginManager(object):
|
|||||||
return self.__dict__[key]
|
return self.__dict__[key]
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self.__dict__.keys())
|
return self.__dict__.keys()
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return key in self.__dict__
|
return key in self.__dict__
|
||||||
@@ -5818,7 +5818,7 @@ class Wiki(object):
|
|||||||
settings.templates = templates
|
settings.templates = templates
|
||||||
settings.controller = controller
|
settings.controller = controller
|
||||||
settings.function = function
|
settings.function = function
|
||||||
settings.groups = list(auth.user_groups.values()) \
|
settings.groups = auth.user_groups.values() \
|
||||||
if groups is None else groups
|
if groups is None else groups
|
||||||
|
|
||||||
db = auth.db
|
db = auth.db
|
||||||
@@ -5914,7 +5914,7 @@ class Wiki(object):
|
|||||||
if (auth.user and
|
if (auth.user and
|
||||||
check_credentials(current.request, gae_login=False) and
|
check_credentials(current.request, gae_login=False) and
|
||||||
'wiki_editor' not in auth.user_groups.values() and
|
'wiki_editor' not in auth.user_groups.values() and
|
||||||
self.settings.groups == list(auth.user_groups.values())):
|
self.settings.groups == 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')
|
||||||
|
|||||||
@@ -439,6 +439,31 @@ def getipaddrinfo(host):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def local_html_escape(data, quote=False):
|
||||||
|
"""
|
||||||
|
Works with bytes.
|
||||||
|
Replace special characters "&", "<" and ">" to HTML-safe sequences.
|
||||||
|
If the optional flag quote is true (the default), the quotation mark
|
||||||
|
characters, both double quote (") and single quote (') characters are also
|
||||||
|
translated.
|
||||||
|
"""
|
||||||
|
if PY2:
|
||||||
|
import cgi
|
||||||
|
data = cgi.escape(data, quote)
|
||||||
|
return data.replace("'", "'") if quote else data
|
||||||
|
else:
|
||||||
|
import html
|
||||||
|
if isinstance(data, str):
|
||||||
|
return html.escape(data, quote=quote)
|
||||||
|
data = data.replace(b"&", b"&") # Must be done first!
|
||||||
|
data = data.replace(b"<", b"<")
|
||||||
|
data = data.replace(b">", b">")
|
||||||
|
if quote:
|
||||||
|
data = data.replace(b'"', b""")
|
||||||
|
data = data.replace(b'\'', b"'")
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def unlocalised_http_header_date(data):
|
def unlocalised_http_header_date(data):
|
||||||
"""
|
"""
|
||||||
Converts input datetime to format defined by RFC 7231, section 7.1.1.1
|
Converts input datetime to format defined by RFC 7231, section 7.1.1.1
|
||||||
|
|||||||
+3
-3985
File diff suppressed because it is too large
Load Diff
+2
-4
@@ -9,6 +9,7 @@
|
|||||||
The widget is called from web2py
|
The widget is called from web2py
|
||||||
----------------------------------
|
----------------------------------
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
@@ -30,9 +31,6 @@ from gluon.settings import global_settings
|
|||||||
from gluon.shell import run, test
|
from gluon.shell import run, test
|
||||||
from gluon.utils import is_valid_ip_address, is_loopback_ip_address, getipaddrinfo
|
from gluon.utils import is_valid_ip_address, is_loopback_ip_address, getipaddrinfo
|
||||||
|
|
||||||
if PY2:
|
|
||||||
input = raw_input
|
|
||||||
|
|
||||||
|
|
||||||
ProgramName = 'web2py Web Framework'
|
ProgramName = 'web2py Web Framework'
|
||||||
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-' + str(
|
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-' + str(
|
||||||
@@ -954,7 +952,7 @@ def console():
|
|||||||
|
|
||||||
if options.gae:
|
if options.gae:
|
||||||
if not os.path.exists('app.yaml'):
|
if not os.path.exists('app.yaml'):
|
||||||
name = input("Your GAE app name: ")
|
name = raw_input("Your GAE app name: ")
|
||||||
content = open(os.path.join('examples', 'app.example.yaml'), 'rb').read()
|
content = open(os.path.join('examples', 'app.example.yaml'), 'rb').read()
|
||||||
open('app.yaml', 'wb').write(content.replace("yourappname", name))
|
open('app.yaml', 'wb').write(content.replace("yourappname", name))
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
echo "This script will:
|
echo "This script will:
|
||||||
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
||||||
2) Install Python 3.7 to /opt and recompile wsgi if not provided
|
2) Install Python 2.6 to /opt and recompile wsgi if not provided
|
||||||
2) Install web2py in /opt/web-apps/
|
2) Install web2py in /opt/web-apps/
|
||||||
3) Configure SELinux and iptables
|
3) Configure SELinux and iptables
|
||||||
5) Create a self signed ssl certificate
|
5) Create a self signed ssl certificate
|
||||||
@@ -56,7 +56,7 @@ echo
|
|||||||
yum update
|
yum update
|
||||||
|
|
||||||
# Install required packages
|
# Install required packages
|
||||||
yum install httpd mod_ssl mod_wsgi wget python3 unzip
|
yum install httpd mod_ssl mod_wsgi wget python unzip
|
||||||
|
|
||||||
###
|
###
|
||||||
### Phase 2 - Install web2py
|
### Phase 2 - Install web2py
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ apt-get -y install libapache2-mod-wsgi
|
|||||||
apt-get -y install python-psycopg2
|
apt-get -y install python-psycopg2
|
||||||
apt-get -y install postfix
|
apt-get -y install postfix
|
||||||
apt-get -y install wget
|
apt-get -y install wget
|
||||||
apt-get -y install python3-matplotlib
|
apt-get -y install python-matplotlib
|
||||||
apt-get -y install python3-reportlab
|
apt-get -y install python-reportlab
|
||||||
apt-get -y install mercurial
|
apt-get -y install mercurial
|
||||||
/etc/init.d/postgresql restart
|
/etc/init.d/postgresql restart
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
echo "This script will:
|
echo "This script will:
|
||||||
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
||||||
2) Install Python 3.7 to /opt and recompile wsgi if not provided
|
2) Install Python 2.6 to /opt and recompile wsgi if not provided
|
||||||
2) Install web2py in /opt/web-apps/
|
2) Install web2py in /opt/web-apps/
|
||||||
3) Configure SELinux and iptables
|
3) Configure SELinux and iptables
|
||||||
5) Create a self signed ssl certificate
|
5) Create a self signed ssl certificate
|
||||||
@@ -54,7 +54,7 @@ echo
|
|||||||
yum update
|
yum update
|
||||||
|
|
||||||
# Install required packages
|
# Install required packages
|
||||||
yum install httpd mod_ssl mod_wsgi wget python3
|
yum install httpd mod_ssl mod_wsgi wget python
|
||||||
|
|
||||||
# Verify we have at least Python 2.5
|
# Verify we have at least Python 2.5
|
||||||
typeset -i version_major
|
typeset -i version_major
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
echo "This script will:
|
echo "This script will:
|
||||||
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
1) Install modules needed to run web2py on Fedora and CentOS/RHEL
|
||||||
2) Install Python 3.7 to /opt and recompile wsgi if not provided
|
2) Install Python 2.6 to /opt and recompile wsgi if not provided
|
||||||
2) Install web2py in /opt/web-apps/
|
2) Install web2py in /opt/web-apps/
|
||||||
3) Configure SELinux and iptables
|
3) Configure SELinux and iptables
|
||||||
5) Create a self signed ssl certificate
|
5) Create a self signed ssl certificate
|
||||||
@@ -55,7 +55,7 @@ echo
|
|||||||
yum update
|
yum update
|
||||||
|
|
||||||
# Install required packages
|
# Install required packages
|
||||||
yum install httpd mod_ssl mod_wsgi wget python3
|
yum install httpd mod_ssl mod_wsgi wget python
|
||||||
|
|
||||||
# Verify we have at least Python 2.5
|
# Verify we have at least Python 2.5
|
||||||
typeset -i version_major
|
typeset -i version_major
|
||||||
|
|||||||
@@ -31,17 +31,18 @@ apt-get -y install zip unzip
|
|||||||
apt-get -y install tar
|
apt-get -y install tar
|
||||||
apt-get -y install openssh-server
|
apt-get -y install openssh-server
|
||||||
apt-get -y install build-essential
|
apt-get -y install build-essential
|
||||||
apt-get -y install python3
|
apt-get -y install python
|
||||||
apt-get -y install ipython3
|
#apt-get -y install python2.5
|
||||||
apt-get -y install python3-dev
|
apt-get -y install ipython
|
||||||
|
apt-get -y install python-dev
|
||||||
apt-get -y install postgresql
|
apt-get -y install postgresql
|
||||||
apt-get -y install apache2
|
apt-get -y install apache2
|
||||||
apt-get -y install libapache2-mod-wsgi
|
apt-get -y install libapache2-mod-wsgi
|
||||||
apt-get -y install python3-psycopg2
|
apt-get -y install python2.5-psycopg2
|
||||||
apt-get -y install postfix
|
apt-get -y install postfix
|
||||||
apt-get -y install wget
|
apt-get -y install wget
|
||||||
apt-get -y install python3-matplotlib
|
apt-get -y install python-matplotlib
|
||||||
apt-get -y install python3-reportlab
|
apt-get -y install python-reportlab
|
||||||
apt-get -y install mercurial
|
apt-get -y install mercurial
|
||||||
/etc/init.d/postgresql restart
|
/etc/init.d/postgresql restart
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,15 @@ parentdir = os.path.dirname(currentdir)
|
|||||||
sys.path.insert(0, parentdir)
|
sys.path.insert(0, parentdir)
|
||||||
|
|
||||||
from gluon.cfs import getcfs
|
from gluon.cfs import getcfs
|
||||||
|
from gluon.utf8 import Utf8
|
||||||
from gluon._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin
|
from gluon._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin
|
||||||
from gluon.languages import findT, sort_function
|
from gluon.languages import findT
|
||||||
|
|
||||||
# This script can be run with no arguments (which sets the application folder to the current working directory, and default language to English), one argument (which sets the default language), or two arguments (application folder path and default language).
|
# This script can be run with no arguments (which sets the application folder to the current working directory, and default language to English), one argument (which sets the default language), or two arguments (application folder path and default language).
|
||||||
# When run, it will update the default language, as well as strip all of the strings found in the non-default languages but not in the default language, and add the strings found in the default language to the non-default languages it is not, making sure translators don't do additional work that will never be used.
|
# When run, it will update the default language, as well as strip all of the strings found in the non-default languages but not in the default language, and add the strings found in the default language to the non-default languages it is not, making sure translators don't do additional work that will never be used.
|
||||||
|
|
||||||
def read_dict_aux(filename):
|
def read_dict_aux(filename):
|
||||||
lang_text = open(filename, 'r').read().replace('\r\n', '\n')
|
lang_text = open(filename, 'r').read().replace(b'\r\n', b'\n')
|
||||||
try:
|
try:
|
||||||
return safe_eval(to_native(lang_text)) or {}
|
return safe_eval(to_native(lang_text)) or {}
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -40,11 +41,14 @@ def safe_eval(text):
|
|||||||
return eval(text, {}, {})
|
return eval(text, {}, {})
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def sort_function(x, y):
|
||||||
|
return cmp(unicode(x, 'utf-8').lower(), unicode(y, 'utf-8').lower())
|
||||||
|
|
||||||
def write_file(file, contents):
|
def write_file(file, contents):
|
||||||
file.write('# -*- coding: utf-8 -*-\n{\n')
|
file.write('# -*- coding: utf-8 -*-\n{\n')
|
||||||
for key in sorted(contents, key = sort_function):
|
for key in sorted(contents, sort_function):
|
||||||
file.write('%s: %s,\n' % (repr(to_unicode(key)),
|
file.write('%s: %s,\n' % (repr(Utf8(key)),
|
||||||
repr(to_unicode(contents[key]))))
|
repr(Utf8(contents[key]))))
|
||||||
file.write('}\n')
|
file.write('}\n')
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
@@ -63,7 +67,7 @@ def update_languages(cwd, default_lang):
|
|||||||
if phrase in default:
|
if phrase in default:
|
||||||
new_dict[phrase] = i18n[phrase]
|
new_dict[phrase] = i18n[phrase]
|
||||||
write_file(open(os.path.join(cwd, "languages", lang), 'w'), new_dict)
|
write_file(open(os.path.join(cwd, "languages", lang), 'w'), new_dict)
|
||||||
print(lang)
|
print lang
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
|
|||||||
Reference in New Issue
Block a user