from datetime import date, datetime, timedelta
def menor_edad(nascut):
""" accepts a string date in iso format Y-m-d and returns True if
it is in spanish legal age today """
t=timedelta(seconds=31556926*18)
fa_divuit=date.today()-t
fecha=datetime.strptime(nascut, '%Y-%m-%d').date()
return (fecha > =fa_divuit)
miércoles, 29 de febrero de 2012
Menor de edad en python / Legal age in python
Hoy día 29/02/2012 (29 de febrero de año bisiesto), me he encontrado con que el algoritmo que usaba para el cálculo de minoría de edad me ha fallado. Después de varias indagaciones he dejado este como bueno:
lunes, 27 de febrero de 2012
Presentación del vector VEGA de la ESA
En este otro vídeo de Euronews hay entrevistas y se profundiza en los detalles más innovadores del proyecto tales como la estructura hecha en materiales compuestos con el método del "filament winding".
viernes, 24 de febrero de 2012
Filtrado fácil de clave foránea en una ficha de django
Es sabido que django mapea las claves foráneas a un ModelChoiceField en ModelForm, pero ¿qué ocurre cuando sólo queremos seleccionar un subconjunto de ellas?.
Por ejemplo, supongamos que estamos dando de alta un empleado y a la hora de seleccionar su categoría sólo queremos que aparezcan las que están asociadas a su sección.
Tenemos la ficha:
class AddForm(forms.ModelForm):
class Meta:
model=Empleado
fields=('clave', 'descripcion', 'categoria', 'jefe_seccion', 'email',)
La propiedad queryset del campo categoría estará definida por defecto como Categoria.objects.all(), así que hacemos:
Con lo que en la ficha sólo nos saldrán las categorías de la sección actual.
Otra forma más complicada consiste en pasarle el parámetro al constructor de la clase pero hay que hacerlo con los kwargs por que si no tendremos problemas en cuando queramos usar la ficha para editar.
Por ejemplo, supongamos que estamos dando de alta un empleado y a la hora de seleccionar su categoría sólo queremos que aparezcan las que están asociadas a su sección.
Tenemos la ficha:
class AddForm(forms.ModelForm):
class Meta:
model=Empleado
fields=('clave', 'descripcion', 'categoria', 'jefe_seccion', 'email',)
La propiedad queryset del campo categoría estará definida por defecto como Categoria.objects.all(), así que hacemos:
p=AddForm()
p.fields['categoria'].queryset=Categoria.objects.filter(seccion=self.seccion)
Con lo que en la ficha sólo nos saldrán las categorías de la sección actual.
Otra forma más complicada consiste en pasarle el parámetro al constructor de la clase pero hay que hacerlo con los kwargs por que si no tendremos problemas en cuando queramos usar la ficha para editar.
class AddForm(forms.ModelForm):
categoria=forms.ModelChoiceField( label=u'Categoría', queryset = Categoria.objects.none())
def __init__(self, *args, **kwargs):
sec = kwargs.pop('sec', None)
super(AddForm, self).__init__(*args, **kwargs)
if sec:
self.fields['categoria'].queryset = Categoria.objects.filter(seccion = sec)
class Meta:
model=Empleado
fields=('clave', 'descripcion', 'categoria', 'jefe_seccion', 'email',)
domingo, 12 de febrero de 2012
Use subversion in windows with the command line
if you hate TortoiseSVN and you prefer to work with svn manually, you can use this wonderful client
CollabNet subversion Command-Line Client
CollabNet subversion Command-Line Client
Usar subversion en windows con la línea de comandos
Por si alguien odia el TortoiseSVN y prefiere trabajar con el subversion "a mano", recomiendo este cliente de CollabNet
CollabNet subversion Command-Line Client
CollabNet subversion Command-Line Client
sábado, 11 de febrero de 2012
Procesador de texto "Sublime Text"
No soy yo muy dado a cambiar mi preciado vi para programar. Sin embargo, me he encontrado con este procesador de texto (hecho en python) que tiene versiones para Linux, Win y Mac. Tiene muy buena pinta. Su nombre es Sublime Text.
Para empezar a usarlo ve a una carpeta que tenga código. Haz Project->Save As... luego Project->Add Folder.
Voy a probarlo una temporada a ver que tal.
Para empezar a usarlo ve a una carpeta que tenga código. Haz Project->Save As... luego Project->Add Folder.
Voy a probarlo una temporada a ver que tal.
martes, 7 de febrero de 2012
Configurar logging en python y django con yaml
Os paso el esquema de logging que utilizo en mis aplicaciones por si os puede servir de ayuda. Lo he ido montando a partir de diversas fuentes y experiencias.
Un punto importante es dejar el fichero de configuración del logging fuera del programa para independizar mejor el sistema de logging de la aplicación.
Este puede ser un ejemplo del fichero de configuración en yaml (logger.conf):
Para cargar la configuración, primero parseamos el yaml (PyYAML) y luego lo enviamos a dictConfig, que realiza la configuración así:
Ahora ya podemos el usar el sistema. En general, es conveniente nombrar cada logger con el nombre de su módulo para que cuando haya muchos mensajes sepamos cuál los está enviando, para ello podemos usar el valor de __name__, así:
Si queremos que cada clase tenga su logger privado, tenemos que tomar una pequeña precaución para evitar un error si otros usan una librería nuestra con otro sistema de handles,
Declaramos una clase "nula":
y ahora, en la clase hacemos
Como veis es un tema un poco denso pero que una vez bien configurado nos será imprescindible para trazar correctamente las aplicaciones. Espero que os haya ayudado.
Un punto importante es dejar el fichero de configuración del logging fuera del programa para independizar mejor el sistema de logging de la aplicación.
Este puede ser un ejemplo del fichero de configuración en yaml (logger.conf):
version: 1
formatters:
brief:
format: '%(name)s - %(levelname)s - %(message)s'
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
detailed:
format: '%(asctime)s %(module)-17s line:%(lineno)-4d %(levelname)-8s %(message)s'
email:
format: 'Timestamp: %(asctime)s\nModule: %(module)s\n Line: %(lineno)d\nMessage: %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: brief
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: detailed
filename: app.log
mode: a
maxBytes: 10485760
backupCount: 5
smtp:
class: logging.handlers.SMTPHandler
level: ERROR
formatter: email
mailhost: smtp.xxxxx.es
fromaddr: yyy@xxxx.es
toaddrs: yyyy@xxxx.es
subject: Error en aplicacion XX
root:
level: DEBUG
handlers: [console]
Se observan los formateadores de los mensajes y los handlers para la cónsola, fichero y correo. Por defecto el logging sale por cónsola, si queremos que los errores salgan por email handlers de root sería [console, smtp], para fichero que rotara cada maxBytes [file], etc... Realmente cómodo.Para cargar la configuración, primero parseamos el yaml (PyYAML) y luego lo enviamos a dictConfig, que realiza la configuración así:
import yaml
import logging
#nos aseguramos de que dictConfig esté presente (python 2.7), sino, lo cargamos de la libreria de django
try:
from logging.config import dictConfig
except ImportError:
from django.utils.dictconfig import dictConfig
# Cargamos la configuracion del fichero, la parseamos y la enviamos a dictConf
try:
logging.config.dictConfig(yaml.load(file('logger.conf','r')))
except Exception, e:
print "Error configurating logger ", str(e)
Ahora ya podemos el usar el sistema. En general, es conveniente nombrar cada logger con el nombre de su módulo para que cuando haya muchos mensajes sepamos cuál los está enviando, para ello podemos usar el valor de __name__, así:
logger=logging.getLogger(__name__) # __name__ contiene el nombre del modulo
logger.debug("blah blah")
Si queremos que cada clase tenga su logger privado, tenemos que tomar una pequeña precaución para evitar un error si otros usan una librería nuestra con otro sistema de handles,
Declaramos una clase "nula":
class Nullhandler(logging.Handler):
def emit(self, record):
pass
y ahora, en la clase hacemos
class Clase():
def __init__(self):
self.__logger=logging.getLogger(__name__)
self.__logger.addHandler(NullHandler())
self.__logger.debug("clase iniciada")
Como veis es un tema un poco denso pero que una vez bien configurado nos será imprescindible para trazar correctamente las aplicaciones. Espero que os haya ayudado.
Suscribirse a:
Entradas (Atom)