-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use BaseResponse for proposal history to add API support #6039
Conversation
b03d954
to
da8557c
Compare
c3452f9
to
0298ceb
Compare
opengever/api/field_deserializers.py
Outdated
|
||
@implementer(IFieldDeserializer) | ||
@adapter(IField, IPersistent, IBrowserRequest) | ||
class AnnotationsDefaultFieldDeserializer(DefaultFieldDeserializer): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok Sorry just realised that naming needs changing
opengever/api/field_deserializers.py
Outdated
|
||
@implementer(IFieldDeserializer) | ||
@adapter(IDatetime, IPersistent, IBrowserRequest) | ||
class AnnotationsDatetimeFieldDeserializer(DatetimeFieldDeserializer): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one too
b779ae5
to
bd180d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the excellent small commits, it really helped reviewing ✨!
I have added some small comments/suggestions, please have a look. Some comments might be outdated due to changes in later commits though.
In general i am a bit unhappy about getting rid of the single classes per history entry as that IMO decreases encapsulation. Instead of one single class we now do have "type"-check logic that is somewhat distributed across different places, e.g. ProposalResponseDescription.mapping
and ProposalResponse.needs_syncing
instead of having it encapsulated in one class/object. Not sure if that is a general decision made with how the Response
now works and if the discussion is out of scope here. Maybe we can discuss it quickly at an upcoming daily or with some ☕️though?
Otherwise i'd give it a 👍.
opengever/meeting/proposalhistory.py
Outdated
implements(IProposalResponse) | ||
|
||
def __init__(self, response_type='commented', text='', **kwargs): | ||
super(ProposalResponse, self).__init__(response_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
response type is a keyword argument, please also use a keyword argument here. Otherwise if Response
suddenly introduces a positional argument code here might not fail, but should.
opengever/meeting/proposalhistory.py
Outdated
data[json_compatible(name)] = value | ||
return data | ||
|
||
def deserialize(self, data): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you make this a factory-classmethod that receives a data dict you can move constructing the instance into the class. think of
response = ProposalResponse.deserialize(data, needs_syncing=False)
instead of
response = ProposalResponse()
response.deserialize(data)
response._needs_syncing = False
opengever/meeting/proposalhistory.py
Outdated
super(ProposalResponse, self).__init__(response_type) | ||
self.text = text | ||
self.additional_data = PersistentDict() | ||
self.additional_data.update(kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why hide it in an additional dict? can't you just setattr(self, thing)
for everything in kwargs
?
Aks as you implement __getattr__
all the attributes that are present on self will shadow names in kwargs
so that will lead to the same result.
update: aha no, it would probably not work with the deserialization/serialization, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, only fields that are defined in the schema get serialized, and I don't want to have all the possible fields in the schema.
opengever/meeting/handlers.py
Outdated
admin_unit_id, | ||
'@@receive-proposal-history', | ||
path=path, | ||
data=request_data,) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing comma in method calls are IMO discouraged. please remove.
opengever/meeting/proposalhistory.py
Outdated
@@ -28,6 +28,7 @@ | |||
from zope.schema import getFields | |||
|
|||
|
|||
NEED_SYNCING = (u'revised', u'reopened', u'commented') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd prefer if this was a constant on ProposalHistory
as it is coupled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProposalHistory
gets deleted in this PR... But I moved NEED_SYNCING
into the ProposalResponse
class
@@ -4,6 +4,7 @@ | |||
from Products.Five import BrowserView | |||
from opengever.base.response import IResponseContainer | |||
from opengever.meeting.proposalhistory import ProposalResponse | |||
from opengever.meeting.activity.activities import ProposalCommentedActivitiy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo, there is one i
too much: ProposalCommentedActivitiy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, that's how the class is defined. Correcting the classname should actually work without problem as these are not persisted objects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think so, yes.
def migrate_records_to_responses(self, context): | ||
fields = getFields(IProposalResponse) | ||
|
||
history = IAnnotations(context).get(annotation_key, None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we also delete the annotation_key
from the objects annotation at the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought to keep them as backup of the data...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok fair enough 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made an issue to delete the data at a later time #6066
@@ -208,6 +207,7 @@ def __call__(self): | |||
document_title=self.context.title, | |||
submitted_version=history_data['submitted_version'], | |||
) | |||
response._needs_syncing = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we avoid setting a protected attribute from "outside". IMO that violates encapsulation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I added needs_syncing
as argument to the __init__
of the ProposalResponse
) | ||
|
||
|
||
class PropsosalHistoryEntryMigrator(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're sure the upgrades have been run for all deployments, right? otherwise we'd loose data here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The oldest deployment is nidau
with version 2018.5.7
. This upgrade is in 2017.5.0
, so 👍
@@ -54,6 +54,8 @@ def migrate_records_to_responses(self, context): | |||
history_type = record.pop('history_type') | |||
userid = record.pop('userid') | |||
text = record.pop('text') | |||
if text is None: | |||
text = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in contrary to what the commit message says this is not a unicode string 😉.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😓 Thanks
Field deserializers are only available for archetype and dexterity contents. Our response object is simply a Persisten object stored in the annotations.
created was a Date field in the IResponse schema but we store the created datetime on the Response object.
These upgrade steps use the proposal history and will not work anymore. As they have been applied already on all our installations we can simply delete them.
bd180d6
to
6e6e450
Compare
def migrate_records_to_responses(self, context): | ||
fields = getFields(IProposalResponse) | ||
|
||
history = IAnnotations(context).get(annotation_key, None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made an issue to delete the data at a later time #6066
@@ -1,94 +0,0 @@ | |||
from opengever.core.upgrade import SQLUpgradeStep |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This upgrade is in 2017.7.0
so it's also ok to delete
In this PR we switch from a proposal specific history (using
IProposalResponse
s) to the recently introducedopengever.base.response.Response
. This allows us to simplify the code in the backend and provides API support for free.This change is necessary to allow displaying of proposal history in the new frontend.
Also note that:
Response
s do not get validated, for which I opened an issue: Missing validation for Responses #6050created
Field inResponse
was of the wrong type. This should not necessitate a migration as we keep the value but simply change the field type to match the value.default
andmissing_value
of thetext
field, to match the value set by default during initialization of theResponse
.For #5934
Checkliste
Zutreffendes soll angehakt stehengelassen werden.
deferrable
, oder können gewisse Schritte des Upgrades konditional ausgeführt werden?