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

Fully translate nested objects in API responses #306

Merged
merged 23 commits into from
Oct 24, 2018

Conversation

mattwiller
Copy link
Contributor

No description provided.

@boxcla
Copy link

boxcla commented Jul 23, 2018

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

@jmoldow
Copy link
Contributor

jmoldow commented Jul 24, 2018

Is this a WIP, or final code for review?

@mattwiller
Copy link
Contributor Author

@jmoldow This is more like a first draft — this works in my local testing, so it would be great if you could look it over and evaluate if you think this is the right approach!

Copy link
Contributor

@Jeff-Meadows Jeff-Meadows left a comment

Choose a reason for hiding this comment

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

My initial thoughts are that this is a rather expensive method. It will create a lot of objects that very often will be totally unused. I wonder if there's a lazy way to do this. For example, we could wait until an object is accessed via __getitem__ to create the smart object.


if isinstance(response_object, Mapping):
for key in response_object:
if isinstance(response_object[key], Mapping):
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 can just use dict instead of Mapping since that's what the JSON parser creates.

for i in range(len(response_object[key])):
response_object[key][i] = self.full_translate(response_object[key][i], session)

if 'type' in response_object:
Copy link
Contributor

Choose a reason for hiding this comment

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

is type totally reserved in the Box API? Can you create a metadata template with type as one of the keys? If so, the code needs to take this into account.

if isinstance(response_object[key], Mapping):
response_object[key] = self.full_translate(response_object[key], session)
elif isinstance(response_object[key], list):
for i in range(len(response_object[key])):
Copy link
Contributor

Choose a reason for hiding this comment

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

the pythonic way would be to use a list comprehension like

response_object[key] = [self.full_translate(o, session) for o in response_object[key]]

return response_object

def _is_constructor_param(self, param):
if param.name is 'self':
Copy link
Contributor

Choose a reason for hiding this comment

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

compare with == not is

'response_object': response_object,
'object_id': _get_object_id(response_object),
}
# NOTE: getargspec() is deprecated, and should be replaced by inspect.signature() when 2.7 support drops
Copy link
Contributor

Choose a reason for hiding this comment

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

I hope 2.7 support doesn't outlast support for getargspec, but it might. It could be safer or more correct to use inspect.signature, falling back to getargspec when unavailable.

I think the mock library does something similar.

@mattwiller
Copy link
Contributor Author

@Jeff-Meadows It looks like mock uses another library — funcsigs — when inspect.signature is unavailable; I think I can just use getargspec() instead though. I'll look into adding the fallback logic.

Also, your previous comment about this method being more expensive is correct — it takes about 45x longer to fully translate than to shallow translate in the tests I ran (against a collection of 1000 files in a folder, as well as a single file). I'm not sure how dire that is in context, but the difference I observed (a few hundred microseconds) for each one of a few thousand items in an iterator could certainly add up to non-trivial amounts of time. I'll also explore how easy it would be to lazily translate nested objects; the case I'm currently worried about is when an APIJSONObject like Event needs to translate a nested BaseObject like File. We may need to have APIJSONObject hold onto a Session instance even though it itself doesn't require it, just in case a nested object does require it at translation time.

@coveralls
Copy link

coveralls commented Oct 11, 2018

Pull Request Test Coverage Report for Build 1202

  • 60 of 71 (84.51%) changed or added relevant lines in 15 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.02%) to 95.255%

Changes Missing Coverage Covered Lines Changed/Added Lines %
boxsdk/client/client.py 11 22 50.0%
Totals Coverage Status
Change from base Build 1148: -0.02%
Covered Lines: 2148
Relevant Lines: 2255

💛 - Coveralls

@Jeff-Meadows
Copy link
Contributor

@mattwiller one more comment - we should review carefully and perhaps give some suggestions to SDK users about when to use translator.get vs translator.translate. It seems that we're going to end up using get for some API calls that could benefit from calling translate.

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.

None yet

5 participants