Skip to content
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

Merged
merged 32 commits into from
Nov 19, 2019

Conversation

njohner
Copy link
Contributor

@njohner njohner commented Nov 11, 2019

In this PR we switch from a proposal specific history (using IProposalResponses) to the recently introduced opengever.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:

  • Responses do not get validated, for which I opened an issue: Missing validation for Responses #6050
  • created Field in Response 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.
  • I changed the default and missing_value of the text field, to match the value set by default during initialization of the Response.

For #5934

Checkliste

Zutreffendes soll angehakt stehengelassen werden.

  • Sind UpgradeSteps deferrable, oder können gewisse Schritte des Upgrades konditional ausgeführt werden?
  • Changelog-Eintrag vorhanden/nötig?
  • Aktualisierung Dokumentation vorhanden/nötig?

@njohner njohner force-pushed the nj_proposal_history branch 3 times, most recently from b03d954 to da8557c Compare November 12, 2019 16:31
@njohner njohner force-pushed the nj_proposal_history branch 2 times, most recently from c3452f9 to 0298ceb Compare November 13, 2019 09:36
@njohner njohner marked this pull request as ready for review November 13, 2019 10:27

@implementer(IFieldDeserializer)
@adapter(IField, IPersistent, IBrowserRequest)
class AnnotationsDefaultFieldDeserializer(DefaultFieldDeserializer):
Copy link
Contributor Author

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


@implementer(IFieldDeserializer)
@adapter(IDatetime, IPersistent, IBrowserRequest)
class AnnotationsDatetimeFieldDeserializer(DatetimeFieldDeserializer):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one too

@njohner njohner force-pushed the nj_proposal_history branch 2 times, most recently from b779ae5 to bd180d6 Compare November 13, 2019 10:43
@njohner njohner requested a review from a team November 13, 2019 14:07
Copy link
Contributor

@deiferni deiferni left a 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 👍.

implements(IProposalResponse)

def __init__(self, response_type='commented', text='', **kwargs):
super(ProposalResponse, self).__init__(response_type)
Copy link
Contributor

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.

data[json_compatible(name)] = value
return data

def deserialize(self, data):
Copy link
Contributor

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

super(ProposalResponse, self).__init__(response_type)
self.text = text
self.additional_data = PersistentDict()
self.additional_data.update(kwargs)
Copy link
Contributor

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?

Copy link
Contributor Author

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.

admin_unit_id,
'@@receive-proposal-history',
path=path,
data=request_data,)
Copy link
Contributor

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.

@@ -28,6 +28,7 @@
from zope.schema import getFields


NEED_SYNCING = (u'revised', u'reopened', u'commented')
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok fair enough 👍

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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):
Copy link
Contributor

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.

Copy link
Contributor Author

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 = ''
Copy link
Contributor

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 😉.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😓 Thanks

def migrate_records_to_responses(self, context):
fields = getFields(IProposalResponse)

history = IAnnotations(context).get(annotation_key, None)
Copy link
Contributor Author

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
Copy link
Contributor Author

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

@njohner njohner merged commit ce1cbbd into master Nov 19, 2019
@njohner njohner deleted the nj_proposal_history branch November 19, 2019 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants