User:Enus Linden/Office Hours/2008 July 18

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
  • [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