#8419 closed defect (worksforme)
self.env.components not concurrent with self.env.is_component_enabled
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | normal | Milestone: | |
Component: | general | Version: | 0.11.4 |
Severity: | normal | Keywords: | |
Cc: | Branch: | ||
Release Notes: | |||
API Changes: | |||
Internal Changes: |
Description
I've encountered this bug building several plugins, and I don't know what exactly the problem is. Even if a component is enabled and self.env.is_component_enabled
confirms this, a KeyError
is thrown looking up the component in self.env.components
(where self
is a Component
):
(Pdb) self.env.components[TicketSystem] *** KeyError: <class 'trac.ticket.api.TicketSystem'> (Pdb) self.env.is_component_enabled(TicketSystem) True (Pdb) TicketSystem(self.env) <trac.ticket.api.TicketSystem object at 0x85c9f8c> (Pdb)
I won't include my code, because I've encountered this in several different places, apparently unrelated. The bug also seems intermittent.
Attachments (0)
Change History (8)
follow-ups: 2 4 comment:1 by , 16 years ago
Milestone: | → 0.11.6 |
---|
comment:2 by , 16 years ago
Replying to cboos:
I've seen something similar once. I'm not sure it was the exact same issue (can't find the backtrace right now), but it was likely a race in the Component system which is what I think your problem could be as well.
I've seen this several times, in completely different code bases. Because it seems unpredictable, a race condition seems likely
comment:3 by , 16 years ago
They are answers to different questsion. env.is_component_enabled()
checks the config settings and other Trac rules (like all trac.*
is enabled by default unless explicitly disabled) and returns boolean used by ComponentManager
to actually enable or disable.
However, a component isn't added to env.components
dictionary before actually being instantiated with the specific env
instance - and thereby tagged on to the environment. This usually gets done on first access by a fresh env to various contributors. However, an env
that hasn't yet been involved in an Admin page, won't have active pure admin provider components (example for illustration).
The book-keeping is done by env.__metaclass__._registry
- it will list all classes loaded (even those disabled), and when requesting the various classes that extend a given ExtensionPoint
you will get back those enabled - and then they will stay attached in env.components
for the life of the environment.
So, for your special need you should check if it is enabled, and then if so instantiate it and use it (it can be instantiated as many times as you like, you just get the same instance returned anyway).
Illustration showing a plain environment that has not yet 'touched' any classes:
>>> from trac.env import Environment >>> myenv = Environment('/some/project') >>> print myenv.components {<class 'trac.env.Environment'>: <trac.env.Environment object at 0x11c20d0>} >>> print myenv.__metaclass__._registry {... 'a really long list' ...}
follow-up: 5 comment:4 by , 16 years ago
Replying to cboos:
… I'm not sure it was the exact same issue (can't find the backtrace right now), but it was likely a race in the Component system
Ok, I remember what it was: a method of a Component was used before the __init__
method of that component was called. So it has nothing to do with the current issue, which is more an API misuse as Simon explained.
Jeff, do you agree on wontfix here?
follow-up: 6 comment:5 by , 16 years ago
Replying to cboos:
Replying to cboos:
… I'm not sure it was the exact same issue (can't find the backtrace right now), but it was likely a race in the Component system
Ok, I remember what it was: a method of a Component was used before the
__init__
method of that component was called. So it has nothing to do with the current issue, which is more an API misuse as Simon explained.Jeff, do you agree on wontfix here?
Makes sense, I think. So just to make sure I understand, env.components
should not be used to fetch components; instead, the component should be instantiated with the environment and that should be used.
follow-up: 7 comment:6 by , 16 years ago
Milestone: | 0.11.6 |
---|---|
Resolution: | → worksforme |
Status: | new → closed |
Replying to Jeff Hammel <jhammel@…>:
Makes sense, I think. So just to make sure I understand,
env.components
should not be used to fetch components; instead, the component should be instantiated with the environment and that should be used.
Correct.
comment:7 by , 16 years ago
Replying to osimons:
Replying to Jeff Hammel <jhammel@…>:
Makes sense, I think. So just to make sure I understand,
env.components
should not be used to fetch components; instead, the component should be instantiated with the environment and that should be used.Correct.
Good to know. I was under the opposite assumption.
comment:8 by , 16 years ago
… another Invalid action "resolve" for me ;-)
Just wanted to add that, indeed, outside of trac/core.py, the ComponentManager.components
field is never used in the Trac code base.
I've seen something similar once. I'm not sure it was the exact same issue (can't find the backtrace right now), but it was likely a race in the Component system which is what I think your problem could be as well.