From 943443f2a9e7d4a58ba67aa23c16c1fffb1a36b9 Mon Sep 17 00:00:00 2001 From: Mka Madlavana Date: Sun, 7 Feb 2021 15:16:58 +0200 Subject: [PATCH] switch from Travis CI to Github Actions (#2) --- .coveragerc | 3 + .coveralls.yml | 1 - .github/workflows/build.yaml | 72 ++++++++++++++ .travis.yml | 25 ----- README.md | 7 +- huaweisms/api/common.py | 40 ++++---- huaweisms/api/device.py | 14 ++- huaweisms/api/dialup.py | 24 ++--- huaweisms/api/monitoring.py | 2 +- huaweisms/api/sms.py | 48 +++++----- huaweisms/api/user.py | 27 +++--- huaweisms/api/ussd.py | 10 +- huaweisms/api/webserver.py | 8 +- huaweisms/api/wlan.py | 68 +++++++------ huaweisms/xml/util.py | 9 +- sample.py | 4 +- sendmsg.py | 12 +-- setup.cfg | 14 +++ setup.py | 109 +++++++++++---------- tests/test_api_common.py | 4 +- tests/test_api_wlan.py | 181 ++++++++++++++++++++--------------- 21 files changed, 391 insertions(+), 291 deletions(-) create mode 100644 .coveragerc delete mode 100644 .coveralls.yml create mode 100644 .github/workflows/build.yaml delete mode 100644 .travis.yml diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..4d8f3c7 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[run] +branch=true +source=huaweisms diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 8c16d4a..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -repo_token: BIhVbLvVn8DiJYEvwSkr7cggHLbn4QIXE diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..f55e262 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,72 @@ +name: build + +on: [push] + +jobs: + lint: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.6, 3.7, 3.8, 3.9] + fail-fast: true + + name: Lint on Python ${{ matrix.python-version }} + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Lint + run: | + pip install '.[linting]' + flake8 --ignore=E501 . + + test: + needs: [lint] + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [2.7, 3.6, 3.7, 3.8, 3.9] + fail-fast: true + + name: Test on Python ${{ matrix.python-version }} + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Test + run: | + pip install '.[testing]' + pytest -xv --cov huaweisms --cov-report term-missing tests + + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + publish: + needs: [test] + name: Publish to PyPI + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Build package + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + run: | + pip install setuptools wheel + python setup.py sdist bdist_wheel + - name: Publish package + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 66f289f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: python -python: -- '2.7' -- '3.5' -- '3.6' -- '3.7' -- '3.8' -- '3.9' -sudo: false -install: -- pip install -U pip -- pip install .[testing,linting] -script: -- flake8 --ignore=E501 . -- nosetests --stop --verbose --with-xcoverage --cover-package=huaweisms --cover-tests tests -after_success: -- coveralls -deploy: - provider: pypi - user: dopstar - on: - tags: true - skip_existing: true - password: - secure: q6KoLHszJcxbx2sCX8I6hVxf8ig0p0IZr7W5rxCMGu1bYu+4IY55gBG8ZinNuzWCRvuitV3SbAAqFvwAirzNJ93rlRrTOUfmRxWaSlYrJH9nl6U4I/b9dqzS7uf4BJVQaSn/GMBxOFsDfgphRQNlc6GJqn5UmvSlhLEVfIrXs3q87ixukmrYlJSibZODCE2sx9AZjuQNlwGB4zSt4IpXdZnQuouSq7SHURnJuVYddfO2IBv9N2CFhHckqf4/48KpR4fsYsEHgrvHoyYNKiYVc84nUIwK2av5eC/e4wzP/AxmA7SShXQqlsEJc9ThEJIwkRo6jEbP+iI/v3nmPNpdwS0yJjhZVzwc+VssW4R2Lu8WDKKPs+0NJMWl7wsKuamWwLv2XnXlGuBXrEBom9MVTMxtX3jmT760WokkgXi1IM8YVi6jLfqqQdpd7CZrevZvGtE8aTTqg0tPWWhHfXFCPVeQ7/8XDyNh54OSTWgPx/PnvpMyzAggmzwqTVrMXhkh2QrwdgYVMJnzlRVeC+YqUpk5ykEMGH5VHFz5UUIV9a0QHP/DTkuC9A9QsqTtCCRguWtI+9323mp3b29x0OKpeq/iNdV+RmoTiyfySLbfqCx1KNpU4qZC7d3VGr9nRfVLweyXvOERazWpSm0Z5HHPRiTW1m0xSlH0yEm0Y64pGeE= diff --git a/README.md b/README.md index 9e7522d..2754b6a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -[![Build Status](https://travis-ci.org/dopstar/huawei-modem-python-api-client.svg?branch=master)](https://travis-ci.org/dopstar/huawei-modem-python-api-client) [![Python Version](https://img.shields.io/pypi/pyversions/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) [![PyPI Status](https://img.shields.io/pypi/v/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) [![PyPI Downloads](https://img.shields.io/pypi/dm/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) [![Code Coverage](https://img.shields.io/coveralls/github/dopstar/huawei-modem-python-api-client.svg)](https://coveralls.io/github/dopstar/huawei-modem-python-api-client) [![Licence](https://img.shields.io/github/license/pablo/huawei-modem-python-api-client.svg)](https://raw.githubusercontent.com/pablo/huawei-modem-python-api-client/master/LICENSE.md) +[![Build Status](https://github.com/dopstar/huawei-modem-api-client/workflows/build/badge.svg?branch=master)](https://github.com/dopstar/huawei-modem-api-client/actions?query=workflow%3Abuild) +[![Python Version](https://img.shields.io/pypi/pyversions/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) +[![PyPI Status](https://img.shields.io/pypi/v/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) +[![PyPI Downloads](https://img.shields.io/pypi/dm/huawei-modem-api-client.svg)](https://pypi.python.org/pypi/huawei-modem-api-client) +[![Code Coverage](https://img.shields.io/coveralls/github/dopstar/huawei-modem-python-api-client.svg)](https://coveralls.io/github/dopstar/huawei-modem-python-api-client) +[![Licence](https://img.shields.io/github/license/pablo/huawei-modem-python-api-client.svg)](https://raw.githubusercontent.com/pablo/huawei-modem-python-api-client/master/LICENSE.md) # Python HTTP API client for Huawei Modems diff --git a/huaweisms/api/common.py b/huaweisms/api/common.py index b721b7d..df57e75 100644 --- a/huaweisms/api/common.py +++ b/huaweisms/api/common.py @@ -3,16 +3,15 @@ from xml.dom.minidom import Element import requests -from huaweisms.api.config import MODEM_HOST -from huaweisms.xml.util import get_child_text, parse_xml_string, get_dictionary_from_children +from huaweisms.api.config import MODEM_HOST +from huaweisms.xml.util import get_child_text, get_dictionary_from_children, parse_xml_string logger = logging.getLogger(__name__) class ApiCtx: - def __init__(self, modem_host=None): # type: (...) -> None self.session_id = None @@ -22,10 +21,7 @@ def __init__(self, modem_host=None): self.__modem_host = modem_host if modem_host else MODEM_HOST def __unicode__(self): - return '<{} modem_host={}>'.format( - self.__class__.__name__, - self.__modem_host - ) + return "<{} modem_host={}>".format(self.__class__.__name__, self.__modem_host) def __repr__(self): return self.__unicode__() @@ -35,20 +31,18 @@ def __str__(self): @property def api_base_url(self): - return 'http://{}/api'.format(self.__modem_host) + return "http://{}/api".format(self.__modem_host) @property def token(self): if not self.tokens: - logger.warning('You ran out of tokens. You need to login again') + logger.warning("You ran out of tokens. You need to login again") return None return self.tokens.pop() def common_headers(): - return { - "X-Requested-With": "XMLHttpRequest" - } + return {"X-Requested-With": "XMLHttpRequest"} def check_error(elem): @@ -60,8 +54,8 @@ def check_error(elem): "type": "error", "error": { "code": get_child_text(elem, "code"), - "message": get_child_text(elem, "message") - } + "message": get_child_text(elem, "message"), + }, } @@ -78,21 +72,23 @@ def api_response(r): return { "type": "response", - "response": get_dictionary_from_children(xmldoc.documentElement) + "response": get_dictionary_from_children(xmldoc.documentElement), } def check_response_headers(resp, ctx): # type: (..., ApiCtx) -> ... - if '__RequestVerificationToken' in resp.headers: - toks = [x for x in resp.headers['__RequestVerificationToken'].split("#") if x != ''] + if "__RequestVerificationToken" in resp.headers: + toks = [ + x for x in resp.headers["__RequestVerificationToken"].split("#") if x != "" + ] if len(toks) > 1: ctx.tokens = toks[2:] elif len(toks) == 1: ctx.tokens.append(toks[0]) - if 'SessionID' in resp.cookies: - ctx.session_id = resp.cookies['SessionID'] + if "SessionID" in resp.cookies: + ctx.session_id = resp.cookies["SessionID"] def post_to_url(url, data, ctx=None, additional_headers=None): @@ -103,7 +99,7 @@ def post_to_url(url, data, ctx=None, additional_headers=None): if additional_headers: headers.update(additional_headers) - data = ''.join(line.strip() for line in data.split('\n')) + data = "".join(line.strip() for line in data.split("\n")) r = requests.post(url, data=data, headers=headers, cookies=cookies) check_response_headers(r, ctx) return api_response(r) @@ -126,7 +122,5 @@ def build_cookies(ctx): # type: (ApiCtx) -> ... cookies = None if ctx and ctx.session_id: - cookies = { - 'SessionID': ctx.session_id - } + cookies = {"SessionID": ctx.session_id} return cookies diff --git a/huaweisms/api/device.py b/huaweisms/api/device.py index 41bd726..cb41aa2 100644 --- a/huaweisms/api/device.py +++ b/huaweisms/api/device.py @@ -1,8 +1,4 @@ -from huaweisms.api.common import ( - post_to_url, - get_from_url, - ApiCtx, -) +from huaweisms.api.common import ApiCtx, get_from_url, post_to_url def information(ctx): @@ -23,10 +19,12 @@ def reboot(ctx): Reboots the modem. """ - url = '{}/device/control'.format(ctx.api_base_url) + url = "{}/device/control".format(ctx.api_base_url) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } - payload = '1' + payload = ( + '1' + ) return post_to_url(url, payload, ctx, additional_headers=headers) diff --git a/huaweisms/api/dialup.py b/huaweisms/api/dialup.py index 495a9f7..1f9740d 100644 --- a/huaweisms/api/dialup.py +++ b/huaweisms/api/dialup.py @@ -3,9 +3,9 @@ XML_TEMPLATE = ( '' - '' - '{enable}' - '' + "" + "{enable}" + "" ) @@ -23,20 +23,20 @@ def get_mobile_status(ctx): # type: (huaweisms.api.common.ApiCtx) -> ... url = "{}/dialup/mobile-dataswitch".format(ctx.api_base_url) result = huaweisms.api.common.get_from_url(url, ctx) - if result and result.get('type') == 'response': - response = result['response'] - if response and response.get('dataswitch') == '1': - return 'CONNECTED' - if response and response.get('dataswitch') == '0': - return 'DISCONNECTED' - return 'UNKNOWN' + if result and result.get("type") == "response": + response = result["response"] + if response and response.get("dataswitch") == "1": + return "CONNECTED" + if response and response.get("dataswitch") == "0": + return "DISCONNECTED" + return "UNKNOWN" def switch_mobile_off(ctx): # type: (huaweisms.api.common.ApiCtx) -> ... data = XML_TEMPLATE.format(enable=0) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } url = "{}/dialup/mobile-dataswitch".format(ctx.api_base_url) return huaweisms.api.common.post_to_url(url, data, ctx, additional_headers=headers) @@ -46,7 +46,7 @@ def switch_mobile_on(ctx): # type: (huaweisms.api.common.ApiCtx) -> ... data = XML_TEMPLATE.format(enable=1) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } url = "{}/dialup/mobile-dataswitch".format(ctx.api_base_url) return huaweisms.api.common.post_to_url(url, data, ctx, additional_headers=headers) diff --git a/huaweisms/api/monitoring.py b/huaweisms/api/monitoring.py index 8565e1b..64cf3a0 100644 --- a/huaweisms/api/monitoring.py +++ b/huaweisms/api/monitoring.py @@ -1,4 +1,4 @@ -from huaweisms.api.common import get_from_url, ApiCtx +from huaweisms.api.common import ApiCtx, get_from_url def status(ctx): diff --git a/huaweisms/api/sms.py b/huaweisms/api/sms.py index 6bab73e..3e1b3a7 100644 --- a/huaweisms/api/sms.py +++ b/huaweisms/api/sms.py @@ -1,7 +1,8 @@ from datetime import datetime import six -from huaweisms.api.common import post_to_url, ApiCtx, get_from_url + +from huaweisms.api.common import ApiCtx, get_from_url, post_to_url def get_sms(ctx, box_type=1, page=1, qty=1, unread_preferred=True): @@ -26,24 +27,21 @@ def get_sms(ctx, box_type=1, page=1, qty=1, unread_preferred=True): {} """.format( - page, - qty, - box_type, - 1 if unread_preferred else 0 + page, qty, box_type, 1 if unread_preferred else 0 ) headers = { - '__RequestVerificationToken': ctx.token, - 'X-Requested-With': 'XMLHttpRequest' + "__RequestVerificationToken": ctx.token, + "X-Requested-With": "XMLHttpRequest", } url = "{}/sms/sms-list".format(ctx.api_base_url) r = post_to_url(url, xml_data, ctx, headers) - if r['type'] == 'response': - if r['response']['Count'] != '0': - if isinstance(r['response']['Messages']['Message'], dict): - m = r['response']['Messages']['Message'] - r['response']['Messages']['Message'] = [m] + if r["type"] == "response": + if r["response"]["Count"] != "0": + if isinstance(r["response"]["Messages"]["Message"], dict): + m = r["response"]["Messages"]["Message"] + r["response"]["Messages"]["Message"] = [m] return r @@ -54,7 +52,7 @@ def send_sms(ctx, dest, msg): now_str = now.strftime("%Y-%m-%d %H:%M:%S") dest = [dest] if isinstance(dest, six.string_types) else dest - phones_content = '\n'.join('{}'.format(phone) for phone in dest) + phones_content = "\n".join("{}".format(phone) for phone in dest) xml_data = """ -1 @@ -67,11 +65,13 @@ def send_sms(ctx, dest, msg): 1 {} - """.format(phones_content, msg, len(msg), now_str) + """.format( + phones_content, msg, len(msg), now_str + ) headers = { - '__RequestVerificationToken': ctx.token, - 'X-Requested-With': 'XMLHttpRequest' + "__RequestVerificationToken": ctx.token, + "X-Requested-With": "XMLHttpRequest", } url = "{}/sms/send-sms".format(ctx.api_base_url) r = post_to_url(url, xml_data, ctx, headers) @@ -86,11 +86,13 @@ def delete_sms(ctx, index): {} - """.format(index) + """.format( + index + ) headers = { - '__RequestVerificationToken': ctx.token, - 'X-Requested-With': 'XMLHttpRequest' + "__RequestVerificationToken": ctx.token, + "X-Requested-With": "XMLHttpRequest", } url = "{}/sms/delete-sms".format(ctx.api_base_url) r = post_to_url(url, xml_data, ctx, headers) @@ -111,11 +113,13 @@ def sms_set_read(ctx, index): {} - """.format(index) + """.format( + index + ) headers = { - '__RequestVerificationToken': ctx.token, - 'X-Requested-With': 'XMLHttpRequest' + "__RequestVerificationToken": ctx.token, + "X-Requested-With": "XMLHttpRequest", } url = "{}/sms/set-read".format(ctx.api_base_url) return post_to_url(url, xml_data, ctx, headers) diff --git a/huaweisms/api/user.py b/huaweisms/api/user.py index 14dbec8..ec7aa66 100644 --- a/huaweisms/api/user.py +++ b/huaweisms/api/user.py @@ -1,31 +1,28 @@ import base64 - -import hashlib - import binascii - +import hashlib import json import huaweisms.api.webserver -from huaweisms.api.common import common_headers, ApiCtx, post_to_url, get_from_url +from huaweisms.api.common import ApiCtx, common_headers, get_from_url, post_to_url def b64_sha256(data): # type: (str) -> str s256 = hashlib.sha256() - s256.update(data.encode('utf-8')) + s256.update(data.encode("utf-8")) dg = s256.digest() hs256 = binascii.hexlify(dg) - return base64.urlsafe_b64encode(hs256).decode('utf-8', 'ignore') + return base64.urlsafe_b64encode(hs256).decode("utf-8", "ignore") def quick_login(username, password, modem_host=None): # type: (str, str, str) -> ... ctx = ApiCtx(modem_host=modem_host) token = huaweisms.api.webserver.get_session_token_info(ctx.api_base_url) - session_token = token['response']['SesInfo'].split("=") + session_token = token["response"]["SesInfo"].split("=") ctx.session_id = session_token[1] if len(session_token) > 1 else session_token[0] - ctx.login_token = token['response']['TokInfo'] + ctx.login_token = token["response"]["TokInfo"] response = login(ctx, username, password) if not ctx.logged_in: raise ValueError(json.dumps(response)) @@ -46,15 +43,17 @@ def login(ctx, user_name, password): {} 4 - """.format(user_name, password_value) + """.format( + user_name, password_value + ) -# setup headers - headers['__RequestVerificationToken'] = ctx.login_token - headers['X-Requested-With'] = 'XMLHttpRequest' + # setup headers + headers["__RequestVerificationToken"] = ctx.login_token + headers["X-Requested-With"] = "XMLHttpRequest" r = post_to_url(url, xml_data, ctx, headers) - if r['type'] == "response" and r['response'] == "OK": + if r["type"] == "response" and r["response"] == "OK": ctx.logged_in = True return r diff --git a/huaweisms/api/ussd.py b/huaweisms/api/ussd.py index 15b699a..492c834 100644 --- a/huaweisms/api/ussd.py +++ b/huaweisms/api/ussd.py @@ -1,4 +1,4 @@ -from huaweisms.api.common import post_to_url, ApiCtx, get_from_url +from huaweisms.api.common import ApiCtx, get_from_url, post_to_url def status(ctx): @@ -22,11 +22,13 @@ def send(ctx, msg): CodeType - """.format(msg) + """.format( + msg + ) headers = { - '__RequestVerificationToken': ctx.token, - 'X-Requested-With': 'XMLHttpRequest' + "__RequestVerificationToken": ctx.token, + "X-Requested-With": "XMLHttpRequest", } url = "{}/ussd/send".format(ctx.api_base_url) r = post_to_url(url, xml_data, ctx, headers) diff --git a/huaweisms/api/webserver.py b/huaweisms/api/webserver.py index e257d21..d26e9a0 100644 --- a/huaweisms/api/webserver.py +++ b/huaweisms/api/webserver.py @@ -1,7 +1,7 @@ import logging -from huaweisms.api.config import MODEM_HOST from huaweisms.api.common import get_from_url +from huaweisms.api.config import MODEM_HOST logger = logging.getLogger(__name__) @@ -17,10 +17,10 @@ def get_session_token_info(base_url=None): """ if base_url is None: logger.warning( - 'calling %s.get_session_token_info without base_url argument is deprecated', - __name__ + "calling %s.get_session_token_info without base_url argument is deprecated", + __name__, ) - base_url = 'http://{}/api'.format(MODEM_HOST) + base_url = "http://{}/api".format(MODEM_HOST) url = "{}/webserver/SesTokInfo".format(base_url) return get_from_url(url, timeout=30) diff --git a/huaweisms/api/wlan.py b/huaweisms/api/wlan.py index 6a65054..f433efd 100644 --- a/huaweisms/api/wlan.py +++ b/huaweisms/api/wlan.py @@ -15,31 +15,35 @@ def block_host(ctx, mac_address, hostname=None): see http://192.168.8.1/html/wlanmacfilter.html """ - url = '{}/wlan/multi-macfilter-settings'.format(ctx.api_base_url) + url = "{}/wlan/multi-macfilter-settings".format(ctx.api_base_url) if is_host_blocked(ctx, mac_address): return True - response = get_blocked_hosts(ctx)['response'] + response = get_blocked_hosts(ctx)["response"] - for ssid in response['Ssids']['Ssid']: + for ssid in response["Ssids"]["Ssid"]: for index in range(10): - host_key = 'wifihostname{}'.format(index) - mac_key = 'WifiMacFilterMac{}'.format(index) - if ssid.get(host_key) == '' and ssid.get(mac_key) == '': - ssid[host_key] = hostname or '' + host_key = "wifihostname{}".format(index) + mac_key = "WifiMacFilterMac{}".format(index) + if ssid.get(host_key) == "" and ssid.get(mac_key) == "": + ssid[host_key] = hostname or "" ssid[mac_key] = mac_address break else: continue break else: - raise ValueError('Failed to blacklist [{}], slots are full.'.format(mac_address)) + raise ValueError( + "Failed to blacklist [{}], slots are full.".format(mac_address) + ) - payload = huaweisms.xml.util.dict_to_xml({'request': response}) + payload = huaweisms.xml.util.dict_to_xml({"request": response}) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } - return huaweisms.api.common.post_to_url(url, payload, ctx, additional_headers=headers) + return huaweisms.api.common.post_to_url( + url, payload, ctx, additional_headers=headers + ) def unblock_host(ctx, mac_address): @@ -49,52 +53,54 @@ def unblock_host(ctx, mac_address): see http://192.168.8.1/html/wlanmacfilter.html """ - url = '{}/wlan/multi-macfilter-settings'.format(ctx.api_base_url) + url = "{}/wlan/multi-macfilter-settings".format(ctx.api_base_url) if not is_host_blocked(ctx, mac_address): return True - response = get_blocked_hosts(ctx)['response'] + response = get_blocked_hosts(ctx)["response"] - for ssid in response['Ssids']['Ssid']: + for ssid in response["Ssids"]["Ssid"]: for index in range(10): - host_key = 'wifihostname{}'.format(index) - mac_key = 'WifiMacFilterMac{}'.format(index) + host_key = "wifihostname{}".format(index) + mac_key = "WifiMacFilterMac{}".format(index) if ssid.get(mac_key) and ssid[mac_key].lower() == mac_address.lower(): - ssid[host_key] = '' - ssid[mac_key] = '' + ssid[host_key] = "" + ssid[mac_key] = "" - payload = huaweisms.xml.util.dict_to_xml({'request': response}) + payload = huaweisms.xml.util.dict_to_xml({"request": response}) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } - return huaweisms.api.common.post_to_url(url, payload, ctx, additional_headers=headers) + return huaweisms.api.common.post_to_url( + url, payload, ctx, additional_headers=headers + ) def get_blocked_hosts(ctx): # type: (huaweisms.api.common.ApiCtx) -> ... - url = '{}/wlan/multi-macfilter-settings'.format(ctx.api_base_url) + url = "{}/wlan/multi-macfilter-settings".format(ctx.api_base_url) return huaweisms.api.common.get_from_url(url, ctx) def is_host_blocked(ctx, mac_address): # type: (huaweisms.api.common.ApiCtx, str) -> bool response = get_blocked_hosts(ctx) - if not response or response.get('type') != 'response': + if not response or response.get("type") != "response": raise ValueError(response) - ssids = response['response']['Ssids']['Ssid'] + ssids = response["response"]["Ssids"]["Ssid"] for ssid in ssids: for k, v in ssid.items(): - if k.startswith('WifiMacFilterMac') and v.strip().lower() == mac_address.lower(): + if k.startswith("WifiMacFilterMac") and v.strip().lower() == mac_address.lower(): return True return False def _switch_rf_radios(ctx, radio_1_enable, radio_2_enable): - url = '{}/wlan/status-switch-settings'.format(ctx.api_base_url) + url = "{}/wlan/status-switch-settings".format(ctx.api_base_url) headers = { - '__RequestVerificationToken': ctx.token, + "__RequestVerificationToken": ctx.token, } xml_data = """ @@ -112,8 +118,12 @@ def _switch_rf_radios(ctx, radio_1_enable, radio_2_enable): - """.format(radio_1_enable=radio_1_enable, radio_2_enable=radio_2_enable) - return huaweisms.api.common.post_to_url(url, xml_data, ctx, additional_headers=headers) + """.format( + radio_1_enable=radio_1_enable, radio_2_enable=radio_2_enable + ) + return huaweisms.api.common.post_to_url( + url, xml_data, ctx, additional_headers=headers + ) def switch_wlan_24ghz(ctx, on): diff --git a/huaweisms/xml/util.py b/huaweisms/xml/util.py index 14cc813..94b526a 100644 --- a/huaweisms/xml/util.py +++ b/huaweisms/xml/util.py @@ -1,7 +1,8 @@ -import six from typing import Union from xml.dom import minidom -from xml.dom.minidom import Element, Document +from xml.dom.minidom import Document, Element + +import six def get_element_text(elem): @@ -64,7 +65,7 @@ def parse_xml_string(xml_string): def dict_to_xml(data): # type: (dict) -> str if not data: - return '' + return "" def add_children(doc, parent, input_data): if isinstance(input_data, dict): @@ -84,4 +85,4 @@ def add_children(doc, parent, input_data): root = document.createElement(key) document.appendChild(root) add_children(document, root, data[key]) - return document.toxml(encoding='utf8') + return document.toxml(encoding="utf8") diff --git a/sample.py b/sample.py index 0eba31c..618d10c 100644 --- a/sample.py +++ b/sample.py @@ -1,6 +1,6 @@ from pprint import pprint -from huaweisms.api import monitoring, user, sms +from huaweisms.api import monitoring, sms, user from huaweisms.api.common import ApiCtx @@ -18,7 +18,7 @@ def get_session(): def valid_context(ctx): # type: (ApiCtx) -> bool sl = user.state_login(ctx) - if sl['type'] == 'response' and sl['response']['State'] != -1: + if sl["type"] == "response" and sl["response"]["State"] != -1: return True return False diff --git a/sendmsg.py b/sendmsg.py index 02ee7b1..6c823f7 100644 --- a/sendmsg.py +++ b/sendmsg.py @@ -1,6 +1,6 @@ import sys -from huaweisms.api import user, sms +from huaweisms.api import sms, user from huaweisms.api.common import ApiCtx @@ -16,17 +16,17 @@ def get_session(): def valid_context(ctx): # type: (ApiCtx) -> ... sl = user.state_login(ctx) - if sl['type'] == 'response' and sl['response']['State'] != -1: + if sl["type"] == "response" and sl["response"]["State"] != -1: return True return False -if __name__ == '__main__': +if __name__ == "__main__": # USAGE: python3 sendmsg.py # Arguments are if len(sys.argv) != 4: - print('Incomplete arguments ', len(sys.argv) - 1, 'received, 3 required') - print('USAGE:', sys.argv[0], '"admin password" "phone number" "message"') + print("Incomplete arguments ", len(sys.argv) - 1, "received, 3 required") + print("USAGE:", sys.argv[0], '"admin password" "phone number" "message"') exit() PASSWORD = sys.argv[1] @@ -36,7 +36,7 @@ def valid_context(ctx): ctx = get_session() sent = sms.send_sms(ctx, PHONE_NUMBER, MESSAGE) - if sent['type'] == "response" and sent['response'] == "OK": + if sent["type"] == "response" and sent["response"] == "OK": print("Message sent.") else: print("Message error") diff --git a/setup.cfg b/setup.cfg index b88034e..f6d3e44 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,16 @@ [metadata] description-file = README.md + +[bdist_wheel] +universal = 1 + +[flake8] +max-line-length = 100 +inline-quotes = double + +[isort] +balanced_wrapping = true +line_length = 100 +lines_after_imports = 2 +multi_line_output = 3 +order_by_type = true diff --git a/setup.py b/setup.py index dd98c0f..13356ff 100644 --- a/setup.py +++ b/setup.py @@ -1,76 +1,75 @@ from setuptools import setup -version = '1.0.11' -with open('requirements.txt') as fd: +version = "1.1.0" + +with open("requirements.txt") as fd: requirements = [line.strip() for line in fd if line.strip()] testing_requirements = [ - 'nose', - 'mock', - 'faker', - 'nosexcover', - 'python-coveralls', + "nose", + "mock", + "faker", + "pytest", + "pytest-cov", + "codecov", + "coverage", ] -linting_requirements = [ - 'flake8', - 'pylint', - 'bandit<1.7', -] +linting_requirements = ["flake8", "flake8-isort", "flake8-quotes"] -with open('README.md') as fd: +with open("README.md") as fd: long_description = fd.read() -if 'a' in version: - dev_status = '3 - Alpha' -elif 'b' in version: - dev_status = '4 - Beta' +if "a" in version: + dev_status = "3 - Alpha" +elif "b" in version: + dev_status = "4 - Beta" else: - dev_status = '5 - Production/Stable' + dev_status = "5 - Production/Stable" setup_args = { - 'name': 'huawei-modem-api-client', - 'version': version, - 'author': 'Pablo Santa Cruz, Mkhanyisi Madlavana', - 'author_email': 'pablo@roshka.com.py, mkhanyisi@gmail.com', - 'url': 'https://github.com/pablo/huawei-modem-python-api-client', - 'download_url': 'https://github.com/dopstar/huawei-modem-python-api-client/tarball/{0}'.format( + "name": "huawei-modem-api-client", + "version": version, + "author": "Pablo Santa Cruz, Mkhanyisi Madlavana", + "author_email": "pablo@roshka.com.py, mkhanyisi@gmail.com", + "url": "https://github.com/pablo/huawei-modem-python-api-client", + "download_url": "https://github.com/dopstar/huawei-modem-python-api-client/tarball/{0}".format( version ), - 'package_dir': {'huaweisms': 'huaweisms'}, - 'description': 'huaweisms is a python api client for Huawei Modems.', - 'long_description': long_description, - 'long_description_content_type': 'text/markdown', - 'packages': [ - 'huaweisms', - 'huaweisms.api', - 'huaweisms.xml', + "package_dir": {"huaweisms": "huaweisms"}, + "description": "huaweisms is a python api client for Huawei Modems.", + "long_description": long_description, + "long_description_content_type": "text/markdown", + "packages": [ + "huaweisms", + "huaweisms.api", + "huaweisms.xml", ], - 'data_files': [('', ['requirements.txt'])], - 'install_requires': requirements, - 'tests_require': testing_requirements, - 'extras_require': { - 'testing': testing_requirements, - 'linting': linting_requirements, + "data_files": [("", ["requirements.txt"])], + "install_requires": requirements, + "tests_require": testing_requirements, + "extras_require": { + "testing": testing_requirements, + "linting": linting_requirements, }, - 'keywords': ['Huawei', 'Modem', 'HTTP API Client', 'API Client', 'Router'], - 'classifiers': [ - 'Development Status :: {0}'.format(dev_status), - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'License :: OSI Approved :: MIT License', - 'Operating System :: MacOS', - 'Operating System :: POSIX :: Linux', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Software Development :: Version Control :: Git', - 'Programming Language :: Python :: Implementation :: CPython', + "keywords": ["Huawei", "Modem", "HTTP API Client", "API Client", "Router"], + "classifiers": [ + "Development Status :: {0}".format(dev_status), + "Intended Audience :: Developers", + "Natural Language :: English", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Version Control :: Git", + "Programming Language :: Python :: Implementation :: CPython", ], } diff --git a/tests/test_api_common.py b/tests/test_api_common.py index 3b58ace..819e7a8 100644 --- a/tests/test_api_common.py +++ b/tests/test_api_common.py @@ -27,8 +27,8 @@ def test_build_cookies(self): ctx.session_id = fake_id cookies = huaweisms.api.common.build_cookies(ctx) self.assertIsInstance(cookies, dict) - self.assertDictEqual(cookies, {'SessionID': fake_id}) + self.assertDictEqual(cookies, {"SessionID": fake_id}) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_api_wlan.py b/tests/test_api_wlan.py index 29afa6e..c0033d5 100644 --- a/tests/test_api_wlan.py +++ b/tests/test_api_wlan.py @@ -1,43 +1,40 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import random import unittest import faker +import six from mock import patch -import random -import six -import huaweisms.api.wlan import huaweisms.api.common +import huaweisms.api.wlan class WlanTestCase(unittest.TestCase): - @classmethod def setUpClass(cls): cls.fake = faker.Factory.create() - @patch('huaweisms.api.common.get_from_url') + @patch("huaweisms.api.common.get_from_url") def test_get_connected_hosts(self, mock_get_from_url): ctx = huaweisms.api.common.ApiCtx() huaweisms.api.wlan.get_connected_hosts(ctx) mock_get_from_url.assert_called_once_with( - 'http://192.168.8.1/api/wlan/host-list', - ctx + "http://192.168.8.1/api/wlan/host-list", ctx ) - @patch('huaweisms.api.common.get_from_url') + @patch("huaweisms.api.common.get_from_url") def test_get_blocked_hosts(self, mock_get_from_url): fake_ip = self.fake.ipv4() ctx = huaweisms.api.common.ApiCtx(modem_host=fake_ip) huaweisms.api.wlan.get_blocked_hosts(ctx) mock_get_from_url.assert_called_once_with( - 'http://{}/api/wlan/multi-macfilter-settings'.format(fake_ip), - ctx + "http://{}/api/wlan/multi-macfilter-settings".format(fake_ip), ctx ) - @patch('huaweisms.api.wlan.get_blocked_hosts') + @patch("huaweisms.api.wlan.get_blocked_hosts") def test_is_host_blocked_error_part_1(self, mock_get_blocked_hosts): fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -49,7 +46,7 @@ def test_is_host_blocked_error_part_1(self, mock_get_blocked_hosts): huaweisms.api.wlan.is_host_blocked(ctx, fake_mac) mock_get_blocked_hosts.assert_called_once_with(ctx) - @patch('huaweisms.api.wlan.get_blocked_hosts') + @patch("huaweisms.api.wlan.get_blocked_hosts") def test_is_host_blocked_error_part_2(self, mock_get_blocked_hosts): fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -61,7 +58,7 @@ def test_is_host_blocked_error_part_2(self, mock_get_blocked_hosts): huaweisms.api.wlan.is_host_blocked(ctx, fake_mac) mock_get_blocked_hosts.assert_called_once_with(ctx) - @patch('huaweisms.api.wlan.get_blocked_hosts') + @patch("huaweisms.api.wlan.get_blocked_hosts") def test_is_host_blocked__blocked_host(self, mock_get_blocked_hosts): fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -78,7 +75,7 @@ def test_is_host_blocked__blocked_host(self, mock_get_blocked_hosts): } ] } - } + }, } ctx = huaweisms.api.common.ApiCtx(modem_host=fake_ip) @@ -86,7 +83,7 @@ def test_is_host_blocked__blocked_host(self, mock_get_blocked_hosts): mock_get_blocked_hosts.assert_called_once_with(ctx) self.assertTrue(is_blocked) - @patch('huaweisms.api.wlan.get_blocked_hosts') + @patch("huaweisms.api.wlan.get_blocked_hosts") def test_is_host_blocked__unblocked_host(self, mock_get_blocked_hosts): fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -103,7 +100,7 @@ def test_is_host_blocked__unblocked_host(self, mock_get_blocked_hosts): } ] } - } + }, } ctx = huaweisms.api.common.ApiCtx(modem_host=fake_ip) @@ -111,12 +108,17 @@ def test_is_host_blocked__unblocked_host(self, mock_get_blocked_hosts): mock_get_blocked_hosts.assert_called_once_with(ctx) self.assertFalse(is_blocked) - @patch('huaweisms.api.wlan.is_host_blocked') - @patch('huaweisms.api.wlan.get_blocked_hosts') - @patch('huaweisms.xml.util.dict_to_xml') - @patch('huaweisms.api.common.post_to_url') - def test_block_host__already_blocked(self, mock_post_to_url, mock_dict_to_xml, mock_get_blocked_hosts, - mock_is_host_blocked): + @patch("huaweisms.api.wlan.is_host_blocked") + @patch("huaweisms.api.wlan.get_blocked_hosts") + @patch("huaweisms.xml.util.dict_to_xml") + @patch("huaweisms.api.common.post_to_url") + def test_block_host__already_blocked( + self, + mock_post_to_url, + mock_dict_to_xml, + mock_get_blocked_hosts, + mock_is_host_blocked, + ): mock_is_host_blocked.return_value = True fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -128,32 +130,37 @@ def test_block_host__already_blocked(self, mock_post_to_url, mock_dict_to_xml, m mock_get_blocked_hosts.assert_not_called() mock_is_host_blocked.asset_called_once_with(ctx, fake_mac) - @patch('huaweisms.api.wlan.is_host_blocked') - @patch('huaweisms.api.wlan.get_blocked_hosts') - @patch('huaweisms.xml.util.dict_to_xml') - @patch('huaweisms.api.common.post_to_url') - def test_block_host__slots_full(self, mock_post_to_url, mock_dict_to_xml, - mock_get_blocked_hosts, mock_is_host_blocked): + @patch("huaweisms.api.wlan.is_host_blocked") + @patch("huaweisms.api.wlan.get_blocked_hosts") + @patch("huaweisms.xml.util.dict_to_xml") + @patch("huaweisms.api.common.post_to_url") + def test_block_host__slots_full( + self, + mock_post_to_url, + mock_dict_to_xml, + mock_get_blocked_hosts, + mock_is_host_blocked, + ): mock_is_host_blocked.return_value = False mock_get_blocked_hosts.return_value = { - 'type': 'response', - 'response': { + "type": "response", + "response": { "Ssids": { "Ssid": [ { - 'wifihostname{}'.format(i): '', - "WifiMacFilterMac{0}".format(i): self.fake.mac_address() + "wifihostname{}".format(i): "", + "WifiMacFilterMac{0}".format(i): self.fake.mac_address(), } for i in range(10) ] } - } + }, } fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() ctx = huaweisms.api.common.ApiCtx(modem_host=fake_ip) - error_msg = r'Failed to blacklist \[{}\], slots are full.'.format(fake_mac) + error_msg = r"Failed to blacklist \[{}\], slots are full.".format(fake_mac) with six.assertRaisesRegex(self, ValueError, error_msg): huaweisms.api.wlan.block_host(ctx, fake_mac) mock_post_to_url.assert_not_called() @@ -161,35 +168,40 @@ def test_block_host__slots_full(self, mock_post_to_url, mock_dict_to_xml, mock_get_blocked_hosts.assert_called_once_with(ctx) mock_is_host_blocked.asset_called_once_with(ctx, fake_mac) - @patch('huaweisms.api.wlan.is_host_blocked') - @patch('huaweisms.api.wlan.get_blocked_hosts') - @patch('huaweisms.xml.util.dict_to_xml') - @patch('huaweisms.api.common.post_to_url') - def test_block_host__not_blocked(self, mock_post_to_url, mock_dict_to_xml, - mock_get_blocked_hosts, mock_is_host_blocked): + @patch("huaweisms.api.wlan.is_host_blocked") + @patch("huaweisms.api.wlan.get_blocked_hosts") + @patch("huaweisms.xml.util.dict_to_xml") + @patch("huaweisms.api.common.post_to_url") + def test_block_host__not_blocked( + self, + mock_post_to_url, + mock_dict_to_xml, + mock_get_blocked_hosts, + mock_is_host_blocked, + ): mock_is_host_blocked.return_value = False ret_val = { - 'type': 'response', - 'response': { + "type": "response", + "response": { "Ssids": { "Ssid": [ { - 'wifihostname{}'.format(i): '', - "WifiMacFilterMac{}".format(i): self.fake.mac_address() + "wifihostname{}".format(i): "", + "WifiMacFilterMac{}".format(i): self.fake.mac_address(), } for i in range(10) ] } - } + }, } index = random.randint(0, 9) - ret_val['response']['Ssids']['Ssid'][index] = { - 'wifihostname{}'.format(index): '', - 'WifiMacFilterMac{}'.format(index): '' + ret_val["response"]["Ssids"]["Ssid"][index] = { + "wifihostname{}".format(index): "", + "WifiMacFilterMac{}".format(index): "", } mock_get_blocked_hosts.return_value = ret_val - mock_dict_to_xml.return_value = 'a' + mock_dict_to_xml.return_value = "a" fake_ip = self.fake.ipv4() fake_mac = self.fake.mac_address() @@ -201,21 +213,26 @@ def test_block_host__not_blocked(self, mock_post_to_url, mock_dict_to_xml, huaweisms.api.wlan.block_host(ctx, fake_mac) mock_post_to_url.assert_called_once_with( - 'http://{}/api/wlan/multi-macfilter-settings'.format(fake_ip), - 'a', + "http://{}/api/wlan/multi-macfilter-settings".format(fake_ip), + "a", ctx, - additional_headers={'__RequestVerificationToken': fake_token} + additional_headers={"__RequestVerificationToken": fake_token}, ) - mock_dict_to_xml.asset_called_once_with({'request': ret_val}) + mock_dict_to_xml.asset_called_once_with({"request": ret_val}) mock_get_blocked_hosts.assert_called_once_with(ctx) mock_is_host_blocked.asset_called_once_with(ctx, fake_mac) - @patch('huaweisms.api.wlan.is_host_blocked') - @patch('huaweisms.api.wlan.get_blocked_hosts') - @patch('huaweisms.xml.util.dict_to_xml') - @patch('huaweisms.api.common.post_to_url') - def test_unblock_host__not_blocked(self, mock_post_to_url, mock_dict_to_xml, - mock_get_blocked_hosts, mock_is_host_blocked): + @patch("huaweisms.api.wlan.is_host_blocked") + @patch("huaweisms.api.wlan.get_blocked_hosts") + @patch("huaweisms.xml.util.dict_to_xml") + @patch("huaweisms.api.common.post_to_url") + def test_unblock_host__not_blocked( + self, + mock_post_to_url, + mock_dict_to_xml, + mock_get_blocked_hosts, + mock_is_host_blocked, + ): mock_is_host_blocked.return_value = False fake_ip = self.fake.ipv4() @@ -231,26 +248,34 @@ def test_unblock_host__not_blocked(self, mock_post_to_url, mock_dict_to_xml, mock_dict_to_xml.assert_not_called() mock_get_blocked_hosts.assert_not_called() - @patch('huaweisms.api.wlan.is_host_blocked') - @patch('huaweisms.api.wlan.get_blocked_hosts') - @patch('huaweisms.xml.util.dict_to_xml') - @patch('huaweisms.api.common.post_to_url') - def test_unblock_host__blocked(self, mock_post_to_url, mock_dict_to_xml, - mock_get_blocked_hosts, mock_is_host_blocked): + @patch("huaweisms.api.wlan.is_host_blocked") + @patch("huaweisms.api.wlan.get_blocked_hosts") + @patch("huaweisms.xml.util.dict_to_xml") + @patch("huaweisms.api.common.post_to_url") + def test_unblock_host__blocked( + self, + mock_post_to_url, + mock_dict_to_xml, + mock_get_blocked_hosts, + mock_is_host_blocked, + ): mock_is_host_blocked.return_value = True fake_mac = self.fake.mac_address() slots = { - 'type': 'response', - 'response': { + "type": "response", + "response": { "Ssids": { "Ssid": [ - {'wifihostname0': '', "WifiMacFilterMac0": self.fake.mac_address()}, - {'wifihostname1': 'kajshdksj', 'WifiMacFilterMac1': fake_mac} + { + "wifihostname0": "", + "WifiMacFilterMac0": self.fake.mac_address(), + }, + {"wifihostname1": "kajshdksj", "WifiMacFilterMac1": fake_mac}, ] } - } + }, } - mock_dict_to_xml.return_value = 'a' + mock_dict_to_xml.return_value = "a" mock_get_blocked_hosts.return_value = slots fake_ip = self.fake.ipv4() fake_token = self.fake.sha256() @@ -262,16 +287,16 @@ def test_unblock_host__blocked(self, mock_post_to_url, mock_dict_to_xml, mock_is_host_blocked.assert_called_once_with(ctx, fake_mac) mock_get_blocked_hosts.assert_called_once_with(ctx) print(slots) - mock_dict_to_xml.assert_called_once_with({'request': slots['response']}) + mock_dict_to_xml.assert_called_once_with({"request": slots["response"]}) mock_post_to_url.assert_called_once_with( - 'http://{}/api/wlan/multi-macfilter-settings'.format(fake_ip), - 'a', + "http://{}/api/wlan/multi-macfilter-settings".format(fake_ip), + "a", ctx, - additional_headers={'__RequestVerificationToken': fake_token} + additional_headers={"__RequestVerificationToken": fake_token}, ) - self.assertEqual(slots['response']['Ssids']['Ssid'][1]['wifihostname1'], '') - self.assertEqual(slots['response']['Ssids']['Ssid'][1]['WifiMacFilterMac1'], '') + self.assertEqual(slots["response"]["Ssids"]["Ssid"][1]["wifihostname1"], "") + self.assertEqual(slots["response"]["Ssids"]["Ssid"][1]["WifiMacFilterMac1"], "") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()