Skip to content

Conversation

@kelseymorris95
Copy link
Contributor

@kelseymorris95 kelseymorris95 commented Jun 16, 2016

Added an Event class, edited Events.get_event() to return a list of them. Added basic Event unit test file for future use.

Fixes #15.

@boxcla
Copy link

boxcla commented Jun 16, 2016

Hi @kelseymorris95, thanks for the pull request. Before we can merge it, we need you to sign our Contributor License Agreement. You can do so electronically here: http://opensource.box.com/cla

Once you have signed, just add a comment to this pull request saying, "CLA signed". Thanks!

def get_url(self, *args):
"""
Base class override.
Disallow this method for this subclass, should not access Event by event_id.

Choose a reason for hiding this comment

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

Minor: Note that there is no get method in the box v2 api for Event.


def test_init_event(mock_box_session):
event = Event(mock_box_session, "f82c3ba03e41f7e8a7608363cc6c0390183c3f83", {
"type": "event",

Choose a reason for hiding this comment

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

formatting here... actually travis is probably complaining about this.
we usually use the format like:
event = Event(
arg1,
next_arg_on_new_line_if_we_are_using_multiline,
{
foo: bar,
baz: wing,
ding: {
but_were_not_super_strict_I_didnt_put_the_above_curley_on_its_own_line: value1,
but_we_are_picky_about_the_last_item_having_a_trailing_comma: value2,
},
},
)

]
events = test_events.generate_events_with_long_polling(**stream_type_kwargs)
assert next(events) == mock_event
assert next(events) == mock_event_object

Choose a reason for hiding this comment

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

instead of having the mock_event_object fixture you could construct the mock Event here based on the mock_event json. Then do the assert check for equality. Then I think you can remove the mock_event fixture.

Base class override.
Disallow this method for this subclass, should not access Event by event_id.
"""
raise AttributeError("'Event' class has no method 'get_url'")
Copy link
Contributor

Choose a reason for hiding this comment

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

Glad that you noticed this issue.

To me, this sort of thing is a code smell. If a baseclass defines a default behavior, and then a subclass is incapable of performing that behavior, chances are, the subclass should not actually inherit from that baseclass.

I believe that to be the case here. BaseObject is a class that is the root for all possible persistent, addressable resource types in the REST API.

Since we've never thought about non-persistent / non-addressable objects before, we didn't think about this when we first created #15.

I have an idea of what we should do here, but I'm curious for your thoughts.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking the same thing - Event should probably not derive directly from BaseObject.

@kelseymorris95 @jmoldow should we get together to discuss the right plan for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I had discussed this with Jeremy because I wasn't sure what approach was best. Most methods in BaseObject use get_url(), so I think the only behaviours of BaseObject that we actually want to mimic are init, getitem, repr, object_id, and eq.
Is there an option besides reproducing those behaviors separately in Event?

Copy link
Contributor

Choose a reason for hiding this comment

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

Check out #140. The first half is unrelated, but the second half overlaps with what we're talking about here.

@kelseymorris95
Copy link
Contributor Author

CLA signed

@boxcla
Copy link

boxcla commented Jun 16, 2016

Verified that @kelseymorris95 has just signed the CLA. Thanks, and we look forward to your contribution.

@@ -0,0 +1,12 @@
# coding: utf-8

from __future__ import unicode_literals
Copy link
Contributor

Choose a reason for hiding this comment

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

We should also be using absolute_import in all files.

A Box API endpoint for interacting with a Box object.
"""
# Question:
# Should this item type be a part of other objects?
Copy link
Contributor

Choose a reason for hiding this comment

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

No, it isn't necessary. This is just here so that all of its subclasses at least have _item_type defined, even if it is None.

Though this should move to BaseAPIJSONObject, since that is now the base for translation.

@jmoldow
Copy link
Contributor

jmoldow commented Jun 20, 2016

Something to think about: Translator.translate() takes a type, and tries to translate it. If it fails, it'll return BaseObject. Then, the usual procedure is to pass session, object_id, response_object to the class that is returned.

This has two problems:

  • Ideally, the default return value would be either BaseObject or APIJSONObject, depending on the object. I would choose BaseObject if there were an id, and APIJSONObject otherwise. However, we can't do that since the method only accepts type. We'd need to make a backwards-incompatible change to make it accept additional information.
  • The types of classes we return have different __init__ parameters. So you can't initialize an object unless you know in advance which type it's going to be. We could fix this by:
    • Moving the object creation inside of Translator.translate() (after dealing with the above problem).
    • Making APIJSONObject.__init__ have the same argument list as BaseObject.__init__, even though it doesn't need most of them.

Let's not worry about this right now. What we have now works well enough to push what you have as-is. But we'll want to revisit this before or during work on #140.

from .base_api_json_object import BaseAPIJSONObject, BaseAPIJSONObjectMeta


class APIJSONObjectMeta(BaseAPIJSONObjectMeta, ABCMeta):

Choose a reason for hiding this comment

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

This is an empty ABCMeta which is a little strange to me. I don't follow the comment about avoiding conflicts. We get BetaAPIJSONObjectMeta thru BaseAPIJSONObject below in APIJSONObject... so, I'm not sure what this is needed for.

Choose a reason for hiding this comment

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

Thnx for explaining... I think that's worth a link & comment.
http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/
or something saying this addresses the known issue with inheriting from 2 classes with separate metaclasses.

@HootyMcOwlface
Copy link

👍

A JSON object representing the object returned from a Box API request.
:type response_object:
:class:`BoxResponse`
:`dict`
Copy link
Contributor

Choose a reason for hiding this comment

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

No colon here and in other places.

@jmoldow
Copy link
Contributor

jmoldow commented Jun 21, 2016

👍

Thanks @kelseymorris95 ! This all looks great. I'm going to merge it now.

Before releasing this to PyPI, over the next few days, let's make sure we're happy with the names of the new classes, make a final decision about Mapping vs MutableMapping vs dict, and double-check that we aren't introducing any other backwards incompatibilities.

@jmoldow jmoldow merged commit 76652d9 into master Jun 21, 2016
@Jeff-Meadows Jeff-Meadows deleted the add_event branch June 21, 2017 23: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