"""Custom codec to enable automatic preprocessing."""importcodecsfromcollections.abcimportBufferfromfunctoolsimportpartialimportsysimporttracebackENCODING_NAME='macro_polo'def_decode(data:Buffer,errors:str='strict',*,encoding:str)->tuple[str,int]:try:from.macros.predefinedimportmake_default_preprocessor_macrofrom.tokensimportlex,stringifymacro=make_default_preprocessor_macro()decoder=codecs.getdecoder(encoding)source,consumed=decoder(data,errors)tokens=tuple(lex(source))result=stringify(macro(tokens)ortokens)ifresult:# First line will be stripped, since it's assumed to be the 'coding: ...'# directive.result='\n'+resultreturnresult,consumedexcept:traceback.print_exc()raiseclass_IncrementalMacroDecoder(codecs.BufferedIncrementalDecoder):def__init__(self,errors:str='strict',*,encoding:str):super().__init__(errors)self._encoding=encodingdef_buffer_decode(self,input:Buffer,errors:str,final:bool)->tuple[str,int]:ifnotfinal:return'',0return_decode(input,errors,encoding=self._encoding)def_search_hook(encoding:str):ifencoding.startswith(ENCODING_NAME):real_encoding=(encoding.removeprefix(ENCODING_NAME).lstrip('_')orsys.getdefaultencoding())returncodecs.CodecInfo(encode=codecs.getencoder(real_encoding),decode=partial(_decode,encoding=real_encoding),incrementaldecoder=partial(_IncrementalMacroDecoder,encoding=real_encoding),name=encoding,)returnNone
[docs]defregister()->None:"""Register the macro_polo codec."""codecs.register(_search_hook)