"""This project exports your local Zotero library to a usable HTML website."""__author__='Paul Landes'fromtypingimportIterable,Dict,Anyfromdataclassesimportdataclass,fieldimportreimportloggingimportsysimportjsonfrompathlibimportPathfromzensols.configimportConfigFactoryfrom.importZoteroApplicationError,SiteCreator,ZoteroDatabase,CiteDatabaselogger=logging.getLogger(__name__)
[docs]@dataclassclassResource(object):"""Zotsite first class objects. """zotero_db:ZoteroDatabase=field()"""The database access object."""cite_db:CiteDatabase=field()"""Maps Zotero keys to BetterBibtex citekeys."""site_creator:SiteCreator=field()"""Creates the Zotero content web site."""
@dataclassclass_Application(object):resource:Resource=field()"""Zotsite first class objects."""def_get_keys(self,key:str,default:Iterable[str])->Iterable[str]:ifkeyisNone:keys=map(lambdas:s.strip(),sys.stdin.readlines())elifkey=='all':keys=defaultelse:keys=[key]returnkeysdef_format(self,format:str,entry:Dict[str,str]):ifformat=='json':returnjson.dumps(entry)else:returnformat.format(**entry)
[docs]@dataclassclassExportApplication(_Application):"""This project exports your local Zotero library to a usable HTML website. """prune_pattern:str=field(default=None)"""A regular expression used to filter ``Collection`` nodes."""@propertydefsite_creator(self)->SiteCreator:returnself.resource.site_creatordef_prepare_creator(self,output_dir:Path)->Path:ifoutput_dirisnotNone:self.site_creator.out_dir=output_direlse:output_dir=self.site_creator.out_dirifself.prune_patternisnotNone:pat:re.Pattern=re.compile(self.prune_pattern)self.site_creator.prune_visitor.prune_pattern=patreturnoutput_dir
[docs]defexport(self,output_dir:Path=None):"""Generate and export the Zotero website. :param output_dir: the directory to dump the site; default to configuration file """iflogger.isEnabledFor(logging.INFO):logger.info(f'exporting site: {output_dir}')output_dir=self._prepare_creator(output_dir)self.site_creator.export()
[docs]defprint_structure(self):"""Print (sub)collections and papers in those collections as a tree."""self._prepare_creator(None)self.site_creator.print_structure()
[docs]@dataclassclassQueryApplication(_Application):"""Query the Zotero database. """
[docs]deffind_path(self,format:str=None,key:str=None):"""Output paths with default ``{itemKey}={path}`` for ``format``. :param format: the format of the output or ``json`` for all fields :param key: key in format ``<library ID>_<item key>``, standard input if not given, or ``all`` for every entry """defstrip_lib_id(s:str)->str:m:re.Match=lib_id_regex.match(s)ifmisNone:raiseZoteroApplicationError(f'Bad item key format: {key}')lib_id:int=int(m.group(1))iflib_id!=cur_lib_id:raiseZoteroApplicationError(f'Mismatch of configured library ({cur_lib_id}) '+f'and requested in key: {lib_id}')returnre.sub(lib_id_rm_regex,'',s)cur_lib_id:int=self.resource.zotero_db.library_idlib_id_regex:re.Pattern=re.compile(r'^(\d+)_.+')lib_id_rm_regex:re.Pattern=re.compile(r'^\d+_')paths:Dict[str,str]=self.resource.zotero_db.item_pathsformat='{itemKey}={path}'ifformatisNoneelseformatdkeys:Iterable[str]=map(lambdak:f'{cur_lib_id}_{k}',paths.keys())forkeyinmap(strip_lib_id,self._get_keys(key,dkeys)):ifkeynotinpaths:raiseZoteroApplicationError(f'No item: {key} in Zotero database')entry:Dict[str,Any]={'libraryID':cur_lib_id,'itemKey':key,'path':str(paths[key])}print(self._format(format,entry))
[docs]@dataclassclassCiteApplication(_Application):"""Map Zotero keys to BetterBibtex citekeys. """
[docs]defcitekey(self,format:str=None,key:str=None):"""Look up a citation key and print out BetterBibtex field(s) with default ``{itemKey}={citationKey}`` for ``format``. :param key: key in format ``<library ID>_<item key>``, standard input if not given, or ``all`` for every entry :param format: the format of the output or ``json`` for all fields """entries:Dict[str,Dict[str,Any]]=self.resource.cite_db.entriesformat='{itemKey}={citationKey}'ifformatisNoneelseformatforkeyinself._get_keys(key,entries.keys()):ifkeynotinentries:raiseZoteroApplicationError(f"No such entry: '{key}' in BetterBibtex database")entry:Dict[str,Any]=entries[key]print(self._format(format,entry))