Skip to content

Commit 6b60cbf

Browse files
authored
feat(application): Implemented Installation API (#142)
1 parent b4075ab commit 6b60cbf

File tree

4 files changed

+263
-3
lines changed

4 files changed

+263
-3
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from enum import Enum
2+
3+
4+
class UserPermissions(Enum):
5+
OWNER = "owner"
6+
MANAGERS = "managers"
7+
ALL = "all"
8+
GUESTS = "guests"
9+
RESTRICTED = "restricted"
10+
11+
12+
class ProjectPermissions(Enum):
13+
OWN = "own"
14+
RESTRICTED = "restricted"

crowdin_api/api_resources/application/resource.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
from typing import Optional, Iterable
12
from crowdin_api.parser import dumps
2-
3+
from crowdin_api.api_resources.application.types import (
4+
ApplicationPermissions,
5+
ApplicationInstallationPatchRequest,
6+
)
37
from crowdin_api.api_resources.abstract.resources import BaseResource
48

59

@@ -19,6 +23,85 @@ class ApplicationResource(BaseResource):
1923
def get_application_path(self, applicationIdentifier: str, path: str):
2024
return f"applications/{applicationIdentifier}/api/{path}"
2125

26+
def get_application_installations_path(self, identifier: Optional[str] = None):
27+
if identifier:
28+
return f"applications/installations/{identifier}"
29+
return "applications/installations"
30+
31+
def list_application_installations(
32+
self,
33+
offset: Optional[int] = None,
34+
limit: Optional[int] = None,
35+
):
36+
"""
37+
List Application Installations
38+
39+
Link to documentaion:
40+
https://developer.crowdin.com/api/v2/#operation/api.applications.installations.getMany
41+
"""
42+
return self.requester.request(
43+
method="get",
44+
path=self.get_application_installations_path(),
45+
params=self.get_page_params(offset=offset, limit=limit),
46+
)
47+
48+
def install_application(
49+
self, url: str, permissions: Optional[ApplicationPermissions] = None
50+
):
51+
"""
52+
Install Application
53+
54+
Link to documentation:
55+
https://developer.crowdin.com/api/v2/#operation/api.applications.installations.post
56+
"""
57+
request_data = {"url": url, "permissions": permissions}
58+
return self.requester.request(
59+
method="post",
60+
path=self.get_application_installations_path(),
61+
request_data=request_data,
62+
)
63+
64+
def get_application_installation(self, identifier: str):
65+
"""
66+
Get Application Installation
67+
68+
Link to documentation:
69+
https://developer.crowdin.com/api/v2/#operation/api.applications.installations.get
70+
"""
71+
return self.requester.request(
72+
method="get",
73+
path=self.get_application_installations_path(identifier=identifier),
74+
)
75+
76+
def delete_application_installation(
77+
self, identifier: str, force: Optional[bool] = None
78+
):
79+
"""
80+
Delete Applcation Installation
81+
82+
Link to documentation:
83+
https://developer.crowdin.com/api/v2/#operation/api.applications.installations.delete
84+
"""
85+
params = {"force": force}
86+
87+
return self.requester.request(
88+
method="delete",
89+
path=self.get_application_installations_path(identifier=identifier),
90+
params=params,
91+
)
92+
93+
def edit_applicatoin_installation(
94+
self, identifier: str, data: Iterable[ApplicationInstallationPatchRequest]
95+
):
96+
"""
97+
Edit Application Installation
98+
"""
99+
return self.requester.request(
100+
method="patch",
101+
path=self.get_application_installations_path(identifier=identifier),
102+
request_data=data,
103+
)
104+
22105
def get_application_data(self, applicationIdentifier: str, path: str):
23106
"""
24107
Get Application Data.

crowdin_api/api_resources/application/tests/test_applications_resources.py

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from unittest import mock
2-
3-
42
import pytest
53
from crowdin_api.api_resources.application.resource import ApplicationResource
4+
from crowdin_api.api_resources.application.enums import (
5+
UserPermissions,
6+
ProjectPermissions,
7+
)
68
from crowdin_api.requester import APIRequester
79

810

@@ -22,6 +24,140 @@ def test_get_applications_path(self, in_params, path, base_absolut_url):
2224
resource = self.get_resource(base_absolut_url)
2325
assert resource.get_application_path(**in_params) == path
2426

27+
@pytest.mark.parametrize(
28+
"in_params, path",
29+
(
30+
(None, "applications/installations"),
31+
("test", "applications/installations/test"),
32+
),
33+
)
34+
def test_get_application_installation_path(self, in_params, path, base_absolut_url):
35+
resource = self.get_resource(base_absolut_url)
36+
assert resource.get_application_installations_path(in_params) == path
37+
38+
@mock.patch("crowdin_api.requester.APIRequester.request")
39+
def test_list_application_installations(self, m_request, base_absolut_url):
40+
m_request.return_value = "response"
41+
42+
resource = self.get_resource(base_absolut_url)
43+
assert resource.list_application_installations() == "response"
44+
m_request.assert_called_once_with(
45+
method="get",
46+
path=resource.get_application_installations_path(),
47+
params=resource.get_page_params()
48+
)
49+
50+
@pytest.mark.parametrize(
51+
"in_params, request_data",
52+
(
53+
(
54+
{
55+
"url": "https://localhost.dev/crowdin.json",
56+
},
57+
{
58+
"url": "https://localhost.dev/crowdin.json",
59+
"permissions": None
60+
}
61+
),
62+
(
63+
{
64+
"url": "https://localhost.dev/crowdin.json",
65+
"permissions": {
66+
"user": {
67+
"value": UserPermissions.OWNER,
68+
"ids": [1, 2, 3]
69+
},
70+
"project": {
71+
"value": ProjectPermissions.OWN,
72+
"ids": [4, 5, 6]
73+
}
74+
}
75+
},
76+
{
77+
"url": "https://localhost.dev/crowdin.json",
78+
"permissions": {
79+
"user": {
80+
"value": UserPermissions.OWNER,
81+
"ids": [1, 2, 3]
82+
},
83+
"project": {
84+
"value": ProjectPermissions.OWN,
85+
"ids": [4, 5, 6]
86+
}
87+
}
88+
}
89+
),
90+
),
91+
)
92+
@mock.patch("crowdin_api.requester.APIRequester.request")
93+
def test_install_application(self, m_request, in_params, request_data, base_absolut_url):
94+
m_request.return_value = "response"
95+
96+
resource = self.get_resource(base_absolut_url)
97+
assert resource.install_application(**in_params) == "response"
98+
m_request.assert_called_once_with(
99+
method="post",
100+
path=resource.get_application_installations_path(),
101+
request_data=request_data
102+
)
103+
104+
@mock.patch("crowdin_api.requester.APIRequester.request")
105+
def test_get_applcation_installation(self, m_request, base_absolut_url):
106+
m_request.return_value = "response"
107+
108+
identifier = "example-application"
109+
resource = self.get_resource(base_absolut_url)
110+
assert resource.get_application_installation(identifier) == "response"
111+
m_request.assert_called_once_with(
112+
method="get",
113+
path=resource.get_application_installations_path(identifier),
114+
)
115+
116+
@pytest.mark.parametrize(
117+
"in_params, request_param",
118+
(
119+
({}, {"force": None}),
120+
({"force": True}, {"force": True}),
121+
),
122+
)
123+
@mock.patch("crowdin_api.requester.APIRequester.request")
124+
def test_delete_application_installation(
125+
self, m_request, in_params, request_param, base_absolut_url
126+
):
127+
m_request.return_value = "response"
128+
129+
resource = self.get_resource(base_absolut_url)
130+
assert (
131+
resource.delete_application_installation(
132+
identifier="example-app", **in_params
133+
)
134+
== "response"
135+
)
136+
m_request.assert_called_once_with(
137+
method="delete",
138+
path=resource.get_application_installations_path(identifier="example-app"),
139+
params=request_param
140+
)
141+
142+
@mock.patch("crowdin_api.requester.APIRequester.request")
143+
def test_edit_application_installation(
144+
self, m_request, base_absolut_url
145+
):
146+
m_request.return_value = "response"
147+
148+
identifier = "exmaple-application"
149+
data = [{"op": "replace", "path": "/permissions", "value": "test"}]
150+
resource = self.get_resource(base_absolut_url)
151+
assert resource.edit_applicatoin_installation(
152+
identifier=identifier,
153+
data=data,
154+
)
155+
m_request.assert_called_once_with(
156+
method="patch",
157+
path=resource.get_application_installations_path(identifier=identifier),
158+
request_data=data,
159+
)
160+
25161
@mock.patch("crowdin_api.requester.APIRequester.request")
26162
def test_get_application_data(self, m_request, base_absolut_url):
27163
m_request.return_value = "response"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from typing import Iterable
2+
from crowdin_api.typing import TypedDict
3+
from crowdin_api.api_resources.application.enums import (
4+
UserPermissions,
5+
ProjectPermissions,
6+
)
7+
8+
9+
class ApplicationUser(TypedDict):
10+
value: UserPermissions
11+
ids: Iterable[int]
12+
13+
14+
class ApplicationProject(TypedDict):
15+
value: ProjectPermissions
16+
ids: Iterable[int]
17+
18+
19+
class ApplicationPermissions(TypedDict):
20+
user: ApplicationUser
21+
project: ApplicationProject
22+
23+
24+
class ApplicationInstallationPatchRequest(TypedDict):
25+
op: str
26+
path: str
27+
value: str

0 commit comments

Comments
 (0)