Problem mit __getattr__ und Unauthorized...

Django, Flask, Bottle, WSGI, CGI…
Antworten
woolfy
User
Beiträge: 19
Registriert: Montag 6. Februar 2006, 15:14
Wohnort: Stuttgart

Montag 6. Februar 2006, 16:13

Hallo zusammen,

irgendwie muss ich wohl einen Denkfehler haben, oder ich bin in dem falschen glauben es verstanden zu haben...

Ich möchte es einem Objekt (folderish) (ich nenn es hier mal X) ermöglichen, außer auf seine eigenen Attribute auch noch auf weitere zugreifen zu können...
Diese "weiteren Attribute" liegen in Form von PythonScripts in einem Verzeichnis (Y) unterhalb von X (also nicht direkt in X).

Nun habe ich versucht dies mit __getattr__ zu erreichen.
Wenn ich nun versuche ein Script (Z) welches in Y liegt, über X aufzurufen, dann bekomme ich einen "Unauthorized Fehler".

Also z.B. bei folgendem Zugriff:
PythonScript 1: /test_call
=> context.X.getTest()
PythonScript 2: /X/abc/def/Y/getTest
=> return "ok"


Ich bin als Manager/Owner unterwegs und kann Z direkt, problemlos ausführen.

Code: Alles auswählen

class foo(AccessControl.Role.RoleManager, Persistent, Acquisition.Implicit, SimpleItem, PropertyManager):

    ...stuff...

    def __getattr__(self, key):
        """ look for extensions """
        ext = self.extensions() # ext = Folder-Instanz
        if key in ext.objectIds('Script (Python)'):
            #return ext[key] <= geht nicht
            return getattr(ext, key) <= geht auch nicht
        if self.__dict__.has_key(key):
            return self.__dict__[key]
        else:
            raise AttributeError, "Das Objekt hat kein Attribut Namens '%s.'" % (key)

    ...much more stuff...

Danke im Vorraus,
Grüße
Jens

___________
Python 2.1.3
Zope 2.5.1
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 6. Februar 2006, 18:20

woolfy hat geschrieben:

Code: Alles auswählen

    def __getattr__(self, key):
        """ look for extensions """
        ext = self.extensions() # ext = Folder-Instanz
        if key in ext.objectIds('Script (Python)'):
            #return ext[key] <= geht nicht
            return getattr(ext, key) <= geht auch nicht
        if self.__dict__.has_key(key):
            return self.__dict__[key]
        else:
            raise AttributeError, "Das Objekt hat kein Attribut Namens '%s.'" % (key)

Hi Jens!

Konzentriere dich darauf, ob der Ordner mit den Erweiterungen überhaupt gefunden wird.

Code: Alles auswählen

def tryit1(self):
    return self.absolute_url()

Code: Alles auswählen

def tryit2(self):
    folder_name = "extensions"
    if hasattr(self, folder_name):
        folder_obj = getattr(self, folder_name)
        return folder_obj.absolute_url()
    else:
        return "Ordner nicht gefunden"
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 6. Februar 2006, 18:37

Hi Jens!

Code: Alles auswählen

    def tryit3(self, key):
        folder_name = "extensions"
        if hasattr(self, folder_name):
            folder_obj = self[folder_name]
            attr_obj = getattr(folder_obj, key)
            if callable(attr_obj):
                return attr_obj()
            else:
                return attr_obj
        else:
            return "Ordner nicht gefunden" 
Wenn das funktioniert, dann kannst du es mal versuchshalber in __getattr__ einbauen. Wenn es in __getattr__ nicht funktioniert, dann musst du wahrscheinlich mit dieser Einschränkung leben.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 7. Februar 2006, 09:27

Hi Jens!

Lass mich nicht dumm sterben. Funktioniert es?

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
woolfy
User
Beiträge: 19
Registriert: Montag 6. Februar 2006, 15:14
Wohnort: Stuttgart

Dienstag 7. Februar 2006, 11:25

Hallo gerold!

Vielen Dank für deine Hilfe und die schnelle Reaktion.

