castor-extractor 0.23.3__py3-none-any.whl → 0.24.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of castor-extractor might be problematic. Click here for more details.
- CHANGELOG.md +8 -0
- README.md +2 -0
- castor_extractor/commands/extract_looker_studio.py +30 -0
- castor_extractor/knowledge/confluence/client/client.py +0 -13
- castor_extractor/knowledge/confluence/client/endpoints.py +1 -1
- castor_extractor/visualization/looker_studio/__init__.py +1 -0
- castor_extractor/visualization/looker_studio/assets.py +1 -0
- castor_extractor/visualization/looker_studio/client/client.py +56 -6
- castor_extractor/visualization/looker_studio/client/credentials.py +5 -0
- castor_extractor/visualization/looker_studio/client/queries/query.sql +52 -0
- castor_extractor/visualization/looker_studio/extract.py +84 -0
- {castor_extractor-0.23.3.dist-info → castor_extractor-0.24.1.dist-info}/METADATA +11 -1
- {castor_extractor-0.23.3.dist-info → castor_extractor-0.24.1.dist-info}/RECORD +16 -48
- {castor_extractor-0.23.3.dist-info → castor_extractor-0.24.1.dist-info}/entry_points.txt +1 -0
- castor_extractor/visualization/tableau/__init__.py +0 -3
- castor_extractor/visualization/tableau/assets.py +0 -49
- castor_extractor/visualization/tableau/client/__init__.py +0 -2
- castor_extractor/visualization/tableau/client/client.py +0 -229
- castor_extractor/visualization/tableau/client/client_utils.py +0 -75
- castor_extractor/visualization/tableau/client/credentials.py +0 -104
- castor_extractor/visualization/tableau/client/project.py +0 -28
- castor_extractor/visualization/tableau/client/safe_mode.py +0 -70
- castor_extractor/visualization/tableau/constants.py +0 -9
- castor_extractor/visualization/tableau/errors.py +0 -5
- castor_extractor/visualization/tableau/extract.py +0 -121
- castor_extractor/visualization/tableau/gql_fields.py +0 -249
- castor_extractor/visualization/tableau/tests/__init__.py +0 -0
- castor_extractor/visualization/tableau/tests/unit/__init__.py +0 -0
- castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_1_get.json +0 -15
- castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_2_get.json +0 -15
- castor_extractor/visualization/tableau/tests/unit/assets/rest_api/auth.xml +0 -7
- castor_extractor/visualization/tableau/tests/unit/assets/rest_api/project_get.xml +0 -9
- castor_extractor/visualization/tableau/tests/unit/assets/rest_api/user_get.xml +0 -8
- castor_extractor/visualization/tableau/tests/unit/assets/rest_api/view_get_usage.xml +0 -24
- castor_extractor/visualization/tableau/tests/unit/assets/rest_api/workbook_get.xml +0 -19
- castor_extractor/visualization/tableau/tests/unit/graphql/__init__.py +0 -0
- castor_extractor/visualization/tableau/tests/unit/graphql/paginated_object_test.py +0 -63
- castor_extractor/visualization/tableau/tests/unit/rest_api/__init__.py +0 -0
- castor_extractor/visualization/tableau/tests/unit/rest_api/auth_test.py +0 -39
- castor_extractor/visualization/tableau/tests/unit/rest_api/credentials_test.py +0 -13
- castor_extractor/visualization/tableau/tests/unit/rest_api/projects_test.py +0 -59
- castor_extractor/visualization/tableau/tests/unit/rest_api/usages_test.py +0 -49
- castor_extractor/visualization/tableau/tests/unit/rest_api/users_test.py +0 -52
- castor_extractor/visualization/tableau/tests/unit/rest_api/workbooks_test.py +0 -60
- castor_extractor/visualization/tableau/tests/unit/utils/__init__.py +0 -1
- castor_extractor/visualization/tableau/tests/unit/utils/env_key.py +0 -6
- castor_extractor/visualization/tableau/tsc_fields.py +0 -46
- castor_extractor/visualization/tableau/types.py +0 -11
- castor_extractor/visualization/tableau/usage.py +0 -14
- {castor_extractor-0.23.3.dist-info → castor_extractor-0.24.1.dist-info}/LICENCE +0 -0
- {castor_extractor-0.23.3.dist-info → castor_extractor-0.24.1.dist-info}/WHEEL +0 -0
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# Fields which will be use for Tableau GraphQL API
|
|
2
|
-
from enum import Enum
|
|
3
|
-
from typing import Union
|
|
4
|
-
|
|
5
|
-
from .assets import TableauAsset, TableauGraphqlAsset
|
|
6
|
-
|
|
7
|
-
FIELDS = "fields"
|
|
8
|
-
OBJECT_TYPE = "object_type"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class GQLQueryFields(Enum):
|
|
12
|
-
BIN_FIELDS: str = """
|
|
13
|
-
datasource {
|
|
14
|
-
... on PublishedDatasource {
|
|
15
|
-
name
|
|
16
|
-
luid
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
dataType
|
|
20
|
-
description
|
|
21
|
-
fields {
|
|
22
|
-
id
|
|
23
|
-
}
|
|
24
|
-
folderName
|
|
25
|
-
id
|
|
26
|
-
name
|
|
27
|
-
role
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
CALCULATED_FIELDS: str = """
|
|
31
|
-
datasource {
|
|
32
|
-
... on PublishedDatasource {
|
|
33
|
-
name
|
|
34
|
-
luid
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
fields {
|
|
38
|
-
id
|
|
39
|
-
}
|
|
40
|
-
dataType
|
|
41
|
-
description
|
|
42
|
-
folderName
|
|
43
|
-
id
|
|
44
|
-
name
|
|
45
|
-
role
|
|
46
|
-
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
COLUMN_FIELDS: str = """
|
|
50
|
-
columns {
|
|
51
|
-
id
|
|
52
|
-
name
|
|
53
|
-
table {
|
|
54
|
-
... on DatabaseTable {
|
|
55
|
-
id
|
|
56
|
-
description
|
|
57
|
-
name
|
|
58
|
-
fullName
|
|
59
|
-
schema
|
|
60
|
-
database {
|
|
61
|
-
name
|
|
62
|
-
luid
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
datasource {
|
|
69
|
-
... on PublishedDatasource {
|
|
70
|
-
name
|
|
71
|
-
luid
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
dataType
|
|
75
|
-
description
|
|
76
|
-
folderName
|
|
77
|
-
id
|
|
78
|
-
name
|
|
79
|
-
role
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
CUSTOM_SQL_TABLE: str = """
|
|
83
|
-
id
|
|
84
|
-
name
|
|
85
|
-
columns {
|
|
86
|
-
referencedByFields {
|
|
87
|
-
datasource {
|
|
88
|
-
... on PublishedDatasource {
|
|
89
|
-
luid
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
... on EmbeddedDatasource {
|
|
93
|
-
id
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
"""
|
|
99
|
-
|
|
100
|
-
CUSTOM_SQL_QUERY: str = """
|
|
101
|
-
id
|
|
102
|
-
name
|
|
103
|
-
query
|
|
104
|
-
database {
|
|
105
|
-
name
|
|
106
|
-
connectionType
|
|
107
|
-
}
|
|
108
|
-
tables {
|
|
109
|
-
name
|
|
110
|
-
}
|
|
111
|
-
"""
|
|
112
|
-
|
|
113
|
-
DASHBOARDS: str = """
|
|
114
|
-
id
|
|
115
|
-
name
|
|
116
|
-
path
|
|
117
|
-
tags {
|
|
118
|
-
name
|
|
119
|
-
}
|
|
120
|
-
workbook {
|
|
121
|
-
luid # to retrieve the parent
|
|
122
|
-
}
|
|
123
|
-
"""
|
|
124
|
-
|
|
125
|
-
DATASOURCE: str = """
|
|
126
|
-
... on PublishedDatasource {
|
|
127
|
-
luid
|
|
128
|
-
}
|
|
129
|
-
id
|
|
130
|
-
name
|
|
131
|
-
hasExtracts
|
|
132
|
-
upstreamTables {
|
|
133
|
-
id
|
|
134
|
-
schema
|
|
135
|
-
name
|
|
136
|
-
fullName
|
|
137
|
-
database {
|
|
138
|
-
id
|
|
139
|
-
name
|
|
140
|
-
connectionType
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
"""
|
|
144
|
-
|
|
145
|
-
GROUP_FIELDS: str = """
|
|
146
|
-
datasource {
|
|
147
|
-
... on PublishedDatasource {
|
|
148
|
-
name
|
|
149
|
-
luid
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
dataType
|
|
153
|
-
description
|
|
154
|
-
fields {
|
|
155
|
-
id
|
|
156
|
-
}
|
|
157
|
-
folderName
|
|
158
|
-
id
|
|
159
|
-
name
|
|
160
|
-
role
|
|
161
|
-
"""
|
|
162
|
-
|
|
163
|
-
SHEET: str = """
|
|
164
|
-
containedInDashboards {
|
|
165
|
-
id
|
|
166
|
-
}
|
|
167
|
-
id
|
|
168
|
-
index
|
|
169
|
-
name
|
|
170
|
-
upstreamFields{
|
|
171
|
-
name
|
|
172
|
-
}
|
|
173
|
-
workbook {
|
|
174
|
-
luid
|
|
175
|
-
}
|
|
176
|
-
"""
|
|
177
|
-
|
|
178
|
-
WORKBOOK_TO_DATASOURCE: str = """
|
|
179
|
-
luid
|
|
180
|
-
id
|
|
181
|
-
embeddedDatasources {
|
|
182
|
-
id
|
|
183
|
-
name
|
|
184
|
-
}
|
|
185
|
-
upstreamDatasources {
|
|
186
|
-
luid
|
|
187
|
-
name
|
|
188
|
-
}
|
|
189
|
-
"""
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
QueryInfo = list[dict[str, Union[GQLQueryFields, TableauGraphqlAsset]]]
|
|
193
|
-
|
|
194
|
-
QUERY_FIELDS: dict[TableauAsset, QueryInfo] = {
|
|
195
|
-
TableauAsset.CUSTOM_SQL_TABLE: [
|
|
196
|
-
{
|
|
197
|
-
FIELDS: GQLQueryFields.CUSTOM_SQL_TABLE,
|
|
198
|
-
OBJECT_TYPE: TableauGraphqlAsset.CUSTOM_SQL,
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
TableauAsset.CUSTOM_SQL_QUERY: [
|
|
202
|
-
{
|
|
203
|
-
FIELDS: GQLQueryFields.CUSTOM_SQL_QUERY,
|
|
204
|
-
OBJECT_TYPE: TableauGraphqlAsset.CUSTOM_SQL,
|
|
205
|
-
},
|
|
206
|
-
],
|
|
207
|
-
TableauAsset.DASHBOARD: [
|
|
208
|
-
{
|
|
209
|
-
FIELDS: GQLQueryFields.DASHBOARDS,
|
|
210
|
-
OBJECT_TYPE: TableauGraphqlAsset.DASHBOARD,
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
TableauAsset.DATASOURCE: [
|
|
214
|
-
{
|
|
215
|
-
FIELDS: GQLQueryFields.DATASOURCE,
|
|
216
|
-
OBJECT_TYPE: TableauGraphqlAsset.DATASOURCE,
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
TableauAsset.FIELD: [
|
|
220
|
-
{
|
|
221
|
-
FIELDS: GQLQueryFields.BIN_FIELDS,
|
|
222
|
-
OBJECT_TYPE: TableauGraphqlAsset.BIN_FIELD,
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
FIELDS: GQLQueryFields.CALCULATED_FIELDS,
|
|
226
|
-
OBJECT_TYPE: TableauGraphqlAsset.CALCULATED_FIELD,
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
FIELDS: GQLQueryFields.COLUMN_FIELDS,
|
|
230
|
-
OBJECT_TYPE: TableauGraphqlAsset.COLUMN_FIELD,
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
FIELDS: GQLQueryFields.GROUP_FIELDS,
|
|
234
|
-
OBJECT_TYPE: TableauGraphqlAsset.GROUP_FIELD,
|
|
235
|
-
},
|
|
236
|
-
],
|
|
237
|
-
TableauAsset.SHEET: [
|
|
238
|
-
{
|
|
239
|
-
FIELDS: GQLQueryFields.SHEET,
|
|
240
|
-
OBJECT_TYPE: TableauGraphqlAsset.SHEETS,
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
TableauAsset.WORKBOOK_TO_DATASOURCE: [
|
|
244
|
-
{
|
|
245
|
-
FIELDS: GQLQueryFields.WORKBOOK_TO_DATASOURCE,
|
|
246
|
-
OBJECT_TYPE: TableauGraphqlAsset.WORKBOOK_TO_DATASOURCE,
|
|
247
|
-
},
|
|
248
|
-
],
|
|
249
|
-
}
|
|
File without changes
|
|
File without changes
|
castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_1_get.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"data": {
|
|
3
|
-
"datasourcesConnection": {
|
|
4
|
-
"pageInfo": {
|
|
5
|
-
"hasNextPage": true,
|
|
6
|
-
"endCursor": "eyJ0eXBlIjoiUHVibGlzaGVkRGF0YXNvdXJjZSIsInNjb3BlIjoic2l0ZXMvMSIsInNvcnRPcmRlclZhbHVlIjp7Imxhc3RJZCI6IjAwMzllNWQ1LTI1ZmEtMTk2Yi1jNjZlLWMwNjc1ODM5ZTBiMCJ9fQ=="
|
|
7
|
-
},
|
|
8
|
-
"nodes": [
|
|
9
|
-
{
|
|
10
|
-
"id": "0039e5d5-25fa-196b-c66e-c0675839e0b0"
|
|
11
|
-
}
|
|
12
|
-
]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
castor_extractor/visualization/tableau/tests/unit/assets/graphql/metadata/metadata_2_get.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"data": {
|
|
3
|
-
"datasourcesConnection": {
|
|
4
|
-
"pageInfo": {
|
|
5
|
-
"hasNextPage": false,
|
|
6
|
-
"endCursor": "eyJ0eXBlIjoiUHVibGlzaGVkRGF0YXNvdXJjZSIsInNjb3BlIjoic2l0ZXMvMSIsInNvcnRPcmRlclZhbHVlIjp7Imxhc3RJZCI6IjAwYjE5MWNlLTYwNTUtYWZmNS1lMjc1LWMyNjYxMGM4YzRkNiJ9fQ=="
|
|
7
|
-
},
|
|
8
|
-
"nodes": [
|
|
9
|
-
{
|
|
10
|
-
"id": "00b191ce-6055-aff5-e275-c26610c8c4d6"
|
|
11
|
-
}
|
|
12
|
-
]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
-
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
|
|
3
|
-
<credentials token="eIX6mvFsqyansa4KqEI1UwOpS8ggRs2l">
|
|
4
|
-
<site id="6b7179ba-b82b-4f0f-91ed-812074ac5da6" contentUrl="Samples" />
|
|
5
|
-
<user id="1a96d216-e9b8-497b-a82a-0b899a965e01" />
|
|
6
|
-
</credentials>
|
|
7
|
-
</tsResponse>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
-
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
|
|
3
|
-
<pagination pageNumber="1" pageSize="100" totalAvailable="3" />
|
|
4
|
-
<projects>
|
|
5
|
-
<project id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" name="default" description="The default project that was automatically created by Tableau." contentPermissions="ManagedByOwner"><owner id="dd2239f6-ddf1-4107-981a-4cf94e415794" /></project>
|
|
6
|
-
<project id="1d0304cd-3796-429f-b815-7258370b9b74" name="Tableau" description="" contentPermissions="ManagedByOwner"><owner id="2a47bbf8-8900-4ebb-b0a4-2723bd7c46c3" /></project>
|
|
7
|
-
<project id="4cc52973-5e3a-4d1f-a4fb-5b5f73796edf" name="Tableau/Child_1" description="" contentPermissions="ManagedByOwner" parentProjectId="1d0304cd-3796-429f-b815-7258370b9b74"><owner id="dd2239f6-ddf1-4107-981a-4cf94e415794" /></project>
|
|
8
|
-
</projects>
|
|
9
|
-
</tsResponse>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
-
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
|
|
3
|
-
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
|
|
4
|
-
<users>
|
|
5
|
-
<user id="dd2239f6-ddf1-4107-981a-4cf94e415794" name="alice" siteRole="Publisher" lastLogin="2016-08-16T23:17:06Z" externalAuthUserId="" fullName="alice cook" email="alicecook@test.com" />
|
|
6
|
-
<user id="2a47bbf8-8900-4ebb-b0a4-2723bd7c46c3" name="Bob" siteRole="Interactor" externalAuthUserId="" fullName="Bob Smith" email="bob@test.com" />
|
|
7
|
-
</users>
|
|
8
|
-
</tsResponse>
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
-
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
|
|
3
|
-
<pagination pageNumber="1" pageSize="100" totalAvailable="3" />
|
|
4
|
-
<views>
|
|
5
|
-
<view id="d79634e1-6063-4ec9-95ff-50acbf609ff5" name="ENDANGERED SAFARI" contentUrl="SafariSample/sheets/ENDANGEREDSAFARI">
|
|
6
|
-
<workbook id="3cc6cd06-89ce-4fdc-b935-5294135d6d42" />
|
|
7
|
-
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
|
|
8
|
-
<tags />
|
|
9
|
-
<usage totalViewCount="7" />
|
|
10
|
-
</view>
|
|
11
|
-
<view id="f79634e1-6063-4ec9-95ff-50acbf609ff5" name="ENDANGERED SAFARI" contentUrl="SafariSample/sheets/ENDANGEREDSAFARI">
|
|
12
|
-
<workbook id="3cc6cd06-89ce-4fdc-b935-5294135d6d42" />
|
|
13
|
-
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
|
|
14
|
-
<tags />
|
|
15
|
-
<usage totalViewCount="4" />
|
|
16
|
-
</view>
|
|
17
|
-
<view id="fd252f73-593c-4c4e-8584-c032b8022adc" name="Overview" contentUrl="Superstore/sheets/Overview" createdAt="2002-05-30T09:00:00Z" updatedAt="2002-06-05T08:00:59Z" sheetType="story">
|
|
18
|
-
<workbook id="6d13b0ca-043d-4d42-8c9d-3f3313ea3a00" />
|
|
19
|
-
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
|
|
20
|
-
<tags />
|
|
21
|
-
<usage totalViewCount="13" />
|
|
22
|
-
</view>
|
|
23
|
-
</views>
|
|
24
|
-
</tsResponse>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<?xml version='1.0' encoding='UTF-8'?>
|
|
2
|
-
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
|
|
3
|
-
<pagination pageNumber="1" pageSize="100" totalAvailable="2" />
|
|
4
|
-
<workbooks>
|
|
5
|
-
<workbook id="6d13b0ca-043d-4d42-8c9d-3f3313ea3a00" name="Superstore" description="description for Superstore" contentUrl="Superstore" webpageUrl="http://tableauserver/#/workbooks/1/views" showTabs="false" size="1" createdAt="1" updatedAt="1">
|
|
6
|
-
<project id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" name="default" />
|
|
7
|
-
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
|
|
8
|
-
<tags />
|
|
9
|
-
</workbook>
|
|
10
|
-
<workbook id="3cc6cd06-89ce-4fdc-b935-5294135d6d42" name="SafariSample" description="description for SafariSample" contentUrl="SafariSample" webpageUrl="http://tableauserver/#/workbooks/2/views" showTabs="false" size="26" createdAt="1" updatedAt="1">
|
|
11
|
-
<project id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760" name="default" />
|
|
12
|
-
<owner id="5de011f8-5aa9-4d5b-b991-f462c8dd6bb7" />
|
|
13
|
-
<tags>
|
|
14
|
-
<tag label="Safari" />
|
|
15
|
-
<tag label="Sample" />
|
|
16
|
-
</tags>
|
|
17
|
-
</workbook>
|
|
18
|
-
</workbooks>
|
|
19
|
-
</tsResponse>
|
|
File without changes
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import unittest
|
|
3
|
-
from unittest import mock
|
|
4
|
-
|
|
5
|
-
import requests_mock # type: ignore
|
|
6
|
-
import tableauserverclient as TSC # type: ignore
|
|
7
|
-
|
|
8
|
-
from .....tableau import TableauAsset
|
|
9
|
-
from ....client import ApiClient, get_paginated_objects
|
|
10
|
-
from ....constants import TABLEAU_SERVER_VERSION
|
|
11
|
-
from ..utils import KEYS
|
|
12
|
-
|
|
13
|
-
TEST_ASSET_DIR = os.path.join(
|
|
14
|
-
os.path.dirname(__file__),
|
|
15
|
-
"../assets/graphql/metadata",
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
METADATA_1 = os.path.join(TEST_ASSET_DIR, "metadata_1_get.json")
|
|
19
|
-
METADATA_2 = os.path.join(TEST_ASSET_DIR, "metadata_2_get.json")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
EXPECTED_PAGINATED = [
|
|
23
|
-
{"id": "0039e5d5-25fa-196b-c66e-c0675839e0b0"},
|
|
24
|
-
{"id": "00b191ce-6055-aff5-e275-c26610c8c4d6"},
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class PaginatedObjectTests(unittest.TestCase):
|
|
29
|
-
@mock.patch.dict(os.environ, KEYS)
|
|
30
|
-
def setUp(self):
|
|
31
|
-
self._client = ApiClient()
|
|
32
|
-
self._client._server = TSC.Server("http://test")
|
|
33
|
-
|
|
34
|
-
# Fake signin
|
|
35
|
-
self._client._server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67"
|
|
36
|
-
self._client._server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM"
|
|
37
|
-
self._client._server.version = TABLEAU_SERVER_VERSION
|
|
38
|
-
|
|
39
|
-
self.baseurl = self._client._server.metadata.baseurl
|
|
40
|
-
|
|
41
|
-
def test_paginated_object_with_datasources(self):
|
|
42
|
-
with open(METADATA_1, "rb") as f:
|
|
43
|
-
response_1_json = f.read().decode()
|
|
44
|
-
|
|
45
|
-
with open(METADATA_2, "rb") as f:
|
|
46
|
-
response_2_json = f.read().decode()
|
|
47
|
-
|
|
48
|
-
with requests_mock.mock() as m:
|
|
49
|
-
m.post(
|
|
50
|
-
self.baseurl,
|
|
51
|
-
[
|
|
52
|
-
{"text": response_1_json, "status_code": 200},
|
|
53
|
-
{"text": response_2_json, "status_code": 200},
|
|
54
|
-
],
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
results = get_paginated_objects(
|
|
58
|
-
self._client._server,
|
|
59
|
-
TableauAsset.DATASOURCE,
|
|
60
|
-
self._client._page_size,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
self.assertEqual(results, EXPECTED_PAGINATED)
|
|
File without changes
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import os.path
|
|
2
|
-
import unittest
|
|
3
|
-
from unittest import mock
|
|
4
|
-
|
|
5
|
-
import requests_mock # type: ignore
|
|
6
|
-
|
|
7
|
-
from ....client import ApiClient
|
|
8
|
-
from ..utils import KEYS
|
|
9
|
-
|
|
10
|
-
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "../assets/rest_api/")
|
|
11
|
-
|
|
12
|
-
AUTH_XML = os.path.join(TEST_ASSET_DIR, "auth.xml")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class AuthTests(unittest.TestCase):
|
|
16
|
-
@mock.patch.dict(os.environ, KEYS)
|
|
17
|
-
def setUp(self):
|
|
18
|
-
self._client = ApiClient()
|
|
19
|
-
self.baseurl = self._client._server.auth.baseurl
|
|
20
|
-
|
|
21
|
-
def test_auth(self):
|
|
22
|
-
with open(AUTH_XML, "rb") as f:
|
|
23
|
-
response_xml = f.read().decode("utf-8")
|
|
24
|
-
with requests_mock.mock() as m:
|
|
25
|
-
m.post(self.baseurl + "/signin", text=response_xml)
|
|
26
|
-
self._client.login()
|
|
27
|
-
|
|
28
|
-
self.assertEqual(
|
|
29
|
-
"eIX6mvFsqyansa4KqEI1UwOpS8ggRs2l",
|
|
30
|
-
self._client._server.auth_token,
|
|
31
|
-
)
|
|
32
|
-
self.assertEqual(
|
|
33
|
-
"6b7179ba-b82b-4f0f-91ed-812074ac5da6",
|
|
34
|
-
self._client._server.site_id,
|
|
35
|
-
)
|
|
36
|
-
self.assertEqual(
|
|
37
|
-
"1a96d216-e9b8-497b-a82a-0b899a965e01",
|
|
38
|
-
self._client._server.user_id,
|
|
39
|
-
)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from ....client.credentials import CredentialsApi
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_default_site_id():
|
|
5
|
-
creds = CredentialsApi( # noqa: S106
|
|
6
|
-
server_url="url",
|
|
7
|
-
user="test_user",
|
|
8
|
-
password="test_pwd",
|
|
9
|
-
token="token",
|
|
10
|
-
token_name="token_name",
|
|
11
|
-
site_id=None,
|
|
12
|
-
)
|
|
13
|
-
assert creds.to_dict()["site_id"] == ""
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import unittest
|
|
3
|
-
from unittest import mock
|
|
4
|
-
|
|
5
|
-
import requests_mock # type: ignore
|
|
6
|
-
import tableauserverclient as TSC # type: ignore
|
|
7
|
-
|
|
8
|
-
from ....client import ApiClient
|
|
9
|
-
from ..utils import KEYS
|
|
10
|
-
|
|
11
|
-
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "../assets/rest_api/")
|
|
12
|
-
|
|
13
|
-
GET_XML = os.path.join(TEST_ASSET_DIR, "project_get.xml")
|
|
14
|
-
|
|
15
|
-
EXPECTED = [
|
|
16
|
-
{
|
|
17
|
-
"id": "ee8c6e70-43b6-11e6-af4f-f7b0d8e20760",
|
|
18
|
-
"name": "default",
|
|
19
|
-
"description": "The default project that was automatically created by Tableau.",
|
|
20
|
-
"parent_id": None,
|
|
21
|
-
"folder_path": "/default",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"id": "1d0304cd-3796-429f-b815-7258370b9b74",
|
|
25
|
-
"name": "Tableau",
|
|
26
|
-
"description": None,
|
|
27
|
-
"parent_id": None,
|
|
28
|
-
"folder_path": "/Tableau",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"id": "4cc52973-5e3a-4d1f-a4fb-5b5f73796edf",
|
|
32
|
-
"name": "Tableau/Child_1",
|
|
33
|
-
"description": None,
|
|
34
|
-
"parent_id": "1d0304cd-3796-429f-b815-7258370b9b74",
|
|
35
|
-
"folder_path": "/Tableau/Tableau/Child_1",
|
|
36
|
-
},
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class ProjectTests(unittest.TestCase):
|
|
41
|
-
@mock.patch.dict(os.environ, KEYS)
|
|
42
|
-
def setUp(self):
|
|
43
|
-
self._client = ApiClient()
|
|
44
|
-
self._client._server = TSC.Server("http://test")
|
|
45
|
-
|
|
46
|
-
# Fake signin
|
|
47
|
-
self._client._server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67"
|
|
48
|
-
self._client._server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM"
|
|
49
|
-
|
|
50
|
-
self.baseurl = self._client._server.projects.baseurl
|
|
51
|
-
|
|
52
|
-
def test_fetch_projects(self):
|
|
53
|
-
with open(GET_XML, "rb") as f:
|
|
54
|
-
response_xml = f.read().decode("utf-8")
|
|
55
|
-
with requests_mock.mock() as m:
|
|
56
|
-
m.get(self.baseurl, text=response_xml)
|
|
57
|
-
results = self._client._fetch_projects()
|
|
58
|
-
|
|
59
|
-
self.assertEqual(results, EXPECTED)
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import unittest
|
|
3
|
-
from unittest import mock
|
|
4
|
-
|
|
5
|
-
import requests_mock # type: ignore
|
|
6
|
-
import tableauserverclient as TSC # type: ignore
|
|
7
|
-
|
|
8
|
-
from ....client import ApiClient
|
|
9
|
-
from ..utils import KEYS
|
|
10
|
-
|
|
11
|
-
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "../assets/rest_api/")
|
|
12
|
-
|
|
13
|
-
GET_XML = os.path.join(TEST_ASSET_DIR, "view_get_usage.xml")
|
|
14
|
-
|
|
15
|
-
EXPECTED = [
|
|
16
|
-
{
|
|
17
|
-
"workbook_id": "3cc6cd06-89ce-4fdc-b935-5294135d6d42",
|
|
18
|
-
"view_counts": 11,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"workbook_id": "6d13b0ca-043d-4d42-8c9d-3f3313ea3a00",
|
|
22
|
-
"view_counts": 13,
|
|
23
|
-
},
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class UsageTests(unittest.TestCase):
|
|
28
|
-
@mock.patch.dict(os.environ, KEYS)
|
|
29
|
-
def setUp(self):
|
|
30
|
-
self._client = ApiClient()
|
|
31
|
-
self._client._server = TSC.Server("http://test_usage")
|
|
32
|
-
|
|
33
|
-
# Fake signin
|
|
34
|
-
self._client._server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67"
|
|
35
|
-
self._client._server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM"
|
|
36
|
-
|
|
37
|
-
self.baseurl = self._client._server.views.baseurl
|
|
38
|
-
|
|
39
|
-
def test_fetch_usages(self):
|
|
40
|
-
with open(GET_XML, "rb") as f:
|
|
41
|
-
response_xml = f.read().decode("utf-8")
|
|
42
|
-
with requests_mock.mock() as m:
|
|
43
|
-
m.get(
|
|
44
|
-
self.baseurl + "?includeUsageStatistics=true",
|
|
45
|
-
text=response_xml,
|
|
46
|
-
)
|
|
47
|
-
results = self._client._fetch_usages(False)
|
|
48
|
-
|
|
49
|
-
self.assertEqual(results, EXPECTED)
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import unittest
|
|
3
|
-
from unittest import mock
|
|
4
|
-
|
|
5
|
-
import requests_mock # type: ignore
|
|
6
|
-
import tableauserverclient as TSC # type: ignore
|
|
7
|
-
|
|
8
|
-
from ....client import ApiClient
|
|
9
|
-
from ..utils import KEYS
|
|
10
|
-
|
|
11
|
-
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), "../assets/rest_api/")
|
|
12
|
-
|
|
13
|
-
GET_XML = os.path.join(TEST_ASSET_DIR, "user_get.xml")
|
|
14
|
-
|
|
15
|
-
EXPECTED = [
|
|
16
|
-
{
|
|
17
|
-
"id": "dd2239f6-ddf1-4107-981a-4cf94e415794",
|
|
18
|
-
"name": "alice",
|
|
19
|
-
"email": "alicecook@test.com",
|
|
20
|
-
"fullname": "alice cook",
|
|
21
|
-
"site_role": "Publisher",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"id": "2a47bbf8-8900-4ebb-b0a4-2723bd7c46c3",
|
|
25
|
-
"name": "Bob",
|
|
26
|
-
"email": "bob@test.com",
|
|
27
|
-
"fullname": "Bob Smith",
|
|
28
|
-
"site_role": "Interactor",
|
|
29
|
-
},
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class UserTests(unittest.TestCase):
|
|
34
|
-
@mock.patch.dict(os.environ, KEYS)
|
|
35
|
-
def setUp(self):
|
|
36
|
-
self._client = ApiClient()
|
|
37
|
-
self._client._server = TSC.Server("http://test")
|
|
38
|
-
|
|
39
|
-
# Fake signin
|
|
40
|
-
self._client._server._site_id = "dad65087-b08b-4603-af4e-2887b8aafc67"
|
|
41
|
-
self._client._server._auth_token = "j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM"
|
|
42
|
-
|
|
43
|
-
self.baseurl = self._client._server.users.baseurl
|
|
44
|
-
|
|
45
|
-
def test_fetch_users(self):
|
|
46
|
-
with open(GET_XML, "rb") as f:
|
|
47
|
-
response_xml = f.read().decode("utf-8")
|
|
48
|
-
with requests_mock.mock() as m:
|
|
49
|
-
m.get(self.baseurl + "?fields=_all_", text=response_xml)
|
|
50
|
-
results = self._client._fetch_users()
|
|
51
|
-
|
|
52
|
-
self.assertEqual(results, EXPECTED)
|