1
1
import abc
2
2
import copy
3
- from typing import Iterable , Optional , Protocol , Set , Union , TYPE_CHECKING , runtime_checkable
3
+ from typing import Generic , Iterable , Optional , Protocol , Set , TypeVar , Union , TYPE_CHECKING , runtime_checkable
4
4
import urllib .parse
5
5
6
6
from tableauserverclient .server .endpoint .endpoint import Endpoint , api
@@ -62,27 +62,24 @@ def update_tags(self, baseurl, resource_item):
62
62
logger .info ("Updated tags to {0}" .format (resource_item .tags ))
63
63
64
64
65
- class HasID (Protocol ):
66
- @property
67
- def id (self ) -> Optional [str ]:
68
- pass
65
+ class Response (Protocol ):
66
+ content : bytes
69
67
70
68
71
69
@runtime_checkable
72
70
class Taggable (Protocol ):
73
- _initial_tags : Set [str ]
74
71
tags : Set [str ]
72
+ _initial_tags : Set [str ]
75
73
76
74
@property
77
75
def id (self ) -> Optional [str ]:
78
76
pass
79
77
80
78
81
- class Response (Protocol ):
82
- content : bytes
79
+ T = TypeVar ("T" )
83
80
84
81
85
- class TaggingMixin (abc .ABC ):
82
+ class TaggingMixin (abc .ABC , Generic [ T ] ):
86
83
parent_srv : "Server"
87
84
88
85
@property
@@ -98,7 +95,7 @@ def put_request(self, url, request) -> Response:
98
95
def delete_request (self , url ) -> None :
99
96
pass
100
97
101
- def add_tags (self , item : Union [HasID , Taggable , str ], tags : Union [Iterable [str ], str ]) -> Set [str ]:
98
+ def add_tags (self , item : Union [T , str ], tags : Union [Iterable [str ], str ]) -> Set [str ]:
102
99
item_id = getattr (item , "id" , item )
103
100
104
101
if not isinstance (item_id , str ):
@@ -114,7 +111,7 @@ def add_tags(self, item: Union[HasID, Taggable, str], tags: Union[Iterable[str],
114
111
server_response = self .put_request (url , add_req )
115
112
return TagItem .from_response (server_response .content , self .parent_srv .namespace )
116
113
117
- def delete_tags (self , item : Union [HasID , Taggable , str ], tags : Union [Iterable [str ], str ]) -> None :
114
+ def delete_tags (self , item : Union [T , str ], tags : Union [Iterable [str ], str ]) -> None :
118
115
item_id = getattr (item , "id" , item )
119
116
120
117
if not isinstance (item_id , str ):
@@ -130,17 +127,23 @@ def delete_tags(self, item: Union[HasID, Taggable, str], tags: Union[Iterable[st
130
127
url = f"{ self .baseurl } /{ item_id } /tags/{ encoded_tag_name } "
131
128
self .delete_request (url )
132
129
133
- def update_tags (self , item : Taggable ) -> None :
134
- if item .tags == item ._initial_tags :
130
+ def update_tags (self , item : T ) -> None :
131
+ if (initial_tags := getattr (item , "_initial_tags" , None )) is None :
132
+ raise ValueError (f"{ item } does not have initial tags." )
133
+ if (tags := getattr (item , "tags" , None )) is None :
134
+ raise ValueError (f"{ item } does not have tags." )
135
+ if tags == initial_tags :
135
136
return
136
137
137
- add_set = item . tags - item . _initial_tags
138
- remove_set = item . _initial_tags - item . tags
138
+ add_set = tags - initial_tags
139
+ remove_set = initial_tags - tags
139
140
self .delete_tags (item , remove_set )
140
141
if add_set :
141
- item .tags = self .add_tags (item , add_set )
142
- item ._initial_tags = copy .copy (item .tags )
143
- logger .info (f"Updated tags to { item .tags } " )
142
+ tags = self .add_tags (item , add_set )
143
+ setattr (item , "tags" , tags )
144
+
145
+ setattr (item , "_initial_tags" , copy .copy (tags ))
146
+ logger .info (f"Updated tags to { tags } " )
144
147
145
148
146
149
content = Iterable [Union ["ColumnItem" , "DatabaseItem" , "DatasourceItem" , "FlowItem" , "TableItem" , "WorkbookItem" ]]
0 commit comments