From 3087d3b4d5b3590b716929c1ba82ce8ec37cc451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Luna?= Date: Thu, 30 Jan 2025 01:40:54 -0300 Subject: [PATCH 1/2] feat: Add User Report Settings Templates endpoints - Implement UserReportSettingsTemplatesResource class - Add support for List/Add/Get/Edit/Delete User Report Settings Templates - Add comprehensive test coverage for new endpoints - Maintain existing code style and conventions Resolves #192 --- crowdin_api/api_resources/reports/resource.py | 128 +++++++++++ .../reports/tests/test_reports_resources.py | 203 ++++++++++++++++++ 2 files changed, 331 insertions(+) diff --git a/crowdin_api/api_resources/reports/resource.py b/crowdin_api/api_resources/reports/resource.py index f0ba9ea..3ff93df 100644 --- a/crowdin_api/api_resources/reports/resource.py +++ b/crowdin_api/api_resources/reports/resource.py @@ -33,6 +33,9 @@ BaseRates ) +from crowdin_api.api_resources.reports.enums import Currency, Unit +from crowdin_api.api_resources.reports.types import Config, ReportSettingsTemplatesPatchRequest + class BaseReportsResource(BaseResource): def get_reports_path(self, projectId: int, reportId: Optional[str] = None): @@ -1324,3 +1327,128 @@ def generate_organization_translation_costs_post_editing_general_report( }, }, ) + +class UserReportSettingsTemplatesResource(BaseReportSettingsTemplatesResource): + """ + Resource for User Report Settings Templates API. + + Supporting the endpoints for managing user report settings templates. + + Link to documentation: + https://developer.crowdin.com/api/v2/#tag/User-Report-Settings-Templates + """ + + def get_user_report_settings_templates_path( + self, + userId: int, + reportSettingsTemplateId: Optional[int] = None + ): + if reportSettingsTemplateId is not None: + return f"users/{userId}/reports/settings-templates/{reportSettingsTemplateId}" + + return f"users/{userId}/reports/settings-templates" + + def list_user_report_settings_template( + self, + userId: int, + offset: Optional[int] = None, + limit: Optional[int] = None + ): + """ + List User Report Settings Templates. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.users.reports.settings-templates.getMany + """ + return self._get_entire_data( + method="get", + path=self.get_user_report_settings_templates_path(userId=userId), + params=self.get_page_params(offset=offset, limit=limit), + ) + + def add_user_report_settings_template( + self, + userId: int, + name: str, + currency: Currency, + unit: Unit, + config: Config, + ): + """ + Add User Report Settings Template. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.users.reports.settings-templates.post + """ + return self.requester.request( + method="post", + path=self.get_user_report_settings_templates_path( + userId=userId, + ), + request_data={ + "name": name, + "currency": currency, + "unit": unit, + "mode": "simple", + "config": config, + } + ) + + def get_user_report_settings_template( + self, + userId: int, + reportSettingsTemplateId: int, + ): + """ + Get User Report Settings Template. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.users.reports.settings-templates.get + """ + return self.requester.request( + method="get", + path=self.get_user_report_settings_templates_path( + userId=userId, + reportSettingsTemplateId=reportSettingsTemplateId + ), + ) + + def edit_user_report_settings_template( + self, + userId: int, + reportSettingsTemplateId: int, + data: Iterable[ReportSettingsTemplatesPatchRequest], + ): + """ + Edit User Report Settings Template. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.users.reports.settings-templates.patch + """ + return self.requester.request( + method="patch", + path=self.get_user_report_settings_templates_path( + userId=userId, + reportSettingsTemplateId=reportSettingsTemplateId + ), + request_data=data, + ) + + def delete_user_report_settings_template( + self, + userId: int, + reportSettingsTemplateId: int, + ): + """ + Delete User Report Settings Template. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.users.reports.settings-templates.delete + """ + return self.requester.request( + method="delete", + path=self.get_user_report_settings_templates_path( + userId=userId, + reportSettingsTemplateId=reportSettingsTemplateId + ), + ) \ No newline at end of file diff --git a/crowdin_api/api_resources/reports/tests/test_reports_resources.py b/crowdin_api/api_resources/reports/tests/test_reports_resources.py index aed71b6..d0a31ab 100644 --- a/crowdin_api/api_resources/reports/tests/test_reports_resources.py +++ b/crowdin_api/api_resources/reports/tests/test_reports_resources.py @@ -34,6 +34,10 @@ from crowdin_api.api_resources.reports.types import BaseRates, Match from crowdin_api.requester import APIRequester +from crowdin_api.api_resources.reports.resource import UserReportSettingsTemplatesResource +from crowdin_api.api_resources.enums import PatchOperation +from crowdin_api.api_resources.reports.enums import Currency, Unit, ReportSettingsTemplatesPatchPath + class TestReportsResource: resource_class = ReportsResource @@ -2163,3 +2167,202 @@ def test_delete_report_settings_template(self, m_request, base_absolut_url): reportSettingsTemplateId=1 ) ) + +class TestUserReportSettingsTemplatesResource: + resource_class = UserReportSettingsTemplatesResource + + def get_resource(self, base_absolut_url): + return self.resource_class(requester=APIRequester(base_url=base_absolut_url)) + + @pytest.mark.parametrize( + "incoming_data, path", + ( + ({"userId": 1}, "users/1/reports/settings-templates"), + ( + {"userId": 1, "reportSettingsTemplateId": 1}, + "users/1/reports/settings-templates/1" + ), + ), + ) + def test_get_user_report_settings_templates_path( + self, incoming_data, path, base_absolut_url + ): + resource = self.get_resource(base_absolut_url) + assert resource.get_user_report_settings_templates_path(**incoming_data) == path + + @pytest.mark.parametrize( + "incoming_data, request_params", + ( + ( + {}, + { + "limit": 25, + "offset": 0, + }, + ), + ( + { + "limit": 10, + "offset": 2, + }, + { + "limit": 10, + "offset": 2, + }, + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_list_user_report_settings_template( + self, + m_request, + incoming_data, + request_params, + base_absolut_url + ): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.list_user_report_settings_template(userId=1, **incoming_data) == "response" + m_request.assert_called_once_with( + method="get", + path=resource.get_user_report_settings_templates_path(userId=1), + params=request_params, + ) + + @pytest.mark.parametrize( + "incoming_data, request_data", + ( + ( + { + "name": "test_name", + "currency": Currency.UAH, + "unit": Unit.WORDS, + "config": { + "regularRates": [ + { + "mode": "tm_match", + "value": 0.1 + } + ], + "individualRates": [ + { + "languageIds": ["uk"], + "userIds": [1], + "rates": [ + { + "mode": "tm_match", + "value": 0.1 + } + ] + } + ] + } + }, + { + "name": "test_name", + "currency": Currency.UAH, + "unit": Unit.WORDS, + "mode": "simple", + "config": { + "regularRates": [ + { + "mode": "tm_match", + "value": 0.1 + } + ], + "individualRates": [ + { + "languageIds": ["uk"], + "userIds": [1], + "rates": [ + { + "mode": "tm_match", + "value": 0.1 + } + ] + } + ] + } + }, + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_add_user_report_settings_template( + self, + m_request, + incoming_data, + request_data, + base_absolut_url + ): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.add_user_report_settings_template(userId=1, **incoming_data) == "response" + m_request.assert_called_once_with( + method="post", + path=resource.get_user_report_settings_templates_path(userId=1), + request_data=request_data, + ) + + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_get_user_report_settings_template(self, m_request, base_absolut_url): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.get_user_report_settings_template( + userId=1, + reportSettingsTemplateId=1 + ) == "response" + m_request.assert_called_once_with( + method="get", + path=resource.get_user_report_settings_templates_path( + userId=1, + reportSettingsTemplateId=1 + ), + ) + + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_edit_user_report_settings_template(self, m_request, base_absolut_url): + m_request.return_value = "response" + + data = [ + { + "value": "test", + "op": PatchOperation.REPLACE, + "path": ReportSettingsTemplatesPatchPath.NAME, + } + ] + + resource = self.get_resource(base_absolut_url) + assert resource.edit_user_report_settings_template( + userId=1, + reportSettingsTemplateId=1, + data=data + ) == "response" + m_request.assert_called_once_with( + method="patch", + path=resource.get_user_report_settings_templates_path( + userId=1, + reportSettingsTemplateId=1 + ), + request_data=data, + ) + + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_delete_user_report_settings_template(self, m_request, base_absolut_url): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.delete_user_report_settings_template( + userId=1, + reportSettingsTemplateId=1 + ) == "response" + m_request.assert_called_once_with( + method="delete", + path=resource.get_user_report_settings_templates_path( + userId=1, + reportSettingsTemplateId=1 + ), + ) \ No newline at end of file From 7b347772a52ea147f389c7adef788378da301534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Luna?= Date: Thu, 30 Jan 2025 02:00:34 -0300 Subject: [PATCH 2/2] chore: fix flake8 compliance issues Resolved whitespace and newline inconsistencies to ensure adherence to flake8 coding standards. These corrections improve code maintainability and align with best practices for Python formatting. --- crowdin_api/api_resources/reports/resource.py | 7 ++----- .../api_resources/reports/tests/test_reports_resources.py | 5 ++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/crowdin_api/api_resources/reports/resource.py b/crowdin_api/api_resources/reports/resource.py index 3ff93df..8c9a00c 100644 --- a/crowdin_api/api_resources/reports/resource.py +++ b/crowdin_api/api_resources/reports/resource.py @@ -33,9 +33,6 @@ BaseRates ) -from crowdin_api.api_resources.reports.enums import Currency, Unit -from crowdin_api.api_resources.reports.types import Config, ReportSettingsTemplatesPatchRequest - class BaseReportsResource(BaseResource): def get_reports_path(self, projectId: int, reportId: Optional[str] = None): @@ -1328,12 +1325,12 @@ def generate_organization_translation_costs_post_editing_general_report( }, ) + class UserReportSettingsTemplatesResource(BaseReportSettingsTemplatesResource): """ Resource for User Report Settings Templates API. Supporting the endpoints for managing user report settings templates. - Link to documentation: https://developer.crowdin.com/api/v2/#tag/User-Report-Settings-Templates """ @@ -1451,4 +1448,4 @@ def delete_user_report_settings_template( userId=userId, reportSettingsTemplateId=reportSettingsTemplateId ), - ) \ No newline at end of file + ) diff --git a/crowdin_api/api_resources/reports/tests/test_reports_resources.py b/crowdin_api/api_resources/reports/tests/test_reports_resources.py index d0a31ab..141bd67 100644 --- a/crowdin_api/api_resources/reports/tests/test_reports_resources.py +++ b/crowdin_api/api_resources/reports/tests/test_reports_resources.py @@ -35,8 +35,6 @@ from crowdin_api.requester import APIRequester from crowdin_api.api_resources.reports.resource import UserReportSettingsTemplatesResource -from crowdin_api.api_resources.enums import PatchOperation -from crowdin_api.api_resources.reports.enums import Currency, Unit, ReportSettingsTemplatesPatchPath class TestReportsResource: @@ -2168,6 +2166,7 @@ def test_delete_report_settings_template(self, m_request, base_absolut_url): ) ) + class TestUserReportSettingsTemplatesResource: resource_class = UserReportSettingsTemplatesResource @@ -2365,4 +2364,4 @@ def test_delete_user_report_settings_template(self, m_request, base_absolut_url) userId=1, reportSettingsTemplateId=1 ), - ) \ No newline at end of file + )