Die Art und Weise des Aufrufs macht die Probleme und durch dein Beispiel tryit3 wurde das sehr schön klar:

Code: Alles auswählen

    def tryit3(self, key):
        ...
        if callable(attr_obj):
            return attr_obj()
        else:
            return attr_obj


Wenn ich das richtig sehe, dann gibt __getattr__ nur die Instanz des Attributes zurück, und nicht das Ergebnis, wenn man diese auswertet.
__call__ bzw. __repr__ oder sonst was, wird erst nach der Rückgabe des Attributes auf dieses ausgeführt.

Code: Alles auswählen

## folgendes funktioniert:

# Aufruf:
context.X.getTest
# __getattr__:
return getattr(extensions, key)()

##Das Problem dabei ist, dass ich dann bereits den return von "getTest"
##bekomme. Dadurch kann ich keine Parameter übergeben. :o(



## folgendes funktioniert nicht:

# Aufruf:
context.X.getTest()
# __getattr__:
return getattr(extensions, key)

ErrorType: Unauthorized
ErrorValue: You are not allowed to access getTest in this context
ErrorMessage: 


Ich sehe das so:

X.getTest(req=REQUEST)

X wurde zuvor mittels __getattr__ von context ermittelt.
<X instance object>.getTest(req=REQUEST)

Nun soll getTest mittels __getattr__ von X ermittelt werden.
__getattr__ erhält folgende Parameter:
self = <X instance object>, key = 'getTest'

Eigentlich sollte nun __getattr__ die Instanz von getTest zurückgeben, so dass dann folgendes entstehen würde:
<getTest Python Script Instance>(req=REQUEST)

Durch die Klammern wird dann __call__ des Python Scripts mit dem Parameter req aufgerufen.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 7. Februar 2006, 12:01

woolfy hat geschrieben:

Code: Alles auswählen

ErrorType: Unauthorized
ErrorValue: You are not allowed to access getTest in this context
ErrorMessage:
Hi Jens!

Sieht so aus, als ob der Sicherheitsmechanismus von Zope blockt. Entweder du übergehst ihn, indem du direkt auf das Skript zugreifst oder du fragst dich beim DZUG durch ob es eine Möglichkeit gibt, den Sicherheitsmechanismus an deine Bedürfnisse anzupassen. Ich kann dir in diesem Fall leider nicht weiter helfen. Vielleicht genügt es dir ja auch schon, eine Proxy-Funktion (so wie tryit3) zu schreiben, der du den Namen des aufzurufenden Python-Skripts und die Parameter (*args, **dargs) übergeben kannst. Ob das in deine Programmstrategie passt, weiß ich leider nicht.

Code: Alles auswählen

ergebnis = context.X.ext("getTest", vorname="Gerold")
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
woolfy
User
Beiträge: 19
Registriert: Montag 6. Februar 2006, 15:14
Wohnort: Stuttgart

Dienstag 7. Februar 2006, 12:56

Hi gerold,

jetzt wollte ich gerade ne Mail an Zopes Mailing-List schreiben und dabei ist mir ne Idee gekommen.

Das hier funktioniert nun einwandfrei.

Code: Alles auswählen

    def __getattr__(self, key):
        """ look for extensions """
        ext = self.extensions()
        if ext.__dict__.has_key(key):
            return ext.__dict__[key]
        if self.__dict__.has_key(key):
            return self.__dict__[key]
        else:
            raise AttributeError, "Das Objekt hat kein Attribut Namens '%s.'" % (key)
Eigentlich nur zu einfach, aber ich wusste nicht, dass man so ohne weiteres auf __dict__ einer anderen Instanz zugreifen kann..

Ich danke dir für deine Zeit und deine Anregungen!
Gruß
Jens
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 7. Februar 2006, 13:36

woolfy hat geschrieben:Eigentlich nur zu einfach, aber ich wusste nicht, dass man so ohne weiteres auf __dict__ einer anderen Instanz zugreifen kann..
Hi Jens!

Da sieht man den Wald vor lauter Bäumen nicht mehr. :lol:
Freut mich dass es jetzt funktioniert.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten