diff --git a/crowdin_api/api_resources/source_files/resource.py b/crowdin_api/api_resources/source_files/resource.py index 4ac248a..6e540e1 100644 --- a/crowdin_api/api_resources/source_files/resource.py +++ b/crowdin_api/api_resources/source_files/resource.py @@ -42,6 +42,91 @@ class SourceFilesResource(BaseResource): https://developer.crowdin.com/api/v2/#tag/Source-Files """ + # Organization Search + def search_branches( + self, + filter: str, + projectIds: Optional[Iterable[int]] = None, + userId: Optional[int] = None, + page: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ): + """ + Search Branches. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.branches.getMany + https://developer.crowdin.com/enterprise/api/v2/#operation/api.branches.getMany + """ + + params = { + "filter": filter, + "projectIds": None + if projectIds is None + else ",".join(str(projectId) for projectId in projectIds), + "userId": userId, + } + params.update(self.get_page_params(page=page, offset=offset, limit=limit)) + + return self._get_entire_data(method="get", path="branches", params=params) + + def search_directories( + self, + filter: str, + projectIds: Optional[Iterable[int]] = None, + userId: Optional[int] = None, + page: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ): + """ + Search Directories. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.directories.getMany + https://developer.crowdin.com/enterprise/api/v2/#operation/api.directories.getMany + """ + + params = { + "filter": filter, + "projectIds": None + if projectIds is None + else ",".join(str(projectId) for projectId in projectIds), + "userId": userId, + } + params.update(self.get_page_params(page=page, offset=offset, limit=limit)) + + return self._get_entire_data(method="get", path="directories", params=params) + + def search_files( + self, + filter: str, + projectIds: Optional[Iterable[int]] = None, + userId: Optional[int] = None, + page: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ): + """ + Search Files. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.files.getMany + https://developer.crowdin.com/enterprise/api/v2/#operation/api.files.getMany + """ + + params = { + "filter": filter, + "projectIds": None + if projectIds is None + else ",".join(str(projectId) for projectId in projectIds), + "userId": userId, + } + params.update(self.get_page_params(page=page, offset=offset, limit=limit)) + + return self._get_entire_data(method="get", path="files", params=params) + # Branches def get_branch_path(self, projectId: int, branchId: Optional[int] = None): if branchId is not None: diff --git a/crowdin_api/api_resources/source_files/tests/test_source_files_resources.py b/crowdin_api/api_resources/source_files/tests/test_source_files_resources.py index 24ec85b..434bb66 100644 --- a/crowdin_api/api_resources/source_files/tests/test_source_files_resources.py +++ b/crowdin_api/api_resources/source_files/tests/test_source_files_resources.py @@ -31,6 +31,58 @@ def test_resource_with_id(self, base_absolut_url): ) assert resource.get_project_id() == project_id + @pytest.mark.parametrize( + "method, path", + ( + ("search_branches", "branches"), + ("search_directories", "directories"), + ("search_files", "files"), + ), + ) + @pytest.mark.parametrize( + "incoming_data, request_params", + ( + ( + {"offset": 0, "limit": 10}, + { + "filter": "filter", + "projectIds": None, + "userId": None, + "offset": 0, + "limit": 10, + }, + ), + ( + { + "projectIds": [1, 2], + "userId": 3, + "offset": 5, + "limit": 10, + }, + { + "filter": "filter", + "projectIds": "1,2", + "userId": 3, + "offset": 5, + "limit": 10, + }, + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_search_organization_source_files( + self, m_request, incoming_data, request_params, method, path, base_absolut_url + ): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert getattr(resource, method)(filter="filter", **incoming_data) == "response" + m_request.assert_called_once_with( + method="get", + params=request_params, + path=path, + ) + # Branches @pytest.mark.parametrize( "in_params, path", diff --git a/crowdin_api/api_resources/source_strings/enums.py b/crowdin_api/api_resources/source_strings/enums.py index a4f851f..56ad66d 100644 --- a/crowdin_api/api_resources/source_strings/enums.py +++ b/crowdin_api/api_resources/source_strings/enums.py @@ -2,9 +2,11 @@ class ScopeFilter(Enum): + ALL = "all" IDENTIFIER = "identifier" TEXT = "text" CONTEXT = "context" + KEY = "key" class SourceStringsPatchPath(Enum): diff --git a/crowdin_api/api_resources/source_strings/resource.py b/crowdin_api/api_resources/source_strings/resource.py index c624f9f..6e6bfb8 100644 --- a/crowdin_api/api_resources/source_strings/resource.py +++ b/crowdin_api/api_resources/source_strings/resource.py @@ -25,6 +25,38 @@ class SourceStringsResource(BaseResource): https://developer.crowdin.com/api/v2/#tag/Source-Strings """ + def search_strings( + self, + filter: str, + projectIds: Optional[Iterable[int]] = None, + userId: Optional[int] = None, + scope: Optional[ScopeFilter] = None, + denormalizePlaceholders: Optional[DenormalizePlaceholders] = None, + page: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ): + """ + Search Strings. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.strings.getMany + https://developer.crowdin.com/enterprise/api/v2/#operation/api.strings.getMany + """ + + params = { + "filter": filter, + "projectIds": None + if projectIds is None + else ",".join(str(projectId) for projectId in projectIds), + "userId": userId, + "scope": scope, + "denormalizePlaceholders": denormalizePlaceholders, + } + params.update(self.get_page_params(page=page, offset=offset, limit=limit)) + + return self._get_entire_data(method="get", path="strings", params=params) + def get_source_strings_path(self, projectId: int, stringId: Optional[int] = None): if stringId is not None: return f"projects/{projectId}/strings/{stringId}" diff --git a/crowdin_api/api_resources/source_strings/tests/test_source_strings_resources.py b/crowdin_api/api_resources/source_strings/tests/test_source_strings_resources.py index 6fcb768..8deafaf 100644 --- a/crowdin_api/api_resources/source_strings/tests/test_source_strings_resources.py +++ b/crowdin_api/api_resources/source_strings/tests/test_source_strings_resources.py @@ -27,6 +27,54 @@ def test_resource_with_id(self, base_absolut_url): ) assert resource.get_project_id() == project_id + @pytest.mark.parametrize( + "incoming_data, request_params", + ( + ( + {}, + { + "filter": "filter", + "projectIds": None, + "userId": None, + "scope": None, + "denormalizePlaceholders": None, + "offset": 0, + "limit": 25, + }, + ), + ( + { + "projectIds": [1, 2], + "userId": 3, + "scope": ScopeFilter.KEY, + "denormalizePlaceholders": DenormalizePlaceholders.ENABLE, + "offset": 5, + "limit": 10, + }, + { + "filter": "filter", + "projectIds": "1,2", + "userId": 3, + "scope": ScopeFilter.KEY, + "denormalizePlaceholders": DenormalizePlaceholders.ENABLE, + "offset": 5, + "limit": 10, + }, + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_search_strings(self, m_request, incoming_data, request_params, base_absolut_url): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.search_strings(filter="filter", **incoming_data) == "response" + m_request.assert_called_once_with( + method="get", + params=request_params, + path="strings", + ) + @pytest.mark.parametrize( "in_params, path", ( diff --git a/crowdin_api/api_resources/string_translations/resource.py b/crowdin_api/api_resources/string_translations/resource.py index 2711b8a..fbeef0c 100644 --- a/crowdin_api/api_resources/string_translations/resource.py +++ b/crowdin_api/api_resources/string_translations/resource.py @@ -20,6 +20,40 @@ class StringTranslationsResource(BaseResource): https://developer.crowdin.com/api/v2/#tag/String-Translations """ + def search_translations( + self, + filter: str, + projectIds: Optional[Iterable[int]] = None, + userId: Optional[int] = None, + languageIds: Optional[Iterable[str]] = None, + denormalizePlaceholders: Optional[DenormalizePlaceholders] = None, + page: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + ): + """ + Search Translations. + + Link to documentation: + https://developer.crowdin.com/api/v2/#operation/api.translations.getMany + https://developer.crowdin.com/enterprise/api/v2/#operation/api.translations.getMany + """ + + params = { + "filter": filter, + "projectIds": None + if projectIds is None + else ",".join(str(projectId) for projectId in projectIds), + "userId": userId, + "languageIds": None + if languageIds is None + else ",".join(str(languageId) for languageId in languageIds), + "denormalizePlaceholders": denormalizePlaceholders, + } + params.update(self.get_page_params(page=page, offset=offset, limit=limit)) + + return self._get_entire_data(method="get", path="translations", params=params) + # Approval def get_approvals_path(self, projectId: int, approvalId: Optional[int] = None): if approvalId is not None: diff --git a/crowdin_api/api_resources/string_translations/tests/test_string_translations_resources.py b/crowdin_api/api_resources/string_translations/tests/test_string_translations_resources.py index cdbf9e3..d4cd36e 100644 --- a/crowdin_api/api_resources/string_translations/tests/test_string_translations_resources.py +++ b/crowdin_api/api_resources/string_translations/tests/test_string_translations_resources.py @@ -26,6 +26,56 @@ def test_resource_with_id(self, base_absolut_url): ) assert resource.get_project_id() == project_id + @pytest.mark.parametrize( + "incoming_data, request_params", + ( + ( + {}, + { + "filter": "filter", + "projectIds": None, + "userId": None, + "languageIds": None, + "denormalizePlaceholders": None, + "offset": 0, + "limit": 25, + }, + ), + ( + { + "projectIds": [1, 2], + "userId": 3, + "languageIds": ["uk", "de"], + "denormalizePlaceholders": DenormalizePlaceholders.ENABLE, + "offset": 5, + "limit": 10, + }, + { + "filter": "filter", + "projectIds": "1,2", + "userId": 3, + "languageIds": "uk,de", + "denormalizePlaceholders": DenormalizePlaceholders.ENABLE, + "offset": 5, + "limit": 10, + }, + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_search_translations( + self, m_request, incoming_data, request_params, base_absolut_url + ): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.search_translations(filter="filter", **incoming_data) == "response" + m_request.assert_called_once_with( + method="get", + params=request_params, + path="translations", + ) + # Approval @pytest.mark.parametrize( "in_params, path",