[PEAK] Using attribute bindings within constructor when using Component Factories

Wayne Larsen wayne at larsen.st
Sun Jan 18 01:49:31 EST 2004


Thanks for the response,

The problem I had with assembly events, is that there does not seem to 
be any guarantee of order given an inheritance structure.  So, for example:

class TestService(binding.Component):
     protocols.advise(
         instancesProvide=[ITestService]
         )

     log = binding.Obtain('logger:TestService')
     message = binding.Obtain(PropertyName('helloworld.message'))

     def __init(self):
         self.log.info('from Parent __init: %s' % self.message)

     __init = binding.Make(__init, uponAssembly=1)

     def hello(self):
         self.log.info(self.message)


class ChildTestService(TestService):
     def __init(self):
         self.log.info('from Child __init: %s' % self.message)

     __init = binding.Make(__init, uponAssembly=1)

class GrandChildTestService(ChildTestService):
     def __init(self):
         self.log.info('from GrandChild __init: %s' % self.message)

     __init = binding.Make(__init, uponAssembly=1)

class Test(running.commands.AbstractCommand):
     log = binding.Obtain('logger:helloworld')
     ts = binding.Obtain(ITestService)

     def _run(self):
         self.ts.hello()

The output of this gives me:
GrandChildTestService[5161]: from Parent __init: Hello, world!
GrandChildTestService[5161]: from GrandChild __init: Hello, world!
GrandChildTestService[5161]: from Child __init: Hello, world!
GrandChildTestService[5161]: Hello, world!

The problem here is converting an existing application.  The "normal" 
way of doing this is to put all intialization into your constructor. 
This initialization means setting themselves up based on data that I 
want to move into config files.   If those classes depend on the base 
class initalizing first, I am unsure whether I can rely on assembly 
events.  Is there any guarantee of order for assembly events?

Thanks,
Wayne

Phillip J. Eby wrote:

> So, really, that boils down to "don't override the constructor unless 
> you're doing something that does no lookups", or just, "don't override 
> the constructor".
> 
> Instead, you should be using "assembly events".  For example, if you 
> wanted your TestService to log a message as soon as it's "snapped into" 
> the application, you could add:
> 
>     def __logStartup(self):
>         self.log.info(self.message)
> 
>     __logStartup = binding.Make(__logStartup, uponAssembly=True)
> 
> Then, as soon as the service knows its parent (and the parent knows its 
> parent, and so on up to a "known root" component (a component that knows 
> it has no parents), the __logStartup method will be called.  This is 
> much better than overriding the constructor, since you can access any 
> attributes and do any lookups with full access to your parent components.
> 





More information about the PEAK mailing list