Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Raise exceptions for errors #29

Merged
merged 4 commits into from
Jan 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pushbullet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 8 additions & 0 deletions pushbullet/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class PushBulletError(Exception):
pass

class InvalidKeyError(PushBulletError):
pass

class PushError(PushBulletError):
pass
6 changes: 0 additions & 6 deletions pushbullet/invalid_key_error.py

This file was deleted.

50 changes: 24 additions & 26 deletions pushbullet/pushbullet.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -92,19 +92,19 @@ 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}
r = self._session.post(self.CONTACTS_URL, data=json.dumps(data))
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}
Expand All @@ -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}
Expand All @@ -124,27 +125,28 @@ 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()
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}
Expand All @@ -154,7 +156,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):
Expand All @@ -168,18 +170,14 @@ 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, r.json()
else:
return False, r.json()
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, r.json()
else:
return False, r.json()
if r.status_code != requests.codes.ok:
raise PushBulletError(r.text)

def upload_file(self, f, file_name, file_type=None):
if not file_type:
Expand All @@ -191,15 +189,15 @@ 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")
upload_url = r.json().get("upload_url")

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}
Expand Down Expand Up @@ -242,9 +240,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()
Expand Down
68 changes: 36 additions & 32 deletions readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
~~~~~~~~~~~~~~

Expand All @@ -67,30 +69,32 @@ 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
^^^^^^^^^^^^^^^^^^

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

.. 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
^^^^^^^^^^^^^^
Expand All @@ -100,17 +104,19 @@ 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:


.. 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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -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
^^^^^^^^^^^^^^^^^^^^
Expand All @@ -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.

Expand All @@ -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
Expand All @@ -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
~~~~~~~~~~~~
Expand All @@ -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.
Expand All @@ -229,24 +237,24 @@ Contacts work just like devices:
print(pb.contacts)
# [Contact('Peter' <[email protected]>), Contact('Sophie' <[email protected]>]

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

.. code:: python

success, bob = pb.new_contact("Bob", "[email protected]")
bob = pb.new_contact("Bob", "[email protected]")

Editing contacts
^^^^^^^^^^^^^^^^^
Expand All @@ -255,34 +263,30 @@ 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 <https://www.pushbullet.com/api>`__
contains a list of possible status codes.

TODO
----

- Websocket support
- Tests, tests, tests. Write them.
- More tests. Write them all.

License
-------
Expand Down