From 3c5caae93f2a00eb09427d27747aa83ce91179e1 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Mon, 15 Feb 2021 10:31:30 -0500 Subject: [PATCH 1/5] Dev version bump --- blinkpy/helpers/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blinkpy/helpers/constants.py b/blinkpy/helpers/constants.py index 164a44af..4cc5b7b1 100644 --- a/blinkpy/helpers/constants.py +++ b/blinkpy/helpers/constants.py @@ -3,8 +3,8 @@ import os MAJOR_VERSION = 0 -MINOR_VERSION = 17 -PATCH_VERSION = 0 +MINOR_VERSION = 18 +PATCH_VERSION = "0.dev0" __version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}" From 83df95f0da3ad6f81a573302049c4fd5dd42a54d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 17 Feb 2021 06:07:15 +0000 Subject: [PATCH 2/5] Bump pylint from 2.6.0 to 2.6.2 Bumps [pylint](https://github.com/PyCQA/pylint) from 2.6.0 to 2.6.2. - [Release notes](https://github.com/PyCQA/pylint/releases) - [Changelog](https://github.com/PyCQA/pylint/blob/master/ChangeLog) - [Commits](https://github.com/PyCQA/pylint/compare/pylint-2.6.0...pylint-2.6.2) Signed-off-by: dependabot-preview[bot] --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index bea74d14..922e2753 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -3,7 +3,7 @@ coverage==5.4 flake8==3.8.4 flake8-docstrings==1.5.0 pre-commit==2.10.1 -pylint==2.6.0 +pylint==2.6.2 pydocstyle==5.1.1 pytest==6.2.2 pytest-cov==2.11.1 From b12d9ba9690583ada101303e32baa476e17854e8 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Thu, 18 Feb 2021 08:34:57 -0500 Subject: [PATCH 3/5] Add throttling to download function --- README.rst | 6 +++--- blinkpy/blinkpy.py | 11 ++++++++--- tests/test_blink_functions.py | 29 +++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index 32d867c6..7fcd6d96 100644 --- a/README.rst +++ b/README.rst @@ -174,13 +174,13 @@ Similar methods exist for individual cameras: Download videos ---------------- -You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``stop=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specify one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras. +You can also use this library to download all videos from the server. In order to do this, you must specify a ``path``. You may also specifiy a how far back in time to go to retrieve videos via the ``since=`` variable (a simple string such as ``"2017/09/21"`` is sufficient), as well as how many pages to traverse via the ``stop=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specify one or more cameras via the ``camera=`` property. This can be a single string indicating the name of the camera, or a list of camera names. By default, it is set to the string ``'all'`` to grab videos from all cameras. If you are downloading many items, setting the ``delay`` parameter is advised in order to throttle sequential calls to the API. By default this is set to ``1`` but can be any integer representing the number of seconds to delay between calls. -Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34am to the ``/home/blink`` directory: +Example usage, which downloads all videos recorded since July 4th, 2018 at 9:34am to the ``/home/blink`` directory with a 2s delay between calls: .. code:: python - blink.download_videos('/home/blink', since='2018/07/04 09:34') + blink.download_videos('/home/blink', since='2018/07/04 09:34', delay=2) .. |Build Status| image:: https://github.com/fronzbot/blinkpy/workflows/build/badge.svg diff --git a/blinkpy/blinkpy.py b/blinkpy/blinkpy.py index 82054589..44010c01 100644 --- a/blinkpy/blinkpy.py +++ b/blinkpy/blinkpy.py @@ -264,7 +264,9 @@ def save(self, file_name): """Save login data to file.""" util.json_save(self.auth.login_attributes, file_name) - def download_videos(self, path, since=None, camera="all", stop=10, debug=False): + def download_videos( + self, path, since=None, camera="all", stop=10, delay=2, debug=False + ): """ Download all videos from server since specified time. @@ -275,6 +277,7 @@ def download_videos(self, path, since=None, camera="all", stop=10, debug=False): :param camera: Camera name to retrieve. Defaults to "all". Use a list for multiple cameras. :param stop: Page to stop on (~25 items per page. Default page 10). + :param delay: Number of seconds to wait in between subsequent video downloads. :param debug: Set to TRUE to prevent downloading of items. Instead of downloading, entries will be printed to log. """ @@ -301,9 +304,9 @@ def download_videos(self, path, since=None, camera="all", stop=10, debug=False): _LOGGER.info("No videos found on page %s. Exiting.", page) break - self._parse_downloaded_items(result, camera, path, debug) + self._parse_downloaded_items(result, camera, path, delay, debug) - def _parse_downloaded_items(self, result, camera, path, debug): + def _parse_downloaded_items(self, result, camera, path, delay, debug): """Parse downloaded videos.""" for item in result: try: @@ -351,6 +354,8 @@ def _parse_downloaded_items(self, result, camera, path, debug): "Address: {address}, Filename: {filename}" ) ) + if delay > 0: + time.sleep(delay) class BlinkSetupError(Exception): diff --git a/tests/test_blink_functions.py b/tests/test_blink_functions.py index 8a71294b..c4c7d7c6 100644 --- a/tests/test_blink_functions.py +++ b/tests/test_blink_functions.py @@ -2,6 +2,7 @@ import unittest from unittest import mock import logging +import time from blinkpy import blinkpy from blinkpy.sync_module import BlinkSyncModule @@ -88,9 +89,33 @@ def test_parse_downloaded_items(self, mock_req): "DEBUG:blinkpy.blinkpy:foo: /bar.mp4 is marked as deleted.", ] with self.assertLogs() as dl_log: - blink.download_videos("/tmp", stop=2) + blink.download_videos("/tmp", stop=2, delay=0) self.assertEqual(dl_log.output, expected_log) + @mock.patch("blinkpy.blinkpy.api.request_videos") + def test_parse_downloaded_throttle(self, mock_req): + """Test ability to parse downloaded items list.""" + generic_entry = { + "created_at": "1970", + "device_name": "foo", + "deleted": False, + "media": "/bar.mp4", + } + result = [generic_entry] + mock_req.return_value = {"media": result} + self.blink.last_refresh = 0 + start = time.time() + self.blink.download_videos("/tmp", stop=2, delay=0, debug=True) + now = time.time() + delta = now - start + self.assertTrue(delta < 0.1) + + start = time.time() + self.blink.download_videos("/tmp", stop=2, delay=0.1, debug=True) + now = time.time() + delta = now - start + self.assertTrue(delta >= 0.1) + @mock.patch("blinkpy.blinkpy.api.request_videos") def test_parse_camera_not_in_list(self, mock_req): """Test ability to parse downloaded items list.""" @@ -113,7 +138,7 @@ def test_parse_camera_not_in_list(self, mock_req): "DEBUG:blinkpy.blinkpy:Skipping videos for foo.", ] with self.assertLogs() as dl_log: - blink.download_videos("/tmp", camera="bar", stop=2) + blink.download_videos("/tmp", camera="bar", stop=2, delay=0) self.assertEqual(dl_log.output, expected_log) @mock.patch("blinkpy.blinkpy.api.request_network_update") From 4e6b570cba4bc9ae3be945848d0a91dd722eece7 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Thu, 18 Feb 2021 08:38:27 -0500 Subject: [PATCH 4/5] Change default delay to 1s --- blinkpy/blinkpy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blinkpy/blinkpy.py b/blinkpy/blinkpy.py index 44010c01..eda5eb3d 100644 --- a/blinkpy/blinkpy.py +++ b/blinkpy/blinkpy.py @@ -265,7 +265,7 @@ def save(self, file_name): util.json_save(self.auth.login_attributes, file_name) def download_videos( - self, path, since=None, camera="all", stop=10, delay=2, debug=False + self, path, since=None, camera="all", stop=10, delay=1, debug=False ): """ Download all videos from server since specified time. From 3ddfd106781bcd7efb805d9c8e6a38013a0832b8 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Thu, 18 Feb 2021 09:42:45 -0500 Subject: [PATCH 5/5] Version bump --- CHANGES.rst | 7 +++++++ blinkpy/helpers/constants.py | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a9924a39..37756920 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,13 @@ Changelog A list of changes between each release +0.17.1 (2021-02-18) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Add delay parameter to Blink.download_videos method in order to throttle API during video retrieval (`#437 `__) +- Bump pylint to 2.6.2 + + 0.17.0 (2021-02-15) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/blinkpy/helpers/constants.py b/blinkpy/helpers/constants.py index 4cc5b7b1..167aec6e 100644 --- a/blinkpy/helpers/constants.py +++ b/blinkpy/helpers/constants.py @@ -3,8 +3,8 @@ import os MAJOR_VERSION = 0 -MINOR_VERSION = 18 -PATCH_VERSION = "0.dev0" +MINOR_VERSION = 17 +PATCH_VERSION = 1 __version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"