pax_global_header00006660000000000000000000000064145530537060014522gustar00rootroot0000000000000052 comment=60115c974e7eede472b6538d612e7e516b0e6b5a misialq-openerz-api-60115c9/000077500000000000000000000000001455305370600156625ustar00rootroot00000000000000misialq-openerz-api-60115c9/.github/000077500000000000000000000000001455305370600172225ustar00rootroot00000000000000misialq-openerz-api-60115c9/.github/workflows/000077500000000000000000000000001455305370600212575ustar00rootroot00000000000000misialq-openerz-api-60115c9/.github/workflows/python-publish.yml000066400000000000000000000020751455305370600247730ustar00rootroot00000000000000# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. name: Upload Python Package on: release: types: [published] permissions: contents: read jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v3 with: python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip pip install build - name: Build package run: python -m build - name: Publish package uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} misialq-openerz-api-60115c9/.github/workflows/tests.yaml000066400000000000000000000022151455305370600233050ustar00rootroot00000000000000name: Run the tests on: pull_request: branches: ["master"] push: branches: ["master"] jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: [3.8, 3.9, '3.10'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Set up PYTHONPATH run: | echo "PYTHONPATH=$PYTHONPATH:/home/runner/work/openerz-api" >> $GITHUB_ENV - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Lint with flake8 run: | pip install flake8 # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest run: | pip install pytest testfixtures pytest misialq-openerz-api-60115c9/.gitignore000066400000000000000000000010101455305370600176420ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging bin/ build/ develop-eggs/ dist/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Rope .ropeproject # Django stuff: *.log *.pot # Sphinx documentation docs/_build/misialq-openerz-api-60115c9/LICENSE000066400000000000000000000020631455305370600166700ustar00rootroot00000000000000MIT License Copyright (c) [2020] [Michał Ziemski] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.misialq-openerz-api-60115c9/README.md000066400000000000000000000013151455305370600171410ustar00rootroot00000000000000### OpenERZ Python API This wrapper allows you to interact with the OpenERZ API using Python code. For more information about the API itself see: [http://openerz.metaodi.ch/documentation](http://openerz.metaodi.ch/documentation) and [https://github.com/metaodi/openerz](https://github.com/metaodi/openerz) #### Usage example A ready-to-run example can also be found in the `examples` directory. ``` from openerz_api.main import OpenERZConnector ZIP = 8001 WASTE = "paper" # initialize the connector given zip code and waste type connector = OpenERZConnector(zip_code=ZIP, waste_type=WASTE) # retrieve the next pick-up date within a period of choice next_pickup = connector.find_next_pickup(day_offset=15) ``` misialq-openerz-api-60115c9/examples/000077500000000000000000000000001455305370600175005ustar00rootroot00000000000000misialq-openerz-api-60115c9/examples/example.py000066400000000000000000000005721455305370600215110ustar00rootroot00000000000000from openerz_api.main import OpenERZConnector ZIP = 8001 WASTE = "paper" # initialize the connector given zip code and waste type connector = OpenERZConnector(zip_code=ZIP, waste_type=WASTE) # retrieve the next pick-up date within a period of choice next_pickup = connector.find_next_pickup(day_offset=15) print(f"Next pickup date for {WASTE} in {ZIP} area: {next_pickup}") misialq-openerz-api-60115c9/openerz_api/000077500000000000000000000000001455305370600201755ustar00rootroot00000000000000misialq-openerz-api-60115c9/openerz_api/__init__.py000066400000000000000000000000001455305370600222740ustar00rootroot00000000000000misialq-openerz-api-60115c9/openerz_api/main.py000066400000000000000000000065051455305370600215010ustar00rootroot00000000000000import logging import requests from datetime import datetime, timedelta class OpenERZConnector: """A simple connector to interact with OpenERZ API.""" def __init__(self, zip_code, waste_type): """Initialize the API connector. Args: zip_code (int): post code of the area of interest waste_type (str): type of waste to be picked up (paper/cardboard/waste/cargotram/etram/organic/textile) """ self.zip = zip_code self.waste_type = waste_type self.start_date = datetime.now() self.end_date = None self.last_api_response = None self.logger = logging.getLogger(__name__) def update_start_date(self): """Set the start day to today.""" self.start_date = datetime.now() def find_end_date(self, day_offset=31): """Find the end date for the request, given an offset expressed in days. Args: day_offset (int): difference in days between start and end date of the request """ self.end_date = self.start_date + timedelta(days=day_offset) def make_api_request(self): """Construct a request and send it to the OpenERZ API.""" headers = {"accept": "application/json"} start_date = self.start_date.strftime("%Y-%m-%d") end_date = self.end_date.strftime("%Y-%m-%d") payload = { "zip": self.zip, "types":self.waste_type, "start": start_date, "end": end_date, "offset": 0, "limit": 1, "lang": "en", "sort": "date", } url = f"https://openerz.metaodi.ch/api/calendar.json" try: self.last_api_response = requests.get(url, params=payload, headers=headers) except requests.exceptions.RequestException as connection_error: self.logger.error("RequestException while making request to OpenERZ: %s", connection_error) def parse_api_response(self): """Parse the JSON response received from the OpenERZ API and return a date of the next pickup.""" if not self.last_api_response.ok: self.logger.warning( "Last request to OpenERZ was not successful. Status code: %d", self.last_api_response.status_code, ) return None response_json = self.last_api_response.json() if response_json["_metadata"]["total_count"] == 0: self.logger.warning("Request to OpenERZ returned no results.") return None result_list = response_json.get("result") first_scheduled_pickup = result_list[0] if first_scheduled_pickup["zip"] == self.zip and first_scheduled_pickup["waste_type"] == self.waste_type: return first_scheduled_pickup["date"] self.logger.warning("Either zip or waste type does not match the ones specified in the configuration.") return None def find_next_pickup(self, day_offset=31): """Find the next pickup date within the next X days, given zip_code and waste type Args: day_offset (int): difference in days between start and end date of the request """ self.update_start_date() self.find_end_date(day_offset=day_offset) self.make_api_request() next_pickup_date = self.parse_api_response() return next_pickup_date misialq-openerz-api-60115c9/requirements.txt000066400000000000000000000000221455305370600211400ustar00rootroot00000000000000requests ~= 2.23.0misialq-openerz-api-60115c9/setup.py000066400000000000000000000012741455305370600174000ustar00rootroot00000000000000import setuptools with open("README.md", "r") as fh: long_description = fh.read() setuptools.setup( name="openerz-api", version="0.3.0", author="Michał Ziemski", author_email="michal@terrestryal.com", description="A Python wrapper around the OpenERZ API.", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/misialq/openerz-api", packages=setuptools.find_packages(), classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], install_requires=["requests",], python_requires=">=3.6", ) misialq-openerz-api-60115c9/tests/000077500000000000000000000000001455305370600170245ustar00rootroot00000000000000misialq-openerz-api-60115c9/tests/__pycache__/000077500000000000000000000000001455305370600212345ustar00rootroot00000000000000misialq-openerz-api-60115c9/tests/__pycache__/test_api.cpython-37-pytest-5.4.1.pyc000066400000000000000000000267331455305370600274770ustar00rootroot00000000000000B Z^R% @sddlZddlmmZddlmZddlZddlm Z ddl m Z ddl m Z ddlmZeddd d d ddd ZGd ddZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&ZdS)'N)datetime)patch)RequestException) LogCapture)OpenERZConnectori )yearmonthdayhourminutesecond microsecondc@s eZdZdZddZddZdS)MockAPIResponsez+Provide fake response from the OpenERZ API.cCs||_||_||_dS)zInitialize all the values.N)ok status_code json_data)selfZis_okrrr2/Users/misialq/Repos/openerz-api/tests/test_api.py__init__szMockAPIResponse.__init__cCs|jS)zReturn response data.)r)rrrrjsonszMockAPIResponse.jsonN)__name__ __module__ __qualname____doc__rrrrrrr srcCs tddfS)z/Set up things to be run when tests are started.iglass) MOCK_DATETIMErrrr setup_methodsr!c Cs~t|}t|}||k}|std|fd||fdtksFttrPttnddtksht|rrt|ndt|dtksttrttnddtkst|rt|ndt|d}dd|i}tt|d}}}x| D]v}||}||} || k}|shtd|fd || ft|t| d } d d | i} tt| d}}} qWdS) N)==)zN%(py3)s {%(py3)s = %(py0)s(%(py1)s) } == %(py8)s {%(py8)s = %(py5)s(%(py6)s) }lendict1dict2)py0py1py3py5py6Zpy8zassert %(py10)sZpy10)z%(py1)s == %(py4)s)r'py4zassert %(py6)sr*) r# @pytest_ar_call_reprcompare @py_builtinslocals_should_repr_global_name _safereprAssertionError_format_explanationkeys) r$r% @py_assert2Z @py_assert7 @py_assert4Z @py_format9Z @py_format11key @py_assert0 @py_assert3 @py_format5 @py_format7rrrassertDictEquals"  , r<c Cst\}}}td}||j_t||}|j}d}||k}|std|fd||fdt ksjt |rtt |ndt |t |d}dd|i} t t | d }}}|j}d }||k}|s6td|fd ||fdt kst |rt |ndt |t |d}dd|i} t t | d }}}|j}||k}|std|fd ||fdt kst |rt |ndt |d t kst |rt |nd d} dd| i} t t | d }}|j}d }||k}|sltd|fd||fdt ks.t |r8t |ndt |t |d}dd|i} t t | d }}}|j}d }||k}|std|fd||fdt kst |rt |ndt |t |d}dd|i} t t | d }}}Wd QRXd S)z-Test whether all values initialized properly.zopenerz_api.main.datetimei)r")z+%(py2)s {%(py2)s = %(py0)s.zip } == %(py5)s test_openerz)r&py2r)zassert %(py7)sZpy7Nr)z2%(py2)s {%(py2)s = %(py0)s.waste_type } == %(py5)s)z2%(py2)s {%(py2)s = %(py0)s.start_date } == %(py4)s mock_datetime)r&r>r+zassert %(py6)sr*)is)z0%(py2)s {%(py2)s = %(py0)s.end_date } is %(py5)s)z9%(py2)s {%(py2)s = %(py0)s.last_api_response } is %(py5)s)r!rnow return_valuerzipr,r-r.r/r0r1r2r3 waste_type start_dateend_datelast_api_response) r?zip_coderD patched_timer= @py_assert1r6r9 @py_format6Z @py_format8r:r;rrr test_init%sV   N  P  p R  R rLc Cst\}}}td}||j_t||}|jdd|j_|tdddddddd}|j}||k}|st d |fd ||fd t kst |rt |nd t |d t kst |rt |nd d }dd|i} tt | d}}WdQRXdS)z-Test whether start date is updated correctly.zopenerz_api.main.datetimer )r irr r)r r r rrrr)r")z2%(py2)s {%(py2)s = %(py0)s.start_date } == %(py4)sr=expected_start_date)r&r>r+zassert %(py6)sr*N)r!rrArBrreplaceZupdate_start_daterrEr,r-r.r/r0r1r2r3) r?rHrDrIr=rMrJr9r:r;rrrtest_sensor_update_start_date4s   h rOc Cst\}}}td}||j_t||}|tdddddddd}|j}||k}|st d |fd ||fd t kst |rt |nd t |d t kst |rt |nd d }dd|i} tt| d}}WdQRXdS)z'Test whether end date is correctly set.zopenerz_api.main.datetimeirr r r)r r r rrrr)r")z0%(py2)s {%(py2)s = %(py0)s.end_date } == %(py4)sr=expected_end_date)r&r>r+zassert %(py6)sr*N)r!rrArBrZ find_end_daterrFr,r-r.r/r0r1r2r3) r?rHrDrIr=rQrJr9r:r;rrrtest_sensor_find_end_dateBs   h rRc Cs6t\}}}td}i|j_td}||j_t||}|jdddd|_|ddi}d }d d d d d ddd}|jj d \} } | d } | |k} | st d| fd| |ft | dt kst |rt |ndd} dd| i}tt |d} } t| d|t| d|WdQRXWdQRXdS)zTest making API requests.zopenerz_api.main.requestszopenerz_api.main.datetimeirPr)r r r acceptzapplication/jsonz1http://openerz.metaodi.ch/api/calendar/glass.jsoniz 2019-12-10z 2020-01-10rendate)rCstartendoffsetlimitlangsort)r")z%(py1)s == %(py3)s expected_url)r'r(zassert %(py5)sr)Nheadersparams)r!rgetrBrArrNrFmake_api_requestZcall_args_listr,r-r1r.r/r0r2r3r<)r?rHrDZpatched_requestsrIr=Zexpected_headersr\Zexpected_payload used_argsZ used_kwargsr8r5 @py_format4rKrrrtest_sensor_make_api_requestOs6    F rcc Cst\}}}tdp}td|_tdR}||j_t||}|jdddd|_t }| |j dd d Wd QRXWd QRXWd QRXd S) zTest making API requests.zopenerz_api.main.requests.getzConnection timed outzopenerz_api.main.datetimeirPr)r r r )zopenerz_api.mainERRORzFRequestException while making request to OpenERZ: Connection timed outF)Z order_mattersN) r!rr side_effectrArBrrNrFrr` check_present)r?rHrDZ patched_getrIr= captured_logsrrr-test_sensor_make_api_request_connection_errorks     rhc Cst\}}}td}||j_t||}|jdddd|_ddiddd d gd }td d ||_| }d }||k}|st d|fd||fdt kst |rt |ndt |d} dd| i} tt | d}}WdQRXdS)z.Test whether API response is parsed correctly.zopenerz_api.main.datetimeirPr)r r r total_countirz 2020-01-10)rCtyperU) _metadataresultT)r")z%(py0)s == %(py3)stest_pickup_date)r&r(zassert %(py5)sr)N)r!rrArBrrNrFrrGparse_api_responser,r-r.r/r0r1r2r3) r?rHrDrIr= response_datarnr5rJrbrKrrr!test_sensor_parse_api_response_oks    F rqc Cst\}}}td}||j_t||}|jdddd|_ddigd}t}td d ||_ | }d }||k} | st d | fd ||fdt kst |rt |ndt |d} dd| i} tt | d } }|dWd QRXWd QRXd S)zDTest whether API response is parsed correctly when no data returned.zopenerz_api.main.datetimeirPr)r r r rir)rkrlTrmN)r@)z%(py0)s is %(py3)srn)r&r(zassert %(py5)sr))zopenerz_api.mainWARNINGz'Request to OpenERZ returned no results.)r!rrArBrrNrFrrrGror,r-r.r/r0r1r2r3rf) r?rHrDrIr=rprgrnr5rJrbrKrrr&test_sensor_parse_api_response_no_datas"   F rsc Cs t\}}}td}||j_t||}|jdddd|_ddiddd d gd }t}td d ||_ | }d}||k} | st d| fd||fdt kst |rt |ndt |d} dd| i} tt | d} }|dWdQRXWdQRXdS)z-Test handling unexpected zip in API response.zopenerz_api.main.datetimeirPr)r r r riirz 2020-01-10)rCrjrU)rkrlTrmN)r@)z%(py0)s is %(py3)srn)r&r(zassert %(py5)sr))zopenerz_api.mainrrzPEither zip or waste type does not match the ones specified in the configuration.)r!rrArBrrNrFrrrGror,r-r.r/r0r1r2r3rf) r?rHrDrIr=rprgrnr5rJrbrKrrr(test_sensor_parse_api_response_wrong_zips&   F rtc Cs t\}}}td}||j_t||}|jdddd|_ddiddd d gd }t}td d ||_ | }d}||k} | st d| fd||fdt kst |rt |ndt |d} dd| i} tt | d} }|dWdQRXWdQRXdS)z4Test handling unexpected waste type in API response.zopenerz_api.main.datetimeirPr)r r r riiZmetalz 2020-01-10)rCrjrU)rkrlTrmN)r@)z%(py0)s is %(py3)srn)r&r(zassert %(py5)sr))zopenerz_api.mainrrzPEither zip or waste type does not match the ones specified in the configuration.)r!rrArBrrNrFrrrGror,r-r.r/r0r1r2r3rf) r?rHrDrIr=rprgrnr5rJrbrKrrr)test_sensor_parse_api_response_wrong_types&   F ruc Cst\}}}td}||j_t||}|jdddd|_digi}t}tdd||_ | }d }||k} | st d | fd ||fd t kst |rt |nd t |d } dd| i} tt | d } }|dWd QRXWd QRXd S)z+Test handling of an erroneous API response.zopenerz_api.main.datetimeirPr)r r r rlFiN)r@)z%(py0)s is %(py3)srn)r&r(zassert %(py5)sr))zopenerz_api.mainrrzs*      misialq-openerz-api-60115c9/tests/test_api.py000066400000000000000000000225531455305370600212150ustar00rootroot00000000000000from datetime import datetime from unittest.mock import patch from requests.exceptions import RequestException from testfixtures import LogCapture from openerz_api.main import OpenERZConnector MOCK_DATETIME = datetime(year=2019, month=12, day=10, hour=11, minute=15, second=0, microsecond=0) class MockAPIResponse: """Provide fake response from the OpenERZ API.""" def __init__(self, is_ok, status_code, json_data): """Initialize all the values.""" self.ok = is_ok self.status_code = status_code self.json_data = json_data def json(self): """Return response data.""" return self.json_data def setup_method(): """Set up things to be run when tests are started.""" return MOCK_DATETIME, 1234, "glass" def assertDictEqual(dict1, dict2): assert len(dict1) == len(dict2) for key in dict1.keys(): assert dict1[key] == dict2[key] def test_init(): """Test whether all values initialized properly.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) assert test_openerz.zip == 1234 assert test_openerz.waste_type == "glass" assert test_openerz.start_date == mock_datetime assert test_openerz.end_date is None assert test_openerz.last_api_response is None def test_sensor_update_start_date(): """Test whether start date is updated correctly.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) patched_time.now.return_value = mock_datetime.replace(day=11) test_openerz.update_start_date() expected_start_date = datetime(year=2019, month=12, day=11, hour=11, minute=15, second=0, microsecond=0) assert test_openerz.start_date == expected_start_date def test_sensor_find_end_date(): """Test whether end date is correctly set.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.find_end_date() expected_end_date = datetime(year=2020, month=1, day=10, hour=11, minute=15, second=0, microsecond=0) assert test_openerz.end_date == expected_end_date def test_sensor_make_api_request(): """Test making API requests.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.requests") as patched_requests: patched_requests.get.return_value = {} with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) test_openerz.make_api_request() expected_headers = {"accept": "application/json"} expected_url = "https://openerz.metaodi.ch/api/calendar.json" expected_payload = { "zip": 1234, "types": "glass", "start": "2019-12-10", "end": "2020-01-10", "offset": 0, "limit": 1, "lang": "en", "sort": "date", } used_args, used_kwargs = patched_requests.get.call_args_list[0] assert used_args[0] == expected_url assertDictEqual(used_kwargs["headers"], expected_headers) assertDictEqual(used_kwargs["params"], expected_payload) def test_sensor_make_api_request_connection_error(): """Test making API requests.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.requests.get") as patched_get: patched_get.side_effect = RequestException("Connection timed out") with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) with LogCapture() as captured_logs: test_openerz.make_api_request() captured_logs.check_present( ( "openerz_api.main", "ERROR", "RequestException while making request to OpenERZ: Connection timed out", ), order_matters=False, ) def test_sensor_parse_api_response_ok(): """Test whether API response is parsed correctly.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) response_data = { "_metadata": {"total_count": 1}, "result": [{"zip": 1234, "waste_type": "glass", "date": "2020-01-10"}], } test_openerz.last_api_response = MockAPIResponse(True, 200, response_data) test_pickup_date = test_openerz.parse_api_response() assert test_pickup_date == "2020-01-10" def test_sensor_parse_api_response_no_data(): """Test whether API response is parsed correctly when no data returned.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) response_data = {"_metadata": {"total_count": 0}, "result": []} with LogCapture() as captured_logs: test_openerz.last_api_response = MockAPIResponse(True, 200, response_data) test_pickup_date = test_openerz.parse_api_response() assert test_pickup_date is None captured_logs.check_present(("openerz_api.main", "WARNING", "Request to OpenERZ returned no results.",)) def test_sensor_parse_api_response_wrong_zip(): """Test handling unexpected zip in API response.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) response_data = { "_metadata": {"total_count": 1}, "result": [{"zip": 1235, "type": "glass", "date": "2020-01-10"}], } with LogCapture() as captured_logs: test_openerz.last_api_response = MockAPIResponse(True, 200, response_data) test_pickup_date = test_openerz.parse_api_response() assert test_pickup_date is None captured_logs.check_present( ( "openerz_api.main", "WARNING", "Either zip or waste type does not match the ones specified in the configuration.", ) ) def test_sensor_parse_api_response_wrong_type(): """Test handling unexpected waste type in API response.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) response_data = { "_metadata": {"total_count": 1}, "result": [{"zip": 1234, "waste_type": "metal", "date": "2020-01-10"}], } with LogCapture() as captured_logs: test_openerz.last_api_response = MockAPIResponse(True, 200, response_data) test_pickup_date = test_openerz.parse_api_response() assert test_pickup_date is None captured_logs.check_present( ( "openerz_api.main", "WARNING", "Either zip or waste type does not match the ones specified in the configuration.", ) ) def test_sensor_parse_api_response_not_ok(): """Test handling of an erroneous API response.""" mock_datetime, zip_code, waste_type = setup_method() with patch("openerz_api.main.datetime") as patched_time: patched_time.now.return_value = mock_datetime test_openerz = OpenERZConnector(zip_code, waste_type) test_openerz.end_date = mock_datetime.replace(year=2020, month=1, day=10) response_data = {"result": [{}]} with LogCapture() as captured_logs: test_openerz.last_api_response = MockAPIResponse(False, 404, response_data) test_pickup_date = test_openerz.parse_api_response() assert test_pickup_date is None captured_logs.check_present( ("openerz_api.main", "WARNING", "Last request to OpenERZ was not successful. Status code: 404",) )