developer.cl desarrollo, gestión y otras cosas acerca de proyectos de software

22Jun/090

Extendiendo manage.py para sincornizar con Flex

Publicado por lcruz

Estamos haciendo un sistema que tendrá como interfaces algunas pantallas en Flex por lo que ha surgido la necesidad de publicar algunos servicios remotos utilizando PyAMF. En Flex utilizamos Cairngorm como MVC, este requiere la definición de un archivo de servicios Services.xml que estoy intendando generar utilizando Python y que mejor que hacerlo utilizando el mismo estilo que utiliza DJango para la sincronización de la base de datos. Por ello estoy intenando generar una opción nueva el comando manage.py de la aplicación DJango:

manage.py syncflex

Gracias a la flexibilidad de DJango esto es bastante fácil nada más debes crear una clase que debes llamar Command que extienda a la clase BaseCommand y ubicarla en paquete managment/commands bajo alguna de tus aplicaciones en mi caso yo estoy haciendo un pequeño ERP así que la ubique en la ruta flex/managment/commands:

Arbol de Proyectos

En mi caso dado que mi comando no tiene argumentos extendere la clase NoArgsCommand :

class Command(NoArgsCommand):
 
    help = "Sync Flex Commands"
    requires_model_validation = False    
 
    def handle_noargs(self, **options):
 
        # Your code here

El método handle_noargs es el que nos permite ejecutar las acciones realizadas por nuestro comando cuando es invocado, en mi caso la implementación es la siguiente (algo básica por ahora):

def handle_noargs(self, **options):
 
        from pyamf.remoting.gateway.django import DjangoGateway
 
        import sys
 
        project = settings.ROOT_URLCONF.split('.')[0]
 
 
        #import types
        for app in models.get_apps():
            if project == app.__name__.split('.')[0]:
                app_name = app.__name__.split('.')[-2]
                package = project + '.' + app_name  + '.gateway'
                try:
                    mod = __import__(package, globals(), locals(), ['gateway'], -1)
                    for d in dir(mod):
                        attr = getattr(mod, d)
                        try:
 
                            if isinstance(attr, DjangoGateway):
                               self.processClass(d, attr)
 
                        except TypeError:
                            pass
                except ImportError:
                    pass

Como se puede ver su funcionamiento se basa en introspección, para ello busco un módulo llamado gateway dentro de mis aplicaciones DJango una vez que encuentro el módulo busco en él las clases que extiendan a DjangoGateway para generar el archivo Services.xml. Un ejemplo de mi archivo gateway.py es:

from pyamf.remoting.gateway.django import DjangoGateway
from django.contrib.auth.models import User
from sampleapp.contabilidad.models import Comprobante
from sampleapp.gateway.amf import AMFGateway 
 
class ComprobanteGateway(AMFGateway):
 
    def obtenerComprobantes(self, request, data):     
       # Implemetnar
       pass           
 
class CuentaGateway(AMFGateway):
 
    def obtenerCuentas(self, request, data):     
       # Implemetnar
       pass
 
contabilidadGateway = DjangoGateway({'gwComprobante' : ComprobanteGateway, 'gwCuenta' : CuentaGateway,})

Si vemos la implementación del método processClass tenemos lo siguiente:

def processClass(self, name, gateway):     
        import inspect   
 
        print ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
               "<cairngorm:ServiceLocator xmlns:mx=\"http://www.adobe.com/2006/mxml\""
               "xmlns:cairngorm=\"com.adobe.cairngorm.business.*\">\n")  
        for g in gateway.services:
            print ("<mx:RemoteObject id=\"" + g + "\" "
                   "\n\t\tdestination=\"" + g + "\" "
                   "\n\t\tendpoint=\"" + settings.REMOTING_URL +  "/" + name + "\" "
                   "\n\t\tshowBusyCursor=\"true\" " 
                   "\n\t\tresult=\"event.token.resultHandler( event );\" " 
                   "\n\t\tfault=\"event.token.faultHandler( event );\">")
 
            service = gateway.services[g]            
            for m in service.getMethods():
                print "\t<mx:method name=\"" + m + "\" />" 
            print "</mx:RemoteObject>\n"
 
        print "</cairngorm:ServiceLocator>"

Con eso ya estamos casí listos sólo nos falta agregar nuestra aplicación para que DJango la conozca y definir la variable REMOTING_URL para ello sólo editamos nuestro archivo settings.py:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'sampleapp.contabilidad',    
    'sampleapp.compra',
    'sampleapp.agricola',
    'sampleapp.rrhh',
    'sampleapp.maquinaria',
    'sampleapp.comun',    
    'sampleapp.actividad',
    'sampleapp.flex',
)
 
# --------------------------------------------------
# My customs settings
# --------------------------------------------------
REMOTING_URL = "http://localhost:8080/remoting"

Con eso ya estamos listo ahora sólo ejecutamos manage.py syncflex en la consola:

 manage.py syncflex

Aquí una muestra del resultado:

<?xml version="1.0" encoding="utf-8"?>
<cairngorm:ServiceLocator xmlns:mx="http://www.adobe.com/2006/mxml"xmlns:cairngorm="com.adobe.cairngorm.business.*">
 
