[Python] mod_python ed il giusto handler

Andrea Giammarchi andrea a 3site.it
Ven 18 Ago 2006 23:06:44 CEST


Lawrence Oluyede ha scritto:
> Mi scrivi 5 righe della parte Python di gestione della roba JS con la
> tua libreria?
ti posto in fondo tutta la libreria .. che è ancora alpha e non è 
completa, ha diversi buchi, ma tutto sommato comincia a funzionare




> Non trovo un motivo valido per avere questa caratteristica
> sinceramente, magari mi sbaglio
esporti classi che hanno metodi utili per il JS
da JS usi queste classi, le istanzi, sfrutti gli oggetti già definiti 
dalla lib e per ogni oggetto hai già i metodi e per ogni metodo i tre 
metodi call, result, progress, puoi usarli tutti o nessuno
Questa è la parte che interessa il primo invio poi questi oggetti, visto 
che hai esportato delle classi presenti con il methodTable, puoi usarli 
sul client o sul server perchè sono già presenti, il caso di oggetti
non presenti e creati runtime è molto particolare e sono un pò stanco 
per spiegarlo bene.




> E' troppo perchè sono varie funzioni.
appunto, io vorrei avere tutto disponibile subito


> Quindi scrivi una lib in Python per risolvere un problema che ha solo
> quella schifezza di PHP?
ho già risposto a questa domanda, scrivo una lib che non è per l'uno o 
per l'altro, ma che per avere senso a livello di portabilità del client 
deve basarsi o su JSON o su PHP_Serializer, io ho scelto la seconda per 
rispetto del predominante nel web, PHP



> Interazione avanzate in AJAX?
si, se AHAH è l' abc , con altre lib puoi fare interazioni più 
complesse, quindi più avanzate



>
>> > callRemote("sayHello").addCallback(function(str) {alert(str)})
>> la callback semplifica ? callRemote è una sola funzione ?
>> devo farne una per ogni tipo di callRemote ??? .... e quando ti passa 
>> a te ?
>
> Che vuol dire tipo di callRemote? La callRemot chiama una funzione e
> piglia il valore di ritorno. Che c'è da riscrivere?
niente, avevo capito male ... però questo non è un approccio procedurale ?
io preferirei
myClassVar.sayHello.call();

e nel frattempo hai anche un'istanza di classe da gestire come vuoi



> Tutto su che?
u ... unicode


> L'hai detto tu che non usi JSON perchè non c'è una libreria in PHP
> decente preinstallata. Tra l'altro non avrai lo stesso problema di
> deployment con la tua libreria rispetto a quelle più performanti per
> PHP ma non preinstallate?
molto meno, per il semplice fatto che non ci sono caratteri da 
modificare, solo length da sfruttare.
La serializzazione / unserializzazione di PHP è molto più semplice di 
quella json, sia in conversione che in riconversione, Python e C# se la 
cavano bene anche senza moduli dedicati.
Il problema della length per UTF-8, come ho detto, è pià per portabilità 
della classe PHP_Serializer che altro, perchè trattando stringhe come 
text (numero dei caratteri), non è necessario usare
UTF-8 con altri linguaggi diversi dal PHP, quindi è molto rapida.

Anzi ... a dirla tutta, in PyRex le uniche reali ottimizzazioni sono 
proprio per la __slen, che se "inusata", potrebbe avere poco senso di 
esistere.


> Non è un partito preso, è un non reinventare la ruota
infatti non l'ho reinventata, l'ho solo aggiustata (male, datemi tempo)


> La tua lib in pyrex sarà ancora meno portabile sui server che non
> preinstallano le librerie JSON in PHP performanti, vero?
come sopra








ACE.py
import types, re, PHP_Serializer

HAND_RULES = {
    "DEBUG"    :False,
    "UTF8"    :False,
    "GZ"    :False
}


def in_list(value, values):
    result = False
    for i in range(0, len(values)):
        if value == values[i]:
            result = True
            break
    return result

class ACE:
   
    php = None        # PHP_Serializer
    utf8 = False        # is UTF8 enabled or not
    next = True        # has any error
    gz = False        # uses gz compression
    dodebug = False        # creates a debug file
    debug = []        # debug informations
    types = {        # valid variable types
        "s":"string", "N":"null", "O":"Class", "b":"boolean", 
"i":"integer", "d":"float", "a":"array", "u":"undefined"
    }
   
    def __init__(self, settings):
        self.utf8 = settings["UTF8"]
        self.dodebug = settings["DEBUG"]
        self.gz = not self.dodebug and settings["GZ"]
        self.php = PHP_Serializer.PHP_Serializer(self.utf8)
   
    def getMethods(self, classDict):
        tmp = None
        result = []
        if classDict.has_key("methodTable") and 
type(classDict["methodTable"]) is types.DictType:
            for key in classDict["methodTable"]:
                tmp = classDict["methodTable"][key]
                if type(tmp) is types.DictType and (not 
tmp.has_key("access") or tmp["access"] == "remote"):
                    result.append(key)
        return result
   
    def getMethodInformations(self, tmpclass, method):
        i = 0
        result = {}
        vars = tmpclass.__class__.__dict__["methodTable"][method]
        if vars.has_key("arguments") and type(vars["arguments"]):
            result = {"info":[], "required":0}
            if type(vars["arguments"]) is types.ListType:
                for key in range(0, len(vars["arguments"])):
                    
