From b420f4614f33ba2a1eb92f1d39ac85539490d0a5 Mon Sep 17 00:00:00 2001 From: Richard Borcsik Date: Mon, 12 Jan 2015 00:35:12 +0100 Subject: [PATCH 1/4] Raise exceptions for errors --- pushbullet/__init__.py | 2 +- pushbullet/errors.py | 8 ++++++ pushbullet/invalid_key_error.py | 6 ----- pushbullet/pushbullet.py | 47 ++++++++++++++++++--------------- 4 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 pushbullet/errors.py delete mode 100644 pushbullet/invalid_key_error.py diff --git a/pushbullet/__init__.py b/pushbullet/__init__.py index 148cc13..869c662 100644 --- a/pushbullet/__init__.py +++ b/pushbullet/__init__.py @@ -2,4 +2,4 @@ from .pushbullet import PushBullet from .device import Device from .listener import Listener -from .invalid_key_error import InvalidKeyError +from .errors import PushBulletError, InvalidKeyError, PushError diff --git a/pushbullet/errors.py b/pushbullet/errors.py new file mode 100644 index 0000000..2908060 --- /dev/null +++ b/pushbullet/errors.py @@ -0,0 +1,8 @@ +class PushBulletError(Exception): + pass + +class InvalidKeyError(PushBulletError): + pass + +class PushError(PushBulletError): + pass diff --git a/pushbullet/invalid_key_error.py b/pushbullet/invalid_key_error.py deleted file mode 100644 index e0e81df..0000000 --- a/pushbullet/invalid_key_error.py +++ /dev/null @@ -1,6 +0,0 @@ -class InvalidKeyError(Exception): - def __init__(self): - self.value = "Invalid API Key" - - def __str__(self): - return repr(self.value) diff --git a/pushbullet/pushbullet.py b/pushbullet/pushbullet.py index a041199..acb9bfb 100644 --- a/pushbullet/pushbullet.py +++ b/pushbullet/pushbullet.py @@ -4,7 +4,7 @@ from .device import Device from .channel import Channel from .contact import Contact -from .invalid_key_error import InvalidKeyError +from .errors import PushBulletError, InvalidKeyError, PushError from .filetype import get_file_type @@ -92,9 +92,9 @@ def new_device(self, nickname): if r.status_code == requests.codes.ok: new_device = Device(self, r.json()) self.devices.append(new_device) - return True, new_device + return new_device else: - return False, None + raise PushBulletError(r.text) def new_contact(self, name, email): data = {"name": name, "email": email} @@ -102,9 +102,9 @@ def new_contact(self, name, email): if r.status_code == requests.codes.ok: new_contact = Contact(self, r.json()) self.contacts.append(new_contact) - return True, new_contact + return new_contact else: - return False, None + raise PushBulletError(r.text) def edit_device(self, device, nickname=None, model=None, manufacturer=None): data = {"nickname": nickname} @@ -113,9 +113,10 @@ def edit_device(self, device, nickname=None, model=None, manufacturer=None): if r.status_code == requests.codes.ok: new_device = Device(self, r.json()) self.devices[self.devices.index(device)] = new_device - return True, new_device + return new_device else: - return False, device + raise PushBulletError(r.text) + def edit_contact(self, contact, name): data = {"name": name} @@ -124,27 +125,29 @@ def edit_contact(self, contact, name): if r.status_code == requests.codes.ok: new_contact = Contact(self, r.json()) self.contacts[self.contacts.index(contact)] = new_contact - return True, new_contact + return new_contact else: - return False, contact + raise PushBulletError(r.text) + def remove_device(self, device): iden = device.device_iden r = self._session.delete("{}/{}".format(self.DEVICES_URL, iden)) if r.status_code == requests.codes.ok: self.devices.remove(device) - return True, r.json() + return True else: - return False, r.json() + raise PushBulletError(r.text) + def remove_contact(self, contact): iden = contact.iden r = self._session.delete("{}/{}".format(self.CONTACTS_URL, iden)) if r.status_code == requests.codes.ok: self.contacts.remove(contact) - return True, r.json() + return True else: - return False, r.json() + raise PushBulletError(r.text) def get_pushes(self, modified_after=None, limit=None): data = {"modified_after": modified_after, "limit": limit} @@ -154,7 +157,7 @@ def get_pushes(self, modified_after=None, limit=None): while get_more_pushes: r = self._session.get(self.PUSH_URL, params=data) if r.status_code != requests.codes.ok: - return False, r.json() + raise PushBulletError(r.text) pushes_list += r.json().get("pushes") if 'cursor' in r.json() and (not limit or len(pushes_list) < limit): @@ -169,17 +172,17 @@ def dismiss_push(self, iden): r = self._session.post("{}/{}".format(self.PUSH_URL, iden), data=json.dumps(data)) if r.status_code == requests.codes.ok: - return True, r.json() + return True else: - return False, r.json() + raise PushBulletError(r.text) def delete_push(self, iden): r = self._session.delete("{}/{}".format(self.PUSH_URL, iden)) if r.status_code == requests.codes.ok: - return True, r.json() + return True else: - return False, r.json() + raise PushBulletError(r.text) def upload_file(self, f, file_name, file_type=None): if not file_type: @@ -191,7 +194,7 @@ def upload_file(self, f, file_name, file_type=None): r = self._session.post(self.UPLOAD_REQUEST_URL, data=json.dumps(data)) if r.status_code != requests.codes.ok: - return False, r.json() + raise PushBulletError(r.text) upload_data = r.json().get("data") file_url = r.json().get("file_url") @@ -199,7 +202,7 @@ def upload_file(self, f, file_name, file_type=None): upload = requests.post(upload_url, data=upload_data, files={"file": f}) - return True, {"file_type": file_type, "file_url": file_url, "file_name": file_name} + return {"file_type": file_type, "file_url": file_url, "file_name": file_name} def push_file(self, file_name, file_url, file_type, body=None, device=None, contact=None, email=None, channel=None): data = {"type": "file", "file_type": file_type, "file_url": file_url, "file_name": file_name} @@ -242,9 +245,9 @@ def _push(self, data): r = self._session.post(self.PUSH_URL, data=json.dumps(data)) if r.status_code == requests.codes.ok: - return True, r.json() + return r.json() else: - return False, r.json() + raise PushError(r.text) def refresh(self): self._load_devices() From 9ce9e7ab1b7da544b93c6ead6a5fce718a19d76f Mon Sep 17 00:00:00 2001 From: Richard Borcsik Date: Sat, 31 Jan 2015 21:17:30 +0100 Subject: [PATCH 2/4] We don't need to return anything here. --- pushbullet/pushbullet.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pushbullet/pushbullet.py b/pushbullet/pushbullet.py index acb9bfb..6645679 100644 --- a/pushbullet/pushbullet.py +++ b/pushbullet/pushbullet.py @@ -135,7 +135,6 @@ def remove_device(self, device): r = self._session.delete("{}/{}".format(self.DEVICES_URL, iden)) if r.status_code == requests.codes.ok: self.devices.remove(device) - return True else: raise PushBulletError(r.text) @@ -171,17 +170,13 @@ def dismiss_push(self, iden): data = {"dismissed": True} r = self._session.post("{}/{}".format(self.PUSH_URL, iden), data=json.dumps(data)) - if r.status_code == requests.codes.ok: - return True - else: + if r.status_code =! requests.codes.ok: raise PushBulletError(r.text) def delete_push(self, iden): r = self._session.delete("{}/{}".format(self.PUSH_URL, iden)) - if r.status_code == requests.codes.ok: - return True - else: + if r.status_code != requests.codes.ok: raise PushBulletError(r.text) def upload_file(self, f, file_name, file_type=None): From 05117a623bdc40718c74496bdcac668b99a76190 Mon Sep 17 00:00:00 2001 From: Richard Borcsik Date: Sat, 31 Jan 2015 21:17:57 +0100 Subject: [PATCH 3/4] Update readme --- readme.rst | 68 +++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/readme.rst b/readme.rst index 658c9ab..3b0088c 100644 --- a/readme.rst +++ b/readme.rst @@ -59,6 +59,8 @@ Authentication pb = PushBullet(api_key) +If your key is invalid (that is, the Pushbullet API returns a ``401``), an ``InvalidKeyError`` is raised. + Pushing things ~~~~~~~~~~~~~~ @@ -67,7 +69,9 @@ Pushing a text note .. code:: python - success, push = pb.push_note("This is the title", "This is the body".) + push = pb.push_note("This is the title", "This is the body".) + +``push`` is a dictionary containing the data returned by the Pushbullet API. Pushing an address ^^^^^^^^^^^^^^^^^^ @@ -75,7 +79,7 @@ Pushing an address .. code:: python address = " 25 E 85th St, 10028 New York, NY" - success, push = pb.push_address("home", address) + push = pb.push_address("home", address) Pushing a list ^^^^^^^^^^^^^^ @@ -83,14 +87,14 @@ Pushing a list .. code:: python to_buy = ["milk", "bread", "cider"] - success, push = phone.push_list("Shopping list", to_buy) + push = phone.push_list("Shopping list", to_buy) Pushing a link ^^^^^^^^^^^^^^ .. code:: python - success, push = phone.push_link("Cool site", "https://github.com") + push = phone.push_link("Cool site", "https://github.com") Pushing a file ^^^^^^^^^^^^^^ @@ -100,9 +104,11 @@ Pushing files is a two part process. First you need to upload the file, and afte .. code:: python with open("my_cool_picture.jpg", "rb") as pic: - success, file_data = pb.upload_file(pic, "picture.jpg") + file_data = pb.upload_file(pic, "picture.jpg") + + push = pb.push_file(**file_data) - success, push = pb.push_file(**file_data) +``upload_file`` returns a dictionary containing ``file_type``, ``file_url`` and ``file_name`` keys. These are the same parameters that ``push_file`` take. The advantage of this is that if you already have a file uploaded somewhere, you can use that instead of uploading again. For example: @@ -110,7 +116,7 @@ The advantage of this is that if you already have a file uploaded somewhere, you .. code:: python - success, push = pb.push_file(file_url="https://i.imgur.com/IAYZ20i.jpg", file_name="cat.jpg", file_type="image/jpeg") + push = pb.push_file(file_url="https://i.imgur.com/IAYZ20i.jpg", file_name="cat.jpg", file_type="image/jpeg") Working with pushes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -119,20 +125,21 @@ You can also view all previous pushes: .. code:: python - success, pushes = pb.get_pushes() + pushes = pb.get_pushes() -Pushes is a list containg dictionaries that have push data. You can use this data to dismiss notifications or delete pushes. +Pushes is a list containig dictionaries that have push data. You can use this data to dismiss notifications or delete pushes. .. code:: python latest = pushes[0] # We already read it, so let's dismiss it - success, error_message = pb.dismiss_push(lates.get("iden")) + pb.dismiss_push(latest.get("iden")) # Now delete it - success, error_message = pb.delete_push(lates.get("iden")) + pb.delete_push(latest.get("iden")) +Both of these raise ``PushBulletError`` if there's an error. Pushing to specific devices ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -153,13 +160,13 @@ Now we can use the device objects like we did with `pb`: .. code:: python - success, push = motog.push_note("Hello world!", "We're using the api.") + push = motog.push_note("Hello world!", "We're using the api.") Alternatively we can pass the device to push methods: .. code:: python - success, push = pb.push_note("Hello world!", "We're using the api.", device=motog) + push = pb.push_note("Hello world!", "We're using the api.", device=motog) Creating new devices ^^^^^^^^^^^^^^^^^^^^ @@ -168,7 +175,7 @@ Creating a new device is easy too, you only need to specify a name for it. .. code:: python - success, listener = pb.new_device("Listener") + listener = pb.new_device("Listener") Now you can use it like any other device. @@ -179,8 +186,8 @@ You can change the nickname, the manufacturer and the model of the device: .. code:: python - success, listener = pb.edit_device(listener, make="Python", model="3.4.1") - success, motog = pb.edit_device(motog, nickname="My MotoG") + listener = pb.edit_device(listener, make="Python", model="3.4.1") + motog = pb.edit_device(motog, nickname="My MotoG") Deleting devices @@ -190,8 +197,9 @@ Of course, you can also delete devices, even those not added by you. .. code:: python - success, error_message = pb.remove_device(listener) + pb.remove_device(listener) +A ``PushBulletError`` is raised on error. Channels ~~~~~~~~~~~~ @@ -212,7 +220,7 @@ Then you can send a push to all subscribers of this channel like so: .. code:: python - success, push = my_channel.push_note("Hello Channel!", "Hello My Channel") + push = my_channel.push_note("Hello Channel!", "Hello My Channel") Note that you can only push to channels which have been created by the current user. @@ -229,16 +237,16 @@ Contacts work just like devices: print(pb.contacts) # [Contact('Peter' ), Contact('Sophie' ] - sophie = pb.contacs[1] + sophie = pb.contacts[1] Now we can use the contact objects like we did with `pb` or with the devices.: .. code:: python - success, push = sophie.push_note("Hello world!", "We're using the api.") + push = sophie.push_note("Hello world!", "We're using the api.") # Or: - success, push = pb.push_note("Hello world!", "We're using the api.", contact=sophie) + push = pb.push_note("Hello world!", "We're using the api.", contact=sophie) Adding new contacts @@ -246,7 +254,7 @@ Adding new contacts .. code:: python - success, bob = pb.new_contact("Bob", "bob@gmail.com") + bob = pb.new_contact("Bob", "bob@gmail.com") Editing contacts ^^^^^^^^^^^^^^^^^ @@ -255,25 +263,22 @@ You can change the name of any contact: .. code:: python - success, bob = pb.edit_contact(bob, "bobby") + bob = pb.edit_contact(bob, "bobby") Deleting contacts ^^^^^^^^^^^^^^^^^^^ .. code:: python - success, error_message = pb.remove_contact(bob) + pb.remove_contact(bob) Error checking ~~~~~~~~~~~~~~ -Most methods return a tuple containing a bool value indicating success or failure, and the response from the server. - -.. code:: Python - - success, push = pb.push_note("Hello world!", "We're using the api.") - +If the Pushbullet api returns an error code a ``PushError`` an __ +``InvalidKeyError`` or a ``PushBulletError`` is raised. The first __ +two are both subclasses of ``PushBulletError`` The `pushbullet api documetation `__ contains a list of possible status codes. @@ -281,8 +286,7 @@ contains a list of possible status codes. TODO ---- -- Websocket support -- Tests, tests, tests. Write them. +- More tests. Write them all. License ------- From 8122c9781b69cd026eee5416866d603d77af8c9c Mon Sep 17 00:00:00 2001 From: Richard Borcsik Date: Sat, 31 Jan 2015 21:20:58 +0100 Subject: [PATCH 4/4] Syntax hiccup --- pushbullet/pushbullet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pushbullet/pushbullet.py b/pushbullet/pushbullet.py index 6645679..8bd5032 100644 --- a/pushbullet/pushbullet.py +++ b/pushbullet/pushbullet.py @@ -170,7 +170,7 @@ def dismiss_push(self, iden): data = {"dismissed": True} r = self._session.post("{}/{}".format(self.PUSH_URL, iden), data=json.dumps(data)) - if r.status_code =! requests.codes.ok: + if r.status_code != requests.codes.ok: raise PushBulletError(r.text) def delete_push(self, iden):