Skip to content
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@ coverage.xml
# Sphinx documentation
docs/_build/

.idea/
venv/
15 changes: 15 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
language: python
python:
- "2.7"
- "3.2"
- "3.3"
- "3.4"
- "pypy"
- "pypy3"
install:
- pip install .
- pip install coveralls
script:
- coverage run setup.py test
after_success:
- coveralls
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# python-gyazo
[![PyPI version](https://badge.fury.io/py/python-gyazo.svg)](http://badge.fury.io/py/python-gyazo)
[![Build Status](https://travis-ci.org/ymyzk/python-gyazo.svg?branch=master)](https://travis-ci.org/ymyzk/python-gyazo)
[![Coverage Status](https://img.shields.io/coveralls/ymyzk/python-gyazo.svg)](https://coveralls.io/r/ymyzk/python-gyazo?branch=master)

A Python wrapper for Gyazo API.

## Requirements
* Python 2.7
* Python 3.4
* Python 3.4+

## Installation
`pip install python-gyazo`
Expand Down
86 changes: 56 additions & 30 deletions gyazo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,81 @@

class Api(object):
def __init__(self, client_id=None, client_secret=None, access_token=None,
api_url=None, upload_url=None):
"""A Python interface for Gyazo API"""

if api_url is None:
self.api_url = 'https://api.gyazo.com'
else:
self.api_url = api_url

if upload_url is None:
self.upload_url = 'https://upload.gyazo.com'
else:
self.upload_url = upload_url

api_url='https://api.gyazo.com',
upload_url='https://upload.gyazo.com'):
"""A Python interface for Gyazo API

:param client_id: API client ID
:type client_id: str or unicode
:param client_secret: API secret
:type client_secret: str or unicode
:param access_token: API access token
:type access_token: str or unicode
:param api_url: (optional) API endpoint URL
(default: https://api.gyazo.com)
:type api_url: str or unicode
:param upload_url: (optional) Upload API endpoint URL
(default: https://upload.gyazo.com)
:type upload_url: str or unicode
"""

self.api_url = api_url
self.upload_url = upload_url
self._client_id = client_id
self._client_secret = client_secret
self._access_token = access_token

def get_image_list(self, page=1, per_page=20):
"""Return a list of user's saved images"""
"""Return a list of user's saved images

:param int page: Page (default: 1)
:param int per_page: Number of images per page
(default: 20, min: 1, max 100)
"""
url = self.api_url + '/api/images'
parameters = {}
parameters['page'] = page
parameters['per_page'] = per_page
parameters = {
'page': page,
'per_page': per_page
}
response = self._request_url(url, 'get', parameters)
headers, result = self._parse_and_check(response)
images = ImageList.from_list(result)
images.set_from_headers(headers)
images.set_attributes_from_headers(headers)
return images

def upload_image(self, image_file):
"""Upload an image"""
"""Upload an image

:param image_file: File-like object of image file
:type image_file: file object
"""
url = self.upload_url + '/api/upload'
files = {}
files['imagedata'] = image_file
files = {
'imagedata': image_file
}
response = self._request_url(url, 'post', files=files)
headers, result = self._parse_and_check(response)
image = Image.from_dict(result)
return image
return Image.from_dict(result)

def delete_image(self, image_id):
"""Delete an image"""
"""Delete an image

:param image_id: Image ID
:type image_id: str or unicode
"""
url = self.api_url + '/api/images/' + image_id
response = self._request_url(url, 'delete')
headers, result = self._parse_and_check(response)
image = Image.from_dict(result)
return image
return Image.from_dict(result)

def _request_url(self, url, method, data=None, files=None):
"""Send HTTP request

:param url: URL
:type url: str or unicode
:param method: HTTP method (get, post or delete)
:type method: str or unicode
"""
headers = {'Authorization': 'Bearer ' + self._access_token}

if method == 'get':
Expand All @@ -82,15 +109,14 @@ def _request_url(self, url, method, data=None, files=None):
return None

def _parse_and_check(self, data):
data_dict = {}
try:
headers = data.headers
data_dict = data.json()
json_data = data.json()
except Exception as e:
raise e

if data.status_code >= 400:
message = data_dict.get('message', 'Error')
message = json_data.get('message', 'Error')
raise GyazoError(message)

return (headers, data_dict,)
return headers, json_data
2 changes: 1 addition & 1 deletion gyazo/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@


class GyazoError(Exception):
pass
pass
47 changes: 24 additions & 23 deletions gyazo/image.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import, unicode_literals
from __future__ import absolute_import, division, unicode_literals
import json
import math

import dateutil.parser
import requests

from .error import GyazoError


class Image(object):
def __init__(self, **kwargs):
defaults = {
'created_at': None,
'image_id': None,
'permalink_url': None,
'star': None,
'thumb_url': None,
'type': None,
'url': None
}
for key in defaults:
setattr(self, key, kwargs.get(key, defaults[key]))
self.created_at = kwargs.get('created_at', None)
self.image_id = kwargs.get('image_id', None)
self.permalink_url = kwargs.get('permalink_url', None)
self.star = kwargs.get('star', None)
self.thumb_url = kwargs.get('thumb_url', None)
self.type = kwargs.get('type', None)
self.url = kwargs.get('url', None)

@property
def filename(self):
Expand Down Expand Up @@ -94,15 +93,11 @@ def from_dict(data):

class ImageList(object):
def __init__(self, **kwargs):
defaults = {
'total_count': None,
'current_page': None,
'per_page': None,
'user_type': None,
'images': []
}
for key in defaults:
setattr(self, key, kwargs.get(key, defaults[key]))
self.total_count = kwargs.get('total_count', None)
self.current_page = kwargs.get('current_page', None)
self.per_page = kwargs.get('per_page', None)
self.user_type = kwargs.get('user_type', None)
self.images = kwargs.get('images', [])

def __len__(self):
return len(self.images)
Expand All @@ -119,7 +114,13 @@ def __delitem__(self, key):
def __iter__(self):
return self.images.__iter__()

def set_from_headers(self, headers):
def has_next_page(self):
return self.current_page < math.ceil(self.total_count / self.per_page)

def has_previous_page(self):
return 0 < self.current_page

def set_attributes_from_headers(self, headers):
self.total_count = headers.get('x-total-count', None)
self.current_page = headers.get('x-current-page', None)
self.per_page = headers.get('x-per-page', None)
Expand All @@ -134,4 +135,4 @@ def set_from_headers(self, headers):

@staticmethod
def from_list(data):
return ImageList(images=[Image.from_dict(d) for d in data])
return ImageList(images=[Image.from_dict(d) for d in data])
48 changes: 28 additions & 20 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,39 @@

try:
from setuptools import setup
except:
except ImportError:
from distutils.core import setup


__author__ = 'Yusuke Miyazaki <miyazaki.dev@gmail.com>'
__version__ = '0.2.0'

requires = [
'requests>=2.4.0',
'python-dateutil>=2.2'
]

classifiers = [
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Topic :: Internet',
'Topic :: Software Development :: Libraries :: Python Modules'
]

setup(name='python-gyazo',
version='0.2.0',
version=__version__,
description='A Python wrapper for Gyazo API',
author='Yusuke Miyazaki',
author=__author__,
author_email='miyazaki.dev@gmail.com',
url='https://github.com/litesystems/python-gyazo',
url='https://github.com/ymyzk/python-gyazo',
packages=['gyazo'],
test_suite='tests',
install_requires=[
'requests>=2.3.0',
'python-dateutil>=2.2'
],
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Topic :: Internet',
'Topic :: Software Development :: Libraries :: Python Modules'
]
)
install_requires=requires,
classifiers=classifiers)
Empty file added tests/__init__.py
Empty file.
70 changes: 70 additions & 0 deletions tests/image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import, unicode_literals
import unittest

from gyazo import Image, ImageList


class TestImage(unittest.TestCase):
def setUp(self):
self.samples = []
self.samples.append({
'url': 'https://i.gyazo.com/2c9044330d710fca3da64b222eddf5b5.png',
'type': 'png',
'created_at': '2014-07-25T08:29:51+0000',
'image_id': '2c9044330d710fca3da64b222eddf5b5',
'thumb_url': 'https://i.gyazo.com/thumb/180/_242799a7d541869e0b73dc93ee113fb5.png',
'permalink_url': 'http://gyazo.com/2c9044330d710fca3da64b222eddf5b5'})
self.samples.append({
'url': 'https://i.gyazo.com/9d04d2da1b4daaaa234c68b5219dc1e3.png',
'type': 'png',
'created_at': '2014-07-20T03:09:34+0900',
'image_id': '9d04d2da1b4daaaa234c68b5219dc1e3',
'thumb_url': 'https://i.gyazo.com/thumb/180/_eadaaad52408b1e53c09111d6959139f.png',
'permalink_url': 'http://gyazo.com/9d04d2da1b4daaaa234c68b5219dc1e3'})
self.samples.append({
'url': '',
'type': 'png',
'created_at': '2014-06-21T13:45:46+0000',
'image_id': '',
'thumb_url': 'https://i.gyazo.com/thumb/180/_ebb000813faac4c0572cc0fc0b2d8ede.png',
'permalink_url': ''})

def test_from_dict(self):
for sample in self.samples:
image = Image.from_dict(sample)
self.assertIsNotNone(image)

def test_to_dict(self):
for sample in self.samples:
image = Image.from_dict(sample).to_dict()
for key in sample:
if sample[key] is not None and sample[key] != '':
self.assertEqual(sample[key], image[key])


class TestImageList(unittest.TestCase):
def test_has_next_page(self):
il = ImageList()
il.total_count = 23
il.per_page = 10
il.current_page = 0
self.assertTrue(il.has_next_page())
il.current_page = 3
self.assertFalse(il.has_next_page())
il.total_count = 20
il.current_page = 0
self.assertTrue(il.has_next_page())
il.current_page = 2
self.assertFalse(il.has_next_page())
il.current_page = 4
self.assertFalse(il.has_next_page())

def test_has_previous_page(self):
il = ImageList()
il.current_page = 0
self.assertFalse(il.has_previous_page())
il.current_page = 1
self.assertTrue(il.has_previous_page())