result["info"].append({"type":self.parseType(vars["arguments"][key]),"required":self.isRequired(vars["arguments"][key])})
            elif type(vars["arguments"]) is types.DictType:
                for key in vars["arguments"]:
                    
result["info"].append({"type":self.parseType(vars["arguments"][key]),"required":self.isRequired(vars["arguments"][key])})
            if result["info"][i]["required"]:
                result["required"] = result["required"] + 1
            i = i + 1
        return result

    def parseType(self, value):
        result = "u"
        if value.has_key("type"):
            result = value["type"].lower()
            if result == "string":
                result = "s"
            elif result == "int" or result == "integer":
                result = "i"
            elif result == "null" or result == "none":
                result = "N"
            elif result == "class" or result == "object":
                result = "O"
            elif result == "bool" or result == "boolean":
                result = "b"
            elif result == "array" or result == "list" or result == 
"dict" or result == "tuple":
                result = "a"
            elif result == "float" or result == "double" or result == 
"long":
                result = "d"
        return result

    def isRequired(self, value):
        result = False
        if value.has_key("required"):
            result = value["required"]
        return result

    def goodRequestVariable(self, settings, i, post, hasinfo):
        if self.next:
            self.next = len(post) > 0
        if self.next and hasinfo and settings["info"].has_key(i):
            if post[0] != settings["info"][i]["type"] and 
settings["info"][i]["type"] != "u":
                if self.dodebug:
                    self.debug.append("Variable #" + str(i + 1) + ' of 
type ' + self.types[settings["info"][i]["type"]] + " is not defined or 
is not correct: " + post)
                self.next = False
        return self.next

    def callClassMethod(self, className, method, _POST):
        i = 0
        istring = "_0"
        hasinfo = False
        args = settings = methodInfo = []
        vars = {}
        tmpclass = self.getClass(className)
        if(tmpclass != None):
            if in_list(method, 
self.getMethods(tmpclass.__class__.__dict__)):
                vars = self.getMethodInformations(tmpclass, method)
                if vars["required"] == 0 or _POST.has_key("_" + 
str((vars["required"] - 1))):
                    while _POST.has_key(istring) and 
self.goodRequestVariable(vars, i, _POST, hasinfo):
                        if self.dodebug:
                            methodInfo.append("args[" + str(i) + "] = " 
+ _POST[istring])
                        args.append(self.unserialize(_POST[istring]))
                        i = i + 1
                        istring = "_" + str(i)
                    if self.next:
                        settings = []
                        i = len(args)
                        for i in range(0, len(args)):
                            settings.append("args[" + str(i) + "]")
                        method = method + "(" + ",".join(settings) + ")"
                        exec "istring=self.php.serialize(tmpclass." + 
method + ")"
                        if self.dodebug:
                            method = method + "<br />" + "<br 
/>".join(methodInfo)
                    elif self.dodebug:
                        self.debug.append("ACE has killed itsself, bye 
bye.")
                elif self.dodebug:
                    while _POST.get("_" + i, None) != None:
                        i = i + 1
                    self.debug.append(method + " method requires at 
least " + vars["required"] + " params and not " + i)
            elif self.dodebug:
                self.debug.append("Choosed method is not availbale: " + 
method)
        elif self.dodebug:
            self.debug.append("Choosed Class or method is not valid: " + 
className + "." + method)
        if not self.next:
            istring = ""
        return istring
   
    def exportClass(self, className):
        result = settings = []
        tmpclass = self.getClass(className)
        if tmpclass != None:
            settings = self.getMethods(tmpclass.__class__.__dict__)
            for i in range(0, len(settings)):
                result.append(settings[i])
        elif self.dodebug:
            self.debug.append("Class " + className + " is not valid")
        return result
   
    def getClass(self, className):
        classExists = None
        try:
            exec "import " + className
            classExists = eval(className + "." + className + "()")
        except:
            classExists = None
        return classExists
   
    def unserialize(self, post):
        result = None
        try:
            result = self.php.unserialize(post)
        except:
            if self.dodebug:
                self.debug.append("Unserialize Exception [utf8: " + 
str(self.utf8) + "] with this var: " + pos)
            self.next = False
        return result;
   

ace = ACE(HAND_RULES)
_POST = {"_0":"s:4:\"ace!\";"}
print ace.exportClass("MyClass")
ace.callClassMethod("MyClass", "hello", _POST)




MyClass.py
class MyClass:
   
    methodTable = {
        "hello":{"access":"remote",
             "arguments":[{
                "type":"string",
                "required":True
            }]}
        }
   
    def hello(self, str):
        print str



Devo ancora lavorarci sopra ... anche e soprattutto per l'import 
dinamico (ogni consiglio è bene accetto)


Maggiori informazioni sulla lista Python