Merge lp://qastaging/~mandel/desktopcouch/record_id into lp://qastaging/desktopcouch

Proposed by Manuel de la Peña
Status: Superseded
Proposed branch: lp://qastaging/~mandel/desktopcouch/record_id
Merge into: lp://qastaging/desktopcouch
Diff against target: 66 lines (+25/-3)
2 files modified
desktopcouch/records/record.py (+24/-1)
desktopcouch/records/server_base.py (+1/-2)
To merge this branch: bzr merge lp://qastaging/~mandel/desktopcouch/record_id
Reviewer Review Type Date Requested Status
Guillermo Gonzalez Approve
Chad Miller (community) Approve
Review via email: mp+15424@code.qastaging.launchpad.net

This proposal has been superseded by a proposal from 2009-12-07.

Commit message

Moved record_id to be a property rather than an attribute in order to be able to give a consistent behavior

To post a comment you must log in.
Revision history for this message
Manuel de la Peña (mandel) wrote :

This branch ensures that the record_id is set whenever the +id key is present in the data pass to create a new record.

Revision history for this message
Manuel de la Peña (mandel) wrote :

Ensured that when creating a record with a dict that contains the key '_id' its vlaue is used for record_id

Revision history for this message
Chad Miller (cmiller) wrote :

Let's not use "warnings" module. Instead, import logging and "logging.warn(...)", usually.

In this case, though, I would be just as happy with an assertion.

if '_id' in data:
   if record_id is not None:
       assert data['_id'] == record_id
       ...

Maybe drop the "record_id" member and make record_id a @property like record_type. Maybe we can drop all "_id" from code except for the getter.

Do we need a setter property also?

review: Needs Fixing
Revision history for this message
Chad Miller (cmiller) wrote :

> if '_id' in data:

if data.get('_id', None) is not None: # safer. Explicit {'_id':None} would fail.

Revision history for this message
Manuel de la Peña (mandel) wrote :

> Let's not use "warnings" module. Instead, import logging and
> "logging.warn(...)", usually.
>
> In this case, though, I would be just as happy with an assertion.
>
> if '_id' in data:
> if record_id is not None:
> assert data['_id'] == record_id
> ...
>
> Maybe drop the "record_id" member and make record_id a @property like
> record_type. Maybe we can drop all "_id" from code except for the getter.
>
> Do we need a setter property also?

I agree with the comments, the new implementation uses an assertion. I have implemented the record_id as a property with a getter and a setter. The setter is needed to pass all current tests.

Revision history for this message
Chad Miller (cmiller) wrote :

13 + if '_id' in data and record_id is not None:
14 + assert data['_id'] == record_id
15 + elif record_id is not None:
16 + self._data['_id'] = record_id

This would be cleaner with two levels of "if".

if record_id is not None: # Explicit setting, so try to use it.
   if data.get('_id', None) is not None: # Overwrite _id if it is None.
      self._data['_id'] = record_id
   else: # _id already set. Verify that the explicit value agrees.
      assert self._data['_id'] == record_id, "record_id doesn't match value in data."

Note the data.get() and the second parameter to assert .

Revision history for this message
Manuel de la Peña (mandel) wrote :

> 13 + if '_id' in data and record_id is not None:
> 14 + assert data['_id'] == record_id
> 15 + elif record_id is not None:
> 16 + self._data['_id'] = record_id
>
>
> This would be cleaner with two levels of "if".
>
> if record_id is not None: # Explicit setting, so try to use it.
> if data.get('_id', None) is not None: # Overwrite _id if it is None.
> self._data['_id'] = record_id
> else: # _id already set. Verify that the explicit value agrees.
> assert self._data['_id'] == record_id, "record_id doesn't match value in
> data."
>
>
>
> Note the data.get() and the second parameter to assert .

What if the record_id is not None and the data['_id']is indeed None? we could try to put in the db {'_id':None} which will raise an exception.

We would have to do yet another check.

Revision history for this message
Manuel de la Peña (mandel) wrote :

> > 13 + if '_id' in data and record_id is not None:
> > 14 + assert data['_id'] == record_id
> > 15 + elif record_id is not None:
> > 16 + self._data['_id'] = record_id
> >
> >
> > This would be cleaner with two levels of "if".
> >
> > if record_id is not None: # Explicit setting, so try to use it.
> > if data.get('_id', None) is not None: # Overwrite _id if it is None.
> > self._data['_id'] = record_id
> > else: # _id already set. Verify that the explicit value agrees.
> > assert self._data['_id'] == record_id, "record_id doesn't match value
> in
> > data."
> >
> >
> >
> > Note the data.get() and the second parameter to assert .
>
> What if the record_id is not None and the data['_id']is indeed None? we could
> try to put in the db {'_id':None} which will raise an exception.
>
> We would have to do yet another check.
Sorry, I just realized what you meant... override _id. Stupid Manuel!

Revision history for this message
Chad Miller (cmiller) wrote :

Looks good to me. Thank you.

review: Approve
Revision history for this message
Guillermo Gonzalez (verterok) wrote :

Looks good.

review: Approve
Revision history for this message
Manuel de la Peña (mandel) wrote :

Major screw up from my part. The committed patch is wrong (major screw up from my port, I should have added a test!!!)

The if statement should be:

if record_id is not None: # Explicit setting, so try to use it.
   if data.get('_id', None) is None: # Overwrite _id if it is None.
      self._data['_id'] = record_id
   else: # _id already set. Verify that the explicit value agrees.
      assert self._data['_id'] == record_id, "record_id doesn't match value in data."

Otherwise we will always raise an exception since None is never equal to record_id!!

I have made the changes in the same lp branch with an addition of a test case to ensure that next time this does not happen.

Sorry for the screw up!

Manuel

114. By Manuel de la Peña

Removed the use of an assertion. Used assertRaise in test.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'desktopcouch/records/record.py'
--- desktopcouch/records/record.py 2009-08-05 11:18:46 +0000
+++ desktopcouch/records/record.py 2009-11-30 16:39:11 +0000
@@ -247,9 +247,19 @@
247 record_type = data['record_type']247 record_type = data['record_type']
248 else:248 else:
249 raise NoRecordTypeSpecified249 raise NoRecordTypeSpecified
250
250 super(Record, self).__init__(data)251 super(Record, self).__init__(data)
251 self._data['record_type'] = record_type252 self._data['record_type'] = record_type
252 self.record_id = record_id253
254 if record_id is not None:
255 # Explicit setting, so try to use it.
256 if data.get('_id', None) is not None:
257 # Overwrite _id if it is None.
258 self._data['_id'] = record_id
259 else:
260 # _id already set. Verify that the explicit value agrees.
261 assert self._data['_id'] == record_id, "record_id doesn't match value in data."
262
253263
254 def __getitem__(self, key):264 def __getitem__(self, key):
255 if is_internal(key):265 if is_internal(key):
@@ -288,6 +298,18 @@
288 return [298 return [
289 key for key in super(Record, self).keys() if not is_internal(key)]299 key for key in super(Record, self).keys() if not is_internal(key)]
290300
301 def _get_record_id(self):
302 """Gets the record id."""
303 if '_id' in self._data:
304 return self._data['_id']
305 return None
306
307 def _set_record_id(self, value):
308 """Sets the record id."""
309 self._data['_id'] = value
310
311 record_id = property(_get_record_id, _set_record_id)
312
291 @property313 @property
292 def application_annotations(self):314 def application_annotations(self):
293 """Get the section with application specific data."""315 """Get the section with application specific data."""
@@ -297,3 +319,4 @@
297 def record_type(self):319 def record_type(self):
298 """Get the record type."""320 """Get the record type."""
299 return self._data.setdefault('record_type', None)321 return self._data.setdefault('record_type', None)
322
300323
=== modified file 'desktopcouch/records/server_base.py'
--- desktopcouch/records/server_base.py 2009-11-23 17:29:05 +0000
+++ desktopcouch/records/server_base.py 2009-11-30 16:39:11 +0000
@@ -149,12 +149,11 @@
149 return None149 return None
150 data.update(couch_record)150 data.update(couch_record)
151 record = self.record_factory(data=data)151 record = self.record_factory(data=data)
152 record.record_id = record_id
153 return record152 return record
154153
155 def put_record(self, record):154 def put_record(self, record):
156 """Put a record in back end storage."""155 """Put a record in back end storage."""
157 record_id = record.record_id or record._data.get('_id', '')156 record_id = record.record_id
158 record_data = record._data157 record_data = record._data
159 if record_id:158 if record_id:
160 self.db[record_id] = record_data159 self.db[record_id] = record_data

Subscribers

People subscribed via source and target branches