Compare commits

..
Author SHA1 Message Date
Kevin FronczakandGitHub a435a5281b Add codecov token to fix upload failures 2020-10-05 09:06:05 -04:00
dependabot-preview[bot]andGitHub a2eb04ceee Bump pytest from 6.0.1 to 6.1.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.0.1 to 6.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.0.1...6.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 06:32:48 +00:00
Kevin FronczakandGitHub dae2413ed1 Merge pull request #381 from rohitsud/patch-1
Fix readme param and spelling
2020-09-28 11:10:32 -04:00
Kevin FronczakandGitHub cd9792193f Merge pull request #377 from fronzbot/dependabot/pip/coverage-5.3
Bump coverage from 5.2.1 to 5.3
2020-09-28 11:09:35 -04:00
Kevin FronczakandGitHub 75dbd1e498 Merge pull request #368 from fronzbot/dependabot/pip/pytest-cov-2.10.1
Bump pytest-cov from 2.10.0 to 2.10.1
2020-09-27 21:59:53 -04:00
rohitsudandGitHub a374009835 Fix readme param and spelling 2020-09-27 13:06:24 -07:00
dependabot-preview[bot]andGitHub e00600c955 Bump coverage from 5.2.1 to 5.3
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2.1 to 5.3.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.2.1...coverage-5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 06:38:09 +00:00
dependabot-preview[bot]andGitHub 141fea542c Bump pytest-cov from 2.10.0 to 2.10.1
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.10.0 to 2.10.1.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.10.0...v2.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-17 08:14:22 +00:00
Kevin Fronczak ed4450778d Dev bump 2020-08-02 03:35:42 +00:00
Kevin FronczakandGitHub 41d59b1df0 Merge pull request #362 from fronzbot/update-changelog
Update changelog for 0.16.3
2020-08-01 23:29:04 -04:00
Kevin FronczakandGitHub fd104c09da Merge pull request #361 from fronzbot/add-user-agent-everywhere
Add user agent to all headers
2020-08-01 23:28:54 -04:00
Kevin Fronczak 6dbed91426 Update changelog for 0.16.3 2020-08-02 03:24:38 +00:00
Kevin Fronczak cb43f17d75 Add user agent to all headers 2020-08-02 03:22:49 +00:00
Kevin FronczakandGitHub 5ebf278ad3 Merge pull request #360 from fronzbot/dev-bump
Dev version bump
2020-08-01 23:13:46 -04:00
Kevin Fronczak 7f782533b8 Dev version bump 2020-08-02 03:09:22 +00:00
Kevin FronczakandGitHub 1790c1beae Merge pull request #358 from fronzbot/bugfix-version-bump
Version bump
2020-08-01 23:07:58 -04:00
Kevin Fronczak 09e1c382d3 Version bump 2020-08-02 03:04:09 +00:00
Kevin FronczakandGitHub ceb2270ee5 Merge pull request #357 from fronzbot/simplify-login
Updated headers to include user-agent, removed extra data at login
2020-08-01 23:01:34 -04:00
Kevin Fronczak 986a3c81f3 Updated headers to include user-agent, removed extra data at login 2020-08-02 02:57:26 +00:00
Kevin FronczakandGitHub 11d6bbb916 Merge pull request #354 from fronzbot/dev-rc-bump
Dev rc bump
2020-07-31 22:15:13 -04:00
Kevin FronczakandGitHub b02f6318a7 Merge pull request #353 from fronzbot/update-app-version
Update app version and set reauth to True...should fix login problems
2020-07-31 22:15:02 -04:00
Kevin FronczakandGitHub c1435e74e8 Merge pull request #352 from fronzbot/dependabot/pip/pytest-6.0.1
Bump pytest from 6.0.0 to 6.0.1
2020-07-31 22:13:28 -04:00
Kevin Fronczak b30da661e5 Dev rc bump 2020-08-01 02:12:42 +00:00
Kevin Fronczak 3a22dddc82 Update app version and set reauth to True...should fix login problems 2020-08-01 02:10:25 +00:00
dependabot-preview[bot]andGitHub a19a17d4dc Bump pytest from 6.0.0 to 6.0.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.0.0...6.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-31 08:16:15 +00:00
Kevin FronczakandGitHub bff6ef92ce Merge pull request #350 from fronzbot/dev-version-bump
Dev bump
2020-07-29 11:38:18 -04:00
Kevin Fronczak 263572eb66 Dev bump 2020-07-29 15:28:13 +00:00
Kevin FronczakandGitHub 3a97a928de Merge pull request #348 from fronzbot/0.16.1-changelog
Updated versions and changelog for 0.16.1
2020-07-29 11:27:26 -04:00
Kevin Fronczak 0322414de1 Updated versions and changelog for 0.16.1 2020-07-29 15:23:59 +00:00
Kevin FronczakandGitHub 1c75e86863 Merge pull request #347 from fronzbot/unpin-reqs
Set min version for reqs instead of pinning
2020-07-29 11:23:11 -04:00
Kevin FronczakandGitHub 0ae71f6367 Merge pull request #345 from fronzbot/dependabot/pip/pytest-6.0.0
Bump pytest from 5.4.3 to 6.0.0
2020-07-29 11:19:38 -04:00
Kevin FronczakandGitHub af7c38695a Merge pull request #344 from fronzbot/dependabot/pip/coverage-5.2.1
Bump coverage from 5.2 to 5.2.1
2020-07-29 11:19:21 -04:00
Kevin Fronczak c741c22876 Set min version for reqs instead of pinning 2020-07-29 15:15:19 +00:00
dependabot-preview[bot]andGitHub 06b9b12eeb Bump pytest from 5.4.3 to 6.0.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.3 to 6.0.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/5.4.3...6.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-29 08:05:56 +00:00
dependabot-preview[bot]andGitHub daf7078f98 Bump coverage from 5.2 to 5.2.1
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2 to 5.2.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.2...coverage-5.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 08:17:40 +00:00
Kevin FronczakandGitHub c2db57ecb3 Merge pull request #341 from fronzbot/dev-bump
Dev version bump
2020-07-20 23:01:51 -04:00
Kevin Fronczak 0336c6a8f8 Dev version bump 2020-07-20 02:24:28 +00:00
Kevin Fronczak 22d3fa9565 Merge remote-tracking branch 'origin/master' into dev 2020-07-20 02:19:27 +00:00
Kevin FronczakandGitHub 9d81973b3a Merge pull request #339 from fronzbot/retry-options
Retry options
2020-07-19 21:47:40 -04:00
Kevin Fronczak fe8eac3dc6 Update documentation 2020-07-20 01:42:07 +00:00
Kevin Fronczak 5fc315201a Add tests for retry options 2020-07-20 01:33:11 +00:00
Kevin Fronczak a9d3d5568b Adding retry options to auth class 2020-07-20 01:25:09 +00:00
Kevin FronczakandGitHub f88dbdaeba Merge pull request #338 from fronzbot/fix-auth-tests
Fix broken test and missing try/except
2020-07-19 21:24:50 -04:00
Kevin Fronczak 48028914de Fix broken test and missing try/except 2020-07-20 01:18:41 +00:00
Kevin FronczakandGitHub fcdb70d246 Merge pull request #337 from fronzbot/remove-exec-info
Removed all exc_info parameters during logging
2020-07-19 20:51:38 -04:00
Kevin Fronczak e8589bfa05 Fix test 2020-07-20 00:48:40 +00:00
Kevin Fronczak 854ffbf26a Removed all exc_info parameters during logging 2020-07-20 00:37:30 +00:00
Kevin FronczakandGitHub ca109f703c Merge pull request #336 from fronzbot/dev-bump
Dev version bump
2020-07-19 20:37:22 -04:00
Kevin Fronczak 82d5a7ea51 Dev version bump 2020-07-20 00:34:06 +00:00
Kevin FronczakandGitHub 79ead7b826 Merge pull request #333 from fronzbot/dependabot/pip/pytest-timeout-1.4.2
Bump pytest-timeout from 1.4.1 to 1.4.2
2020-07-16 13:03:03 -04:00
dependabot-preview[bot]andGitHub 6e360b2bb1 Bump pytest-timeout from 1.4.1 to 1.4.2
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.4.1...1.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-16 08:06:30 +00:00
Kevin FronczakandGitHub 1aaa5b649f Merge pull request #331 from fronzbot/remove-host
Remove host from auth header
2020-07-11 11:24:47 -04:00
Kevin FronczakandGitHub 435f3b9831 Update CHANGES.rst 2020-07-11 10:44:37 -04:00
Kevin FronczakandGitHub bcf0bb5525 Merge pull request #330 from fronzbot/bugfix
Bugfix: remove Host from auth header
2020-07-11 10:42:44 -04:00
Kevin Fronczak 322aae37dc fix test (remove host) 2020-07-11 14:41:44 +00:00
Kevin Fronczak 45cb4028b8 Remove host from auth header 2020-07-11 14:39:45 +00:00
Kevin Fronczak 151d9b7375 Version bump 2020-07-11 14:37:04 +00:00
Kevin Fronczak d393c861d7 bugfix: remove host from auth header 2020-07-11 14:36:37 +00:00
Kevin Fronczak 02c4b2e7e1 Add rst linter to pre-commit and fix flake8 2020-07-11 14:36:06 +00:00
13 changed files with 177 additions and 42 deletions
+2
View File
@@ -34,6 +34,8 @@ jobs:
tox -r -e cov tox -r -e cov
- name: Codecov - name: Codecov
uses: codecov/codecov-action@v1.0.6 uses: codecov/codecov-action@v1.0.6
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with: with:
flags: unittests flags: unittests
file: ./coverage.xml file: ./coverage.xml
+50
View File
@@ -4,6 +4,56 @@ Changelog
A list of changes between each release A list of changes between each release
0.16.3 (2020-08-02)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Add user-agent to all headers
0.16.2 (2020-08-01)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Add user-agent to header at login
- Remove extra data parameters at login (not-needed)
- Bump pytest to 6.0.1
0.16.1 (2020-07-29)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Unpin requirements, set minimum version instead
- Bump coverage to 5.2.1
- Bump pytest to 6.0.0
0.16.0 (2020-07-20)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking Changes:**
- Add arm property to camera, deprecate motion enable method (`#273 <https://github.com/fronzbot/blinkpy/pull/273>`__)
- Complete refactoring of auth logic (breaks all pre-0.16.0 setups!) (`#261 <https://github.com/fronzbot/blinkpy/pull/261>`__)
**New Features:**
- Add is_errored property to Auth class (`#275 <https://github.com/fronzbot/blinkpy/pull/275>`__)
- Add new endpoint to get user infor (`#280 <https://github.com/fronzbot/blinkpy/pull/280>`__)
- Add get_liveview command to camera module (`#289 <https://github.com/fronzbot/blinkpy/pull/289>`__)
- Add blink Mini Camera support (`#290 <https://github.com/fronzbot/blinkpy/pull/290>`__)
- Add option to skip homescreen check (`#305 <https://github.com/fronzbot/blinkpy/pull/305>`__)
- Add different timeout for video and image retrieval (`#323 <https://github.com/fronzbot/blinkpy/pull/323>`__)
- Modifiy session to use HTTPAdapter and handle retries (`#324 <https://github.com/fronzbot/blinkpy/pull/324>`__)
- Add retry option overrides (`#339 <https://github.com/fronzbot/blinkpy/pull/339>`__)
**All changes:**
Please see the change list in the (`Release Notes <https://github.com/fronzbot/releases/tag/v0.16.0>`__)
0.15.1 (2020-07-11)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Bugfix: remove "Host" from auth header (`#330 <https://github.com/fronzbot/blinkpy/pull/330>`__)
0.15.0 (2020-05-08) 0.15.0 (2020-05-08)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Breaking Changes:** **Breaking Changes:**
+1 -1
View File
@@ -174,7 +174,7 @@ Similar methods exist for individual cameras:
Download videos 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 ``page=`` variable. Note that by default, the library will search the first ten pages which is sufficient in most use cases. Additionally, you can specidy 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.
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:
+8 -5
View File
@@ -3,7 +3,7 @@
import logging import logging
from json import dumps from json import dumps
from blinkpy.helpers.util import get_time, Throttle from blinkpy.helpers.util import get_time, Throttle
from blinkpy.helpers.constants import DEFAULT_URL, TIMEOUT from blinkpy.helpers.constants import DEFAULT_URL, TIMEOUT, DEFAULT_USER_AGENT
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -20,21 +20,24 @@ def request_login(
:param url: Login url. :param url: Login url.
:login_data: Dictionary containing blink login data. :login_data: Dictionary containing blink login data.
""" """
headers = {"Host": DEFAULT_URL, "Content-Type": "application/json"} headers = {
"Host": DEFAULT_URL,
"Content-Type": "application/json",
"Accept": "/",
"user-agent": DEFAULT_USER_AGENT,
}
data = dumps( data = dumps(
{ {
"email": login_data["username"], "email": login_data["username"],
"password": login_data["password"], "password": login_data["password"],
"notification_key": login_data["notification_key"], "notification_key": login_data["notification_key"],
"unique_id": login_data["uid"], "unique_id": login_data["uid"],
"app_version": "6.0.7 (520300) #afb0be72a",
"device_identifier": login_data["device_id"], "device_identifier": login_data["device_id"],
"client_name": "Computer", "client_name": "Computer",
"client_type": "android",
"os_version": "5.1.1",
"reauth": "false", "reauth": "false",
} }
) )
return auth.query( return auth.query(
url=url, url=url,
headers=headers, headers=headers,
+32 -11
View File
@@ -6,7 +6,12 @@ from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry from urllib3.util.retry import Retry
from blinkpy import api from blinkpy import api
from blinkpy.helpers import util from blinkpy.helpers import util
from blinkpy.helpers.constants import BLINK_URL, LOGIN_ENDPOINT, TIMEOUT from blinkpy.helpers.constants import (
BLINK_URL,
DEFAULT_USER_AGENT,
LOGIN_ENDPOINT,
TIMEOUT,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -53,17 +58,22 @@ class Auth:
"""Return authorization header.""" """Return authorization header."""
if self.token is None: if self.token is None:
return None return None
return {"Host": self.host, "TOKEN_AUTH": self.token} return {"TOKEN_AUTH": self.token, "user-agent": DEFAULT_USER_AGENT}
def create_session(self): def create_session(self, opts=None):
"""Create a session for blink communication.""" """Create a session for blink communication."""
if opts is None:
opts = {}
backoff = opts.get("backoff", 1)
retries = opts.get("retries", 3)
retry_list = opts.get("retry_list", [429, 500, 502, 503, 504])
sess = Session() sess = Session()
assert_status_hook = [ assert_status_hook = [
lambda response, *args, **kwargs: response.raise_for_status() lambda response, *args, **kwargs: response.raise_for_status()
] ]
sess.hooks["response"] = assert_status_hook sess.hooks["response"] = assert_status_hook
retry = Retry( retry = Retry(
total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] total=retries, backoff_factor=backoff, status_forcelist=retry_list
) )
adapter = HTTPAdapter(max_retries=retry) adapter = HTTPAdapter(max_retries=retry)
sess.mount("https://", adapter) sess.mount("https://", adapter)
@@ -103,11 +113,7 @@ class Auth:
try: try:
_LOGGER.info("Token expired, attempting automatic refresh.") _LOGGER.info("Token expired, attempting automatic refresh.")
self.login_response = self.login() self.login_response = self.login()
self.region_id = self.login_response["region"]["tier"] self.extract_login_info()
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["authtoken"]["authtoken"]
self.client_id = self.login_response["client"]["id"]
self.account_id = self.login_response["account"]["id"]
self.is_errored = False self.is_errored = False
except LoginError: except LoginError:
_LOGGER.error("Login endpoint failed. Try again later.") _LOGGER.error("Login endpoint failed. Try again later.")
@@ -117,6 +123,14 @@ class Auth:
raise TokenRefreshFailed raise TokenRefreshFailed
return True return True
def extract_login_info(self):
"""Extract login info from login response."""
self.region_id = self.login_response["region"]["tier"]
self.host = f"{self.region_id}.{BLINK_URL}"
self.token = self.login_response["authtoken"]["authtoken"]
self.client_id = self.login_response["client"]["id"]
self.account_id = self.login_response["account"]["id"]
def startup(self): def startup(self):
"""Initialize tokens for communication.""" """Initialize tokens for communication."""
self.validate_login() self.validate_login()
@@ -174,11 +188,18 @@ class Auth:
"Connection error. Endpoint %s possibly down or throttled.", url, "Connection error. Endpoint %s possibly down or throttled.", url,
) )
except BlinkBadResponse: except BlinkBadResponse:
code = None
reason = None
try:
code = response.status_code
reason = response.reason
except AttributeError:
pass
_LOGGER.error( _LOGGER.error(
"Expected json response from %s, but received: %s: %s", "Expected json response from %s, but received: %s: %s",
url, url,
response.status_code, code,
response.reason, reason,
) )
except UnauthorizedError: except UnauthorizedError:
try: try:
+1 -3
View File
@@ -151,9 +151,7 @@ class BlinkCamera:
if config.get("thumbnail", False): if config.get("thumbnail", False):
thumb_addr = config["thumbnail"] thumb_addr = config["thumbnail"]
else: else:
_LOGGER.warning( _LOGGER.warning("Could not find thumbnail for camera %s", self.name)
"Could not find thumbnail for camera %s", self.name, exc_info=True
)
if thumb_addr is not None: if thumb_addr is not None:
new_thumbnail = f"{self.sync.urls.base_url}{thumb_addr}.jpg" new_thumbnail = f"{self.sync.urls.base_url}{thumb_addr}.jpg"
+3 -2
View File
@@ -3,8 +3,8 @@
import os import os
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 16 MINOR_VERSION = 17
PATCH_VERSION = "0-rc11" PATCH_VERSION = "0.dev0"
__version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}" __version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}.{PATCH_VERSION}"
@@ -58,6 +58,7 @@ ONLINE = {"online": True, "offline": False}
""" """
OTHER OTHER
""" """
DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
DEVICE_ID = "Blinkpy" DEVICE_ID = "Blinkpy"
TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S%z" TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
DEFAULT_MOTION_INTERVAL = 1 DEFAULT_MOTION_INTERVAL = 1
+3 -5
View File
@@ -93,9 +93,7 @@ class BlinkSyncModule:
self.serial = self.summary["serial"] self.serial = self.summary["serial"]
self.status = self.summary["status"] self.status = self.summary["status"]
except KeyError: except KeyError:
_LOGGER.error( _LOGGER.error("Could not extract some sync module info: %s", response)
"Could not extract some sync module info: %s", response, exc_info=True
)
is_ok = self.get_network_info() is_ok = self.get_network_info()
self.check_new_videos() self.check_new_videos()
@@ -158,7 +156,7 @@ class BlinkSyncModule:
try: try:
return response["event"] return response["event"]
except (TypeError, KeyError): except (TypeError, KeyError):
_LOGGER.error("Could not extract events: %s", response, exc_info=True) _LOGGER.error("Could not extract events: %s", response)
return False return False
def get_camera_info(self, camera_id, **kwargs): def get_camera_info(self, camera_id, **kwargs):
@@ -170,7 +168,7 @@ class BlinkSyncModule:
try: try:
return response["camera"][0] return response["camera"][0]
except (TypeError, KeyError): except (TypeError, KeyError):
_LOGGER.error("Could not extract camera info: %s", response, exc_info=True) _LOGGER.error("Could not extract camera info: %s", response)
return {} return {}
def get_network_info(self): def get_network_info(self):
+23
View File
@@ -30,6 +30,29 @@ By default, the ``blink.auth.Auth`` class creates its own websession via its ``c
blink.auth = Auth() blink.auth = Auth()
blink.auth.session = YourCustomSession blink.auth.session = YourCustomSession
Custom Retry Logic
--------------------
The built-in auth session via the ``create_session`` method allows for customizable retry intervals and conditions. These parameters are:
- retries
- backoff
- retry_list
``retries`` is the total number of retry attempts that each http request can do before timing out. ``backoff`` is a parameter that allows for non-linear retry times such that the time between retries is backoff*(2^(retries) - 1). ``retry_list`` is simply a list of status codes to force a retry. By default ``retries=3``, ``backoff=1``, and ``retry_list=[429, 500, 502, 503, 504]``. To override them, you need to add you overrides to a dictionary and use that to create a new session with the ``opts`` variable in the ``create_session`` method. The following example can serve as a guide where only the number of retries and backoff factor are overridden:
.. code:: python
from blinkpy.blinkpy import Blink
from blinkpy.auth import Auth
blink = Blink()
blink.auth = Auth()
opts = {"retries": 10, "backoff": 2}
blink.auth.session = blink.auth.create_session(opts=opts)
Custom HTTP requests Custom HTTP requests
--------------------- ---------------------
In addition to custom sessions, custom blink server requests can be performed. This give you the ability to bypass the built-in ``Auth.query`` method. It also allows flexibility by giving you the option to pass your own url, rather than be limited to what is currently implemented in the ``blinkpy.api`` module. In addition to custom sessions, custom blink server requests can be performed. This give you the ability to bypass the built-in ``Auth.query`` method. It also allows flexibility by giving you the option to pass your own url, rather than be limited to what is currently implemented in the ``blinkpy.api`` module.
+4 -4
View File
@@ -1,4 +1,4 @@
python-dateutil~=2.8.1 python-dateutil>=2.8.1
requests~=2.24.0 requests>=2.24.0
python-slugify~=4.0.1 python-slugify>=4.0.1
testtools==2.4.0 testtools>=2.4.0
+4 -4
View File
@@ -1,13 +1,13 @@
black==19.10b0 black==19.10b0
coverage==5.2 coverage==5.3
flake8==3.8.3 flake8==3.8.3
flake8-docstrings==1.5.0 flake8-docstrings==1.5.0
pre-commit==2.6.0 pre-commit==2.6.0
pylint==2.5.3 pylint==2.5.3
pydocstyle==5.0.2 pydocstyle==5.0.2
pytest==5.4.3 pytest==6.1.1
pytest-cov==2.10.0 pytest-cov==2.10.1
pytest-sugar==0.9.4 pytest-sugar==0.9.4
pytest-timeout==1.4.1 pytest-timeout==1.4.2
restructuredtext-lint==1.3.1 restructuredtext-lint==1.3.1
pygments==2.6.1 pygments==2.6.1
+45 -3
View File
@@ -128,8 +128,7 @@ class TestAuth(unittest.TestCase):
def test_header(self): def test_header(self):
"""Test header data.""" """Test header data."""
self.auth.token = "bar" self.auth.token = "bar"
self.auth.host = "foo" expected_header = {"TOKEN_AUTH": "bar", "user-agent": const.DEFAULT_USER_AGENT}
expected_header = {"Host": "foo", "TOKEN_AUTH": "bar"}
self.assertDictEqual(self.auth.header, expected_header) self.assertDictEqual(self.auth.header, expected_header)
def test_header_no_token(self): def test_header_no_token(self):
@@ -231,7 +230,7 @@ class TestAuth(unittest.TestCase):
@mock.patch("blinkpy.auth.Auth.refresh_token") @mock.patch("blinkpy.auth.Auth.refresh_token")
def test_query_retry_failed(self, mock_refresh, mock_validate): def test_query_retry_failed(self, mock_refresh, mock_validate):
"""Check handling of failed retry request.""" """Check handling of failed retry request."""
self.auth.seession = MockSession() self.auth.session = MockSession()
mock_validate.side_effect = [UnauthorizedError, BlinkBadResponse] mock_validate.side_effect = [UnauthorizedError, BlinkBadResponse]
mock_refresh.return_value = True mock_refresh.return_value = True
self.assertEqual(self.auth.query(url="http://example.com"), None) self.assertEqual(self.auth.query(url="http://example.com"), None)
@@ -239,6 +238,49 @@ class TestAuth(unittest.TestCase):
mock_validate.side_effect = [UnauthorizedError, TokenRefreshFailed] mock_validate.side_effect = [UnauthorizedError, TokenRefreshFailed]
self.assertEqual(self.auth.query(url="http://example.com"), None) self.assertEqual(self.auth.query(url="http://example.com"), None)
def test_default_session(self):
"""Test default session creation."""
sess = self.auth.create_session()
adapter = sess.adapters["https://"]
self.assertEqual(adapter.max_retries.total, 3)
self.assertEqual(adapter.max_retries.backoff_factor, 1)
self.assertEqual(
adapter.max_retries.status_forcelist, [429, 500, 502, 503, 504]
)
def test_custom_session_full(self):
"""Test full custom session creation."""
opts = {"backoff": 2, "retries": 10, "retry_list": [404]}
sess = self.auth.create_session(opts=opts)
adapter = sess.adapters["https://"]
self.assertEqual(adapter.max_retries.total, 10)
self.assertEqual(adapter.max_retries.backoff_factor, 2)
self.assertEqual(adapter.max_retries.status_forcelist, [404])
def test_custom_session_partial(self):
"""Test partial custom session creation."""
opts1 = {"backoff": 2}
opts2 = {"retries": 5}
opts3 = {"retry_list": [101, 202]}
sess1 = self.auth.create_session(opts=opts1)
sess2 = self.auth.create_session(opts=opts2)
sess3 = self.auth.create_session(opts=opts3)
adapt1 = sess1.adapters["https://"]
adapt2 = sess2.adapters["https://"]
adapt3 = sess3.adapters["https://"]
self.assertEqual(adapt1.max_retries.total, 3)
self.assertEqual(adapt1.max_retries.backoff_factor, 2)
self.assertEqual(adapt1.max_retries.status_forcelist, [429, 500, 502, 503, 504])
self.assertEqual(adapt2.max_retries.total, 5)
self.assertEqual(adapt2.max_retries.backoff_factor, 1)
self.assertEqual(adapt2.max_retries.status_forcelist, [429, 500, 502, 503, 504])
self.assertEqual(adapt3.max_retries.total, 3)
self.assertEqual(adapt3.max_retries.backoff_factor, 1)
self.assertEqual(adapt3.max_retries.status_forcelist, [101, 202])
class MockSession: class MockSession:
"""Object to mock a session.""" """Object to mock a session."""
+1 -4
View File
@@ -117,10 +117,7 @@ class TestBlinkCameraSetup(unittest.TestCase):
"WARNING:blinkpy.camera:Could not retrieve calibrated " "WARNING:blinkpy.camera:Could not retrieve calibrated "
"temperature." "temperature."
), ),
( ("WARNING:blinkpy.camera:Could not find thumbnail for camera new"),
"WARNING:blinkpy.camera:Could not find thumbnail for camera new"
"\nNoneType: None"
),
], ],
) )