diff options
-rw-r--r-- | README.md | 79 | ||||
-rw-r--r-- | pyagl/services/base.py | 13 | ||||
-rw-r--r-- | pyagl/services/bluetooth_pbap.py | 3 | ||||
-rw-r--r-- | pyagl/tests/test_bluetooth.py | 2 | ||||
-rw-r--r-- | pyagl/tests/test_weather.py | 1 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | setup.py | 2 |
7 files changed, 92 insertions, 9 deletions
@@ -0,0 +1,79 @@ +#pyagl + +## Basic info +Python library with bindings and tests for Automotive Grade Linux services + +Currently the library works only with images built with `aglsetup.sh agl-devel`, +the non-agl-devel image does not expose websockets on TCP ports. + +The library implements CLI-callable main() methods and argparse with --help supplements in most modules. +When installing the library into a new virtualenv, the modules should be executable with +`python3 -m pyagl.services.<service> --help` - which should return CLI usage of the invoked module +First positional argument is IP Address of the target board + +## Examples: +```shell script +$ python3 -m pyagl.services.bluetooth_pbap --help +usage: bluetooth_pbap.py [-h] [-l {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}] [--port PORT] [--listener] [--subscribe event] [--unsubscribe event] [--json JSON] [--verb VERB] [--api API] [--import_contacts] [--status] [--contacts] [--history HISTORY] ipaddr + +Utility to interact with agl-service-* via it's websocket + +positional arguments: + ipaddr AGL host address + +optional arguments: + -h, --help show this help message and exit + -l {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}, --loglevel {CRITICAL,FATAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET} + Level of logging verbosity + --port PORT AGL service websocket port + --listener Register a listener for incoming events + --subscribe event Subscribe to event type + --unsubscribe event Unsubscribe from event type + --import_contacts + --status + --contacts + --history HISTORY Request call history - ICH/OCH/MCH/CCH +``` +```shell script +$ python3 -m pyagl.services.bluetooth_pbap 192.168.234.251 --contacts +Sent contacts request with messageid 896503218 +[RESPONSE][Status: success][896503218][Info: contacts][Data: {'vcards': [{'fn': 'John Smith', 'telephone': [{'HOME': '+15557028324'}]}...]}, +``` + +Until the package is uploaded onto PyPI, either: +* `git clone` the repository +* `cd` into the cloned directory +* `pip install .` + +or + +* `pip install` the generated zip from the repository(when public) +--- +## Creating new modules +Creating a new modules and tests can be done with a few steps: +1. clone the repository +2. cd \<repo\>/pyagl +3. cookiecutter -f ../templates/ + +## Running the tests +The tests can be run either directly from the cloned repository or the default Python site-packages directory per system default or virtualenv: +* for example on Debian systems the default site packages dir should be in /usr/local/lib/python3.8/dist-packages/pyagl/tests +* otherwise for virtualenv - <virtualenv_dir>/lib/python3.8/site-packages/pyagl/tests + +pytest + +Running the tests rests on the assumptions that the following environment variables will be exported: +All tests require AGL_TGT_IP and will look for AGL_TGT_PORT +* AGL_TGT_IP - required - the containing the IP Address for the AGL instance +* AGL_TGT_PORT - optional - if not exported, the library wil connect to the IP address via ssh to find out the service's listening TCP port +* AGL_BTMAP_RECIPIENT - optional - When running Bluetooth MAP tests, this would be used as phone number to write text messages to +* AGL_BTMAP_TEXT - optional - When running Bluetooth MAP tests, messages will be composed with this text +* AGL_PBAP_PHONENUM - optional - When running Bluetooth PBAP tests, this phone number will be used to .search() +* AGL_PBAP_VCF - optional - Bluetooh PBAP tests - query a contact entry out of the phonebook +* AGL_BT_TEST_ADDR - optional - Bluetooth tests - pair/connect/disconnect with an actual Bluetooth device(phone)'s address +it should have the DBus address style as "dev_00_01_02_03_04_05" instead regular colon-separated MAC address + +Should some of the optional variables be omitted, the fixtures and their dependent tests should fail gracefully + with "XFAIL"(expected fail) or "SKIP" result. + +There are tests that are dependent on other tests, therefore if the dependent tests fail, the whole test chain will be skipped.
\ No newline at end of file diff --git a/pyagl/services/base.py b/pyagl/services/base.py index 231ebb1..42468a8 100644 --- a/pyagl/services/base.py +++ b/pyagl/services/base.py @@ -111,9 +111,9 @@ class AGLBaseService: parser.add_argument('--listener', default=False, help='Register a listener for incoming events', action='store_true') parser.add_argument('--subscribe', type=str, help='Subscribe to event type', action='append', metavar='event') parser.add_argument('--unsubscribe', type=str, help='Unsubscribe from event type', action='append', metavar='event') - parser.add_argument('--json', type=str, help='Send your own json string') - parser.add_argument('--verb', type=str, help='Send the json above to specific verb') - parser.add_argument('--api', type=str, help='Send the above two to a specific api') + # parser.add_argument('--json', type=str, help='Send your own json string') + # parser.add_argument('--verb', type=str, help='Send the json above to specific verb') + # parser.add_argument('--api', type=str, help='Send the above two to a specific api') return parser def __init__(self, api: str, ip: str, port: str = None, url: str = None, @@ -240,9 +240,12 @@ class AGLBaseService: async def afbresponse(self): return AFBResponse(await self.response()) - async def request(self, verb: str, values: Union[str, dict] = "", msgid: int = None): + async def request(self, verb: str, values: Union[str, dict] = "", msgid: int = None, api=None): msgid = next(newrand()) if msgid is None else msgid - l = json.dumps([AFBT.REQUEST, str(msgid), f'{self.api}/{verb}', values]) + if api is not None: + l = json.dumps([AFBT.REQUEST, str(msgid), f'{api}/{verb}', values]) + else: + l = json.dumps([AFBT.REQUEST, str(msgid), f'{self.api}/{verb}', values]) self.logger.debug(f'[AGL] <- {l}') await self.send(l) return msgid diff --git a/pyagl/services/bluetooth_pbap.py b/pyagl/services/bluetooth_pbap.py index 027ac89..9ac0dea 100644 --- a/pyagl/services/bluetooth_pbap.py +++ b/pyagl/services/bluetooth_pbap.py @@ -12,7 +12,8 @@ class BTPBAPService(AGLBaseService): parser.add_argument('--import_contacts', action='store_true') parser.add_argument('--status', action='store_true') parser.add_argument('--contacts', action='store_true') - parser.add_argument('--history', help='Request call history - ICH/OCH/MCH/CCH') + parser.add_argument('--history', choices=['ich','och','mch','cch'], help='Request call history - Incoming/Outgoing' + '/Missed/Combined calls') def __init__(self, ip, port=None, service='agl-service-bluetooth-pbap'): super().__init__(api='bluetooth-pbap', ip=ip, port=port, service=service) diff --git a/pyagl/tests/test_bluetooth.py b/pyagl/tests/test_bluetooth.py index f5903ec..167ff7f 100644 --- a/pyagl/tests/test_bluetooth.py +++ b/pyagl/tests/test_bluetooth.py @@ -30,7 +30,7 @@ async def service(): @pytest.mark.xfail @pytest.fixture(scope='module') def btaddr(): - bthtestaddr = os.environ.get('AGL_TEST_BT_ADDR', None) + bthtestaddr = os.environ.get('AGL_BT_TEST_ADDR', None) if not bthtestaddr: pytest.xfail('No test bluetooth test address set in environment variables') diff --git a/pyagl/tests/test_weather.py b/pyagl/tests/test_weather.py index 7b35c6d..c59f49a 100644 --- a/pyagl/tests/test_weather.py +++ b/pyagl/tests/test_weather.py @@ -1,7 +1,6 @@ import asyncio import os import pytest -import urllib3 import logging from pyagl.services.base import AFBResponse, AFBT from pyagl.services.weather import WeatherService as ws diff --git a/requirements.txt b/requirements.txt index 3d1f9db..c08fa44 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ pycparser==2.20 pyparsing==2.4.7 pytest==5.4.1 pytest-asyncio==0.11.0 +pytest-dependency==0.5.1 six==1.14.0 wcwidth==0.1.9 websockets==8.1 @@ -14,7 +14,7 @@ setuptools.setup( url="https://github.com/refresher/pyagl", packages=setuptools.find_packages(), license="Apache 2.0", - install_requires=['websockets', 'parse', 'asyncssh', 'pytest', 'pytest-asyncio', 'pytest-depends'], + install_requires=['websockets', 'parse', 'asyncssh', 'pytest', 'pytest-asyncio', 'pytest-dependency'], classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Console', |