User:Enus Linden/Office Hours/2008 July 18

From Second Life Wiki
Jump to navigation Jump to search
  • [9:29] Saijanai Kuhn: Ah as a way of introducing Tao's topic later: https://wiki.secondlife.com/wiki/Pyogp/Client_Lib/Development/Zope
  • [9:29] Enus Linden: thanks sai, was grabbing that link myself
  • [9:29] Asterion Coen: hehe yes, i was about to ask what Pyogp is :)
  • [9:30] Saijanai Kuhn: And generically https://wiki.secondlife.com/wiki/Pyogp/
  • [9:30] Enus Linden: and more generally, and to your question
  • [9:30] Enus Linden: [1]
  • [9:30] Locklainn Linden: hahah
  • [9:30] Enus Linden: sigh
  • [9:30] Locklainn Linden: wow
  • [9:30] Enus Linden: sai is my secretary now, hired on the spot
  • [9:30] Saijanai Kuhn: can't type well, but the spam just flies off the fingertips
  • [9:30] Locklainn Linden: haha
  • [9:30] Tao Takashi: heh :)
  • [9:31] Infinity Linden: hmm... reads your mind... knows how to rile the populous... purports to be a secret smalltalk agent...
  • [9:31] Enus Linden: So i reckon we might as well get rolling
  • [9:32] Bartholomew Kleiber: Hi all
  • [9:32] Enus Linden: thanks for coming to the first of my office hours. We're gonna talk pyogp today
  • [9:32] Enus Linden: and for the forseeable future
  • [9:32] Infinity Linden: yay
  • [9:32] Saijanai Kuhn: pyogp => https://wiki.secondlife.com/wiki/Pyogp/
  • [9:32] Enus Linden: as other topics need to pop up, they will i'm sure
  • [9:33] Enus Linden: The intent today isn't so much to introduce pyogp, the wiki can serve that function
  • [9:33] Enus Linden: we are gonna have Tao give us some words on pyogp's use of zca thoguh
  • [9:34] Enus Linden: tao, you ready to chat?
  • [9:34] Tao Takashi: Mostly answering question of those who have read the tutorial but might not get the concept or are confused in general
  • [9:34] Tao Takashi: yes
  • [9:34] Saijanai Kuhn: ZCA intro => https://wiki.secondlife.com/wiki/Pyogp/Client_Lib/Development/Zope
  • [9:34] Tao Takashi: right. So who here has read it?
  • [9:34] Enus Linden: raises hand
  • [9:34] Locklainn Linden: raises hand
  • [9:35] Tao Takashi: well, I didn't ;-)
  • [9:35] Locklainn Linden: oh boy
  • [9:35] Saijanai Kuhn: I read an earlier version I think
  • [9:35] Tao Takashi: but I should and clean up typos ;-)
  • [9:35] Tao Takashi: and who here has questions about it? I think Saijanai has
  • [9:36] Infinity Linden: is there sample code that uses it (in the PyOGP context?)
  • [9:36] Locklainn Linden: yea
  • [9:36] Tao Takashi: I need to understand what you guys don't understand so I can explain these parts :)
  • [9:36] Locklainn Linden: Credentials
  • [9:36] Saijanai Kuhn: welll, I understand the concepts. I'l need to actually go step by step through typing a simple example in before I "get it" is all
  • [9:36] Tao Takashi: yes, or PlaceAvatarAdapter in agent.py
  • [9:36] Tao Takashi: ok, so let's take credentials
  • [9:37] Tao Takashi: grr, cannot find the URL
  • [9:37] RacerX Gullwing: [2] ?
  • [9:37] Asterion Coen: things happens
  • [9:38] Saijanai Kuhn: [3]
  • [9:38] Saijanai Kuhn:  ?
  • [9:38] Tao Takashi: [4]
  • [9:38] Tao Takashi: This is the source file
  • [9:38] Saijanai Kuhn: ah, never in a millions years ...;-)
  • [9:38] Tao Takashi: glad, trac has line numbers :)
  • [9:38] Tao Takashi: does everybody see this file?
  • [9:39] Tao Takashi: Enus could put this on a parcel media url ;-)
  • [9:39] Bartholomew Kleiber: I do
  • [9:39] Elric Anthony: nods
  • [9:39] Locklainn Linden: yep
  • [9:39] Tao Takashi: but it's probably too long
  • [9:39] Tao Takashi: but as long as you see it in a browser that's ok
  • [9:39] Enus Linden: i'll trust browsers for now (and will put up a screen for next time)
  • [9:39] Tao Takashi: so what you see there is a simple class called PlainPasswordCredential
  • [9:39] Tao Takashi: is just stores firstname, lastname and a password
  • [9:40] Sea Urchin: beanbag: Going to next texture.
  • [9:40] Tao Takashi: what we need to do for logging into an agent domain is to convert this data to LLSD
  • [9:40] Dahlia Trimble: plain text, not a hash?
  • [9:40] Tao Takashi: this is plain text but there will be other credentials which have a hash
  • [9:40] Infinity Linden: "go with him here.. that's later
  • [9:41] Tao Takashi: so normally you would implement a method like get_llsd() which returns the data as LLSD XML
  • [9:41] Sea Urchin: beanbag: Going to next texture.
  • [9:41] Tao Takashi: but the problem here is that later you might want to replace this by using JSON
  • [9:42] Tao Takashi: so you would need a different method get_json()
  • [9:42] Tao Takashi: now imagine you want to replace this in your application
  • [9:42] Tao Takashi: you can subclass from this class of course and implement it or even exchange the existing method to return json
  • [9:43] Tao Takashi: but other packages would then still use the class defined in pyogp.lib.base
  • [9:43] Tao Takashi: not yours
  • [9:43] Tao Takashi: what you want is to be flexible in how it is serialized into whatever format you want
  • [9:43] Tao Takashi: as a default we want to provide LLSD
  • [9:43] Tao Takashi: so what we do instead is using an adapter
  • [9:44] Tao Takashi: an adapter is mainly a new object which is a wrapper around the original object (in our case the PlainPasswordCredential instance)
  • [9:44] Tao Takashi: can you follow me so far? :)
  • [9:44] Tao Takashi: if you have questions inbetween please ask
  • [9:44] Tao Takashi: so this PlainPasswordLLSDSerializer class is such a wrapper class
  • [9:45] Tao Takashi: as you can see in it's __init__() on line 31, it simply takes another object and stores it as self.context
  • [9:45] Tao Takashi: so self.context will store an instance of PlainPasswordCredential
  • [9:45] Enus Linden: line 31?
  • [9:45] Tao Takashi: in my trac view it says 31 where it says self.context = context
  • [9:46] Latha Serevi: I was late; could someone please re-paste the relevent one or two URLs for us latecomers? Thx.
  • [9:46] Enus Linden: i see, tx
  • [9:46] Tao Takashi: it starts at 29
  • [9:46] Tao Takashi: This is the source code we are talking about: [5]
  • [9:46] Enus Linden: high level doc: [6] using the svn trac as an example to step through
  • [9:46] Tao Takashi: now having this in self.context we can obtain e.g. the firstname by using self.context.firstname
  • [9:47] Tao Takashi: Hey Vektor, you are on the wrong grid! ;-)
  • [9:47] Tao Takashi: but good to see you anyway :)
  • [9:47] Tao Takashi: so what we now implement in PlainPasswordLLSDSerializer is a serialize() method which simply uses this information from self.context to construct an LLSD string
  • [9:47] Tao Takashi: see line 33-43
  • [9:48] Saijanai Kuhn: For ka leteecomers, we're looking at: [7]
  • [9:48] Tao Takashi: so what we now could do is the following:
  • [9:48] Infinity Linden: hey Tao... are you using context to have any particular behavor, or is it just a holder of slots?
  • [9:48] Tao Takashi: credentials = PlainPasswordCredential("some","name",pw")
  • [9:48] Tao Takashi: it is just a convention for naming where the wrapped object is stored
  • [9:49] Infinity Linden: oh.. okay
  • [9:49] Tao Takashi: and we can instantiate the wrapper around it:
  • [9:49] Tao Takashi: wrapper = PlainPasswordLLSDSerializer(credentials)
  • [9:49] Saijanai Kuhn: its like "self" in a non-oop language
  • [9:49] Tao Takashi: and we could call this wrapper now: wrapper.serialize()
  • [9:49] Tao Takashi: and we would get an LLSD string
  • [9:49] Infinity Linden: were you thinking of doing a Factory pattern so all the contexts respond to the same protocol?
  • [9:50] Tao Takashi: unfortunately I am not so good at patterns as I tend to forget the specifics ;-)
  • [9:50] Infinity Linden: that might help with refactoring if/when we move to authentication++
  • [9:50] Tao Takashi: but the pattern here is bascially passing in an object and store it in self.context to add additional functionality to it
  • [9:50] Tao Takashi: like serialize() in our case
  • [9:51] Tao Takashi: so instead of implementing serialize directly in the main class we write a layer on top basically
  • [9:51] Infinity Linden: basically it means that you have a superclass upon which you call a class method and it decides which of it's subclasses to implement
  • [9:51] Tao Takashi: well, this has nothing to do with actual subclassing
  • [9:51] Infinity Linden: i'll just update yer code and post it somewhere
  • [9:51] Infinity Linden: right.. it's about interface
  • [9:51] Tao Takashi: yes, I am coming to that now
  • [9:51] Elric Anthony: So registration allows you to access your extender class without without including a package?
  • [9:52] Infinity Linden: classic Factory pattern uses subclasses just for naming convenience
  • [9:52] Infinity Linden: and to encapsulate common behavior
  • [9:52] Tao Takashi: Elric: I will explain registration now
  • [9:52] Tao Takashi: so the problem we have now is that we need to rely on the fact that self.context really has firstname, lastname and password
  • [9:52] Tao Takashi: if we pass in something else it will apparently break
  • [9:53] Tao Takashi: so in order to do that we define interfaces. An interface basically is a collection of methods and attributes which has a name
  • [9:53] Tao Takashi: in our case we define an interface called IPlainPasswordCredential
  • [9:53] Tao Takashi: you can find this in [8]
  • [9:53] Tao Takashi: in line 6
  • [9:53] Tao Takashi: so it really just lists those attributes
  • [9:54] Tao Takashi: with some documentation what they mean
  • [9:54] Tao Takashi: and what the interface is about
  • [9:54] Tao Takashi: it also derives from a more general interface which is not used right now but maybe is of some use later (ICredential)
  • [9:54] Tao Takashi: now we only need to mark the class that it implements this interface
  • [9:55] Tao Takashi: this is done by the implements(IPlainPasswordCredential) call in [9] in line 12
  • [9:55] Tao Takashi: now the system knows that PlainPasswordCredential implements this interface
  • [9:55] Infinity Linden: hmm... why would we want an interface for plain password credential?
  • [9:55] Tao Takashi: because we need to define what attributes it has
  • [9:55] Infinity Linden: I understand why we might want an interface for Credential
  • [9:56] Elric Anthony: So the extender class doesn't have to imort it?
  • [9:56] Infinity Linden: why do we need to define what attributes it has?
  • [9:56] Tao Takashi: because the adapter relies on this interface and accesses the attributes which are defined in it
  • [9:56] Tao Takashi: see line 37-39 in credentials.py
  • [9:57] Tao Takashi: the actual adapter does not need to know about our actual implementation of PlainPasswordCredential
  • [9:57] Tao Takashi: it just needs to know that this context we pass in has those 3 attributes
  • [9:57] Tao Takashi: and another form of credential might have different attributes
  • [9:57] Tao Takashi: so we need a different serialization method for this and thus a different adapter
  • [9:57] Infinity Linden: right... but what's the advantage to building a ZCA interface around it
  • [9:58] Tao Takashi: I will come to that in a bit
  • [9:58] Tao Takashi: also note line 27 of credentials.py
  • [9:58] Enus Linden: but any implementation can work so long as it uses the same parameter api...
  • [9:58] Tao Takashi: there it says adapts(IPlainPasswordCredential)
  • [9:58] Tao Takashi: Enus: As long as your credential has those attributes and thus implements this interface it will work
  • [9:59] Infinity Linden: but we're going to have different attributes for different implementations of the IPlainPasswordCredential...
  • [9:59] Tao Takashi: the adapts() directive tells the ZCA that this wrapper which we call an adapter needs a context object which implements this interface
  • [9:59] Tao Takashi: Infinity: why's that?
  • [9:59] Saijanai Kuhn: you don't even need specific parameters for the adapter, do you?
  • [9:59] Infinity Linden: so we have a different client protocol for each thing that uses IPlainPasswordCredential
  • [9:59] Tao Takashi: well, as you see, the adapter expects firstname, lastname and password
  • [10:00] Tao Takashi: so the adapter wants to make sure the context object also has those
  • [10:00] Tao Takashi: so it says that it adapts to any object which implements IPlainPasswordCredential which in turn means that it has those 3 attributes
  • [10:01] Tao Takashi: and as you can see it also has an implements(ICredentialSerializer) line in line 26
  • [10:01] Infinity Linden: okay... i gotta run. Thanks Tao.. good intro... ZCA looks useful, but I still need convincing about this specific example. and with that I'll just shut up and write some code to demonstrate my concerns...
  • [10:01] Saijanai Kuhn: so its checking the context for the parameter-names, rather than checking for specific names passed in a function?
  • [10:01] Infinity Linden: cheers
  • [10:01] Tao Takashi: this way it says that it implements this interface. And if you look in interfaces.py again you see this interface there and that it has a serialize() and a header() method we need to implement
  • [10:02] Enus Linden: infinity, raise those concerns asap. i'm surious what they are
  • [10:02] Tao Takashi: Sai: well, it's not checking the context
  • [10:02] Tao Takashi: it's expecting the context to have those
  • [10:03] Tao Takashi: as it says by having adapts(IPlainPasswordCredential) that it's only supposed to work if the context is implementing this interface
  • [10:03] Tao Takashi: which is defined as having those attributes. So in the end context needs to have those attributes
  • [10:03] Enus Linden: haven't tried: what happens if an attribute is missing, or if extras exist?
  • [10:03] Tao Takashi: let me search for an example of where it's used
  • [10:04] Tao Takashi: well, then it breaks in line 37-39 somewhere
  • [10:04] Tao Takashi: and you have a bug in your code
  • [10:04] Tao Takashi: because then you haven't implemented the interface correctly you were saying you do
  • [10:04] Saijanai Kuhn: OK almost seeing it
  • [10:04] Tao Takashi: the interface btw is not checked on runtime but you can check for the existance of methods in a class at least in a unit test
  • [10:04] Tao Takashi: so what is checked is only the name
  • [10:05] jashua Alter: gave you SR-720h Skymaster 1.0.
  • [10:05] Tao Takashi: so let me search for a usage example
  • [10:05] Tao Takashi: ah, one thing before that
  • [10:05] Tao Takashi: we need to tell the ZCA that this adapter is available
  • [10:05] Tao Takashi: just writing it there does not tell it
  • [10:05] Tao Takashi: this is what the last 2 lines in credentials.py are for
  • [10:05] Tao Takashi: this just stores it in some global configuration also called the registry
  • [10:06] Tao Takashi: now for usage
  • [10:06] Tao Takashi: look at [10]
  • [10:06] Tao Takashi: and you see line 31 there
  • [10:06] Tao Takashi: it says:
  • [10:06] Tao Takashi: serializer = ICredentialSerializer(credentials)
  • [10:07] Tao Takashi: what we have is an object credentials which is an instance of the PlainPasswordCredential class
  • [10:07] Tao Takashi: so it implements the interface IPlainPasswordCredential
  • [10:07] Tao Takashi: (there are actually functions in the ZCA to test which interfaces an object implements, it can also be more than one interface)
  • [10:08] Tao Takashi: what we now need though is to serialize this credential
  • [10:08] Tao Takashi: so we need LLSD, not an object
  • [10:08] Tao Takashi: before that I explained how you can invoke the wrapper manually
  • [10:08] Tao Takashi: simply by saying PlainPasswordLLSDSerializer(credential)
  • [10:08] Tao Takashi: but then we would have this wrapper class hard coded in our code
  • [10:09] Tao Takashi: we couldn't replace it later on easily in our own application without changing agentdomain.py
  • [10:09] Tao Takashi: so instead we call it by it's interface:
  • [10:09] Tao Takashi: serializer = ICredentialSerializer(credentials)
  • [10:09] Tao Takashi: what happens now is the following:
  • [10:09] Tao Takashi: 1. The ZCA looks up which interfaces credentials implements and finds IPlainPasswordCredential
  • [10:10] Tao Takashi: 2. The ZCA looks up in it's registry if there is some adapter which implements the interface ICredentialSerializer and adapts to IPlainPasswordCredential
  • [10:10] Tao Takashi: 3. Happily it finds our adapter PlainPasswordLLSDSerializer
  • [10:10] Tao Takashi: 4. It does the same thing I wrote above: PlainPasswordLLSDSerializer(credential)
  • [10:10] Tao Takashi: and returns it
  • [10:11] Tao Takashi: now we have an object which wraps our original object but it has a different interface: ICredentialSerializer
  • [10:11] Tao Takashi: we now know that this interface has a serialize() method which we can call now
  • [10:11] Tao Takashi: So all in all it's an indirection here over the interface name
  • [10:12] Tao Takashi: which means: If we simply override the registration somewhere and do not provide PlainPasswordLLSDSerializer but our own PlainPasswordJSONSerializer instead
  • [10:12] Tao Takashi: we would not need to change the login code but we can simply do the additional registration on startup time in our own application which uses this library
  • [10:12] Tao Takashi: and this is basically everything about adapters
  • [10:13] Tao Takashi: questions? :)
  • [10:13] Tao Takashi: I guess now you have more questions than before
  • [10:13] Tao Takashi: I might also put an example up which has all the code in one file
  • [10:14] Enus Linden: so i think it's important to point out that using zca in this way in pyogp makes it feasible to have a core codebase that does what we collectively want pyogp to do, which is enable testing of OGP
  • [10:14] Enus Linden: plus
  • [10:14] Enus Linden: make it so that it's extendable and bits are swappable
  • [10:14] Tao Takashi: that's the LL goal ;-) I also would like to use it for implementing agent domains, region domains and clients
  • [10:14] Tao Takashi: someday
  • [10:15] Enus Linden: so the intial goal, LL's and AWGsa, is a codebase that supports testing OGP
  • [10:15] Enus Linden: where it goes from there is up to those who carry it forward : )
  • [10:15] Tao Takashi: so one advantage of doing things like this is that you can easily exchange parts like the serialization without changing the library itself
  • [10:16] Tao Takashi: it's of course also doable in different ways like using some other means of configuration but this is somewhat a proven way and a well tested framework for doing this
  • [10:16] Tao Takashi: an additional advantage IMHO is that you have to think about your interfaces
  • [10:16] Tao Takashi: this makes IMHO sense as it helps to get a cleaner architecture
  • [10:16] Enus Linden: tao, we've been churning a bit on things. I feel like we're settling down on structure, do you agree? what big changes remain?
  • [10:16] Tao Takashi: and they can also serve as documentation. The first thing you should read in a new component should be it's interfaces.py
  • [10:17] Enus Linden: granted, this is a very young project...
  • [10:17] Tao Takashi: well, I don't think there are many changes as there is not yet so much there to change ;-)
  • [10:17] Tao Takashi: so we first need more additions on which e.g. Locklainn is working on (Message Parsing)
  • [10:18] Locklainn Linden: yep, and building and reading :)
  • [10:18] Saijanai Kuhn: and more reading :-/
  • [10:18] Enus Linden: how about networking? and it's a given that many components remain to be built (like 99% of it), but architecture wise.....
  • [10:18] Tao Takashi: Sai: is this adapter stuff now clearer to you?
  • [10:19] Tao Takashi: right, I was planning to continue work on a network layer
  • [10:19] Tao Takashi: so we can easily exchange e.g. urllib2 with eventlet or some mockup network layer for testing
  • [10:20] Saijanai Kuhn: not really. I had that level of understanding alrady, I think. What I need to do is just write two different "hello world" implementations and play with making them interfaces/adapters/whateverss
  • [10:20] Tao Takashi: maybe try to implement something like the document example I gave in the tutorial
  • [10:20] Tao Takashi: so you have some simple class which has some attributes and you want to add functionality to it by using adapters
  • [10:20] Tao Takashi: like get_size()
  • [10:21] Tao Takashi: and another advantage of adapters is I think that they are small and easy to test
  • [10:22] Tao Takashi: just give them a mockup object which implements the needed interface and you can test the outcome
  • [10:22] Enus Linden: tess, whump, anyone else: questions at this point?
  • [10:22] Tao Takashi: I also wanted to write down some best practives for developing
  • [10:22] Tao Takashi: like how it's best to start with some example (like in a doctest), then try to define interfaces and then implement everything until the doctest passes
  • [10:23] Tao Takashi: or unit test if you prefer
  • [10:23] Locklainn Linden: called Test-Driven-Development
  • [10:23] Enus Linden: shudder to think it's possible
  • [10:23] Whump Linden: Tao, I had a question, but I'll take it off line. Schedule stuff for OGPB.
  • [10:24] Tao Takashi: Enus: I did the base library stuff like this
  • [10:24] Tao Takashi: I started with login.txt
  • [10:24] Tao Takashi: helps to understand how components might look like
  • [10:24] Tao Takashi: because you start with using them
  • [10:24] Tao Takashi: Whump: ok, I will also be on #pyogp and #gridnauts
  • [10:24] Whump Linden: cool, thanks
  • [10:25] Tao Takashi: whump: and another question: Would it be ok to put the gridnauts mailing list on gmane.org?
  • [10:25] Tao Takashi: (like we did with pyogp)
  • [10:25] Saijanai Kuhn: Think I found my helloworld example: [11]
  • [10:26] Tao Takashi: yes, Lennart is good at explaining things, maybe also link this from the wiki
  • [10:26] Bartholomew Kleiber: Saijanai: thx, just what I needed, too
  • [10:26] Enus Linden: more to read, sweet
  • [10:27] Enus Linden: Tao thanks for the overview...
  • [10:27] Tao Takashi: please email to the pyogp list if you have questions
  • [10:27] Enus Linden: and for updates watch [12] and it's family of pages
  • [10:27] Bartholomew Kleiber: tao: Only speaking for me I missed reading the page Zope Wiki page and do so ASAP because this seems very important to understand. Other than that I think I got the point from your explanations.
  • [10:28] Tao Takashi: Bartholomew: Great :) And we should maybe do this sprint someday soon :)
  • [10:28] Bartholomew Kleiber: 'tis true :-).
  • [10:28] Enus Linden: so we're about out of time. pyogp will eat a lot of this meetings time in the short term. eventually general QA related issues will pop up as well.
  • [10:29] Enus Linden: feel free to hollar at #pyogp as needed all
  • [10:29] Enus Linden: i gotta run
  • [10:29] Saijanai Kuhn: great first meeting
  • [10:29] Tao Takashi: thanks for hosting, Enus :)
  • [10:29] Tess Linden: thanks!
  • [10:29] Kitty Tandino: <3 hugs e
  • [10:29] Tiffany Sicling: yes, thanks :)
  • [10:29] Enus Linden: agreed. secretary sai, you got a transcript, or shall i?
  • [10:29] Vektor Linden: Thanks Enus!
  • [10:30] Saijanai Kuhn: probably you should so I see howyou want to mark it up on your user page
  • [10:30] Dahlia Trimble: gotta run too, Thanks Tao and everyone :)
  • [10:30] Enus Linden: sure thing sai. catch y'all later on!
  • [10:30] Saijanai Kuhn: laters Enus
  • [10:30] Bartholomew Kleiber: bye
  • [10:30] Asterion Coen: have dhaliaste transcript here