On Thu, 17 May 2007 19:29:26 +0300, kgi <iacovou@gmail.com> wrote:
On Thursday 17 May 2007 18:31:59 Jean-Paul Calderone wrote:
Hi Jean-Paul; thanks for your quick answer.
The import system requires more or less complete knowledge of what modules are defined in order to resolve dependencies. If each LiveElement took care to declaring which file it needed, then the page would need to be rendered completely before Athena could figure out which modules needed to be loaded, by which time it is a little too late to include them in the page (perhaps this could be made to work, but it would be a hassle).
OK, I guess I'll just have to bite the bullet. Adding something to sys.path is not such a big deal.
I wouldn't be happy to see a solution that required declaring all LiveElement classes a LivePage is going to use, since my own most common use-case for LivePages involves my not having any idea what most of the LiveElements will be (and in fact, changing what they will be with almost every render). I'm open to other suggestions and discussion about improving this area of Athena, though.
Oh, really? That's interesting. How does Athena push new Javascript code to a page after the initial render? I didn't even know it was possible to do such a thing: for me, Javascript has always been something you link to from the page header. Looks like my 4th Edition "JS Definitive Guide" (2001) is showing its age :-)
Basically it just notices when some required javascript is absent, loads it from the server, and eval()'s it. The same dependency system is used to resolve dependencies at page render time (which are turned into <script> tags in the <head> of the rendered page) and dynamically after the initial page render (which are turned into these dynamic load/evals).
The idea is to provide a package hierarchy, as Python has. The strings will be split on "." in a couple places, but if there is simply no "." in them, this will work (since it is equivalent to any top-level name in an arrangement which does use dotted names). The goal of dotted names is to avoid polluting the top-level namespace more than necessary.
You're talking about Javascript's top-level namespace, right? (I assume these strings never go anywhere near Python's namespace). OK, that sounds logical; I was just wondering whether there was anything more to it that.
Yep.
For sanity's sake, I would define classes in a module as attributes of that module, rather than using arbitrary other names
Hmm, I'm not quite sure I understand what you mean in this context. I *think* you're talking about JS classes, but the terminology is Python terminology.
Yep. Python has a pretty reasonable module system. Athena's JS "module system" is loosely based on it, so a lot of Python terminology makes sense for it as well.
If the former (JS classes) do you mean, you'd prefer to have a single (or a few) javascript file(s) and have these define the JS for *lots* of related LiveElement classes, which all declare themselves to be a (namespaced) jsClass, and all these jsClasses map to the same physical JS file?
I didn't mean to imply anything about how much or little JS is in any single source file. Mostly I just wanted to point out that I think a single source file should completely define any particular module. ie, if a.js puts things onto the JS "module" A, b.js should _not_ put things onto it.
In other words, for project "Cutlery":
# In Python LivePage stuff:
class Fork ( LiveElement ): jsClass = u'Cutlery.Fork'
class Spoon ( LiveElement ): jsClass = u'Cutlery.Spoon'
class Knife ( LiveElement ): jsClass = u'Cutlery.Knife'
# In Python plugin code:
jsModules.mapping = { # Note: the same file! u'Cutlery.Fork' : 'cutlery.js', u'Cutlery.Spoon' : 'cutlery.js', u'Cutlery.Knife' : 'cutlery.js', }
Note that since the dependency resolution system works upwards, this mapping only needs one entry for this example to work: jsModules.mapping = {u'Cutlery': 'cutlery.js'}
# In the file cutlery.js:
Cutlery = {};
Cutlery.Fork = Nevow.Athena.Widget.subclass ( 'Cutlery.Fork' ); Cutlery.Fork.methods ( ... );
Cutlery.Spoon = Nevow.Athena.Widget.subclass ( 'Cutlery.Spoon' ); Cutlery.Spoon.methods ( ... );
Cutlery.Knife = Nevow.Athena.Widget.subclass ( 'Cutlery.Knife' ); Cutlery.Knife.methods ( ... );
Is this what you mean?
I... think? so... I'm not sure if you were trying to demonstrate something by putting the jsModules mapping into the same file as the rest of the Python (since you pointed it out, I suspect you were, but I'm not sure what).
Actually, I have a couple more very quick questions that I thought up while typing this:
- Am I right in thinking that no athena JS files ever need to have declare any of the modules mentioned in BOOTSTRAP_MODULES (e.g. Divmod, Nevow.Athena)?
Well, it'll work if they don't, since those are always loaded on every page, but I might decide to change what's in BOOTSTRAP_MODULES. :) To be safe, I'd declare any dependency, even one that's in that collection at the time.
- Is there a recommended way for LiveElements to access each other on the server? For example, I click on an element of (client-side) Foo that invokes a method on (server-side) Foo; this then needs to update the state of (server-side) Bar, which needs to update (client-side) Bar. At the moment I'm using an manual ad-hoc registry, with the occasional (naughty?) obj.fragmentParent thrown in. I was wondering if there was a more robust method already in place that I had totally missed (like the LiveElements being assigned names upon creation, which can then be automagically found through something like page.findElementByName ( "Bar" )).
Unfortunately, names would have to be unique within the context of a page, which leads to the possibility of collisions. Resolving this would make it impossible to know the actual name of the element you want. :) I'd suggest instantiating your LiveElements with direct references to whatever other objects they need. This is somewhat similar to a problem many people have when implementing protocols with Twisted. I don't know of a general solution, but arranging for the right objects to be referencable from the right places should solve any particular case that comes up. Jean-Paul