From 81ab7ab05294283359a473cec85e1261d0288755 Mon Sep 17 00:00:00 2001 From: Wittmann Andreas Date: Mon, 30 May 2022 13:31:08 +0200 Subject: [PATCH 1/6] Quick Fix for the pain of wanting control over my tls session. It's my TLS-Session after all, mine alone! --- pyopenproject/api_connection/requests/delete_request.py | 2 +- pyopenproject/api_connection/requests/get_request.py | 2 +- pyopenproject/api_connection/requests/patch_request.py | 2 +- pyopenproject/api_connection/requests/post_request.py | 3 ++- pyopenproject/api_connection/requests/put_request.py | 3 ++- pyopenproject/model/connection.py | 3 ++- pyopenproject/openproject.py | 6 +++--- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyopenproject/api_connection/requests/delete_request.py b/pyopenproject/api_connection/requests/delete_request.py index 38490b66..df032681 100644 --- a/pyopenproject/api_connection/requests/delete_request.py +++ b/pyopenproject/api_connection/requests/delete_request.py @@ -13,5 +13,5 @@ def _execute_request(self): with requests.Session() as s: s.auth = HTTPBasicAuth(self.connection.api_user, self.connection.api_key) s.headers.update({'Content-Type': 'application/json;charset=utf-8'}) - response = s.delete(url=self.connection.url_base + self.context) + response = s.delete(url=self.connection.url_base + self.context, **self.connection.request_args) return response diff --git a/pyopenproject/api_connection/requests/get_request.py b/pyopenproject/api_connection/requests/get_request.py index 8a046c85..6a8c01df 100644 --- a/pyopenproject/api_connection/requests/get_request.py +++ b/pyopenproject/api_connection/requests/get_request.py @@ -13,5 +13,5 @@ def _execute_request(self): with requests.Session() as s: s.auth = HTTPBasicAuth(self.connection.api_user, self.connection.api_key) s.headers.update({"Content-Type": "application/hal+json"}) - response = s.get(self.connection.url_base + self.context) + response = s.get(self.connection.url_base + self.context, **self.connection.request_args) return response diff --git a/pyopenproject/api_connection/requests/patch_request.py b/pyopenproject/api_connection/requests/patch_request.py index 06691bef..c517a3c9 100644 --- a/pyopenproject/api_connection/requests/patch_request.py +++ b/pyopenproject/api_connection/requests/patch_request.py @@ -13,5 +13,5 @@ def _execute_request(self): with requests.Session() as s: s.auth = HTTPBasicAuth(self.connection.api_user, self.connection.api_key) s.headers.update({"Content-Type": "application/json"}) - response = s.patch(self.connection.url_base + self.context, json=self.json) + response = s.patch(self.connection.url_base + self.context, json=self.json, **self.connection.request_args) return response diff --git a/pyopenproject/api_connection/requests/post_request.py b/pyopenproject/api_connection/requests/post_request.py index 417f418d..5012276a 100644 --- a/pyopenproject/api_connection/requests/post_request.py +++ b/pyopenproject/api_connection/requests/post_request.py @@ -17,5 +17,6 @@ def _execute_request(self): url=self.connection.url_base + self.context, json=self.json, files=self.files, - data=self.data) + data=self.data, + **self.connection.request_args) return response diff --git a/pyopenproject/api_connection/requests/put_request.py b/pyopenproject/api_connection/requests/put_request.py index cb91ac2b..a04f4f0c 100644 --- a/pyopenproject/api_connection/requests/put_request.py +++ b/pyopenproject/api_connection/requests/put_request.py @@ -13,5 +13,6 @@ def _execute_request(self): self.connection.url_base + self.context, auth=HTTPBasicAuth(self.connection.api_user, self.connection.api_key), data=self.json, - headers=self.headers + headers=self.headers, + **self.connection.request_args ) diff --git a/pyopenproject/model/connection.py b/pyopenproject/model/connection.py index f9665cb8..984f299e 100644 --- a/pyopenproject/model/connection.py +++ b/pyopenproject/model/connection.py @@ -6,13 +6,14 @@ class Connection: Class Configuration, represents the connection realized with the web application """ - def __init__(self, url, apikey, user=None): + def __init__(self, url, apikey, user=None, **kwargs): """Constructor for class Connection :param url: The application url :param apikey: The apikey :param user: The user (optional) """ self.url_base = url + self.request_args = kwargs self.api_user = "apikey" if user is None else user self.api_key = apikey diff --git a/pyopenproject/openproject.py b/pyopenproject/openproject.py index 74ea86f1..6a9f5a0b 100644 --- a/pyopenproject/openproject.py +++ b/pyopenproject/openproject.py @@ -35,10 +35,10 @@ class OpenProject: - def __init__(self, url, api_key, user=None): - self.conn = Connection(url=url, apikey=api_key) \ + def __init__(self, url, api_key, user=None, **kwargs): + self.conn = Connection(url=url, apikey=api_key, **kwargs) \ if user is None \ - else Connection(url=url, user=user, apikey=api_key) + else Connection(url=url, user=user, apikey=api_key, **kwargs) def get_activity_service(self): return ActivityServiceImpl(self.conn) From 6d4073cf7b115ea328a46b5aad8fc1548ad1d20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alan=20Padierna=20Fern=C3=A1ndez?= Date: Sat, 4 Nov 2023 17:53:25 +0000 Subject: [PATCH 2/6] fix(actions): changed matrix strategy --- .github/workflows/test_cases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_cases.yml b/.github/workflows/test_cases.yml index 45b7e6e1..b6bfb4a2 100644 --- a/.github/workflows/test_cases.yml +++ b/.github/workflows/test_cases.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ 3.9, 3.8, 3.7, 3.6 ] + python-version: ["pypy3.9", "pypy3.10", "3.9", "3.10", "3.11", "3.12"] # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it From c2359f5fd8526db905c5175e232e23ebf981ee8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alan=20Padierna=20Fern=C3=A1ndez?= Date: Sat, 4 Nov 2023 17:56:24 +0000 Subject: [PATCH 3/6] fix(actions): changed matrix strategy --- .github/workflows/test_cases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_cases.yml b/.github/workflows/test_cases.yml index b6bfb4a2..5321cf3b 100644 --- a/.github/workflows/test_cases.yml +++ b/.github/workflows/test_cases.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["pypy3.9", "pypy3.10", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it From 22df90d8337b1d0bf96e5665c3936181d761a9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alan=20Padierna=20Fern=C3=A1ndez?= Date: Sat, 4 Nov 2023 18:15:18 +0000 Subject: [PATCH 4/6] test: fixed some tests cases --- tests/test_cases/membership_service_test.py | 2 +- tests/test_cases/principal_service_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cases/membership_service_test.py b/tests/test_cases/membership_service_test.py index 8f9173b7..166ff6ed 100644 --- a/tests/test_cases/membership_service_test.py +++ b/tests/test_cases/membership_service_test.py @@ -57,7 +57,7 @@ def test_operations(self): membership_to_create.__dict__['_links']['principal']["href"]) membership_aux = Membership(membership.__dict__.copy()) updated_form = self.membershipSer.update_form(membership_aux) - self.assertEqual({'_links': {'roles': [{'href': '/api/v3/roles/5', 'title': 'Reader'}]}}, + self.assertEqual({'_links': {'roles': [{'href': '/api/v3/roles/5', 'title': 'Reader'}]}, '_meta': {'notificationMessage': {'format': 'markdown', 'html': '', 'raw': None}}}, updated_form._embedded['payload']) membership = self.membershipSer.find(membership) self.assertIsNotNone(membership) diff --git a/tests/test_cases/principal_service_test.py b/tests/test_cases/principal_service_test.py index 27817bf4..1214bb7f 100644 --- a/tests/test_cases/principal_service_test.py +++ b/tests/test_cases/principal_service_test.py @@ -17,7 +17,7 @@ def setUp(self): def test_find_all(self): principals = self.principalSer.find_all(filters=None) - self.assertEqual(1, len(principals)) + self.assertEqual(2, len(principals)) def test_filters(self): # Filter member cant be tested with default user From 21286d2161666f5409289ce8e601e1b83977f9f2 Mon Sep 17 00:00:00 2001 From: Allen Chen Date: Fri, 13 Sep 2024 00:26:55 +0800 Subject: [PATCH 5/6] refactor: support filter value type as int if value type as int, don't split it to char. value=22, "values": ["22"] value="22", "values": ["2","2"] --- pyopenproject/business/util/filters.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyopenproject/business/util/filters.py b/pyopenproject/business/util/filters.py index 0611fcab..288bedc3 100644 --- a/pyopenproject/business/util/filters.py +++ b/pyopenproject/business/util/filters.py @@ -21,10 +21,13 @@ def __str__(self) -> str: output += f"\"{self.value[i].name}\":" output += "{" output += f"\"operator\":\"{self.value[i].operator}\",\"values\":[" - for j in range(len(self.value[i].values)): - if j != 0: - output += "," - output += f"\"{self.value[i].values[j]}\"" + if type(self.value[i].values) is int: + output += f"\"{str(self.value[i].values)}\"" + else: + for j in range(len(self.value[i].values)): + if j != 0: + output += "," + output += f"\"{self.value[i].values[j]}\"" output += "]}}" output += "," if len(self.value) != 1 and i != len(self.value)-1 else "" output += "]" From df9cbb676c08b787d4674b3e729040cd6eea2ade Mon Sep 17 00:00:00 2001 From: Allen Chen Date: Sat, 21 Sep 2024 04:29:58 +0800 Subject: [PATCH 6/6] feat: support find_children() in work_package_service_impl.py --- .../command/work_package/find_children.py | 22 +++++++++++++++++++ .../services/work_package_service_impl.py | 4 ++++ 2 files changed, 26 insertions(+) create mode 100644 pyopenproject/business/services/command/work_package/find_children.py diff --git a/pyopenproject/business/services/command/work_package/find_children.py b/pyopenproject/business/services/command/work_package/find_children.py new file mode 100644 index 00000000..5e80a617 --- /dev/null +++ b/pyopenproject/business/services/command/work_package/find_children.py @@ -0,0 +1,22 @@ +from pyopenproject.api_connection.exceptions.request_exception import RequestError +from pyopenproject.api_connection.requests.get_request import GetRequest +from pyopenproject.business.exception.business_error import BusinessError +from pyopenproject.business.services.command.work_package.work_package_command import WorkPackageCommand +from pyopenproject.model import work_package as wp + + +class FindChildren(WorkPackageCommand): + def __init__(self, connection, work_package): + super().__init__(connection) + self.work_package = work_package + self.obj_list=[] + + def execute(self): + try: + if "children" in self.work_package.__dict__["_links"]: + for children in self.work_package.__dict__["_links"]["children"]: + request = GetRequest(self.connection, f'{children["href"]}') + self.obj_list.append(wp.WorkPackage(request.execute())) + return self.obj_list + except RequestError as re: + raise BusinessError(f"Error finding children for work package {self.work_package.id}") from re diff --git a/pyopenproject/business/services/work_package_service_impl.py b/pyopenproject/business/services/work_package_service_impl.py index 05c27337..a0ab6936 100644 --- a/pyopenproject/business/services/work_package_service_impl.py +++ b/pyopenproject/business/services/work_package_service_impl.py @@ -22,6 +22,7 @@ from pyopenproject.business.services.command.work_package.find_watchers import FindWatchers from pyopenproject.business.services.command.work_package.update import Update from pyopenproject.business.services.command.work_package.update_form import UpdateForm +from pyopenproject.business.services.command.work_package.find_children import FindChildren from pyopenproject.business.work_package_service import WorkPackageService @@ -106,3 +107,6 @@ def find_activities(self, work_package): def create_activity(self, work_package, comment, notify=None): return CreateActivity(self.connection, work_package, comment, notify).execute() + + def find_children(self, work_package): + return list(FindChildren(self.connection, work_package).execute())