Skip to content

Commit 232e5b1

Browse files
committed
Decorator for WtSite and WtPage that rely on a valid auth token
1 parent e67def6 commit 232e5b1

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

‎src/osw/wtsite.py‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)