<mx:RemoteObject id="gwCuenta" 
		destination="gwCuenta" 
		endpoint="http://localhost:8080/remoting/contabilidadGateway" 
		showBusyCursor="true" 
		result="event.token.resultHandler( event );" 
		fault="event.token.faultHandler( event );">
	<mx:method name="obtenerCuentas" />
</mx:RemoteObject>
 
<mx:RemoteObject id="gwComprobante" 
		destination="gwComprobante" 
		endpoint="http://localhost:8080/remoting/contabilidadGateway" 
		showBusyCursor="true" 
		result="event.token.resultHandler( event );" 
		fault="event.token.faultHandler( event );">
	<mx:method name="obtenerComprobantes" />
</mx:RemoteObject>
 
</cairngorm:ServiceLocator>
24May/090

Complementos de búsqueda con OpenSearch

Publicado por lcruz

Hace poco escribí algunas extensiones utilizando OpenSearch. OpenSearch es un conjunto de estándares que permiten la publicación de los resultados de los sistemas de búsqueda permitiendo de este modo la sindicación y la agregación de contenidos entre diferentes motores y sistema de búsqueda. OpenSearch se compone de 3 partes, un formato para la descripción de motores de búsqueda, un formato para la descripción de los resultados de búsqueda llamado OpenSearch Response y finalmente los agregadores o sitios capaces de mostrar resultados en formato OpenSearch.

Navegadores como IE7 y Firefox soportan ya OpenSearch, es decir, permiten la incorporación de complementos de búsqueda mediante este estándar, al mismo tiempo cada uno de estos navegadores extiende las capacidades estándares de OpenSearch agregándole sus propios sabores.

La utilización de OpenSearch permite incorporar algo de usabilidad a tus sitios Web, si es que, los mismos presentan buscadores a los usuarios. Yo en mi caso particular utilizo un diccionario en inglés de la empresa WordMagic, este diccionario presenta un buscador en su portada mediante el cuál puedes acceder a las palabras del diccionario. Dado que a mí me resultaba bastante molesto ingresar al sitio para realizar la búsqueda es que me decidí a hacer este complemento, además es muy sencillo hacerlo y lo puedes incorporar también en tus sitios. A continuación veremos este ejemplo:

<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/"> 
    <ShortName>WordMagic</ShortName> 
    <Description>Word Magic Software, Inc. es una compañia dedicada al desarrollo de software con sede en Houston, Texas.</Description> 
    <InputEncoding>UTF-8</InputEncoding> 
    <Image width="16" height="16" type="image/x-icon">http://wordmagicsoft.com/favicon.ico</Image> 
    <Url type="text/html" method="POST" template="http://wordmagicsoft.com/diccionario/search.php"> 
        <Param name="word_to_search" value="{searchTerms}"/> 
        <Param name="search_option" value="es-en"/> 
    </Url> 
</OpenSearchDescription>

Los parámetros especificados son los siguientes:

  • OpenSearchDescription: Este es el nodo principal de un documento OpenSearch.
  • ShortName: Un pequeño titulo que identifique al buscador.
  • Description: Una descripción más larga acerca del buscador.
  • InputEncoding: El encoding que soporta nuestro el buscador.
  • Image: La url de algún icono representativo de nuestro buscador.
  • URL: Describe la interfaz para nuestro buscador, o sea aquella que responderá a las búsquedas. El atributo template permite especificar la url y el atributo method permite indicar si se hará un GET o un POST a la url.

Eso es todo! Guardamos el contenido en un archivo xml, en mi caso le puse wordmagic.xml y ya esta! ahora solo nos queda agregarlo a nuestro navegador, para ello utilizaremos un pequeño javascript, para ello puedes construirte una página con lo siguiente:

<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
    function addWordMagicSearch() { 
        window.sidebar.addSearchEngine("http://developer.cl/opensearch/wordmagic.xml", "http://wordmagicsoft.com/favicon.ico", "WordMagic", ""); 
    } 
//--> 
</SCRIPT>

Luego solo tienes que agregar la llamada en el HTML:

<a href="#" onclick="addWordMagicSearch();">Agregar búsqueda en WordMagic</a>


Mira aquí esta el mio.

8Jul/080

Twitter, algo útil despues de todo.

Publicado por lcruz

image

Antes pensaba que twitter era una perdida de tiempo ¿para que diablos alguien seguirá a otros en una especie de reality virtual con sólo 140 caracteres por escena?   Ahora lo llevo utilizando una par de días y lo encuentro de una simpleza similar a del.icio.us pero con un potencial de igual magnitud: acceso a información de primera línea, una mirada sobre el hombro de gente que la lleva en determinados temas.   Me quede pensando en esto luego de descubrir Watin ojeando twitter. Con una rápida mirada te enteras del diario vivir de gente que consideras un referente, sin quererlo una especie de consejo, un mini-blog, en fin, una herramienta útil para un aprendiz de Jedi como yo.

8Jul/080

Watin, mejor que Selenium pero sólo para .NET

Publicado por lcruz

image

Acabo de encontrar a Watin, una herramienta OpenSource para la automatización de pruebas mediante la imitación o grabación de las secuencias de interacción sobre una página Web, según un experto en el tema es mejor que Selenium, al parece su uso es bastante sencillo y soporta Internet Explorer y Firefox.   Lamentablemente sirve solo para aplicaciones .NET, así que por ahora no me queda otra que seguir intentando configurar Selenium.