From 663843d23c67cec82ff7c0c0633363335c60a6ee Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:15:10 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20Add=20calendars=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client_components/calendars/__init__.py | 0 .../calendars/calendars_component.py | 42 +++++++++++++++++++ zoom_python_client/zoom_api_client.py | 4 ++ .../zoom_auth_api/zoom_auth_api_client.py | 2 +- 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 zoom_python_client/client_components/calendars/__init__.py create mode 100644 zoom_python_client/client_components/calendars/calendars_component.py diff --git a/zoom_python_client/client_components/calendars/__init__.py b/zoom_python_client/client_components/calendars/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/zoom_python_client/client_components/calendars/calendars_component.py b/zoom_python_client/client_components/calendars/calendars_component.py new file mode 100644 index 0000000..e65204a --- /dev/null +++ b/zoom_python_client/client_components/calendars/calendars_component.py @@ -0,0 +1,42 @@ +from typing import Any + +from zoom_python_client.zoom_client_interface import ZoomClientInterface + + +class CalendarsComponent: + def __init__(self, client: ZoomClientInterface) -> None: + self.client = client + + def list_calendar_services(self) -> dict: + api_path = "/rooms/calendar/services" + response = self.client.make_get_request(api_path) + result = response.json() + return result + + def list_calendar_resources(self) -> list[Any]: + calendar_services = self.list_calendar_services() + calendar_service_ids = [ + calendar_service["calendar_service_id"] + for calendar_service in calendar_services["calendar_services"] + ] + calendar_resources = [] + for calendar_service_id in calendar_service_ids: + res = self.list_calendar_resources_by_service_id(calendar_service_id) + for resource in res["calendar_resources"]: + calendar_resources.append(resource) + + return calendar_resources + + def list_calendar_resources_by_service_id(self, calendar_service_id: str) -> dict: + api_path = f"/rooms/calendar/services/{calendar_service_id}/resources" + response = self.client.make_get_request(api_path) + result = response.json() + return result + + def get_calendar_resource_by_ressource_id(self, resource_id: str) -> dict: + all_ressources = self.list_calendar_resources() + for resource in all_ressources: + if resource["calendar_resource_id"] == resource_id: + return resource + + raise ValueError(f"Resource with id {resource_id} not found") diff --git a/zoom_python_client/zoom_api_client.py b/zoom_python_client/zoom_api_client.py index 3161303..ee937dd 100644 --- a/zoom_python_client/zoom_api_client.py +++ b/zoom_python_client/zoom_api_client.py @@ -6,6 +6,9 @@ from dotenv import load_dotenv from zoom_python_client.api_client import ApiClient +from zoom_python_client.client_components.calendars.calendars_component import ( + CalendarsComponent, +) from zoom_python_client.client_components.meeting_livestreams.meeting_livestreams_component import ( MeetingLiveStreamsComponent, ) @@ -74,6 +77,7 @@ def init_components(self): self.webinars = WebinarsComponent(self) self.webinar_livestreams = WebinarLiveStreamsComponent(self) self.rooms = RoomsComponent(self) + self.calendars = CalendarsComponent(self) def __init__( self, diff --git a/zoom_python_client/zoom_auth_api/zoom_auth_api_client.py b/zoom_python_client/zoom_auth_api/zoom_auth_api_client.py index 02732f3..6cad86f 100644 --- a/zoom_python_client/zoom_auth_api/zoom_auth_api_client.py +++ b/zoom_python_client/zoom_auth_api/zoom_auth_api_client.py @@ -125,5 +125,5 @@ def get_expire_seconds_from_file(self): with open(file_path, "r") as token_file: access_token = token_file.read() return access_token - except FileNotFoundError: + except FileNotFoundError: # pragma: no cover return None From 47dd35d46257a7eb906fbbd72637afb0a2b23f5c Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:15:31 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=A4=96=20Add=20tests=20for=20calendar?= =?UTF-8?q?s=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client_components/calendars/__init__.py | 0 .../calendars/test_calendars_component.py | 92 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 tests/zoom_python_client/client_components/calendars/__init__.py create mode 100644 tests/zoom_python_client/client_components/calendars/test_calendars_component.py diff --git a/tests/zoom_python_client/client_components/calendars/__init__.py b/tests/zoom_python_client/client_components/calendars/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/zoom_python_client/client_components/calendars/test_calendars_component.py b/tests/zoom_python_client/client_components/calendars/test_calendars_component.py new file mode 100644 index 0000000..fda05a6 --- /dev/null +++ b/tests/zoom_python_client/client_components/calendars/test_calendars_component.py @@ -0,0 +1,92 @@ +import pytest +import responses + +from tests.zoom_python_client.base_test_case import TestCaseWithAuth +from zoom_python_client.client_components.calendars.calendars_component import ( + CalendarsComponent, +) +from zoom_python_client.zoom_api_client import ZoomApiClient + + +class TestCalendarsComponent(TestCaseWithAuth): + def setUp(self): + super().setUp() + zoom_client = ZoomApiClient("aaa", "bbb", "ccc", "http://localhost") + self.calendars_component = CalendarsComponent(zoom_client) + + @responses.activate + def test_list_calendar_services(self): + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services", + json={"response": "ok"}, + status=200, + ) + calendar_services = self.calendars_component.list_calendar_services() + assert calendar_services == {"response": "ok"} + + @responses.activate + def test_list_calendar_resources(self): + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services", + json={"calendar_services": [{"calendar_service_id": "12345"}]}, + status=200, + ) + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services/12345/resources", + json={"calendar_resources": [{"calendar_resource_id": "12345"}]}, + status=200, + ) + calendar_resources = self.calendars_component.list_calendar_resources() + assert calendar_resources == [{"calendar_resource_id": "12345"}] + + @responses.activate + def test_list_calendar_resources_by_service_id(self): + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services/12345/resources", + json={"response": "ok"}, + status=200, + ) + calendar_resources = ( + self.calendars_component.list_calendar_resources_by_service_id("12345") + ) + assert calendar_resources == {"response": "ok"} + + @responses.activate + def test_get_calendar_resource_by_ressource_id(self): + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services", + json={"calendar_services": [{"calendar_service_id": "12345"}]}, + status=200, + ) + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services/12345/resources", + json={"calendar_resources": [{"calendar_resource_id": "12345"}]}, + status=200, + ) + calendar_resource = ( + self.calendars_component.get_calendar_resource_by_ressource_id("12345") + ) + assert calendar_resource == {"calendar_resource_id": "12345"} + + @responses.activate + def test_get_calendar_resource_by_ressource_id_not_found(self): + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services", + json={"calendar_services": [{"calendar_service_id": "12345"}]}, + status=200, + ) + responses.add( + responses.GET, + "http://localhost/rooms/calendar/services/12345/resources", + json={"calendar_resources": [{"calendar_resource_id": "12345"}]}, + status=200, + ) + with pytest.raises(ValueError): + self.calendars_component.get_calendar_resource_by_ressource_id("123456") From 6a624b3844ab1f74f0f70f05c0d9215d4958c267 Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:15:49 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=E2=9C=A8=20Add=20example=20to=20interact?= =?UTF-8?q?=20with=20calendars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/get_microsoft_user_id_for_rooms.py | 32 ++++++++++++++++++++++ example/list_calendar_ressources.py | 21 ++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 example/get_microsoft_user_id_for_rooms.py create mode 100644 example/list_calendar_ressources.py diff --git a/example/get_microsoft_user_id_for_rooms.py b/example/get_microsoft_user_id_for_rooms.py new file mode 100644 index 0000000..9696ff8 --- /dev/null +++ b/example/get_microsoft_user_id_for_rooms.py @@ -0,0 +1,32 @@ +import logging + +from zoom_python_client.client_components.rooms.rooms_component import ( + RoomsListDict, + RoomType, +) +from zoom_python_client.utils.logger import setup_logs +from zoom_python_client.zoom_api_client import ZoomApiClient + +logger = setup_logs(log_level=logging.INFO) + +zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") + +parameters = RoomsListDict( + type=RoomType.ZOOM_ROOM, +) + +rooms = zoom_client.rooms.get_rooms(parameters) + +logger.info("Found %d rooms:", len(rooms["rooms"])) +for room in rooms["rooms"]: + room_profile = zoom_client.rooms.get_room(room["id"]) + + calendar_ressource = zoom_client.calendars.get_calendar_resource_by_ressource_id( + room_profile["basic"]["calendar_resource_id"] + ) + + logger.info( + "\t- Microsoft user id for room %s is %s", + room["name"], + calendar_ressource["calendar_resource_email"], + ) diff --git a/example/list_calendar_ressources.py b/example/list_calendar_ressources.py new file mode 100644 index 0000000..a77c857 --- /dev/null +++ b/example/list_calendar_ressources.py @@ -0,0 +1,21 @@ +import logging + +from zoom_python_client.utils.logger import setup_logs +from zoom_python_client.zoom_api_client import ZoomApiClient + +logger = setup_logs(log_level=logging.DEBUG) + +zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") + + +result = zoom_client.calendars.list_calendar_resources() + +logger.info("Found %d calendars:", len(result)) + +for calendar_ressources in result: + logger.info( + "\t- %s - %s - %s", + calendar_ressources["calendar_resource_name"], + calendar_ressources["calendar_resource_id"], + calendar_ressources["calendar_resource_email"], + ) From 3eec2fcad19274324dd8c80c2ac48b13fae3ec51 Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:16:07 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=94=A7=20Update=20settings=20for=20vs?= =?UTF-8?q?code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 57 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1999ed7..f0f682a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,55 @@ { + "terminal.integrated.env.osx": { + "PYTHONPATH": "${workspaceFolder}" + }, + "terminal.integrated.env.linux": { + "PYTHONPATH": "${workspaceFolder}" + }, "python.analysis.autoSearchPaths": true, + "python.analysis.autoImportCompletions": true, + "python.analysis.indexing": true, + "python.analysis.packageIndexDepths": [ + { + "name": "pytest", + "depth": 2 + }, + { + "name": "unittest", + "depth": 2 + } + ], "python.analysis.typeCheckingMode": "basic", + "python.analysis.inlayHints.callArgumentNames": true, + "python.analysis.inlayHints.variableTypes": true, + "python.analysis.inlayHints.functionReturnTypes": true, "editor.formatOnSave": true, - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.linting.pylintPath": "venv/bin/pylint", - "terminal.integrated.env.osx": { - "PYTHONPATH": "${workspaceFolder}" + "isort.check": true, + "isort.args": [ + "--profile", + "black" + ], + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": [ + "tests", + "-vv", + "--cov=app", + "--cov-report=term-missing", + "--cov-report=html" + ], + "[python]": { + "editor.codeActionsOnSave": { + "source.organizeImports": true + }, + "editor.defaultFormatter": "ms-python.black-formatter", + "editor.codeLens": true }, "search.exclude": { "**/dist": true, - "**/venv": true + "**/.venv": true }, - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - } -} + "files.exclude": { + "**/__pycache__": true, + "**/.pytest_cache": true, + "**/.mypy*": true, + }, +} \ No newline at end of file From 7ecedcf78120f05354a5854736388396b35789f4 Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:18:02 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=9D=20Update=20doc=20to=20add=20ne?= =?UTF-8?q?w=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 0368e96..2e452b2 100644 --- a/README.md +++ b/README.md @@ -123,3 +123,10 @@ setup_logs(log_level=logging.DEBUG) 1. get all zoom rooms 2. get zoom room details 3. get zoom room sensor data + +### **calendars**: + +1. get calendar services list +2. get calendar resources list +3. get calendar resources by service id list +4. get calendar resource details by id From 1a0b9192ab864016d134509987f5cff21dbe2cd6 Mon Sep 17 00:00:00 2001 From: Samuel Guillemet Date: Wed, 30 Aug 2023 14:18:38 +0200 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=9A=80=20RELEASE:=20Bump=20to=20v0.2.?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 37e8373..459df3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "zoom-python-client" -version = "0.2.1" +version = "0.2.2" authors = ["Rene Fernandez Sanchez "] maintainers = [ "Rene Fernandez Sanchez ",