Yes, if you can't find where you are creating new Satellite instances,
I'd probably stick an assert statement in Satellite.__init__ and see
where it gets triggered.

Simon

On Mon, Jan 15, 2018 at 10:34 AM, Ruben Di Battista
<[email protected]> wrote:
> Dear Simon,
>
> thanks again for your kind help.
>
> Actually the creation of new instances is not intended. But I'm not getting
> where they are created...
>
> I give you more insight:
>
> This is the scheduler object with the associated propagate() method
>
> class Scheduler(six.with_metaclass(abc.ABCMeta)):
>     """ This class gets a list of GroundStation objects and a list of
> Satellites
>     objects and compute all the passages of the Satellites over the
>     GroundStations
>
>     Args:
>         sat_list(list): List of Satellites objects
>         gs_list(list): List of GroundStation objects
>         start_day(datetime): The datetime object representing the day from
>             which to start the propagation
>         time_of_propagation(int): Number of hours to propagate
>                 [default:24]
>         deltaT(float): Time step to use for angles retrieval, in seconds
>     """
>
>     def __init__(self, sat_list, gs_list, start_day, time_of_propagation=24,
>                  deltaT=0.05):
>         # Monkey patch the Satellite class with the cost_function specific
>         # of the scheduler algorithm.
>         sat_class = type(sat_list[0])
>         sat_class.cost_function = self.cost_function
>
>         self.sat_list = sat_list
>         self.gs_list = gs_list
>         self.start_day = start_day
>         self.time_of_propagation = time_of_propagation
>         self.deltaT = deltaT
>
>     def propagate(self):
>         """ This method computes all the passages of the Satellites over the
>         GroundStations
>
>         Args:
>
>         Returns:
>             all_passages(PassageList): A list ordered from the earliest
> passage\
>                 of all passages
>
>         Raises:
>             ModelNotAvailable: When a satellite is too far from Earth and
> the
>                 models available in Orbital are not good, a
> ModelNotAvailable is
>                 raised
>         """
>
>         all_passages = PassageList()
>
>         # Loop Over the gs list
>         for gs in self.gs_list:
>             # Loop over the satellites list
>             for sat in self.sat_list:
>                 # Compute all the passages in the specified period
>                 passages = \
>                     sat.get_next_passes(gs, self.start_day,
>                                         self.time_of_propagation,
>                                         deltaT=self.deltaT)
>
>                 # Unfolding the list of passages in a flat list
>                 all_passages = all_passages + passages
>
> return all_passages
>
>
> It just basically loops over all the ground station and satellites and
> generates all the passages. Maybe the fact that I monkey patch the satellite
> class induces the creation of a new instance of `Satellite`?
>
> The details of the `get_next_passes` method of the `Satellite` class for
> what concerns the `Passage` instance creation, skipping the algorithmic
> part, are:
>
>     def _generate_passage(self, next_pass, ground_station, deltaT):
>         """ This method returns a Passage Object from the data returned from
>         the original Orbital.get_next_passes method.
>
>         """
>
>         aos, los, tca = next_pass
>
>         return Passage(satellite=self,
>                        ground_station=ground_station,
>                        aos=aos, los=los, tca=tca,
>                        deltaT=deltaT)
>
>
> `self` should be a reference to the instance of `Satellite` already loaded
> from DB. I will try to dive more into the code...
>
>
> Thanks a lot for the kind help of all of you,
>
> On Monday, January 15, 2018 at 10:06:24 AM UTC+1, Simon King wrote:
>>
>> On Sat, Jan 13, 2018 at 3:31 PM, Ruben Di Battista
>> <[email protected]> wrote:
>> >
>> >
>> > On Friday, January 12, 2018 at 10:54:49 AM UTC+1, Simon King wrote:
>> >>
>> >> If I understand your code correctly, scheduler.propagate() creates a
>> >> large number of Passage instances, and you only want a small subset of
>> >> them to be added to the database. Is that correct?
>> >
>> >
>> > Correct!
>> >
>> >>
>> >> I would guess that the passages are getting added to the session
>> >> because you are setting their 'satellite' property to point to a
>> >> Satellite which is already in the database. This then causes the
>> >> passages to be added to the session due to the default cascade rules
>> >> on the relationship
>> >> (http://docs.sqlalchemy.org/en/latest/orm/cascades.html).
>> >>
>> >> If that really is the case, you can change the cascade rules for that
>> >> relationship, and then you'll probably need to explicitly add the
>> >> passages you want to *keep* to the session instead.
>> >>
>> >> Hope that helps,
>> >>
>> >> Simon
>> >
>> >
>> > Dear Simon,
>> > thank you. That was the case. Modifying the cascade disabling the
>> > backref
>> > cascade does not load in the DB the passages at propagation time.
>> >
>> > But now, when I manually add the subset of passages after the
>> > optimization,
>> > I get a:
>> >
>> > InvalidRequestError: Can't attach instance <Satellite at 0x108c4dfd0>;
>> > another instance with key [...] is already present in this section.
>> >
>> > So, I suppose that disabling the backref cascade now SQLAlchemy is not
>> > capable anymore to recognize the already loaded Satellite objects...
>> >
>> > Should I maybe merge somewhere?
>> >
>>
>> It sounds like your propagate() function is creating new Satellite
>> instances with the same primary key as instances that have been loaded
>> from the database. Merging is one way to avoid that, and the
>> UniqueObject pattern is another. It's difficult to say which is more
>> appropriate for your usage without seeing more code. But if
>> propagate() is only supposed to be calculating passages, I don't
>> understand why new Satellites are being created at all - shouldn't all
>> the Satellites already be loaded?
>>
>> Simon
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to