@@ -217,6 +217,25 @@ def from_credentials(
217217 site = wt .create_site_object (_domain , "" , _credentials )
218218 return cls (WtSite .WtSiteLegacyConfig (site = site ))
219219
220+ @staticmethod
221+ def try_and_renew_token (func ):
222+ """ "Tries to execute the method call. If the auth token has expired already,
223+ the token is renewed and the method call is retried.
224+
225+ This decorator should be used closest to to the funciton definition (before
226+ any other decorator).
227+ """
228+
229+ def wrapper (self , * args , ** kwargs ):
230+ try :
231+ return func (self , * args , ** kwargs )
232+ except mwclient .errors .APIError :
233+ # Refresh token for longer taking processes
234+ self ._site .get_token ("csrf" , force = True )
235+ return func (self , * args , ** kwargs )
236+
237+ return wrapper
238+
220239 class GetPageParam (OswBaseModel ):
221240 titles : Union [str , List [str ]]
222241 """title string or list of title strings of the pages to download"""
@@ -252,6 +271,7 @@ class GetPageResult(OswBaseModel):
252271 class Config :
253272 arbitrary_types_allowed = True # allows to use WtPage in type hints
254273
274+ @try_and_renew_token
255275 def get_page (self , param : GetPageParam ) -> GetPageResult :
256276 """Downloads a page or a list of pages from the site.
257277
@@ -319,6 +339,7 @@ def get_page_(title: str, index: int = None):
319339 return self .GetPageResult (pages = pages , errors = exceptions )
320340
321341 @deprecated ("Use get_page instead" )
342+ @try_and_renew_token
322343 def get_WtPage (self , title : str = None ):
323344 """Creates a new WtPage object for the given title
324345 and loads the page from the site if the page already exists.
@@ -341,6 +362,7 @@ class GetPageContentResult(OswBaseModel):
341362 class Config :
342363 arbitrary_types_allowed = True
343364
365+ @try_and_renew_token
344366 def get_page_content (self , full_page_titles : List [str ]) -> GetPageContentResult :
345367 get_page_res = self .get_page (WtSite .GetPageParam (titles = full_page_titles ))
346368 contents_dict = {}
@@ -395,6 +417,7 @@ def _clear_cookies(self):
395417 class SearchParam (wt .SearchParam ):
396418 pass
397419
420+ @try_and_renew_token
398421 def prefix_search (self , text : Union [str , SearchParam ]):
399422 """Send a prefix search request to the site.
400423
@@ -409,6 +432,7 @@ def prefix_search(self, text: Union[str, SearchParam]):
409432 """
410433 return wt .prefix_search (self ._site , text )
411434
435+ @try_and_renew_token
412436 def semantic_search (self , query : Union [str , SearchParam ]):
413437 """Send a swm ask query to the site.
414438
@@ -437,6 +461,7 @@ class ModifySearchResultsParam(OswBaseModel):
437461 dryrun : bool = False
438462 """if True, no actual changes are made"""
439463
464+ @try_and_renew_token
440465 def modify_search_results (
441466 self ,
442467 mode : str ,
@@ -512,6 +537,7 @@ def __init__(self, **data):
512537 if self .parallel is None :
513538 self .parallel = False
514539
540+ @try_and_renew_token
515541 def upload_page (
516542 self ,
517543 param : Union [UploadPageParam , "WtPage" , List ["WtPage" ]],
@@ -579,6 +605,7 @@ def __init__(self, **data):
579605 if self .parallel is None :
580606 self .parallel = False
581607
608+ @try_and_renew_token
582609 def copy_pages (self , param : CopyPagesParam ):
583610 """Copies pages from a source site to this (target) site."""
584611
@@ -626,6 +653,7 @@ def __init__(self, **data):
626653 if len (self .page ) > 5 and self .parallel is None :
627654 self .parallel = True
628655
656+ @try_and_renew_token
629657 def delete_page (
630658 self ,
631659 param : Union ["WtPage" , List ["WtPage" ], str , List [str ], DeletePageParam ],
@@ -697,6 +725,7 @@ class CreatePagePackageParam(OswBaseModel):
697725 class Config :
698726 arbitrary_types_allowed = True
699727
728+ @try_and_renew_token
700729 def create_page_package (self , param : CreatePagePackageParam ):
701730 """Create a page package, which is a locally stored collection of wiki pages
702731 and their slots, based on a configuration object.
@@ -858,6 +887,7 @@ class ReadPagePackageResult(OswBaseModel):
858887 class Config :
859888 arbitrary_types_allowed = True
860889
890+ @try_and_renew_token
861891 def read_page_package (self , param : ReadPagePackageParam ) -> ReadPagePackageResult :
862892 """Read a page package, which is a locally stored collection of wiki pages and
863893 their slots' content.
@@ -1007,6 +1037,7 @@ class UploadPagePackageParam(OswBaseModel):
10071037 class Config :
10081038 arbitrary_types_allowed = True
10091039
1040+ @try_and_renew_token
10101041 def upload_page_package (self , param : UploadPagePackageParam ):
10111042 """Uploads a page package to the wiki defined by a list of WtPage objects or
10121043 a storage path.
@@ -1031,6 +1062,7 @@ def upload_page_package(self, param: UploadPagePackageParam):
10311062 for page in pages :
10321063 page .edit ()
10331064
1065+ @try_and_renew_token
10341066 def get_file_pages (self , limit : int = 1000000 ) -> List [str ]:
10351067 """Get all file pages in the wiki"""
10361068 full_page_titles = wt .prefix_search (
@@ -1039,6 +1071,7 @@ def get_file_pages(self, limit: int = 1000000) -> List[str]:
10391071 )
10401072 return full_page_titles
10411073
1074+ @try_and_renew_token
10421075 def get_file_info_and_usage (
10431076 self ,
10441077 page_titles : Union [str , List [str ], SearchParam ],
@@ -1156,6 +1189,7 @@ def _replace_jsonld_context_mapping(
11561189 )
11571190 return context
11581191
1192+ @try_and_renew_token
11591193 def get_jsonld_context_loader (self , params : JsonLdContextLoaderParams = None ):
11601194 if params is None :
11611195 params = self .JsonLdContextLoaderParams ()
@@ -1275,6 +1309,25 @@ def init(self):
12751309 # todo: set content for slots not in revision["slots"] (use
12761310 # SLOTS) --> create empty slots
12771311
1312+ @staticmethod
1313+ def try_and_renew_token (func ):
1314+ """Tries to execute the method call. If the auth token has expired already,
1315+ the token is renewed and the method call is retried.
1316+
1317+ This decorator should be used closest to to the funciton definition (before
1318+ any other decorator).
1319+ """
1320+
1321+ def wrapper (self , * args , ** kwargs ):
1322+ try :
1323+ return func (self , * args , ** kwargs )
1324+ except mwclient .errors .APIError :
1325+ # Refresh token for longer taking processes
1326+ self .wtSite ._site .get_token ("csrf" , force = True )
1327+ return func (self , * args , ** kwargs )
1328+
1329+ return wrapper
1330+
12781331 def parse_main_slot (self ):
12791332 """Parses the main slot content of the page
12801333 Requires wikitext dependencies installed with 'pip install osw[wikitext]'
@@ -1646,6 +1699,7 @@ def _edit(
16461699 if changed :
16471700 self .changed = True
16481701
1702+ @try_and_renew_token
16491703 def delete (self , comment : str = None ):
16501704 """Deletes the page from the site
16511705
@@ -1656,6 +1710,7 @@ def delete(self, comment: str = None):
16561710 """
16571711 self ._page .delete (comment )
16581712
1713+ @try_and_renew_token
16591714 def move (self , new_title : str , comment : str = None , redirect : bool = True ):
16601715 """Moves (=renames) the page to a new title
16611716
@@ -1713,6 +1768,7 @@ class PageCopyResult(OswBaseModel):
17131768 class Config :
17141769 arbitrary_types_allowed = True
17151770
1771+ @try_and_renew_token
17161772 def copy (self , config : CopyPageConfig ) -> PageCopyResult :
17171773 if config .comment is None :
17181774 config .comment = f"[bot edit] Copied from { config .source_site .mw_site .host } "
@@ -1874,6 +1930,7 @@ def dump_slot_content(slot_key_, content_type_, content_):
18741930
18751931 return package_page
18761932
1933+ @try_and_renew_token
18771934 def get_file_info_and_usage (
18781935 self , debug : bool = False
18791936 ) -> Dict [str , Union [str , List [str ]]]:
@@ -1894,6 +1951,7 @@ def get_file_info_and_usage(
18941951 title = wt .SearchParam (query = self .title , debug = debug ),
18951952 )[0 ]
18961953
1954+ @try_and_renew_token
18971955 def find_file_page_refs_in_slots (self , slots : List [str ] = None ) -> List [str ]:
18981956 """Find all file page references in the content of the given slots."""
18991957 if slots is None :
@@ -1939,6 +1997,7 @@ def find_file_page_refs_in_slots(self, slots: List[str] = None) -> List[str]:
19391997 print ("Warning: Error while parsing uuid in editor template" )
19401998 return list (set (file_page_refs ))
19411999
2000+ @try_and_renew_token
19422001 def purge (self ):
19432002 """Purge the page from the site cache.
19442003 Triggers a rebuild / refresh of the page.
@@ -1962,6 +2021,7 @@ class ExportResult(OswBaseModel):
19622021 success : bool
19632022 """if true, the export was successful, else false"""
19642023
2024+ @try_and_renew_token
19652025 def export_xml (self , config : Optional [ExportConfig ] = None ) -> ExportResult :
19662026 """Exports the page to XML
19672027
@@ -2035,6 +2095,7 @@ class ImportResult(OswBaseModel):
20352095 imported_revisions : int
20362096 error_msg : Optional [str ] = None
20372097
2098+ @try_and_renew_token
20382099 def import_xml (self , config : ImportConfig ) -> ImportResult :
20392100 """Imports the page from an XML export
20402101
0 commit comments