Skip to content

Conversation

@mattwiller
Copy link
Contributor

No description provided.

@boxcla
Copy link

boxcla commented Oct 25, 2018

Verified that @mattwiller has signed the CLA. Thanks for the pull request!

@coveralls
Copy link

coveralls commented Oct 25, 2018

Pull Request Test Coverage Report for Build 1308

  • 104 of 106 (98.11%) changed or added relevant lines in 4 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.04%) to 97.056%

Changes Missing Coverage Covered Lines Changed/Added Lines %
boxsdk/object/metadata_template.py 79 81 97.53%
Totals Coverage Status
Change from base Build 1307: 0.04%
Covered Lines: 2637
Relevant Lines: 2717

💛 - Coveralls

`bool`
"""

return 'displayName' in obj and obj['type'] != 'metadata_template'
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a pretty ugly hack, and could easily break in the future, if the API ever returns another object with displayName as a field.

Perhaps we could solve this issue a different way.

  1. Add an optional parent object parameter to the translate method so that it could determine if the parent is a metadata_template.
  2. Add blacklist fields to object classes. When we come across a metadata_template, perhaps we know not to translate its fields.

:return:
"""
if obj.get('type', '') == 'event':
obj_type = obj.get('type')
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic probably belongs in object classes. I know this method isn't new as of this review, but it's becoming more obvious that this is the wrong place for this logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree. Once we know the type, we can call a staticmethod on the class to get the ID.

But I hate that we have to do this. As I said below, I think we can get rid of the event_id lookup, because we end up throwing it away anyway.

That leaves only metadata_template which requires this logic. And I wish they would standardize all of their APIs around PKs instead of scope/template. Can we at least, in the SDK, standardize around PK?

@mattwiller
Copy link
Contributor Author

@Jeff-Meadows I added the field exclusion mechanism so object classes can specify which fields should not be translated. I wasn't certain how we might want to decentralize the logic for finding an ID, so I left it in the translator for now.

)

@api_call
def create_metadata_template(self, display_name, fields, template_key=None, hidden=False, scope='enterprise'):
Copy link
Contributor

Choose a reason for hiding this comment

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

Personal taste, I feel like scope should come before the other optional parameters.

scope is logically the most important part of this operation. And in the APIs, scope always proceeds templateKey.

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 don't mind moving it, but I put it last since at this time only enterprise scope templates can be created. Nobody calling this method today (and likely for the near future) will be setting that parameter, whereas they will likely want to set the others.

:return:
"""
if obj.get('type', '') == 'event':
obj_type = obj.get('type')
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree. Once we know the type, we can call a staticmethod on the class to get the ID.

But I hate that we have to do this. As I said below, I think we can get rid of the event_id lookup, because we end up throwing it away anyway.

That leaves only metadata_template which requires this logic. And I wish they would standardize all of their APIs around PKs instead of scope/template. Can we at least, in the SDK, standardize around PK?

"""
return self.translator.get('metadata_template')(
session=self._session,
object_id='{0}/{1}'.format(scope, template_key),
Copy link
Contributor

Choose a reason for hiding this comment

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

I really don't like doing this.

Can we flip things around here?

  • object_id is always the primary key id. For the template_id constructor, we pass it in as-is, without any GET requests.
  • For the scope, template_key constructor, we do the GET call in order to get the id. And we also pass the response_object, so that we keep the scope and template_key around. Also, we pass in an extra boolean flag (which is normally defaulted to False, but we would pass True here) specifying that the client wants to use the scope/templateKey, not the ID.
  • For APIs that only work with scope/templateKey, always use scope/templateKey
  • For APIs that work with either id or scope/templateKey, default to using id. But use scope/templateKey if that optional boolean was set to True, indicating that scope/templateKey is the desired client behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thinking about this more, I feel even more strongly that we should make this change.

I think the current approach is going to cause us problems, now and in the future.

You can already see one problem forming in this PR, where there's a bunch of places in the code where we need to manually concat the scope and templateKey to form the object_id.

Another place we're going to run into problems is with POST and PUT operations where the body expects metadata template. If we naively do template.object_id, that might be incorrect if the API expects the actual id (I know of at least one API that was supposed to be doing this in the future). If we do template.id, that field might not actually be available, if it wasn't constructed with one.

For simplicity, we could make it so that if we're constructed with the id, we fetch the scope and templateKey, and also vice-versa, that way we always have all of those pieces of information available.

)

@api_call
def get_metadata_template_by_id(self, template_id):
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we get rid of the .get() behavior here? (and if so, rename the method)


if metadata_template_response.get('scope') and metadata_template_response.get('templateKey'):
assert metadata_template.scope == metadata_template_response['scope']
assert metadata_template.template_key == metadata_template_response['templateKey']
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 you have this in a different test too, but just for completeness, can we assert that metadata_template.object_id is None if metadata_template_response.get('id') is None

@mattwiller mattwiller merged commit 7fb1f16 into master Nov 1, 2018
@mattwiller mattwiller deleted the metadata_template_endpoints branch November 1, 2018 02:05
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.

6 participants