Re: [web2py] Re: web2py and python3

2015-12-06 Thread Pablo Angulo
I also have to work with unicode all the time. While it's true that
python3 deals better with this issue, there is no way that web2py can
move to python3 and our current code keeps working, precisely because of
this issue. Our code has lots of .encode('utf8'), .decode('utf8'),
unicode(...), etc. We would have to migrate our apps to python3.

So a new framework that is based on the same ideas and part of the
existing code, as Massimo have said explicitely, is the only possible
strategy. But while we do the necessary porting of our code to python3,
we will also get other benefits in the deal. python3 being non-backwards
compatible forces a non-backwards compatible version of web2py.

El 07/12/15 a las 02:09, Alex escribió:
> I'm still missing a clear strategy from the devs... I could understand if you 
> don't have enough resources and ask for help (web2py is open source and 
> anybody can contribute after all). But saying that python3 is useless and 
> nobody wants it is not a good approach. > > It seems like most of you only 
> deal with ascii characters. Only if
you constantly deal with non-ascii characters you really feel the pain
of python2. e.g. ajax request with user input, use string for mail.send
or T(..).format(..) -> unicode error. Basically I have to test all user
string input if it is unicode and convert to str > > Alex > -- >
Resources: > - http://web2py.com > - http://web2py.com/book
(Documentation) > - http://github.com/web2py/web2py (Source code) > -
https://code.google.com/p/web2py/issues/list (Report Issues) > --- > You
received this message because you are subscribed to a topic in the
Google Groups "web2py-users" group. > To unsubscribe from this topic,
visit https://groups.google.com/d/topic/web2py/UKcWKU66qnA/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
web2py+unsubscr...@googlegroups.com
. > For more options, visit
https://groups.google.com/d/optout.


-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: always https

2015-08-10 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

El 10/08/15 a las 10:11, Paolo Amboni escribió:
 OK I'm waiting for a free certificate.

 But what i can't understand is why all the site is https not only the
admin interface.

I told you, some web2py contributor it was best to do it that way in
2015, and everyone else thought it was a good idea, so the install
script was changed so that all http is redirected to https.
Specifically, this config tells apache redirect all http to https:


https://github.com/web2py/web2py/blob/master/scripts/setup-web2py-ubuntu.sh
VirtualHost *:80
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
  CustomLog /var/log/apache2/access.log common
  ErrorLog /var/log/apache2/error.log
/VirtualHost

while the one on the manual just configures http:

http://web2py.com/books/default/chapter/29/13/deployment-recipes#mod_wsgi

|VirtualHost *:80
  ServerName web2py.example.com
  WSGIDaemonProcess web2py user=www-data group=www-data
display-name=%{GROUP}
  WSGIProcessGroup web2py
  WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py

#This is Apache 2.2.x permission syntax. See Apache docs for 2.4 syntax
# http://httpd.apache.org/docs/2.4/upgrading.html#run-time

  Directory /home/www-data/web2py
AllowOverride None
Order Allow,Deny
Deny from all
Files wsgihandler.py
  Allow from all
/Files
  /Directory

  AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*)   
/users/www-data/web2py/applications/$1/static/$2
  Directory /users/www-data/web2py/applications/*/static/
Order Allow,Deny
Allow from all
  /Directory

  Location /admin
  Deny from all
  /Location

  LocationMatch ^/([^/]+)/appadmin
  Deny from all
  /LocationMatch

  CustomLog /private/var/log/apache2/access.log common
  ErrorLog /private/var/log/apache2/error.log
/VirtualHost|


 I will study all the deployment chapter of the book to find some clues and 
 how to use the new certificate.
 Thanks.

In the manual, or in the script, it configures a self-signed
certificate. You can use the script, or follow the book, but then you
must replace the self-signed certificates

|  SSLCertificateFile /etc/apache2/ssl/server.crt
  SSLCertificateKeyFile /etc/apache2/ssl/server.key
|

by certificated signed by startssl (only for non-commercial purposes),
or gandi.net, or any other authority. You must follow their particular
procedure to generate your server.key file and then get the correct
server.crt file.
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iQIcBAEBCAAGBQJVyGMLAAoJEATsOw+FDrzILdIP+wfVshYU7F4teHsQZGfhCC5X
md2vA3SuNU6LE4Q+kNHaFAoY05ziUywetObgGpw36+qe59I4UePa7F3f9aNqhaQP
yFiBmdpNZZmBGUWzHABI9JbSXAjc5be/4ReNUDcAx7MKT7wpTEeXJDlsn62e4Xom
M6pXfOrLrtygsXGB0JF0DeJ3QL+EjcXPvTEQBC3x3C3bnKugDtzKfNzbxWmUhdaY
ybs5e4rmD1g+b6QG50j/imnnGm4Pqfo+iI9AmcxGfs4bjWp7vup6JV8Lr4W+CsAV
sccY0Jy6FDeqhQpdKPWcLe3YRrpY0p6wouzOZHlUfF8FeFPT7F6p9rOxEdw/2yJ6
uHfXG+9vFslM3y5lWfUp2ymp4dm0P31jfAc8eftLV+ZumiLDndO491EgJj8ewz9z
+4VMWryEW+uJF1yUjpxikeQlvIMrGz+CEj4Yj/1mB6T4g3NKgtUdyIPP3ptjrWbQ
ZMBTYPXhWETiNlf33N/YdSfz/9rzTjw+N1Vn1bc1k2WB9oyBGY7P2A/OqxrOD/G3
Mr/bFWwH0pD2UpvSWI+nUwIDoPtwgCx0SyiyItqBXnKBc5rQKSmdDBd1WSyTLWbG
zqesLbifwzfN+zK+x6oAozp2fUWLq4CgcPTOPp9RBPwdPSD7lDHrShzfoyqxYvDy
CMRh3KXHYMhdG4H2e3IU
=+WTS
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: always https

2015-08-10 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

El 10/08/15 a las 10:57, Paolo Amboni escribió:
 OK now is much more clear.
 If i replace the apache configuration file with the one that i find on
the book i can have https  on admin interface only?

Yes, apache will forward both http and https to web2py, without any
redirection. Then web2py will display admin disabled because of
insecure channel if you try to enter throught http. Not a problem, I
hope, since admin interface is not for regular users.

 I got a certificate from startssl but i really can't find a way to export or 
 generate the
server.crt and server.key files.

You have to follow their instructions. The procedure varies with the
registrar. One thing is for sure:
you generate server.key: it's your private key that you do not share
with anyone, not even with the registrar.
you probably generate a csr file alongside the key file.
Then you give the csr to the registrar, the registrar verifies in some
way that you are the owner of the domain, and then they give you the crt.
You must look for details searching for apache2, openssl, and/or
startssl (you're using apache2, are you?)
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iQIcBAEBCAAGBQJVyHD2AAoJEATsOw+FDrzIMEQP/iZgK2bdfJr+dQKFYinUncbf
BxDZY8nPb35LE0vaiyYodRaszMkJna7tQMGXNi17mOa49s4Wrw8obtz1fh8ieYo2
2CLnp0rWLLX9Gu1CcWsCCzgxEZqDQcvJXtJSUNwOrA+xYBmBHifVYGXygawS2Avw
kCn0cjQv7Z/LWm2U3ezrjVuVOM12ihIJpVazsgov36WbdcphHQ4lIEOLwmO/F4Kq
Kwy/CqhbQZaM9+scsp3pTE+s1DIhHyYRPU/K8oIZGH3d8h5D/TfS2uKqc42EDMSV
pgYq9jFwDADS6q7Km8Bx8rcn6OBez/6rCpD69MAZE3EPHePysCpN/YTENIbh9TUh
hnPPCZYEkcPFyLdCfZaOyinM0Hi9tKxjqby1sfnol3dEjurqDrL45Ja8TBwgwpBu
qRJBaZve0OLZeF7ld+Ugh+P61IolfEGp1DMEeCPZIac193y4Wou0b/WnKYVBeG9j
o1qLLARAqZcjOtTxQXLdrBnrOLsLwtQRGpzJcm6HZXv4OvB4iudqyRpuDP871Nbo
72PSwodKBBBjywrml49zyeElk7jzdhytPWEonLG3dtfSznnezj7A2GC4gaX/voej
z0bIuKMQNiJDGKwChnZn8bRuXODcODKH8sWmX8qTrLCfGpWRn7OGA9Vw1g1z6x64
Je12wGEqWxoa/1ga+mej
=pVQl
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[web2py] web2py on arch linux, for development and production

2015-07-31 Thread Pablo Angulo
Hello!

I've been developing with web2py in arch linux for some time now with no
problem (just recall to run python2 web2py.py). It's a fine distro,
and if you think it takes ages to install (it does), you can use manjaro
linux which is basically archlinux preconfigured with very sensible
choices (and xfce, of course (no flamewar intended ;-) )).

Yesterday I had to reinstall a webapp, and found out that ovh offers
arch linux for its vps, so I couldn't resist and tried to install web2py
for production with nginx. As there is no deployment script, I looked at
the other distros and translated as necessary. This is the log:

- changing the package manager is as simple as always (but there is no
build-essentials package, instead there's a collection called
base-devel: pacman -S base-devel).
- nginx and mariadb are pretty much the same everywhere, no problem
there. However I liked the way ubuntu splits the nginx configuration
into different sites, mimicking apache, so I borrowed the /etc/nginx
from my earlier ubuntu server.
- uwsgi compiles fine, install fine, but you have to write its own
systemd unit. I was having a hard time configuring uwsgi.service (I had
never done it) until I found the centos7 install script prepares a
systemd unit, so I copied that one from there and it's working with
minor changes.
- archlinux has python=python3, so I have to adapt the deploy
instructions here and there and change python for python2.
- arch linux does less things by default, but I only recall having to
edit /etc/locale.gen and then running locale-gen

If there are more people interested, I can help them and eventually
write a script, but I'm not an expert sysadmin and I prefer not to write
a install script until someone else can proof read it. There's also the
thing that the different install script for different distros have taken
different choice for example for deploying uwsgi, and I don't have a
clue which are best. For example, for ubuntu:

 [uwsgi]

 socket = /tmp/web2py.socket
 pythonpath = /home/www-data/web2py/
 mount = /=wsgihandler:application
 processes = 4
 master = true
 harakiri = 60
 reload-mercy = 8
 cpu-affinity = 1
 stats = /tmp/stats.socket
 max-requests = 2000
 limit-as = 512
 reload-on-as = 256
 reload-on-rss = 192
 uid = www-data
 gid = www-data
 touch-reload = /home/www-data/web2py/routes.py
 cron = 0 0 -1 -1 -1 python /home/www-data/web2py/web2py.py -Q -S
 welcome -M -R scripts/sessions2trash.py -A -o
 no-orphans = true

but for centos7

 [uwsgi]
 chdir = WEB2PY_PATH_PLACEHOLDER/WEB2PY_APP_PLACEHOLDER
 module = wsgihandler:application

 master = true
 processes = 5

 uid = USERNAME_PLACEHOLDER
 socket = /run/uwsgi/WEB2PY_APP_PLACEHOLDER.sock
 chown-socket = USERNAME_PLACEHOLDER:nginx
 chmod-socket = 660
 vacuum = true

and I have the gutt feeling that does options in the ubuntu version of
uwsgi.ini would be fine too for centos7, but damn if I know :-\ !

Another example: in the ubuntu install script it is possible to
repackage all the static files whenever you call

restart uwsgi-emperor

That's a very good idea, isn't it? I've certainly grabbed that idea, so
my uwsgi.service goes like this:

 [Unit]
 Description=uWSGI Emperor service

 [Service]
 ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown
 www-data:www-data /run/uwsgi; su www-data -c  python2
 /home/www-data/web2py/web2py.py -S YOUR_APP_HERE/appadmin -R
 scripts/zip_static_files.py'
 ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/sites
 Restart=always
 KillSignal=SIGQUIT
 Type=notify
 NotifyAccess=all

 [Install]
 WantedBy=multi-user.target


-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[web2py] plugin for handsontable

2015-07-29 Thread Pablo Angulo
I have packaged a plugin with one possible use of the great library
handsontable:

http://www.web2pyslices.com/slice/show/2042/handsontable-plugin-for-a-spreadsheet

You may comment on the plugin as you want, but I specifically want to
ask if you find the following trick acceptable (or improvable):

The Handsontable plugin is used to load client side a potentially very
big table, and the data is stored by handsontable. I decided to suscribe
to the afterValidate event of the Handsontable object:

afterValidate:function(isValid,value,row,prop,source){
if(isValid){
override[[rowids[row], prop]] = value;
}
}

and record only the values that the user updates.
Close to the div that holds the table there is a form consisting of a
submit button and hidden field.
Then before the form is submitted, I stringify the object with all the
changes, and attach it to the hidden form field:

$('#submit').on('click', function(){
$('#override').val(JSON.stringify(override));
});

Back in web2py, I recover the changes by the user in this way:

import json as json_parser
override = json_parser.loads(request_vars.override)

Any comments would be appreciated.

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: New feature in trunk: API tokens

2015-07-10 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

 diff --git a/applications/welcome/controllers/default.py
b/applications/welcome/controllers/default.py
 index c775603..e99ef0f 100644
 --- a/applications/welcome/controllers/default.py
 +++ b/applications/welcome/controllers/default.py
 @@ -57,4 +57,10 @@ def call():
  
  return service()
  
 +@auth.requires_membership('masters')
 +def master_zone():
 +return dict(a='Hello, Master', b=request.vars.message)
  
 +def get_master_code():
 +url = auth.get_authorization_url(a='welcome', c='default',
f='master_zone', vars=dict(message='Greetings'))
 +return dict(a = A('copy this link', _href=url))
 diff --git a/applications/welcome/languages/es.py
b/applications/welcome/languages/es.py
 index 7579cc3..54a57c6 100644
 --- a/applications/welcome/languages/es.py
 +++ b/applications/welcome/languages/es.py
 @@ -55,6 +55,7 @@
  'Available Databases and Tables': 'Bases de datos y tablas disponibles',
  'Back': 'Atrás',
  'Buy this book': 'Compra este libro',
 +Buy web2py's book: Buy web2py's book,
  'Cache': 'Caché',
  'cache': 'caché',
  'Cache Keys': 'Llaves de la Caché',
 @@ -83,6 +84,7 @@
  'compile': 'compilar',
  'compiled application removed': 'aplicación compilada eliminada',
  'Components and Plugins': 'Componentes y Plugins',
 +'Config.ini': 'Config.ini',
  'contains': 'contiene',
  'Controller': 'Controlador',
  'Controllers': 'Controladores',
 @@ -119,6 +121,7 @@
  'Description': 'Descripción',
  'design': 'diseño',
  'DESIGN': 'DISEÑO',
 +'Design': 'Design',
  'Design for': 'Diseño por',
  'detecting': 'detectando',
  'DISK': 'DISCO',
 @@ -145,6 +148,7 @@
  'End of impersonation': 'Fin de suplantación',
  'enter a number between %(min)g and %(max)g': 'introduzca un número
entre %(min)g y %(max)g',
  'enter a value': 'introduzca un valor',
 +'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': 'introduzca un entero
entre %(min)g y %(max)g',
  'enter date and time as %(format)s': 'introduzca fecha y hora como
%(format)s',
  'Error logs for %(app)s': 'Bitácora de errores en %(app)s',
 @@ -177,6 +181,7 @@
  'Groups': 'Grupos',
  'Hello World': 'Hola Mundo',
  'help': 'ayuda',
 +'Helping web2py': 'Helping web2py',
  'Home': 'Inicio',
  'How did you get here?': '¿Cómo llegaste aquí?',
  'htmledit': 'htmledit',
 @@ -217,6 +222,7 @@
  'License for': 'Licencia para',
  'Live Chat': 'Chat en vivo',
  'loading...': 'cargando...',
 +'Log In': 'Log In',
  'Logged in': 'Sesión iniciada',
  'Logged out': 'Sesión finalizada',
  'Login': 'Inicio de sesión',
 @@ -256,6 +262,7 @@
  'not in': 'no en',
  'Object or table name': 'Nombre del objeto o tabla',
  'Old password': 'Contraseña vieja',
 +'Online book': 'Online book',
  'Online examples': 'Ejemplos en línea',
  'Or': 'O',
  'or import from csv file': 'o importar desde archivo CSV',
 @@ -319,6 +326,7 @@
  'Services': 'Servicios',
  'session expired': 'sesión expirada',
  'shell': 'terminal',
 +'Sign Up': 'Sign Up',
  'site': 'sitio',
  'Size of cache:': 'Tamaño de la Caché:',
  'some files could not be removed': 'algunos archivos no pudieron ser
removidos',
 diff --git a/applications/welcome/models/db.py
b/applications/welcome/models/db.py
 index 606dc6f..3438621 100644
 --- a/applications/welcome/models/db.py
 +++ b/applications/welcome/models/db.py
 @@ -8,6 +8,7 @@
  ## if SSL/HTTPS is properly configured and you want all HTTP requests to
  ## be redirected to HTTPS, uncomment the line below:
  # request.requires_https()
 +import random
  
  ## app configuration made easy. Look inside private/appconfig.ini
  from gluon.contrib.appconfig import AppConfig
 @@ -71,6 +72,8 @@ auth.settings.registration_requires_verification = False
  auth.settings.registration_requires_approval = False
  auth.settings.reset_password_requires_verification = True
  
 +auth.settings.jwt_secret = myconf.take('auth.jwt_secret')
 +
  #
  ## Define your tables below (or better in another model file) for example
  ##
 diff --git a/applications/welcome/private/appconfig.ini
b/applications/welcome/private/appconfig.ini
 index f45efbf..6db7544 100644
 --- a/applications/welcome/private/appconfig.ini
 +++ b/applications/welcome/private/appconfig.ini
 @@ -8,7 +8,7 @@ pool_size = 1
  
  ; smtp address and credentials
  [smtp]
 -server = smtp.gmail.com:587
 +server = logging
  sender = y...@gmail.com
  login  = username:password
  
 @@ -16,4 +16,7 @@ login  = username:password
  ; form styling
  [forms]
  formstyle = bootstrap3_inline
 -separator =
 \ No newline at end of file
 +separator =
 +
 +[auth]
 +jwt_secret = very_secret_even_random
 diff --git a/gluon/tools.py b/gluon/tools.py
 index 9d90b9a..da18795 100644
 --- a/gluon/tools.py
 +++ b/gluon/tools.py
 @@ -1171,6 +1171,8 @@ class Auth(object):
  remember_me_form=True,
  allow_basic_login=False,

Re: [web2py] Re: New feature in trunk: API tokens

2015-07-10 Thread Pablo Angulo
Sorry, I see signing the email scrambled the patch:

 diff --git a/applications/welcome/controllers/default.py
 b/applications/welcome/controllers/default.py
 index c775603..e99ef0f 100644
 --- a/applications/welcome/controllers/default.py
 +++ b/applications/welcome/controllers/default.py
 @@ -57,4 +57,10 @@ def call():
  
  return service()
  
 +@auth.requires_membership('masters')
 +def master_zone():
 +return dict(a='Hello, Master', b=request.vars.message)
  
 +def get_master_code():
 +url = auth.get_authorization_url(a='welcome', c='default',
 f='master_zone', vars=dict(message='Greetings'))
 +return dict(a = A('copy this link', _href=url))
 diff --git a/applications/welcome/languages/es.py
 b/applications/welcome/languages/es.py
 index 7579cc3..54a57c6 100644
 --- a/applications/welcome/languages/es.py
 +++ b/applications/welcome/languages/es.py
 @@ -55,6 +55,7 @@
  'Available Databases and Tables': 'Bases de datos y tablas disponibles',
  'Back': 'Atrás',
  'Buy this book': 'Compra este libro',
 +Buy web2py's book: Buy web2py's book,
  'Cache': 'Caché',
  'cache': 'caché',
  'Cache Keys': 'Llaves de la Caché',
 @@ -83,6 +84,7 @@
  'compile': 'compilar',
  'compiled application removed': 'aplicación compilada eliminada',
  'Components and Plugins': 'Componentes y Plugins',
 +'Config.ini': 'Config.ini',
  'contains': 'contiene',
  'Controller': 'Controlador',
  'Controllers': 'Controladores',
 @@ -119,6 +121,7 @@
  'Description': 'Descripción',
  'design': 'diseño',
  'DESIGN': 'DISEÑO',
 +'Design': 'Design',
  'Design for': 'Diseño por',
  'detecting': 'detectando',
  'DISK': 'DISCO',
 @@ -145,6 +148,7 @@
  'End of impersonation': 'Fin de suplantación',
  'enter a number between %(min)g and %(max)g': 'introduzca un número
 entre %(min)g y %(max)g',
  'enter a value': 'introduzca un valor',
 +'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': 'introduzca un entero
 entre %(min)g y %(max)g',
  'enter date and time as %(format)s': 'introduzca fecha y hora como
 %(format)s',
  'Error logs for %(app)s': 'Bitácora de errores en %(app)s',
 @@ -177,6 +181,7 @@
  'Groups': 'Grupos',
  'Hello World': 'Hola Mundo',
  'help': 'ayuda',
 +'Helping web2py': 'Helping web2py',
  'Home': 'Inicio',
  'How did you get here?': '¿Cómo llegaste aquí?',
  'htmledit': 'htmledit',
 @@ -217,6 +222,7 @@
  'License for': 'Licencia para',
  'Live Chat': 'Chat en vivo',
  'loading...': 'cargando...',
 +'Log In': 'Log In',
  'Logged in': 'Sesión iniciada',
  'Logged out': 'Sesión finalizada',
  'Login': 'Inicio de sesión',
 @@ -256,6 +262,7 @@
  'not in': 'no en',
  'Object or table name': 'Nombre del objeto o tabla',
  'Old password': 'Contraseña vieja',
 +'Online book': 'Online book',
  'Online examples': 'Ejemplos en línea',
  'Or': 'O',
  'or import from csv file': 'o importar desde archivo CSV',
 @@ -319,6 +326,7 @@
  'Services': 'Servicios',
  'session expired': 'sesión expirada',
  'shell': 'terminal',
 +'Sign Up': 'Sign Up',
  'site': 'sitio',
  'Size of cache:': 'Tamaño de la Caché:',
  'some files could not be removed': 'algunos archivos no pudieron ser
 removidos',
 diff --git a/applications/welcome/models/db.py
 b/applications/welcome/models/db.py
 index 606dc6f..3438621 100644
 --- a/applications/welcome/models/db.py
 +++ b/applications/welcome/models/db.py
 @@ -8,6 +8,7 @@
  ## if SSL/HTTPS is properly configured and you want all HTTP requests to
  ## be redirected to HTTPS, uncomment the line below:
  # request.requires_https()
 +import random
  
  ## app configuration made easy. Look inside private/appconfig.ini
  from gluon.contrib.appconfig import AppConfig
 @@ -71,6 +72,8 @@ auth.settings.registration_requires_verification = False
  auth.settings.registration_requires_approval = False
  auth.settings.reset_password_requires_verification = True
  
 +auth.settings.jwt_secret = myconf.take('auth.jwt_secret')
 +
  #
  ## Define your tables below (or better in another model file) for example
  ##
 diff --git a/applications/welcome/private/appconfig.ini
 b/applications/welcome/private/appconfig.ini
 index f45efbf..6db7544 100644
 --- a/applications/welcome/private/appconfig.ini
 +++ b/applications/welcome/private/appconfig.ini
 @@ -8,7 +8,7 @@ pool_size = 1
  
  ; smtp address and credentials
  [smtp]
 -server = smtp.gmail.com:587
 +server = logging
  sender = y...@gmail.com
  login  = username:password
  
 @@ -16,4 +16,7 @@ login  = username:password
  ; form styling
  [forms]
  formstyle = bootstrap3_inline
 -separator =
 \ No newline at end of file
 +separator =
 +
 +[auth]
 +jwt_secret = very_secret_even_random
 diff --git a/gluon/tools.py b/gluon/tools.py
 index 9d90b9a..da18795 100644
 --- a/gluon/tools.py
 +++ b/gluon/tools.py
 @@ -1171,6 +1171,8 @@ class Auth(object):
  remember_me_form=True,
  

Re: [web2py] Re: New feature in trunk: API tokens

2015-07-01 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

Just one more comment: I wrote hash(SALT+request.url+'#'+user_id) but
meant hash(SUPER_SECRET_GLOBAL_PASSWORD+request.url+'#'+user_id)

El 01/07/15 a las 00:06, Pablo Angulo escribió:

 This email was going to be a simple Great!, but eventually I have
many comments:

 El 29/06/15 a las 20:37, Massimo Di Pierro escribió:
  2. yes that is correct (except
   it is _token=, not token=). Just mind that the token is as good as
   a password and may be unsafe to send it via email. If if you need
   it, you can do it.

 Is it less safe than sending auth.email_reset_password(), which anyone
can ask? Actually, that's my number 1 use case. I want local admins to
register users in bulk, then send each user an email that would
automatically log her in, and send her right into a custom profile page.
Depending on how unsafe it is, I may use for all the other emails, like
for example: click *here* to accept the new offer but click *here* to
reject it, with no login.


 More comments: If I understand the new code correctly:
 1- the token is valid until admin explicitely takes action or it
expires by date, but if I want for example one-use-only tokens, I have
to write a custom requires_login_or_token
 2- no token is created on user creation, so I have to create the
tokens using for example a hook on db.auth_user._after_insert
 3- a user can have many tokens, so I could create a token whenever I
send her an email with auto-login. But is this sensible? What is the use
case for having many tokens per user?


 Actually, I've been using something related for some time. In some
functions, say for example:

 example.com/c/f?a=1b=2

 it is possible to share a link of the kind:

 example.com/c/f?a=1b=2auth_code=SJAkKS_random_garbage_QWKSDW

 If anyone gets the link with the correct auth_code, she can access the
page. Otherwise, permissions depend on auth_membership:


  
auth.basic()   
  

if
  
productor.random_string==request.vars.auth_code:
  


  
pass   
  

elif not
   auth.login(): 
  

raise HTTP(403, T('You don't have permission. Please
   log in.'))

elif (auth.has_membership(role='admins_%s'%grupo)
   or


  
auth.has_membership(role='webadmins')):  
  


  
pass  
  


  
else:  
  

session.flash = T('You don't have permission.')

redirect(URL(...)) 

 I don't know if this pattern deserves its own generic implementation.
Something like:
  auth.allow_login_by_keycode=1
 that alters the behaviour of all decorators requires_login,
requires_membership, requires, so that:
  - If request.vars._keycode is exactly hash(SALT+request.url), let them in
  - Otherwise, require login, membarship, etc
 The admin would then decide when to share to link with the _keycode,
if at all. There should be a function auth.get_keycode(url)...

 Maybe we could use hash(SALT+request.url+'#'+user_id) to achieve both
effects: if request.vars._keycode is exactly
hash(SALT+request.url+'#'+user_id), you may access the url as if you
were user_id. If the url is
example.com/user/login?_next=/controller/function%3Fa%3D1_keycode=XASXA_correct_keycode_ASKAJ,
this automatically logs the user in, and redirects to
example.com/controller/function?a=1, now logged as user_id. But there
would be no need to use different decorators, and it also allows for
other possibilities that I don't think I can do with
requires_login_or_token.

 I hope at least one of these comments make sense to you :-) !

 --
 Resources:
 - http://web2py.com
 - http://web2py.com/book (Documentation)
 - http://github.com/web2py/web2py (Source code)
 - https://code.google.com/p/web2py/issues/list (Report Issues)
 ---
 You received this message because you are subscribed to a topic in the
Google Groups web2py-users group.
 To unsubscribe from this topic, visit
https://groups.google.com/d/topic/web2py/QtP9re5WqqE/unsubscribe.
 To unsubscribe from this group and all its topics, send an email to
web2py+unsubscr...@googlegroups.com
mailto:web2py+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.


-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py

Re: [web2py] Re: New feature in trunk: API tokens

2015-06-30 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

This email was going to be a simple Great!, but eventually I have many
comments:

El 29/06/15 a las 20:37, Massimo Di Pierro escribió:
 2. yes that is correct (except it is _token=, not token=). Just mind that the 
 token is as good as a
password and may be unsafe to send it via email. If if you need it, you
can do it.

Is it less safe than sending auth.email_reset_password(), which anyone
can ask? Actually, that's my number 1 use case. I want local admins to
register users in bulk, then send each user an email that would
automatically log her in, and send her right into a custom profile page.
Depending on how unsafe it is, I may use for all the other emails, like
for example: click *here* to accept the new offer but click *here* to
reject it, with no login.


More comments: If I understand the new code correctly:
1- the token is valid until admin explicitely takes action or it expires
by date, but if I want for example one-use-only tokens, I have to write
a custom requires_login_or_token
2- no token is created on user creation, so I have to create the tokens
using for example a hook on db.auth_user._after_insert
3- a user can have many tokens, so I could create a token whenever I
send her an email with auto-login. But is this sensible? What is the use
case for having many tokens per user?


Actually, I've been using something related for some time. In some
functions, say for example:

example.com/c/f?a=1b=2

it is possible to share a link of the kind:

example.com/c/f?a=1b=2auth_code=SJAkKS_random_garbage_QWKSDW

If anyone gets the link with the correct auth_code, she can access the
page. Otherwise, permissions depend on auth_membership:

 auth.basic()  
   
 if
productor.random_string==request.vars.auth_code: 

pass
 elif not
auth.login():  
 raise HTTP(403, T('You don't have permission. Please log in.'))
 elif (auth.has_membership(role='admins_%s'%grupo)
or
  
auth.has_membership(role='webadmins')):   
 
pass   

else:   

 session.flash = T('You don't have permission.')
 redirect(URL(...)) 

I don't know if this pattern deserves its own generic implementation.
Something like:
 auth.allow_login_by_keycode=1
that alters the behaviour of all decorators requires_login,
requires_membership, requires, so that:
 - If request.vars._keycode is exactly hash(SALT+request.url), let them in
 - Otherwise, require login, membarship, etc
The admin would then decide when to share to link with the _keycode, if
at all. There should be a function auth.get_keycode(url)...

Maybe we could use hash(SALT+request.url+'#'+user_id) to achieve both
effects: if request.vars._keycode is exactly
hash(SALT+request.url+'#'+user_id), you may access the url as if you
were user_id. If the url is
example.com/user/login?_next=/controller/function%3Fa%3D1_keycode=XASXA_correct_keycode_ASKAJ,
this automatically logs the user in, and redirects to
example.com/controller/function?a=1, now logged as user_id. But there
would be no need to use different decorators, and it also allows for
other possibilities that I don't think I can do with
requires_login_or_token.

I hope at least one of these comments make sense to you :-) !
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iQIcBAEBCAAGBQJVkxLiAAoJEATsOw+FDrzIhocP/0GUWq9q2bJXDJABXL3aJL0n
a1vTKnGWH00YiyhvXUyMBaIpkqhIj+kK423QVcJjqqEDQyVn2ctn9UhfnywoRUZ/
J18ECE1qZlW2+q44V7+v14s9RjSSNB47EVFfGz2xUv3xRhGYB25DZ/PdB0U2ZV+O
Q4j2/PqG6035IfHkCAX+jYgZLW0sv/KcFF28S0Dk2Ojd5SAWgVGcrz2ujq0jSoJO
SA7hqW1vYGmocAy0nkIM7pWiIoEPDo9UByUvEH/xsn1ArvEe4mQ8BVMry6w438yF
dnmGcPVWxbH5zriRwZEZJtwTvyVMMGLhVvpqkb4fTwSvKXfuZxxnuLCIJsRoaeb+
6o3sgDnzW7AYeds0haJz3MV0XAL9mtvls+aWrY9eAOxIvosT4Nu8e45FFzGrj0nl
maDTVTQJwMcGPqx+eK3FBIdcy0njYBwRvuWr5HJWx/aJf5DN30rUvWADDhH8jQ3d
GQs+3WlXrWrZWfM+yxLDJ/aUczkabZ73OaOb6aPfmzWGXGCEnY9nuYh1PXQIpuC/
ICW6+MZtQlu6Onl3irqt555hGh6SBSmPproFMp0yUiv0GuSvSY4uYP7KhQ9H96DE
NyKEGaWWm0Hhx0ZO8KntINYPbhpnCHIRBJVUpT2XZss6YgX0iMHEhw/GXRO4BryC
A96YHISuVuyCIVpJyg1h
=WSf2
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: New feature in trunk: API tokens

2015-06-29 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

ok, thanks!

But I have two questions:
1. what can I do with auth.requires_membership and
auth.requires(custom_function), which I use a lot?
2. so if I have to send an email, all I have to do is find the use token
in the database with:

user_token = db.auth_token(user_id).token

and then use that in the url:

body = template%dict(link=URL(c=controller, f=function,
vars=dict(a=1,b=2, token=user_token)))

is that correct? If it is, it's awesome!

El 29/06/15 a las 17:32, Massimo Di Pierro escribió:
 You can use these tokens for your purpose. You would also have to do (in 
 models/db.py)

auth.requires_login = auth.requires_login_or_token

 In the general case the user many want to allow the token only on some
API so we want to distinguish.

 Massimo

 On Monday, 29 June 2015 09:25:35 UTC-5, p...@cancamusa.net wrote:

 Hello:

 I'm actually interested in a way to send user notification emails
with custom links, so that a click sends the user to the website and
also logs the user in automatically.

 Is that what these tokens are for? If they are, I don't see why I
would use the decorator requires_login some times, and
requires_login_or_token other times.

 But I'm afraid this is not their goal, is it?

 --
 Resources:
 - http://web2py.com
 - http://web2py.com/book (Documentation)
 - http://github.com/web2py/web2py (Source code)
 - https://code.google.com/p/web2py/issues/list (Report Issues)
 ---
 You received this message because you are subscribed to a topic in the
Google Groups web2py-users group.
 To unsubscribe from this topic, visit
https://groups.google.com/d/topic/web2py/QtP9re5WqqE/unsubscribe.
 To unsubscribe from this group and all its topics, send an email to
web2py+unsubscr...@googlegroups.com
mailto:web2py+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iQIcBAEBCAAGBQJVkXneAAoJEATsOw+FDrzIFloQAIYv09fk+uXW+kynEW4ZyxrP
HwjxVlEcDKUtFVLTpCCAI11nI4Mw/h+OSxfZ59wYVwEHGrz3bVrpwvB5auIwWvRR
1AH1h50TW6s/vkjF6/23NEYm2nLV6oPpKN/Evj4YDhAYFTb9VuWQoxEuW/Sjyf47
cUADobtBXKCAsXhXwGdZeO3bNRr+RNN5M3tmrOo4qxorK+gB3ExRLLS6NUCHHy+0
JHKTF4T2aP9GZoWDVElu+yrHwWsGf9qduf0Jj+YT8U4/5ac/f8fYCAPHQ8RmZa38
8GJKXh0Gb1c03aeu11ygPSFGxcuuZumQwpmcWFnH15qvs2UJtnEiy0xZOMEYe/cl
qcttu7GApclDTeYro6zHrmDKTFQHZ2FRmab/JsOBri705qGoB7i3O8QgnYb/57gf
5TamJsQD4rVkxKz2J7M66/vA+bYJ7O0HtgVyI2tuBnkVWjJ/p+FdvurPOF9pH9Le
AgzNaoh0OcuXQBgHcGORPIs07hLRppxQ0A1aiXYsu5asTW9q4CiZO/phfxdIX3da
8NpDgINhxjAEBJfnBmE3Qijoae9ysxW6z/BcaywjEWlXL7g9P3m3D0ZNKQ4pM+VP
u6PWvbbYrxZKpLEdyIsCr99EWleKUggvhagWtw5cZKFcF3auHppI2ZESTv5I919L
DMJPaZsu0diR4lOVIr6i
=0m8I
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: Triggering a one-time migration when schema changes

2015-04-11 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

El 09/04/15 a las 10:21, Niphlod escribió:
 another caveat circumvented, another step in the good direction now the 
 problem is only IF you
have conditional models.

I tried this and it triggered the migration on a conditional model:

python web2py.py -S welcome/appadmin -M
-BEGIN PGP SIGNATURE-
Version: GnuPG v1

iQIcBAEBAgAGBQJVKNFIAAoJEATsOw+FDrzItWIP/jpsx/N3/TmOgUii5SFQd1ui
BiLPSzJ18btLxsUNoXJ657s5Y84160TmUS0kE39XI1GLMs1dJlMQIDWArlKhgEPO
NdnPn7GFi5TILDn9eOoErseGQucNNN34GjF4PH+tdsuBhKTf14HIR1XpkHm+gkKT
4tlF0Tf+VQ7vJ7QXuvGa1L4Tp+8MPst8/LFtnYHsdCymfjIUHrIMOwvvWw9WGUaG
F95pthU4wnG5hExLVNvdavgDPq2hsb8trvMBE5nFZzDktTuG661xG+1hdZGIu8nO
33+T6KGfLirtMit7jcwN0n9ywUYDK4mXbOeVdKqw9KZm2E3zbT86me3LRbm8kl5j
8vOaHbbzXu14IIbpFjuQ4JnfsZeMRzvS0PgGEj9DbVJ0/DCkRiYFAj7agDFVCPiP
qqUWjCszTqVzZsHKDBZG3CzL8VhtpbO94M3VrOPt4M7S1F/9RktXpf2H3sfUwPLH
OnlqK93jZuqMtrmOwrANY7eM/eKdW7/RZM4S+NmrEDlcg7A2t6xPxHvtm6TYaLJA
j5vn69QrHdqSgKcE5n2XViXQ4tMyKogQYfjnJzJ9+XSVp06PJD+Iq4k0kuIaMWCx
fF24XQVSRqXB6Dpk1KmeMSs7zZMRzod3JxevAjTn8A5+vuqGNZG156XwSdPXAxX4
4DEDFaBBkCXuD3iLsEO6
=1dzt
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: Triggering a one-time migration when schema changes

2015-04-09 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

El 08/04/15 a las 20:58, Niphlod escribió:
 good too, but NEEDS to happen without lazy_tables ^_^

This is what I do:

db = DAL('mysql://web2pyuser:pass@localhost/database', migrate=migrate,
lazy_tables=(not migrate))
-BEGIN PGP SIGNATURE-
Version: GnuPG v1

iQIcBAEBAgAGBQJVJjHBAAoJEATsOw+FDrzI1NoP/3QsGdBNKTDZT14MHzyW1UL1
x625V/FwVQ9Fnd3s06IghvochXgGZhZ6TkA4Paztk6H0NtrZiUirKNKyDV9fC6z8
9j5nNutRaHFRSkLCl47Z7wGKg3cMTxT4hQoK5tq2UlXfHeFtDmUmAT+gC6ITqyaz
loovKP33J3lMSyk+0eWdIuCq02rU4hb1JOIpIm9OeJg3lnENmQn88B4MvIynI+PO
GyQh/yV0U9GdLuYwkU0sqnaMduCCgUpoDqM7o+hlKh1OHq/0GyfsDMcwHGYIEs57
TbaEvr/Rqd0AD3NDFaemJl/z1MlYr+mmmRE8u3LLToVQ60npUlazaz8jPFwIT0M7
y8RkwHDa2qdOC7mDwUMz9gPcXlHpYD4mIJakpJOQTroPlTcHco3/Bvam4Z+mWN0s
HsdIBtAnCZC7/YPkk3RsCzdj1zaxcqmqQIPRlhrGLzdLsFQ9l9fMeYUGOpu+yKQ0
ercAa6MtGEdHexE00ZZ90hj8tjkxlWZ8Al27yh0UkVCe33QtXfWj7mQGRkSlC1yR
W5ho1+F0JIO+R49MCPTR9bRxRNOCN79PDM6ai6sxV8HEjselDBlMNQd7zIc7pLnr
wlxXkYQ3BkiUjxU3eVE1gLeRVpyLkwxAM9bRvQgUMIXvxcTNkOk6o4uv6Ah1sBNl
RniOrtMhhfO7kYm6Y3KG
=m8+M
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: Please help us test the 2.9.12 binaries

2015-03-03 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

El 03/03/15 a las 00:43, Dave S escribió:
 Well, that's what this thread is about.  Finding out what broke, whether it 
 is a new bug or a place
where backwards compatibility /needs/ to be broken (for example , having
in the old versions incorrectly followed a specification), or something
that requires discussion.

...and this thread has played its role. Now it's time, I propose, to
update the changelog. Nothing is broken, the problem is tiny and won't
affect most people. But the way it is now, a person who upgrades might
find that her code breaks, then either spend some time fixing it (and
may not fix it in the canonical way), or spend some time looking for
this thread.

If you put a warning in the changelog, as has been done other times, the
canonical fix will be available in the very directory of the web2py
installation, in the first file you should read before upgrading.

That's all I have to say, I don't have any trouble with changing a few
lines of my code, I understand it's for the better and I just want to
avoid trouble to some people over there. But if you don't think it's the
right thing to do, be my guest!

Have a nice day! I mean it :-) !
-BEGIN PGP SIGNATURE-
Version: GnuPG v1

iQIcBAEBAgAGBQJU9X5uAAoJEATsOw+FDrzIvKMP+gJczrvySxmrDE7HahomTGFi
Rba/ygsi04xRb2ktISO4oZKBMFj6ZzW7nCTQXdG/9YpdzZWjCNEZJQS4TDUapZQG
xtzTAVLOTgXfNj1tr4oCRQuuEXBem9kHycUDs2VePeRUpTkx92Txgylnb3ipqWEh
pt63tUIyQwlb5y1AOw6Rw2DNan10DRLCd6ypPcgCILOJRrPAv1kO+AX8xOTVTXse
OS66hVlKJQKFCnsNVaqhD1PpJcjdOAetE9hqhlycK63vVHvNdjzzWM0yU22mC+z4
LGQRh7KGsMuk+hWq5UcLdrGLhNcr1/DdMPrRTn/BZCprpyoVhdP0CE3QdD6xQl1b
ypqlHDH+fuNz5EyEUrJSuTu3lobcSfb4Svh+T22cRESss3+hpg+WnLhB7kGHPCB2
3506J3Xo3n6qkJ2ZvL3NzrYpGG/S4wLeRce2AdMx3es8cXU91KyulojzzkRq5Hbl
CEVANYYZZoIpql0i8zq94kG0b0lw8MeZdJYSAqGbq2LmjYg3sAhXwol9zHwNa9dj
9MJwRLC7XfQP8pt/pV+HmzY3LxcpHOHzmUBSQwppPXH+dbjgA4mOv3MDjG/fsKjq
PXtpFYAkRf/rjb6oaiX0KIN2XPyxOXvj7im4ZrZrdr23z7IYvAbFGUiIzWvGWq50
7cJhX97hskVWNTWnUDGc
=AveM
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: Please help us test the 2.9.12 binaries

2015-03-02 Thread Pablo Angulo

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Hello, Dave!

El 02/03/15 a las 21:26, Dave S escribió:
 Well, from the original message in this thread:

 2.9.12 includes mostly bug fixes but there is some major DAL
refactoring so we are concerned about backward compatibility. We think
it works but please let us know asap if this breaks your code.

Certainly, major DAL refactoring would be a better description than
Modular DAL, thanks Giovanni in the changelog. That's the document we
are supposed to read before upgrading, and not every thread in this group.

 Now, to address your problem, we need to know /what/ broke.  Can you
give us some code examples?

The examples were already in this thread:

 -from gluon.dal import Table
 +try:#web2py =2.9.12
 +   from gluon.dal.objects import Table
 +except:#web2py =2.9.11
 +   from gluon.dal import Table

 -from gluon.dal import Expression
 +try:#web2py =2.9.12
 +   from gluon.dal.objects import Expression
 +except:#web2py =2.9.11
 +   from gluon.dal import Expression

 -from gluon.dal import Rows
 +try:#web2py =2.9.12
 +   from gluon.dal.objects import Rows
 +except:#web2py =2.9.11
 +   from gluon.dal import Rows

Anyway, I apologize that I could not make the tests earlier, and I want
to thank every one involved in this release. The changes I had to do are
no big deal, but there is so much emphasis in this project on not
breaking backwards compatibility, that I wanted to suggest to tell about
this issue in the changelog.

Regards
-BEGIN PGP SIGNATURE-
Version: GnuPG v1

iQIcBAEBAgAGBQJU9NRNAAoJEATsOw+FDrzIKbsP/RZx3E41AWYDpAZcFmQedcwp
MH8w4O6u2UHKtFSk58zDcQRSuoHkOmyTL4CY+uR5LqHDrgQ+LQIV3mWpCSr7k7JR
PIb9ZIJKvhrs03I67Hl/lYHVELE7+Zmur6V+EN1Fqid9l6CQ7UjucDsJpLTndMaO
EO3DSqX10ZqoiOEyiCDl2F1G1dEt+B81QOT3W5KX4CabjyEyfEjcQHlpoXbYjdyx
JXE/GSBbaqFT8g9QIIU/p/PN58vzW6EfH/COHz8GcRqc893AIdVxyKTvrVXfPwgs
RkxtVchQdoC/OOHjiQHcnHTb18esPJxMCgxryVFVlLLNVUElf3qMOD7IBkDFStTE
+oJ6eN4i91x9336GCxmmZLxeKy0MY6ctu+065ssEiG6GdkhsGH+ckh+EuRXiHRqP
D9MTmmWdt2mqAkCJaALdObL4rUX2nn+z7aY9enHzGt4BEMd0nPY+9IWBU/9FEzk0
nw86DCsuLzEN9LqC5vAsQp8LzAoM74ZkpbVsTiz1ZdAkaEPQ34gslQN6vHYeuH2y
7US5RR9XgWUuf0DAy/+f6OI2AGsH2njF9cCfS+DaJ89Z6ZGcOEhxqk4DmR6/pBgU
5YwU1UMPYmZUBgOBvByI/spY8tMT2B3fU2BewgZLstHGuMjwO1plXWdgmHUtGfzS
PofspetlV4f7SU/Vm7zw
=xBEb
-END PGP SIGNATURE-

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[web2py] translating the views

2014-10-01 Thread Pablo Angulo
I sometimes find very inconvenient the translate feature. Some views
contain a lot of static text, so if I want to translate it I would do:

p{{=T('I sometimes find very inconvenient the translate feature. Some
views contain a lot of text, so if I want to translate it I would
do:')}}/p

but if there are other html tags, I have to choose between:

{{=T('''pSome  strongimportant/strong text and other
liemphasizes/li items./p
pAnother paragraph/p
pand the last one/p''')}}

which is not ideal because any translator can break the DOM correctness
of the page for just one language, or
p{{=T('Some')}} strong{{=T(''important'')}}/strong ...

which is cumbersome, and the complete sentence may not make sense at all
if the pieces are translated at random order.

I'm considering using MARKMIN, so the view would be:

{{=MARKMIN(T('''
# Title

this is **bold** or ''italic'' and this [[a link http://web2py.com]]
'''))}}

But before I dive deeper: what do you think?

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: add static files to header from a module

2014-08-16 Thread Pablo Angulo
I think I got it:

- As Leonel said, Simply adding to current.response.files may not works
if the request is ajax. I have to add: if a component is loaded with
the LOAD function, adding to current.response.files will not work even
if ajax=False and ajax_trap=False.

- The statements:

current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.js'))
current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.css'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.barRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.pointLabels.min.js'))

must be placed in the __init__ method, or any other method that is
called from the controller, not from the view (like the xml method).

The combination of both issues confused me, so thanks for your help!

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: add static files to header from a module

2014-08-13 Thread Pablo Angulo
If I understand, you mean that whenever I call JQPlot

jqplot = JQPlot(*args, col_represent=str)

I have to append the following lines:

response.files.append(URL('static', 'jqplot/jquery.jqplot.min.js'))
response.files.append(URL('static', 'jqplot/jquery.jqplot.min.css'))
response.files.append(URL('static',
'jqplot/plugins/jqplot.barRenderer.min.js'))
response.files.append(URL('static',
'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
response.files.append(URL('static',
'jqplot/plugins/jqplot.pointLabels.min.js'))

or at least a call like

jqplot = JQPlot(*args, col_represent=str)
add_jqplot_static_files()

to avoid repetition.

yeah, that would sure work, but still: any other ideas?

I'm specifically interested in knowing why

current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.js'))
current.response.files.append(URL('static',
'jqplot/jquery.jqplot.min.css'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.barRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
current.response.files.append(URL('static',
'jqplot/plugins/jqplot.pointLabels.min.js'))

in the module does not work. I get the feeling that I will stump into
that wall more times if I just hack my way around the problem now.

El 13/08/14 a las #4, Cliff Kachinske escribió:
 Put the appending code in the controller.

 On Wednesday, August 13, 2014 7:14:46 AM UTC-4, pa...@cancamusa.net
 wrote:


 Dear all:
 In the process of moving functionality from models to modules, I'm
 trying to add some filesto the header. When the file was in
 models, I did:

 response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.js'))
 response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.css'))

 now that it's in modules, I tried:

 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.js'))
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.css'))

 but it doesn't work...
 I've found a workaround, the last line in JQPlot.xml was:

 return current.response.render('jqplot.html', d)

 so I can add script html tags to the template jqplot.html:

 script src=/karakolas/static/jqplot/jquery.jqplot.min.js/script
 script src=/karakolas/static/jqplot/jquery.jqplot.min.css/script

 but I'm sure it can be done better...
 Thanks

 -- 
 Resources:
 - http://web2py.com
 - http://web2py.com/book (Documentation)
 - http://github.com/web2py/web2py (Source code)
 - https://code.google.com/p/web2py/issues/list (Report Issues)
 ---
 You received this message because you are subscribed to a topic in the
 Google Groups web2py-users group.
 To unsubscribe from this topic, visit
 https://groups.google.com/d/topic/web2py/1h3Ni_iywzY/unsubscribe.
 To unsubscribe from this group and all its topics, send an email to
 web2py+unsubscr...@googlegroups.com
 mailto:web2py+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: add static files to header from a module

2014-08-13 Thread Pablo Angulo
El 13/08/14 a las #4, Anthony escribió:
 Can you show your module code? Are you doing the appending at the top
 level in the module, or within a function/method?

The latter:

 # -*- coding: utf-8 -*-
 # (C) Copyright (C) 2012-14 Pablo Angulo
 # This file is part of karakolas karakolas.org.

 # karakolas is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
 # published by the Free Software Foundation, either version 3 of the
 # License, or (at your option) any later version.

 # karakolas is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.

 # You should have received a copy of the GNU Affero General Public
 # License along with karakolas.  If not, see
 # http://www.gnu.org/licenses/.

 from gluon.html import URL, FORM
 from gluon import current
 from collections import defaultdict

 class JQPlot(FORM):

 def __init__(self, query,
  row_field, col_field, data_field,
  row_ids=None, col_ids=None,
  row_represent=None, col_represent=None,
 data_represent=None,
  _id='',
  **attributes):
 '''Muestra una gráfica ligeramente interactiva para visualizar
 una relacion que representa una funcion (ref1,ref2) - valor
 '''
 FORM.__init__(self, **attributes)
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.js'))
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.css'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.barRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.pointLabels.min.js'))

 self.query  = query
 self.row_field  = row_field
 self.col_field  = col_field
 self.data_field = data_field

 self.row_represent = row_represent or row_field.represent or
 (lambda x:x)
 self.col_represent = col_represent or col_field.represent or
 (lambda x:x)
 try:
 self.data_represent = data_represent or
 data_field.represent or (lambda x:x)
 except AttributeError:
 #A f.sum() or f.count() doesn't have a represent attribute
 self.data_represent = (lambda x:x)

 self.row_ids   = row_ids or [r[row_field] for r in
 current.db(query).select(row_field, groupby=row_field)]
 self.row_names = [self.row_represent(rid) for rid in self.row_ids]
 self.col_ids   = col_ids or [r[col_field] for r in
 current.db(query).select(col_field, groupby=col_field)]
 self.col_names = [self.col_represent(cid) for cid in self.col_ids]

 def xml(self):

 d = defaultdict(float)
 recs = current.db(self.query).select(
 self.row_field, self.col_field, self.data_field,
 groupby=self.row_field|self.col_field
)

 for row in recs:
 d[row[self.row_field],
 row[self.col_field]]=row[self.data_field]

 data = [[float(d[r,c]) for c in self.col_ids] for r in
 self.row_ids]
 series_labels = ','.join({label:'%s'}%self.row_represent(r)
 for r in self.row_ids)
 ticks = self.col_names

 d = dict(data=data,ticks=ticks, series_labels=series_labels)
 return current.response.render('jqplot.html', d)

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: add static files to header from a module

2014-08-13 Thread Pablo Angulo
El 13/08/14 a las #4, Leonel Câmara escribió:
 Simply adding to current.response.files may not works if the request
 is ajax (say your module is loaded).

But it's not loaded via ajax, I call it like this:

 @requires_get_arguments(('grupo', db.grupo),
 ('productor', db.productor),
 _consistency= (
 ((db.grupo.id==db.grupoXred.grupo) 
 
 (db.productor.grupo==db.grupoXred.red)),
 
 (db.productor.grupo==db.grupo.id) )
)
 @auth.requires_membership('admins_%s'%request.vars.grupo)
 def grafica_grupo_productor():
 '''Muestra tabla y grafica de productos x fecha_pedido para un
 productor fijo,
 con la cantidad total que se pide de cada producto en cada fecha
 '''

 iproductor = int(request.vars.productor)
 productor  = db.productor[iproductor]
 igrupo = int(request.vars.grupo)
 grupo  = db.grupo(igrupo)

 response.title = T('Estadísticas del grupo %s con
 %s')%(grupo.nombre, productor.nombre)

 def row_represent(pid):
 return db.producto[pid].nombre
 args = ((db.item.productoXpedido==db.productoXpedido.id) 
 (db.productoXpedido.pedido==db.pedido.id) 
 (db.pedido.productor==iproductor) 
 (db.item.grupo==igrupo),
 db.productoXpedido.producto,
 db.pedido.fecha_reparto,
 db.item.cantidad.sum())
 sheet = ROSheet(*args,
 row_represent=row_represent,
 col_totals=True)
 jqplot = JQPlot(*args,
 row_represent=row_represent,
 col_represent=str)
 return dict(sheet=sheet, jqplot=jqplot,
  nombre_productor=productor.nombre,
  grupo=grupo)

and the view is:

 {{extend 'layout.html'}}
 ... etc ...
 {{=jqplot}}
 {{=sheet}}
 ... etc ...


-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: add static files to header from a module

2014-08-13 Thread Pablo Angulo
I also tried to place the
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.js'))
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.css'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.barRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.pointLabels.min.js'))
in the xml method, but it didn't make to the response either.

El 13/08/14 a las #4, Pablo Angulo escribió:
 El 13/08/14 a las #4, Anthony escribió:
 Can you show your module code? Are you doing the appending at the top
 level in the module, or within a function/method?
 The latter:

 # -*- coding: utf-8 -*-
 # (C) Copyright (C) 2012-14 Pablo Angulo
 # This file is part of karakolas karakolas.org.

 # karakolas is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
 # published by the Free Software Foundation, either version 3 of the
 # License, or (at your option) any later version.

 # karakolas is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.

 # You should have received a copy of the GNU Affero General Public
 # License along with karakolas.  If not, see
 # http://www.gnu.org/licenses/.

 from gluon.html import URL, FORM
 from gluon import current
 from collections import defaultdict

 class JQPlot(FORM):

 def __init__(self, query,
  row_field, col_field, data_field,
  row_ids=None, col_ids=None,
  row_represent=None, col_represent=None,
 data_represent=None,
  _id='',
  **attributes):
 '''Muestra una gráfica ligeramente interactiva para visualizar
 una relacion que representa una funcion (ref1,ref2) - valor
 '''
 FORM.__init__(self, **attributes)
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.js'))
 current.response.files.append(URL('static',
 'jqplot/jquery.jqplot.min.css'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.barRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.categoryAxisRenderer.min.js'))
 current.response.files.append(URL('static',
 'jqplot/plugins/jqplot.pointLabels.min.js'))

 self.query  = query
 self.row_field  = row_field
 self.col_field  = col_field
 self.data_field = data_field

 self.row_represent = row_represent or row_field.represent or
 (lambda x:x)
 self.col_represent = col_represent or col_field.represent or
 (lambda x:x)
 try:
 self.data_represent = data_represent or
 data_field.represent or (lambda x:x)
 except AttributeError:
 #A f.sum() or f.count() doesn't have a represent attribute
 self.data_represent = (lambda x:x)

 self.row_ids   = row_ids or [r[row_field] for r in
 current.db(query).select(row_field, groupby=row_field)]
 self.row_names = [self.row_represent(rid) for rid in self.row_ids]
 self.col_ids   = col_ids or [r[col_field] for r in
 current.db(query).select(col_field, groupby=col_field)]
 self.col_names = [self.col_represent(cid) for cid in self.col_ids]

 def xml(self):

 d = defaultdict(float)
 recs = current.db(self.query).select(
 self.row_field, self.col_field, self.data_field,
 groupby=self.row_field|self.col_field
)

 for row in recs:
 d[row[self.row_field],
 row[self.col_field]]=row[self.data_field]

 data = [[float(d[r,c]) for c in self.col_ids] for r in
 self.row_ids]
 series_labels = ','.join({label:'%s'}%self.row_represent(r)
 for r in self.row_ids)
 ticks = self.col_names

 d = dict(data=data,ticks=ticks, series_labels=series_labels)
 return current.response.render('jqplot.html', d)

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Free web2py hosting for a free software web2py application

2014-03-25 Thread Pablo Angulo

Dear Philip:
I tried pythonanywhere and it could work, but I'd have to write code to 
mold into the limitations of that hosting and accept that a few things 
wouldn't work: do you still offer your spare hosting space? You'd need 
to install the following packages.


|sudo apt-get install latex-xcolor texlive-latex-extra 
texlive-fonts-recommended python-numpy python-setuptools python-pysqlite2

sudo easy_install xlutils|

Regards

On 21/03/14 10:11, Philip Kilner wrote:

Hi,

I have spare capacity on a 4Gb London-based Ubuntu 12.04 Linode.

The hosting management is via Virtualmin, so there are facilities for
email etc. etc.

As long as the server load is not going to be insane, I'd be happy to
host free of charge - drop me a note off-list if you'd like to pursue that.




--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
You received this message because you are subscribed to the Google Groups web2py-users group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [web2py] Re: /var/.htaccess and Internal Server Error

2013-04-15 Thread Pablo Angulo
El 15/04/13 16:31, LightDot escribió:
 That's intriguing. Since it's a clean server and you didn't put it
 there, it makes me wonder where it came from.

Hmmm, most probably, I untarred a file with a moodle file folder at the
wrong place, then moved the folder but not the hidden file .htaccess!
Thanks for your patience

-- 

--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




[web2py] copy database, problem with foreign key constraint

2013-02-26 Thread pablo . angulo
Hello:
I'm trying to copy the contents from the testing sqlite database into 
apache.
Both:
 - the script cpdb,
 - export and import of a csv file, 
 - manual, careful export and import of each table of a database
fail. The reason is related to foreign keys. The method

import_from_csv_files 

will assign new correlative values ot the id field, and thus all foreign 
keys will become invalid, if you have ever deleted even only one record in 
the original database.

Is there another way to copy the database?

Regards

-- 

--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




[web2py] Re: copy database, problem with foreign key constraint

2013-02-26 Thread pablo . angulo
The diagnostic is confirmed by the following experiment: I filled the few 
missing lines in the csv files with dummy data so that all ids are 
consecutive starting at 1, and the import worked.

-- 

--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




[web2py] Re: Graph Model (proposal to contribute)

2013-02-18 Thread pablo . angulo


https://lh5.googleusercontent.com/-kybjcR5IeLg/USI_PoFwEYI/AAM/qjEgUJHNrJA/s1600/tablas4.png
Thanks a ton, Jose, I did a much more modest attempt at the same thing:

print 'digraph Bloques{\n' \
  'ranksep=2\n' \
  'splines=true\n'
for table in db:
for field in table:
if field.type.startswith('reference'):
t = '%s - %s'%(table, field.type[10:])
type = field.type[10:]
elif field.type.startswith('list:reference'):
t = '%s - %s [arrowhead=veevee ]'%(table, field.type[15:])
else: continue
if field.name!=type:
 t += '[ label = %s ]'%field.name
print t
print '}'


This generates a diagram with only the references between the tables, 
labeling the arrows if the field name is different from the target table.
Calling 

dot -Tpng db.dot -o db_picture.png

gives a file like in the example above.

BTW; have you considered using canviz?:

 http://code.google.com/p/canviz/
I'm not sure it does what Massimo wants, because it might need the 
coordinates of the points, that are obtained with a call to 'dot'.

Regards

-- 

--- 
You received this message because you are subscribed to the Google Groups 
web2py-users group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




[web2py] Re: 'list:reference', contains, Mysql, instr

2013-01-22 Thread pablo . angulo


El lunes, 21 de enero de 2013 22:47:41 UTC+1, Massimo Di Pierro escribió:

 Now I understand the problem. You want to pass an expression where a value 
 is expected. I do not believe we can support this. INSTR does not solve the 
 problem because it would not be correct to looks for substrings. In fact 
 paper.authors may contain '|12|13|' and it would incorrectly return that 
 author '2' is one of authors because it is a substring.


ok, but we can use CONCAT to append and prepend '|', that's more standard 
that instr.
 


 You have to do it in two steps:

 person = db(db.person.name='').select().first()
 papers = db.paper.authors.contains(person.id).select()


But it's not a one-time query. I'm working in something like appadmin, 
tweaking smart_query and SQLFORM.grid to help the user build compund 
querys. I'd rather normalize the database.

BTW, I will come later with some ideas/questions.

Thanks again
 


 Massimo


 On Jan 21, 2013, at 3:33 PM, pablo@uam.es javascript: wrote:



 El lunes, 21 de enero de 2013 18:56:07 UTC+1, Massimo Di Pierro escribió:

 Before we attempt to fix this. It works for me as it is with sqlite. Why 
 does doesn't it wirk with mysql? MySQL has a LIKE operator. Wat error do 
 you get?


 execution of:

 db(db.paper.authors.contains(person.id))._select()

 gives:

 SELECT  person.id, paper.id, paper.title, paper.authors FROM person, 
 paper WHERE (paper.authors LIKE '%|person.id|%');
  
 which I think tries to find those papers whose authors field contains 
 the literal person.id, instead of the pairs (paper,person) such that 
 the person is one of the authors of the paper.

 With the modification I wrote before, it gets converted into:

 'SELECT  person.id, paper.id, paper.title, paper.authors FROM person, 
 paper WHERE INSTR(paper.authors, person.id);'

 with a different meaning.

 I can see why using the INSTR operator on MySQL may be better but do we 
 know it is faster?


 I haven't made any speed test, I'd go for anything that works in sqlite 
 and mysql/mariadb.

 Thanks for your attention!
  


 Massimo

 On Monday, 21 January 2013 08:55:40 UTC-6, pablo@uam.es wrote:

   Hello:
   I was getting incorrect SQL from statements like:

 db(db.paper.authors.contains(person.id)).select()

 where

 db.define_table('paper',
 Field('title'),
 Field('authors', 'list:reference person'),
 )


   so I rewrote dal.MySQLAdapter.CONTAINS from:

 def CONTAINS(self, first, second):
 if first.type in ('string', 'text'):
 key = '%'+str(second).replace('%','%%')+'%'
 elif first.type.startswith('list:'):
 key = 
 '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
 return '(%s LIKE %s)' % 
 (self.expand(first),self.expand(key,'string'))

 into:

 def CONTAINS(self, first, second):
 if first.type in ('string', 'text'):
 key = '%'+str(second).replace('%','%%')+'%'
 elif first.type.startswith('list:reference'):
 return 'INSTR(%s, %s)'%(first, str(second))
 elif first.type.startswith('list:'):
 key = 
 '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
 return '(%s LIKE %s)' % 
 (self.expand(first),self.expand(key,'string'))

 now the above query works, but that's in MySQL, not SQLite, which 
 apparently does not have  a INSTR operation, despite the fact that it is 
 advertised!

 https://www.sqlite.org/lang_corefunc.html

 Can anybody think of a solution that works in more databases




-- 





[web2py] Re: 'list:reference', contains, Mysql, instr

2013-01-22 Thread pablo . angulo


 person = db(db.person.name='').select().first()
 papers = db.paper.authors.contains(person.id).select()


 Sorry, I didn't read carefully enough. That's not what I need, I need to 
perform a join. My real-world query is rather like:

db.define_table('person',
Field('name', unique=True),
Field('some_field'),
)

Advisor = db.person.with_alias('advisor')
GradStudent = db.person.with_alias('grad')

db.define_table('thesis_project',
Field('advisors', 'list:reference person'),
Field('candidate', db.person),
Field('title', 'text')
)



and then:

db( db.thesis_project.advisors.contains(Advisor.id)  
   (db.thesis_project.candidate==GradStudent.id)  
   (Advisor.some_field==some_value)  
   (GradStudent.some_field==some_value)).select(...)



and it works in mysql using INSTR and CONCAT, and there are other solutions 
with other functions that don't seem to work in sqlite, even though some of 
them are advertised. That's my puzzle.


-- 





[web2py] 'list:reference', contains, Mysql, instr

2013-01-21 Thread pablo . angulo
  Hello:
  I was getting incorrect SQL from statements like:

db(db.paper.authors.contains(person.id)).select()

where

db.define_table('paper',
Field('title'),
Field('authors', 'list:reference person'),
)


  so I rewrote dal.MySQLAdapter.CONTAINS from:

def CONTAINS(self, first, second):
if first.type in ('string', 'text'):
key = '%'+str(second).replace('%','%%')+'%'
elif first.type.startswith('list:'):
key = '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
return '(%s LIKE %s)' % 
(self.expand(first),self.expand(key,'string'))

into:

def CONTAINS(self, first, second):
if first.type in ('string', 'text'):
key = '%'+str(second).replace('%','%%')+'%'
elif first.type.startswith('list:reference'):
return 'INSTR(%s, %s)'%(first, str(second))
elif first.type.startswith('list:'):
key = '%|'+str(second).replace('|','||').replace('%','%%')+'|%'
return '(%s LIKE %s)' % 
(self.expand(first),self.expand(key,'string'))

now the above query works, but that's in MySQL, not SQLite, which 
apparently does not have  a INSTR operation, despite the fact that it is 
advertised!

https://www.sqlite.org/lang_corefunc.html

Can anybody think of a solution that works in more databases

-- 





[web2py] sqlite OperationalError: database is locked in a cron job

2011-05-23 Thread Pablo Angulo
Hello: I'm working on a cron job that must write to the database: is
this allowed? I don't know if the following error is sqlite only:

  File web2py/gluon/dal.py, line 4487, in insert
return self._db._adapter.insert(self,self._listify(fields))
  File web2py/gluon/dal.py, line 772, in insert
raise e
pysqlite2.dbapi2.OperationalError: database is locked

Regards


[web2py] plugins for plugin_wiki

2011-05-09 Thread Pablo Angulo
  Hello!
  I have written two extra plugins for plugin-wiki, one for using Gallery:

http://galleria.aino.se/

and another for using videojs (html5 video with flash fallback):

http://videojs.com/

  Are you interested? Then how should I ship them: isolated or as a
patch to plugin_wiki? They are very simple, but they need extra css and
javascript files.

  Regards