diff --git a/.github/workflows/test_cases.yml b/.github/workflows/test_cases.yml index 45b7e6e1..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: [ 3.9, 3.8, 3.7, 3.6 ] + 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 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/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()) 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 += "]" 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) 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 ae3a8e3c..0e4ceb78 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 can not be tested with default user