i\'m having a problem very similar to this SO question, but my attempts to apply these previous answers isn\'t going thru and it was suggested i start it as a new question:
You're calling getBarChoices()
at definition time, when defining the class IFoo
. So from bar import IBar
will be executed while parsing foo.py
leading to the circular import.
As far as I see it, you have basically two choices:
1) Use a string as identifier for object_provides.
You're doing that already anyway by using IFoo.__identifier__
, but if you make it static instead of dynamic that will eliminate your circular dependencies:
source = ObjPathSourceBinder(object_provides='ns.content.bar.IBar')
bar = Relation(source=source,required=False)
No need to import IBar
in foo.py
. This has the obvious disadvantage that the location of IBar
is now hardcoded in your code, so whenever you change the name or location of IBar
you'll need to update its dotted name in foo.py
.
2) Marker interfaces
The other alternative would be to let IFoo
and IBar
implement marker interfaces that you keep in a third file, ns/content/interfaces.py
for example. That way you could do something along the lines of
interfaces.py
from zope.interface import Interface
class IBarMarker(Interface):
"""Marker interface for IBar objects.
"""
class IFooMarker(Interface):
"""Marker interface for IFoo objects.
"""
foo.py
from zope.interface import directlyProvides
from plone.directives import form
from plone.formwidget.contenttree import ObjPathSourceBinder
from plone.formwidget.autocomplete import AutocompleteFieldWidget
from z3c.relationfield.schema import RelationChoice
from ns.content.interfaces import IBarMarker
from ns.content.interfaces import IFooMarker
class IFoo(form.Schema):
directlyProvides(IFooMarker)
form.widget(bar=AutocompleteFieldWidget)
bar = RelationChoice(source=ObjPathSourceBinder(
object_provides=IBarMarker.__identifier__),
required=False)
bar.py
class IBar(form.Schema):
directlyProvides(IBarMarker)
form.widget(foo=AutocompleteFieldWidget)
foo = RelationChoice(source=ObjPathSourceBinder(
object_provides=IFooMarker.__identifier__),
required=False)