Well... If it was so simple, I'd have done it already. As I said, you
need to take into account tthe args and kwargs defined on the inverse
(and also prevent that inverse to setup the property too). I'll have a
look at the test thing tomorrow.

On 6/25/07, remi jolin <[EMAIL PROTECTED]> wrote:
>
> le 25.06.2007 17:15 Gaetan de Menten a écrit:
> > On 6/25/07, remi jolin <[EMAIL PROTECTED]> wrote:
> >
> >> le 23.06.2007 00:00 Gaetan de Menten a écrit:
> >>
> >>> This is a (known) bug in Elixir. The cause is that we don't setup
> >>> backrefs as we should.
> >>>
> >>> As I said to André Felipe Dias:
> >>> ======
> >>> Feel free to work on a patch, though I'm not sure how hard it would
> >>> be. Basically, when a relationship has an inverse, it must setup a
> >>> backref. The catch is that you must catch all the arguments of the
> >>> inverse relationship and pass them through to the backref.
> >>> ======
> >>>
> >>>
> >> Gaetan,
> >>
> >> I made a (simple) patch and a test for backrefs. It seems to work (at
> >> least as I expect it to work ;-)  )
> >>
> >
> > Great news!
> >
> >
> >> I also found an issue in the test_multi.py test but I think it is a bug
> >> in the test (I've corrected it  also).
> >>
> >
> > I'll see about that.
> >
> >
> >> The only test that does not pass is test_has_property but I think it
> >> because my version of sqlalchemy is too old (0.3.6) "ImportError: cannot
> >> import name column_property"
> >>
> >
> > Indeed.
> >
> >
> >> How can we get further ?
> >>
> >
> > Please send the patch here and I'll have a look at it and commit it if
> > it's good enough and otherwise tell you what's wrong.
> >
> >
> Here are all the patchs and the new test.
> As you see, the patch is very simple but seems to do the work...
>
> Index: elixir/relationships.py
> ===================================================================
> --- elixir/relationships.py     (révision 135)
> +++ elixir/relationships.py     (copie de travail)
> @@ -329,6 +329,8 @@
>                 (self.inverse_name == other.name or not
> self.inverse_name) and \                (other.inverse_name == self.name
> or not other.inverse_name)
>
> +    def __repr__(self):
> +        return "<%s name:%s>" % (self.__class__.__name__, self.name)
>
>  class BelongsTo(Relationship):
>      '''
> @@ -447,7 +449,10 @@
>          if self.primaryjoin_clauses:
>              kwargs['primaryjoin'] = and_(*self.primaryjoin_clauses)
>          kwargs['uselist'] = False
> -
> +
> +        if self.inverse:
> +            kwargs['backref'] = self.inverse.name
> +
>          self.property = relation(self.target, **kwargs)
>          self.entity.mapper.add_property(self.name, self.property)
>
> @@ -487,6 +492,7 @@
>              kwargs['primaryjoin'] = and_(*self.inverse.primaryjoin_clauses)
>
>          kwargs['uselist'] = self.uselist
> +        kwargs['backref'] = self.inverse.name
>
>          self.property = relation(self.target, **kwargs)
>          self.entity.mapper.add_property(self.name, self.property)
> @@ -660,6 +666,9 @@
>              kwargs['order_by'] = \
>
> self.target._descriptor.translate_order_by(kwargs['order_by'])
>
> +        if self.inverse:
> +            kwargs['backref'] = self.inverse.name
> +
>          self.property = relation(self.target,
> secondary=self.secondary_table,
>                                   uselist=True, **kwargs)
>          self.entity.mapper.add_property(self.name, self.property)
>
> -------------------------------
> Index: tests/test_multi.py
> ===================================================================
> --- tests/test_multi.py (révision 135)
> +++ tests/test_multi.py (copie de travail)
> @@ -52,7 +52,8 @@
>
>          homer = Person.get_by(name="Homer")
>          lisa = Person.get_by(name="Lisa")
> -
> +        slh = Animal.get_by(name="Santa's Little Helper")
> +
>          print homer
>
>          assert len(homer.animals) == 2
> -----------------------
> The problem here is that after the objectstore.clear(), slh contained
> some "zombi" datas, not something from the database... Perharps, we
> should separate in 2 different functions the load of the database (up to
> objectstore.clear() and the requests so we get sure that a var doesn't
> keep an unrelevant data...
> Same issue with test_autoload.py.
>
> Index: tests/test_autoload.py
> ===================================================================
> --- tests/test_autoload.py      (révision 135)
> +++ tests/test_autoload.py      (copie de travail)
> @@ -101,7 +101,8 @@
>
>          homer = Person.get_by(name="Homer")
>          lisa = Person.get_by(name="Lisa")
> -
> +        slh = Animal.get_by(name="Santa's Little Helper")
> +
>          print homer
>
>          assert len(homer.animals) == 2
> ------------------------------------
> tests/test_backref.py (new test...)
>
> """
>     simple test case for backrefs
> """
>
> import sqlalchemy
> from elixir import *
>
> #-----------
>
> class TestMultiBelongsTo(object):
>     def setup(self):
>         global Person, Animal
>
>         #---------------------------------------
>         # classes for the multi belongs_to test
>
>         class Person(Entity):
>             has_field('name', Unicode(32))
>
>             has_many('pets', of_kind='Animal', inverse='owner')
>             has_many('animals', of_kind='Animal', inverse='feeder')
>
>             def __str__(self):
>                 s = '%s\n' % self.name.encode('utf-8')
>                 for pet in self.pets:
>                     s += '  * pet: %s\n' % pet.name
>                 return s
>
>         class Animal(Entity):
>             has_field('name', String(15))
>             has_field('color', String(15))
>
>             belongs_to('owner', of_kind='Person')
>             belongs_to('feeder', of_kind='Person')
>
>         engine = sqlalchemy.create_engine('sqlite:///')
>         metadata.connect(engine)
>         create_all()
>
>     def teardown(self):
>         cleanup_all()
>         objectstore.clear()
>
>     def test_belongs_to_multi_ref(self):
>         snowball = Animal(name="Snowball II", color="grey")
>         slh = Animal(name="Santa's Little Helper")
>         homer = Person(name="Homer", animals=[snowball, slh], pets=[slh])
>         lisa = Person(name="Lisa", pets=[snowball])
>
>         print homer
>
>         assert lisa == snowball.owner
>         assert homer == slh.feeder
>         assert homer == lisa.pets[0].feeder
>         assert homer == slh.owner
>
>         objectstore.flush()
>         objectstore.clear()
>
>         homer = Person.get_by(name="Homer")
>         lisa = Person.get_by(name="Lisa")
>         slh = Animal.get_by(name="Santa's Little Helper")
>
>         print "homer:", homer
>         print "slh.owner:", slh.owner
>
>         assert len(homer.animals) == 2
>         assert homer == lisa.pets[0].feeder
>         assert homer == slh.owner
>
> class TestMovies(object):
>     def setup(self):
>         global Director, Movie, Actor, Media
>
>         class Director(Entity):
>             with_fields(
>                 name = Field(Unicode(60))
>             )
>
>             has_many('movies', of_kind='Movie', inverse='director')
>
>
>         class Movie(Entity):
>             """
>                 simple movie class
>             """
>
>             # columns
>             with_fields(
>                 title = Field(Unicode(50)),
>                 year = Field(Integer)
>             )
>
>             # relationships
>             belongs_to('director', of_kind="Director", inverse='movies')
>
>             has_and_belongs_to_many('actors', of_kind="Actor",
> inverse='movies')            has_one('media', of_kind='Media',
> inverse='movie')
>
>
>         class Actor(Entity):
>             with_fields(
>                 name = Field(Unicode(60))
>             )
>
>             has_and_belongs_to_many('movies', of_kind="Movie",
> inverse="actors")
>
>         class Media(Entity):
>             with_fields(
>                 number = Field(Integer, primary_key=True)
>             )
>
>             belongs_to('movie', of_kind='Movie', inverse='media')
>
>         engine = sqlalchemy.create_engine('sqlite:///')
>         metadata.connect(engine)
>         create_all()
>
>     def teardown(self):
>         drop_all()
>         objectstore.clear()
>
>     def test_bidirectional(self):
>         brunner = Movie(title="Blade Runner", year=1982)
>         alien = Movie(title="Alien", year=1979)
>         swars = Movie(title="Star Wars", year=1977)
>
>         m1 = Media(number=1)
>         brunner.media = m1
>         m7 = Media(number=7)
>         m7.movie = alien
>
>         rscott = Director(name="Ridley Scott")
>         glucas = Director(name="George Lucas")
>
>         hford = Actor(name="Harrison Ford")
>         mhamill = Actor(name="Mark Hamill")
>         sweaver = Actor(name="Sigourney Weaver")
>
>         rscott.movies.append(brunner)
>         rscott.movies.append(alien)
>         swars.director = glucas
>
>         swars.actors.append(hford)
>         swars.actors.append(mhamill)
>         alien.actors.append(sweaver)
>         brunner.actors.append(hford)
>
>         # directors
>         assert rscott == brunner.director
>         assert rscott == alien.director
>         assert swars in glucas.movies
>
>         # actors
>         assert swars in hford.movies
>         assert swars in mhamill.movies
>         assert alien in sweaver.movies
>         assert brunner in hford.movies
>         assert len(hford.movies) == 2
>
>         # media
>         assert alien.media == m7
>         assert m1.movie == brunner
>
>
> if __name__ == '__main__':
>     test = TestMultiBelongsTo()
>     test.setup()
>     test.test_belongs_to_multi_ref()
>     test.teardown()
>
>     test = TestMovies()
>     test.setup()
>     test.test_bidirectional()
>     test.teardown()
>
>
> >
>


-- 
Gaëtan de Menten
http://openhex.org

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"SQLElixir" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlelixir?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to