From 31559819bcf30500a069217d78b81835410c51e1 Mon Sep 17 00:00:00 2001 From: salvoventura Date: Mon, 21 Jan 2019 21:38:34 -0800 Subject: [PATCH 1/2] - Add support for PyPexel new /curated/ API endpoint -- Add tests for Curated() -- Add documentation for Curated() - Add Random() class (emulated via Curated() according to documentation) -- Add documentation for Random() --- docs/source/classes/class_curated.rst | 252 ++++++++++++++++++ docs/source/classes/class_random_.rst | 74 +++++ docs/source/conf.py | 2 +- docs/source/examples.rst | 20 ++ docs/source/index.rst | 1 + pypexels/examples/example_random.py | 40 +++ pypexels/pypexels.py | 8 + pypexels/src/__init__.py | 2 + pypexels/src/curated.py | 35 +++ pypexels/src/random_.py | 48 ++++ .../resource__curated_per_page_5_page_2.json | 1 + .../resource__popular_per_page_5_page_2.json | 2 +- ...ch_per_page_5_page_2_query_red_flower.json | 2 +- pypexels/tests/resources/resource_download.py | 6 + pypexels/tests/test_curated.py | 70 +++++ setup.py | 6 +- 16 files changed, 562 insertions(+), 7 deletions(-) create mode 100644 docs/source/classes/class_curated.rst create mode 100644 docs/source/classes/class_random_.rst create mode 100644 pypexels/examples/example_random.py create mode 100644 pypexels/src/curated.py create mode 100644 pypexels/src/random_.py create mode 100644 pypexels/tests/resources/resource__curated_per_page_5_page_2.json create mode 100644 pypexels/tests/test_curated.py diff --git a/docs/source/classes/class_curated.rst b/docs/source/classes/class_curated.rst new file mode 100644 index 0000000..21ec8cd --- /dev/null +++ b/docs/source/classes/class_curated.rst @@ -0,0 +1,252 @@ +################## +API: Class Curated +################## +This class is used to access the **curated** photos on the ``PyPexels`` ``/curated/`` REST API. + +It is returned as result from a call to ``PyPexels.curated(page, per_page)`` + + +========== +Properties +========== +Properties exposed by the ``Curated`` class. + +----------------------------------------------------- +**Curated.entries** +----------------------------------------------------- + Iterator for the returned objects contained in this ``Curated`` instance. + Each entry will be an instance of class ``Photo``. + + ========== ======================================== + iterator each time an instance of class ``Photo`` + ========== ======================================== + + **Example** + :: + + import pypexels + py_pexel = pypexels.PyPexels(api_key='YOUR_API_KEY') + + # + # + curated_photos_page = py_pexel.curated(per_page=40) + for photo in curated_photos_page.entries: + print(photo.id, photo.photographer, photo.url) + # no need to specify per_page: will take from original object + curated_photos_page = curated_photos_page.get_next_page() + curated_results = py_pexel.curated(per_page=40) + for photo in curated_results.entries: + print(photo.id, photo.photographer, photo.url) + +----------------------------------------------------- +**Curated.page** +----------------------------------------------------- + Current curated photos page number. + + ========== ======================================== + int current curated photos page number + ========== ======================================== + +----------------------------------------------------- +**Curated.per_page** +----------------------------------------------------- + Current curated photos per_page value. + + ========== ======================================== + int current curated photos per_page value + ========== ======================================== + +----------------------------------------------------- +**Curated.has_previous** +----------------------------------------------------- + Returns boolean **True** or **False** depending on whether the current results page + has a previous page to navigate to or not. + + ========== ======================================== + boolean presence of previous page results + ========== ======================================== + +----------------------------------------------------- +**Curated.has_next** +----------------------------------------------------- + Returns boolean **True** or **False** depending on whether the current results page + has a next page to navigate to or not. + + ========== ======================================== + boolean presence of next page results + ========== ======================================== + +----------------------------------------------------- +**Curated.body** +----------------------------------------------------- + Returns JSON body of curated photos page. + + ========== ======================================== + JSON JSON converted body of results page + ========== ======================================== + +----------------------------------------------------- +**Curated.headers** +----------------------------------------------------- + Returns response headers of curated photos page. + + ========== ======================================== + dict headers of results page + ========== ======================================== + +----------------------------------------------------- +**Curated.link_self** +----------------------------------------------------- + Returns URL to current results page + + ========== ======================================== + str URL to current results page + ========== ======================================== + +----------------------------------------------------- +**Curated.link_next** +----------------------------------------------------- + Returns URL to next results page + + ========== ======================================== + str URL to next results page + ========== ======================================== + +----------------------------------------------------- +**Curated.link_previous** +----------------------------------------------------- + Returns URL to previous results page + + ========== ======================================== + str URL to previous results page + ========== ======================================== + +----------------------------------------------------- +**Curated.link_first** +----------------------------------------------------- + Returns URL to first results page + + ========== ======================================== + str URL to first results page + ========== ======================================== + + +.. note:: ``curated.total_results`` always returns 0 (zero). + ``curated.link_last`` always points to the first page. + + +======= +Methods +======= +Methods exposed by the ``Curated`` class. + +----------------------------------------------------- +**Curated.get_page()** +----------------------------------------------------- + Returns the requested curated photos page with the current `query` and `per_page` parameters. + The returned page may not contain `entries` if the page is out of boundaries. + + **Parameters** + + ============ ====== =========================== ==================================== + Argument Type Optional/Required Notes + ============ ====== =========================== ==================================== + **page** number required Page number to retrieve. + ============ ====== =========================== ==================================== + + **Returns** + + ========== ======================================================================== + **Object** Instance of class ``Curated`` + ========== ======================================================================== + +-------- + + +----------------------------------------------------- +**Curated.get_next_page()** +----------------------------------------------------- + Returns next available curated photos page with the current `query`, `page`, and `per_page` parameters. + Returns `None` if no page is available. + + **Returns** + + ========== ======================================================================== + **Object** Instance of class ``Curated`` or `None` + ========== ======================================================================== + + **Example** + :: + + import pypexels + py_pexel = pypexels.PyPexels(api_key='YOUR_API_KEY') + + # + # + search_results = py_pexel.curated(query='red flowers', per_page=40) + while search_results is not None: + print 'Current page number %s' % search_results.page + search_results = search_results.get_next_page() + +-------- + + +----------------------------------------------------- +**Curated.get_previous_page()** +----------------------------------------------------- + Returns previous available curated photos page with the current `query`, `page`, and `per_page` parameters. + Returns `None` if no page is available. + + **Returns** + + ========== ======================================================================== + **Object** Instance of class ``Curated`` or `None` + ========== ======================================================================== + + **Example** + :: + + import pypexels + py_pexel = pypexels.PyPexels(api_key='YOUR_API_KEY') + + # + # + search_results = py_pexel.curated(query='red flowers', page=3, per_page=40) + while search_results is not None: + print 'Current page number %s' % search_results.page + search_results = search_results.get_previous_page() + +-------- + + +----------------------------------------------------- +**Curated.get_first_page()** +----------------------------------------------------- + Returns first curated photos page with the current `query`, `page`, and `per_page` parameters. + Returns `None` if no page is available. + + **Returns** + + ========== ======================================================================== + **Object** Instance of class ``Curated`` or `None` + ========== ======================================================================== + + **Example** + :: + + import pypexels + py_pexel = pypexels.PyPexels(api_key='YOUR_API_KEY') + + # + # + search_results = py_pexel.curated(query='red flowers', page=3, per_page=40) + print 'Current page number %s' % search_results.page + # To something with search_results + + # Go back to first page + search_results = search_results.get_first_page(): + print 'Current page number %s' % search_results.page + +-------- + +.. note:: ``curated.get_last_page()`` always returns the first page. diff --git a/docs/source/classes/class_random_.rst b/docs/source/classes/class_random_.rst new file mode 100644 index 0000000..2c60618 --- /dev/null +++ b/docs/source/classes/class_random_.rst @@ -0,0 +1,74 @@ +################# +API: Class Random +################# +This class is used to emulate a **random** API using the ``PyPexels`` ``/curated/`` REST API. + +It is returned as result from a call to ``PyPexels.random(per_page)`` + + +========== +Properties +========== +Properties exposed by the ``Random`` class. + +----------------------------------------------------- +**Random.entries** +----------------------------------------------------- + Returns an iterator for the returned objects contained in this ``Random`` instance. + Each entry will be an instance of class ``Photo``. + + ========== ======================================== + iterator each time an instance of class ``Photo`` + ========== ======================================== + + **Example** + :: + + import pypexels + py_pexel = pypexels.PyPexels(api_key='YOUR_API_KEY') + + # + # + random_results = py_pexel.random(per_page=10) + for photo in random_results.entries: + print(photo.id, photo.photographer, photo.url) + + +----------------------------------------------------- +**Random.per_page** +----------------------------------------------------- + Current random results per_page value. + + ========== ======================================== + int current random results per_page value + ========== ======================================== + +----------------------------------------------------- +**Random.has_previous** +----------------------------------------------------- + Returns always boolean **False** + + ========== ======================================== + boolean presence of previous page results + ========== ======================================== + +----------------------------------------------------- +**Random.has_next** +----------------------------------------------------- + Returns always boolean **True** + + ========== ======================================== + boolean presence of next page results + ========== ======================================== + + + +------------------ +**IMPORTANT NOTE** +------------------ +Although this class will expose additional methods and properties from the ``PyPexels.Curated`` class, you should only +rely upon and make use of the methods and properties listed above. Remember, this is a `convenience` class that provides +some uniformity in behavior while emulating a random image generator. If you need to fully control the content and +behavior of the classes, then revert to use ``PyPexels.Curated`` class, with ``per_page=1`` and ``page=randint()`` value +directly. + diff --git a/docs/source/conf.py b/docs/source/conf.py index f5a03c3..066b946 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -64,7 +64,7 @@ # General information about the project. project = u'PyPexels' -copyright = u'2017 Salvatore Ventura' +copyright = u'2017,2018,2019 Salvatore Ventura' author = u'Salvatore Ventura' # The version info for the project you're documenting, acts as replacement for diff --git a/docs/source/examples.rst b/docs/source/examples.rst index 6b7e9be..47f3f8a 100644 --- a/docs/source/examples.rst +++ b/docs/source/examples.rst @@ -49,3 +49,23 @@ each, retrieve each photo in there, and print some of their attributes. if not search_results.has_next: break search_results = search_results.get_next_page() + + +====== +Random +====== +The code below will return random images. Use the parameter ``per_page`` to specify how many random images the iterator +will allow. + +.. code-block:: python + + from pypexels import PyPexels + api_key = 'YOUR_API_KEY' + + # instantiate PyPexels object + py_pexel = PyPexels(api_key=api_key) + + random_photos_page = py_pexel.random(per_page=3) + for photo in random_photos_page.entries: + print(photo.id, photo.photographer, photo.url) + diff --git a/docs/source/index.rst b/docs/source/index.rst index e5d00b2..3ac935e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,6 +15,7 @@ The source code is available on GitHub at `https://github.com/salvoventura/pypex classes/class_pypexels classes/class_popular classes/class_search + classes/class_random classes/class_photo version license diff --git a/pypexels/examples/example_random.py b/pypexels/examples/example_random.py new file mode 100644 index 0000000..b9d87b4 --- /dev/null +++ b/pypexels/examples/example_random.py @@ -0,0 +1,40 @@ +############################################################################### +# Copyright (c) 2019 Salvatore Ventura +# +# File: example_random.py +# +# Author: Salvatore Ventura +# Date: 20 Jan 2019 +# Purpose: Exemplify usage of Random +# +# Revision: 1 +# Comment: What's new in revision 1 +# +############################################################################### +import logging +import os +from pypexels import PyPexels +api_key = os.environ.get('API_KEY', None) or 'DUMMY_API_KEY' + +# Initialize app logging +logger = logging.getLogger() +logging.basicConfig(filename='app_random.log', level=logging.DEBUG) + +# pypexels logger defaults to level logging.ERROR +# If you need to change that, use getLogger/setLevel +# on the module logger, like this: +logging.getLogger(PyPexels.logger_name).setLevel(logging.DEBUG) + +# add a headers to the log +logger.debug(80*'=') +logging.debug('Testing PyPexels.random()') +logger.debug(80*'=') + +# instantiate PyPexels object +py_pexel = PyPexels(api_key=api_key) + + +random_photos_page = py_pexel.random(per_page=7) +for photo in random_photos_page.entries: + print(photo.id, photo.photographer, photo.url) + diff --git a/pypexels/pypexels.py b/pypexels/pypexels.py index 08e4d11..97069e3 100644 --- a/pypexels/pypexels.py +++ b/pypexels/pypexels.py @@ -12,9 +12,12 @@ # ############################################################################### # from .src.liblogging import logger +from random import randint from .src import API_VERSION, LIB_NAME from .src import Popular +from .src import Curated from .src import Search +from .src import Random class PyPexels(object): @@ -27,6 +30,11 @@ def __init__(self, api_key, api_version=API_VERSION): def popular(self, **kwargs): return Popular(api_key=self.api_key, api_version=self.api_version, **kwargs) + def curated(self, **kwargs): + return Curated(api_key=self.api_key, api_version=self.api_version, **kwargs) + def search(self, **kwargs): return Search(api_key=self.api_key, api_version=self.api_version, **kwargs) + def random(self, **kwargs): + return Random(api_key=self.api_key, api_version=self.api_version, **kwargs) diff --git a/pypexels/src/__init__.py b/pypexels/src/__init__.py index d4efcd7..660853c 100644 --- a/pypexels/src/__init__.py +++ b/pypexels/src/__init__.py @@ -13,5 +13,7 @@ ############################################################################### from .errors import PexelsError from .popular import Popular +from .curated import Curated from .search import Search +from .random_ import Random from .settings import API_VERSION, API_ROOT, LIB_NAME, LOG_LEVEL diff --git a/pypexels/src/curated.py b/pypexels/src/curated.py new file mode 100644 index 0000000..aee781d --- /dev/null +++ b/pypexels/src/curated.py @@ -0,0 +1,35 @@ +############################################################################### +# Copyright (c) 2019 Salvatore Ventura +# +# File: curated.py +# +# Author: Salvatore Ventura +# Date: 20 Jan 2019 +# Purpose: Handle Curated photo pages +# +# Revision: 1 +# Comment: What's new in revision 1 +# +############################################################################### +# from .liblogging import logger +from .errors import PexelsError +from .models import Photo +from .pexelspage import PexelsPage +from .settings import API_VERSION + + +class Curated(PexelsPage): + + def __init__(self, api_key, url='/curated', api_version=API_VERSION, **kwargs): + + if url.find('/curated') == -1: + raise PexelsError('Invalid _url for class Curated(): %s' % url) + + valid_options = ['page', 'per_page'] + super(Curated, self).__init__(url=url, api_key=api_key, api_version=api_version, valid_options=valid_options, + **kwargs) + + @property + def entries(self): + for entry in self.body.get('photos', []): + yield Photo.parse(entry) diff --git a/pypexels/src/random_.py b/pypexels/src/random_.py new file mode 100644 index 0000000..98ce01b --- /dev/null +++ b/pypexels/src/random_.py @@ -0,0 +1,48 @@ +############################################################################### +# Copyright (c) 2019 Salvatore Ventura +# +# File: random_.py +# +# Author: Salvatore Ventura +# Date: 20 Jan 2019 +# Purpose: Emulate random photo pages, using the Curated Photos endpoint and +# setting per_page=1, page=random(1,1000), and making it an iterator +# +# Revision: 1 +# Comment: What's new in revision 1 +# +############################################################################### +from .liblogging import logger +from random import randint +from .errors import PexelsError +from .models import Photo +from .pexelspage import PexelsPage +from .settings import API_VERSION + + +class Random(PexelsPage): + + def __init__(self, api_key, url='/curated', api_version=API_VERSION, **kwargs): + valid_options = ['page', 'per_page'] + self.entries_count = kwargs.get('per_page', 0) + kwargs['per_page'] = 1 + kwargs['page'] = 1 + super(Random, self).__init__(url=url, api_key=api_key, api_version=api_version, valid_options=valid_options, **kwargs) + + @property + def entries(self): + for _ in range(self.entries_count): + random_page = randint(1, 1000) + random_collection = self.get_page(random_page) + for entry in random_collection.body.get('photos', []): + yield Photo.parse(entry) + + @property + def has_next(self): + # You can continue to get pages of random photos forever + return True + + @property + def has_previous(self): + # You can't go back in time: no history is kept (for now) + return False diff --git a/pypexels/tests/resources/resource__curated_per_page_5_page_2.json b/pypexels/tests/resources/resource__curated_per_page_5_page_2.json new file mode 100644 index 0000000..b412a04 --- /dev/null +++ b/pypexels/tests/resources/resource__curated_per_page_5_page_2.json @@ -0,0 +1 @@ +{"body": {"per_page": 5, "next_page": "https://api.pexels.com/v1/curated/?page=3&per_page=5", "page": 2, "prev_page": "https://api.pexels.com/v1/curated/?page=1&per_page=5", "photos": [{"src": {"medium": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg", "landscape": "https://images.pexels.com/photos/1805416/pexels-photo-1805416.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/women-s-white-wedding-gown-1805416/", "photographer": "Criativithy", "photographer_url": "https://www.pexels.com/@criativithy-894081", "height": 4000, "width": 6000, "id": 1805416}, {"src": {"medium": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg", "landscape": "https://images.pexels.com/photos/1805439/pexels-photo-1805439.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/women-s-red-crew-neck-shirt-1805439/", "photographer": "bruce mars", "photographer_url": "https://www.pexels.com/@olly", "height": 2296, "width": 3444, "id": 1805439}, {"src": {"medium": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg", "landscape": "https://images.pexels.com/photos/1319839/pexels-photo-1319839.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/people-walking-on-street-during-night-time-1319839/", "photographer": "Qihong", "photographer_url": "https://www.pexels.com/@qihong-265354", "height": 4000, "width": 6000, "id": 1319839}, {"src": {"medium": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg", "landscape": "https://images.pexels.com/photos/1805445/pexels-photo-1805445.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/black-and-white-beaded-necklace-1805445/", "photographer": "Cami Henry", "photographer_url": "https://www.pexels.com/@cami-henry-895402", "height": 4016, "width": 6016, "id": 1805445}, {"src": {"medium": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg", "landscape": "https://images.pexels.com/photos/1805818/pexels-photo-1805818.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/green-and-white-wooden-board-1805818/", "photographer": "P C", "photographer_url": "https://www.pexels.com/@pcees", "height": 2400, "width": 3619, "id": 1805818}]}, "headers": {"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", "X-Ratelimit-Remaining": "19932", "X-Ratelimit-Limit": "20000", "Transfer-Encoding": "chunked", "Vary": "Origin", "X-Request-Id": "fd56a9af-695f-473f-a4db-2772cda01c7e", "Server": "cloudflare", "Connection": "keep-alive", "Etag": "W/\"b862c009fd5aaca5fb25fbf8f2a54318\"", "Cache-Control": "max-age=0, private, must-revalidate", "Date": "Mon, 21 Jan 2019 03:45:40 GMT", "X-Frame-Options": "ALLOWALL", "X-Runtime": "0.274668", "Content-Type": "application/json; charset=utf-8", "CF-RAY": "49c6ca0e4a76928e-SJC", "X-Ratelimit-Reset": "1550559445"}, "last_update": "Sun Jan 20 19:45:38 2019", "_url": "/curated?per_page=5&page=2", "status_code": 200} \ No newline at end of file diff --git a/pypexels/tests/resources/resource__popular_per_page_5_page_2.json b/pypexels/tests/resources/resource__popular_per_page_5_page_2.json index 8a5873d..bf09bc5 100644 --- a/pypexels/tests/resources/resource__popular_per_page_5_page_2.json +++ b/pypexels/tests/resources/resource__popular_per_page_5_page_2.json @@ -1 +1 @@ -{"body": {"per_page": 5, "next_page": "https://api.pexels.com/v1/popular/?page=3&per_page=5", "page": 2, "prev_page": "https://api.pexels.com/v1/popular/?page=1&per_page=5", "photos": [{"src": {"medium": "https://images.pexels.com/photos/34950/pexels-photo.jpg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/34950/pexels-photo.jpg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/34950/pexels-photo.jpg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/34950/pexels-photo.jpg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/34950/pexels-photo.jpg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/34950/pexels-photo.jpg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/34950/pexels-photo.jpg", "landscape": "https://images.pexels.com/photos/34950/pexels-photo.jpg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/abandoned-forest-industry-nature-34950/", "photographer": "Snapwire", "height": 3456, "width": 5184, "id": 34950}, {"src": {"medium": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/33045/lion-wild-africa-african.jpg", "landscape": "https://images.pexels.com/photos/33045/lion-wild-africa-african.jpg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/animal-africa-zoo-lion-33045/", "photographer": "Pixabay", "height": 2835, "width": 4252, "id": 33045}, {"src": {"medium": "https://images.pexels.com/photos/7919/pexels-photo.jpg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/7919/pexels-photo.jpg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/7919/pexels-photo.jpg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/7919/pexels-photo.jpg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/7919/pexels-photo.jpg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/7919/pexels-photo.jpg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/7919/pexels-photo.jpg", "landscape": "https://images.pexels.com/photos/7919/pexels-photo.jpg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/mist-misty-fog-foggy-7919/", "photographer": "Life Of Pix", "height": 2832, "width": 6012, "id": 7919}, {"src": {"medium": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg", "landscape": "https://images.pexels.com/photos/68147/waterfall-thac-dray-nur-buon-me-thuot-daklak-68147.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/landscape-nature-wilderness-view-68147/", "photographer": "Public Domain Pictures", "height": 1280, "width": 1920, "id": 68147}, {"src": {"medium": "https://images.pexels.com/photos/17679/pexels-photo.jpg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/17679/pexels-photo.jpg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/17679/pexels-photo.jpg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/17679/pexels-photo.jpg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/17679/pexels-photo.jpg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/17679/pexels-photo.jpg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/17679/pexels-photo.jpg", "landscape": "https://images.pexels.com/photos/17679/pexels-photo.jpg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/umbrellas-art-flying-17679/", "photographer": "Adrianna Calvo", "height": 3485, "width": 5472, "id": 17679}]}, "headers": {"X-Ratelimit-Remaining": "19916", "X-Ratelimit-Limit": "20000", "X-Powered-By": "cloud66", "Transfer-Encoding": "chunked", "Vary": "Origin", "X-Request-Id": "f111ca5f-4ae4-4a70-aeaa-afbef96e1388", "Server": "cloudflare-nginx", "Connection": "keep-alive", "Etag": "W/\"7d5828855044a2e17cb12c7093f07ffe\"", "Cache-Control": "max-age=0, private, must-revalidate", "Date": "Wed, 27 Sep 2017 23:07:35 GMT", "X-Frame-Options": "ALLOWALL", "X-Runtime": "0.058571", "Content-Type": "application/json; charset=utf-8", "CF-RAY": "3a521ebc0e546cac-SJC", "X-Ratelimit-Reset": "1508909360"}, "last_update": "Wed Sep 27 16:07:35 2017", "_url": "/popular?per_page=5&page=2", "status_code": 200} \ No newline at end of file +{"body": {"per_page": 5, "next_page": "https://api.pexels.com/v1/popular/?page=3&per_page=5", "page": 2, "prev_page": "https://api.pexels.com/v1/popular/?page=1&per_page=5", "photos": [{"src": {"medium": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg", "landscape": "https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/nature-red-love-romantic-67636/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 3264, "width": 4928, "id": 67636}, {"src": {"medium": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg", "landscape": "https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/nature-red-forest-leaves-33109/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 2304, "width": 3456, "id": 33109}, {"src": {"medium": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg", "landscape": "https://images.pexels.com/photos/1402787/pexels-photo-1402787.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/photo-of-audi-parked-near-trees-1402787/", "photographer": "Vlad Alexandru Popa", "photographer_url": "https://www.pexels.com/@vladalex94", "height": 4000, "width": 6000, "id": 1402787}, {"src": {"medium": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg", "landscape": "https://images.pexels.com/photos/853199/pexels-photo-853199.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/aerial-view-of-seashore-near-large-grey-rocks-853199/", "photographer": "Artem Bali", "photographer_url": "https://www.pexels.com/@belart84", "height": 4000, "width": 6000, "id": 853199}, {"src": {"medium": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg", "landscape": "https://images.pexels.com/photos/36717/amazing-animal-beautiful-beautifull.jpg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/flight-landscape-nature-sky-36717/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 1195, "width": 1920, "id": 36717}]}, "headers": {"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", "X-Ratelimit-Remaining": "19933", "X-Tyk-Cached-Response": "1", "X-Ratelimit-Limit": "20000", "Transfer-Encoding": "chunked", "Vary": "Origin", "X-Request-Id": "a724ead8-7e13-4408-9636-f69cbf8aed49", "Server": "cloudflare", "Connection": "keep-alive", "Etag": "W/\"558a3735276fc3cbdb96d8a9dcb34ba9\"", "Cache-Control": "max-age=0, private, must-revalidate", "Date": "Mon, 21 Jan 2019 03:45:39 GMT", "X-Frame-Options": "ALLOWALL", "X-Runtime": "0.079599", "Content-Type": "application/json; charset=utf-8", "CF-RAY": "49c6ca0c6dea93a2-SJC", "X-Ratelimit-Reset": "1550559445"}, "last_update": "Sun Jan 20 19:45:38 2019", "_url": "/popular?per_page=5&page=2", "status_code": 200} \ No newline at end of file diff --git a/pypexels/tests/resources/resource__search_per_page_5_page_2_query_red_flower.json b/pypexels/tests/resources/resource__search_per_page_5_page_2_query_red_flower.json index 608026e..7b19bcd 100644 --- a/pypexels/tests/resources/resource__search_per_page_5_page_2_query_red_flower.json +++ b/pypexels/tests/resources/resource__search_per_page_5_page_2_query_red_flower.json @@ -1 +1 @@ -{"body": {"next_page": "https://api.pexels.com/v1/search/?page=3&per_page=5&query=red+flower", "prev_page": "https://api.pexels.com/v1/search/?page=1&per_page=5&query=red+flower", "total_results": 3863, "photos": [{"src": {"medium": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/343232/pexels-photo-343232.jpeg", "landscape": "https://images.pexels.com/photos/343232/pexels-photo-343232.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/beautiful-beauty-blooming-blossom-343232/", "photographer": "Nejc Ko\u0161ir", "height": 3168, "width": 4752, "id": 343232}, {"src": {"medium": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg", "landscape": "https://images.pexels.com/photos/65940/dahlia-dahlias-autumn-asteraceae-65940.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/close-up-photography-of-red-petaled-flower-65940/", "photographer": "Pixabay", "height": 2000, "width": 2418, "id": 65940}, {"src": {"medium": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/531731/pexels-photo-531731.jpeg", "landscape": "https://images.pexels.com/photos/531731/pexels-photo-531731.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/beautiful-bloom-blooming-blossom-531731/", "photographer": "Pixabay", "height": 2828, "width": 4241, "id": 531731}, {"src": {"medium": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg", "landscape": "https://images.pexels.com/photos/87633/tulips-tulip-field-fields-87633.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/red-field-flowers-garden-87633/", "photographer": "Public Domain Pictures", "height": 2505, "width": 5000, "id": 87633}, {"src": {"medium": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?h=350&auto=compress&cs=tinysrgb", "tiny": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?w=280&h=200&fit=crop&auto=compress&cs=tinysrgb", "large": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?w=940&h=650&auto=compress&cs=tinysrgb", "square": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?w=1200&h=1200&fit=crop&auto=compress&cs=tinysrgb", "small": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?h=130&auto=compress&cs=tinysrgb", "portrait": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?w=800&h=1200&fit=crop&auto=compress&cs=tinysrgb", "original": "https://static.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg", "landscape": "https://images.pexels.com/photos/57423/red-rose-rose-rose-bloom-blossom-57423.jpeg?w=1200&h=627&fit=crop&auto=compress&cs=tinysrgb"}, "url": "https://www.pexels.com/photo/red-flower-rose-bloom-57423/", "photographer": "Pixabay", "height": 2218, "width": 3954, "id": 57423}], "per_page": 5, "page": 2}, "headers": {"X-Ratelimit-Remaining": "19915", "X-Ratelimit-Limit": "20000", "X-Powered-By": "cloud66", "Transfer-Encoding": "chunked", "Vary": "Origin", "X-Request-Id": "81a27dbb-b7bd-4018-a9b7-32ba20483775", "Server": "cloudflare-nginx", "Connection": "keep-alive", "Etag": "W/\"6690a8dc6275753424ed9fc970019068\"", "Cache-Control": "max-age=0, private, must-revalidate", "Date": "Wed, 27 Sep 2017 23:07:36 GMT", "X-Frame-Options": "ALLOWALL", "X-Runtime": "0.048889", "Content-Type": "application/json; charset=utf-8", "CF-RAY": "3a521ebe6de02828-SJC", "X-Ratelimit-Reset": "1508909360"}, "last_update": "Wed Sep 27 16:07:36 2017", "_url": "/search?per_page=5&page=2&query=red+flower", "status_code": 200} \ No newline at end of file +{"body": {"next_page": "https://api.pexels.com/v1/search/?page=3&per_page=5&query=red+flower", "prev_page": "https://api.pexels.com/v1/search/?page=1&per_page=5&query=red+flower", "total_results": 10629, "photos": [{"src": {"medium": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg", "landscape": "https://images.pexels.com/photos/60597/dahlia-red-blossom-bloom-60597.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/red-dahlia-flower-60597/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 2736, "width": 3648, "id": 60597}, {"src": {"medium": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg", "landscape": "https://images.pexels.com/photos/54320/rose-roses-flowers-red-54320.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/red-flowers-roses-rose-54320/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 2048, "width": 3072, "id": 54320}, {"src": {"medium": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg", "landscape": "https://images.pexels.com/photos/289590/pexels-photo-289590.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/background-beautiful-black-bloom-289590/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 2304, "width": 3456, "id": 289590}, {"src": {"medium": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg", "landscape": "https://images.pexels.com/photos/207962/pexels-photo-207962.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/artistic-blossom-bright-clouds-207962/", "photographer": "Pixabay", "photographer_url": "https://www.pexels.com/@pixabay", "height": 1200, "width": 1920, "id": 207962}, {"src": {"medium": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&h=350", "tiny": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=200&w=280", "large": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&h=650&w=940", "small": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&h=130", "square": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=1200&w=1200", "large2x": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940", "portrait": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800", "original": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg", "landscape": "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200"}, "url": "https://www.pexels.com/photo/red-rose-flower-658687/", "photographer": "Cindy Gustafson", "photographer_url": "https://www.pexels.com/@cindyg", "height": 1897, "width": 2371, "id": 658687}], "per_page": 5, "page": 2}, "headers": {"Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", "X-Ratelimit-Remaining": "19931", "X-Ratelimit-Limit": "20000", "Transfer-Encoding": "chunked", "Vary": "Origin", "X-Request-Id": "4bff3ad2-9053-4885-a551-945e9babe6ad", "Server": "cloudflare", "Connection": "keep-alive", "Etag": "W/\"db235f2817d8541a77e3f4751a4d2817\"", "Cache-Control": "max-age=0, private, must-revalidate", "Date": "Mon, 21 Jan 2019 03:45:40 GMT", "X-Frame-Options": "ALLOWALL", "X-Runtime": "0.029459", "Content-Type": "application/json; charset=utf-8", "CF-RAY": "49c6ca118e146e4a-SJC", "X-Ratelimit-Reset": "1550559445"}, "last_update": "Sun Jan 20 19:45:39 2019", "_url": "/search?per_page=5&page=2&query=red+flower", "status_code": 200} \ No newline at end of file diff --git a/pypexels/tests/resources/resource_download.py b/pypexels/tests/resources/resource_download.py index 55cddf6..48c77f8 100644 --- a/pypexels/tests/resources/resource_download.py +++ b/pypexels/tests/resources/resource_download.py @@ -53,6 +53,11 @@ def get_resources_popular(): _save_content(sub_url) +def get_resources_curated(): + for sub_url in ['/curated?per_page=5&page=2']: + _save_content(sub_url) + + def get_resources_search(): for sub_url in ['/search?per_page=5&page=2&query=red+flower']: _save_content(sub_url) @@ -60,6 +65,7 @@ def get_resources_search(): def main(): get_resources_popular() + get_resources_curated() get_resources_search() diff --git a/pypexels/tests/test_curated.py b/pypexels/tests/test_curated.py new file mode 100644 index 0000000..3f45602 --- /dev/null +++ b/pypexels/tests/test_curated.py @@ -0,0 +1,70 @@ +############################################################################### +# Copyright (c) 2019 Salvatore Ventura +# +# File: test_curated.py +# +# Author: Salvatore Ventura +# Date: 21 Jan 2019 +# Purpose: Unit Test for Curated() +# +# Revision: 1 +# Comment: What's new in revision 1 +# +############################################################################### +from __future__ import print_function +import responses +import json +import os +from pypexels import PyPexels +from pypexels.src.settings import API_ROOT, API_VERSION + +api_key = os.environ.get('API_KEY', None) or 'API_KEY' + + +class TestCurated: + # TODO: avoid code duplication + # Need to workout how to combine responses.activate so as to avoid + # code duplication, as the testcases are pretty much the same for all + + # TOXINIDIR comes from tox.ini + root_path = os.environ.get('TRAVIS_BUILD_DIR', None) or os.environ.get('TOXINIDIR', None) + + store_mapping = { + 'curated': os.sep.join( + [root_path, 'pypexels', 'tests', 'resources', 'resource__curated_per_page_5_page_2.json']), + } + + @responses.activate + def test_curated(self): + index = 'curated' + resource_filepath = self.store_mapping[index] + stored_response = json.loads(open(resource_filepath).read()) + + responses.add( + responses.GET, + '{}/{}{}'.format(API_ROOT, API_VERSION, stored_response.get('_url')), + # _url contains only the short path like /curated?page=2&per_page=5 + json=stored_response.get('body'), + status=stored_response.get('status_code'), + content_type='application/json', + adding_headers=stored_response.get('headers'), + match_querystring=True, + ) + py_pexels = PyPexels(api_key=api_key) + curated_results_page = py_pexels.curated(page=2, per_page=5) + + # Page properties + print(curated_results_page.page) + print(curated_results_page.per_page) + print(curated_results_page.has_next) + print(curated_results_page.has_previous) + print(curated_results_page.link_self) + print(curated_results_page.link_first) + print(curated_results_page.link_last) + print(curated_results_page.link_next) + print(curated_results_page.link_previous) + + # Entries + for photo in curated_results_page.entries: + print(photo.id, photo.photographer, photo.width, photo.height, photo.url) + print(photo.src) diff --git a/setup.py b/setup.py index 76a6c64..726d8d3 100644 --- a/setup.py +++ b/setup.py @@ -25,11 +25,9 @@ # Specify the Python versions you support here. In particular, ensure # that you indicate whether you support Python 2, Python 3 or both. - 'Programming Language :: Python :: 2.7' - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.6' ], keywords=['pexels', 'rest', 'api', 'python', 'wrapper', 'development', 'pexels.com', 'photography'], install_requires=['requests'], From 2eb6d269e21d9249c82af90f7b60dc1026559f1a Mon Sep 17 00:00:00 2001 From: salvoventura Date: Tue, 22 Jan 2019 08:17:30 -0800 Subject: [PATCH 2/2] - Prepare for release --- README.rst | 8 ++++++++ docs/source/version.rst | 4 ++-- pypexels/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 0dfa70b..bb22de0 100644 --- a/README.rst +++ b/README.rst @@ -56,6 +56,14 @@ Documentation is published on `ReadTheDocs `_. ####### Version ####### +**PyPexels v1.0.0b3 (beta, v3)** + + Third beta release introduces support for `curated` and `random`. + + Note that using this library you still need to abide to Pexels Guidelines, which + are explained on `Pexels API page `_ + + **PyPexels v1.0.0b2 (beta, v2)** Second beta release introduces Python3 support. diff --git a/docs/source/version.rst b/docs/source/version.rst index 722ae71..8e4b56a 100644 --- a/docs/source/version.rst +++ b/docs/source/version.rst @@ -1,8 +1,8 @@ Version ======= -**PyPexels v1.0.0b2 (beta, v2)** +**PyPexels v1.0.0b3 (beta, v3)** - Second beta release introduces Python3 support. + Third beta release introduces support for /curated API, and Random() class. Note that using this library you still need to abide to Pexels Guidelines, which are explained on `Pexels API page `_ diff --git a/pypexels/__init__.py b/pypexels/__init__.py index 13f8cc6..9c613d9 100644 --- a/pypexels/__init__.py +++ b/pypexels/__init__.py @@ -18,6 +18,6 @@ # TRAVIS_COMMIT # TRAVIS_COMMIT_RANGE # TRAVIS_TAG -__version__ = '1.0.0b2' +__version__ = '1.0.0b3' __author__ = 'Salvatore Ventura ' __license__ = 'MIT' diff --git a/setup.py b/setup.py index 726d8d3..6963333 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='pypexels', - version='1.0.0b2', + version='1.0.0b3', packages=['pypexels', 'pypexels.src'], url='https://github.com/salvoventura/pypexels', license='MIT',