K i"dZddlZddlZddlZddlZddlZddlZddlmZddl Z ddl m Z ddl m Z mZddlmZddlmZdZgd Zej*j-d d ej.d kDr ej0n ej2Zej.d kDr ej2n ej6ZGd dej:Z ej>Z Gdde Z#Gdde#Z$Gdde#Z%Gdde#Z&Gdde#Z'Gdde#Z(e$e%e'e(e&gZ)e*e+de)DZ,e)Dcgc]}|jZc}Z.e*e+de)DZ/e)Dcgc]}|j`dk(s|jZ c}Z1e(jdZ3dZ4dZ5ed !d"Z6e5e*e,e.#d$Z7Gd%d&Z8Gd'd(e8eZ9e5d)jud*e,Dd)jue1d)jue3+Gd,d-e8Z;Gd.d/Zd1k(re=yy#e!$rejDZ YwxYwcc}wcc}w)2zthreadpoolctl This module provides utilities to introspect native libraries that relies on thread pools (notably BLAS and OpenMP implementations) and dynamically set the maximal number of threads they can use. N)final) find_library)ABCabstractmethod) lru_cache)ContextDecoratorz3.6.0)threadpool_limitsthreadpool_infoThreadpoolController LibControllerregisterKMP_DUPLICATE_LIB_OKTruelcPeZdZdefdej fdej fdefgZy) _dl_phdr_info dlpi_addr dlpi_name dlpi_phdr dlpi_phnumN) __name__ __module__ __qualname__ _SYSTEM_UINTctypesc_char_pc_void_p_SYSTEM_UINT_HALF_fields_S/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/threadpoolctl.pyrr8s2 l# foo& foo& () Hr rceZdZdZedddddZdZdZedZ e dZ e d Z e d Z d Zd Zy) r a Abstract base class for the individual library controllers A library controller must expose the following class attributes: - user_api : str Usually the name of the library or generic specification the library implements, e.g. "blas" is a specification with different implementations. - internal_api : str Usually the name of the library or concrete implementation of some specification, e.g. "openblas" is an implementation of the "blas" specification. - filename_prefixes : tuple Possible prefixes of the shared library's filename that allow to identify the library. e.g. "libopenblas" for libopenblas.so. and implement the following methods: `get_num_threads`, `set_num_threads` and `get_version`. Threadpoolctl loops through all the loaded shared libraries and tries to match the filename of each library with the `filename_prefixes`. If a match is found, a controller is instantiated and a handler to the library is stored in the `dynlib` attribute as a `ctypes.CDLL` object. It can be used to access the necessary symbols of the shared library to implement the above methods. The following information will be exposed in the info dictionary: - user_api : standardized API, if any, or a copy of internal_api. - internal_api : implementation-specific API. - num_threads : the current thread limit. - prefix : prefix of the shared library's filename. - filepath : path to the loaded shared library. - version : version of the library (if available). In addition, each library controller may expose internal API specific entries. They must be set as attributes in the `set_additional_attributes` method. Nfilepathprefixparentc||_||_||_tj|t |_|j\|_|_ |j|_ |jy)z0This is not meant to be overriden by subclasses.modeN) r&r%r$rCDLL _RTLD_NOLOADdynlib _find_affixes_symbol_prefix_symbol_suffix get_versionversionset_additional_attributes)selfr$r%r&s r!__init__zLibController.__init__ls`    kk(> 373E3E3G0T0'')  &&(r cd}|j|j|jdt|j Dcic] \}}||vs ||c}}Scc}}w)&Return relevant info wrapped in a dict)r,r&r.r/)user_api internal_api num_threads)r7r8r9varsitems)r3 hidden_attrskvs r!infozLibController.infowsaO   --++ !%T 0 0 2L1a|6Kq!tL   Ms  AAcy)z>Set additional attributes meant to be exposed in the info dictNrr3s r!r2z'LibController.set_additional_attributesr c"|jS)zExposes the current thread limit as a dynamic property This is not meant to be used or overriden by subclasses. )get_num_threadsrAs r!r9zLibController.num_threadss ##%%r cy)z5Return the maximum number of threads available to useNrrAs r!rDzLibController.get_num_threadsrBr cy)z(Set the maximum number of threads to useNr)r3r9s r!set_num_threadszLibController.set_num_threadsrBr cy)z(Return the version of the shared libraryNrrAs r!r0zLibController.get_versionrBr cy)z8Return the affixes for the symbols of the shared library)rJrrAs r!r-zLibController._find_affixessr cdt|j|j||jdS)zBReturn the symbol of the shared library accounding for the affixesN)getattrr,r.r/)r3names r! _get_symbolzLibController._get_symbols5 KKD//0t7J7J6KLd  r )rrr__doc__rr4r?r2propertyr9rrDrGr0r-rNrr r!r r Hs!F #'T) ) M&&DD7777 r r ceZdZdZdZdZdZdZdZe de jeeDZ dZ d Zd Zd Zd Zd ZdZy)OpenBLASControllerzController class for OpenBLASblasopenblas) libopenblaslibblaslibscipy_openblas)rJscipy_)rJ64__64c#0K|]\}}|d|yw)openblas_get_num_threadsNr).0r%suffixs r! zOpenBLASController.s( FF (*6(3sctj|j|jD]&\}}t |j |d|s"||fcSyNr\) itertoolsproduct_symbol_prefixes_symbol_suffixeshasattrr,)r3r%r^s r!r-z OpenBLASController._find_affixessW'//  ! !4#8#8  &NFFt{{vh.Fvh$OPv~%  &r cX|j|_|j|_yN_get_threading_layerthreading_layer_get_architecture architecturerAs r!r2z,OpenBLASController.set_additional_attributes$#88: 224r c8|jd}||SyrarN)r3get_num_threads_funcs r!rDz"OpenBLASController.get_num_threadss&#//0JK  +') )r c:|jd}|||Sy)Nopenblas_set_num_threadsrp)r3r9set_num_threads_funcs r!rGz"OpenBLASController.set_num_threadss(#//0JK  +' 4 4r c|jd}|Gtj|_|j }|ddk(r|dj dSyy)Nopenblas_get_configrsOpenBLASutf-8)rNrrrestypesplitdecode)r3get_version_funcconfigs r!r0zOpenBLASController.get_versionsa ++,AB  ''-  $%'--/FayK'ay''00r cR|jd}||}|dk(ry|dk(ryyy)z&Return the threading layer of OpenBLASopenblas_get_parallelopenmprwpthreadsdisabledunknownrp)r3get_threading_layer_funcrks r!rjz'OpenBLASController._get_threading_layers>#'#3#34K#L # /68O!# A%!r c|jd}|+tj|_|j dSy)z,Return the architecture detected by OpenBLASopenblas_get_corenameNrx)rNrrryr{)r3get_architecture_funcs r!rlz$OpenBLASController._get_architectures> $ 0 01H I ,,2OO ! )(*11': :r N)rrrrOr7r8filename_prefixesrdretuplerbrc check_symbolsr-r2rDrGr0rjrlrr r!rRrRsn'HLG%)/i//0@BRSM &5   r rRcDeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z y ) BLISControllerzController class for BLISrSblis)libblisrV)bli_thread_get_num_threadsbli_thread_set_num_threadsbli_info_get_version_strbli_info_get_enable_openmpbli_info_get_enable_pthreadsbli_arch_query_idbli_arch_stringcX|j|_|j|_yrhrirAs r!r2z(BLISController.set_additional_attributesrnr cRt|jdd}|}|dk(rdS|S)Nrcyrhrrr r!z0BLISController.get_num_threads..rBr rwrLr,r3get_funcr9s r!rDzBLISController.get_num_threadss04;;(DlSj  2%q6;6r cBt|jdd}||S)Nrcyrhrr9s r!rz0BLISController.set_num_threads..rBr rr3r9set_funcs r!rGzBLISController.set_num_threadss& KK57O  $$r ct|jdd}|ytj|_|j dS)Nrrx)rLr,rrryr{)r3 get_version_s r!r0zBLISController.get_version s=t{{,FM  % ~$$W--r c|t|jddryt|jddryy)z"Return the threading layer of BLISrcyNFrrr r!rz5BLISController._get_threading_layer..rBr rrcyrrrr r!rz5BLISController._get_threading_layer..rBr rrrrAs r!rjz#BLISController._get_threading_layers7 L74;; .OrBr rrwrrs r!rDz#FlexiBLASController.get_num_threadsNs04;;(C\Rj  2%q6;6r cBt|jdd}||S)Nrcyrhrrs r!rz5FlexiBLASController.set_num_threads..WrBr rrs r!rGz#FlexiBLASController.set_num_threadsUs& KK46N  $$r ct|jdd}|ytj}tj}tj}|tj|tj|tj||j d|j d|j S)Nr.)rLr,rrbyrefvalue)r3rmajorminorpatchs r!r0zFlexiBLASController.get_version[st{{,CTJ     V\\%(&,,u*=v||E?RS++a }Aekk];;r cTd|rdnd}t|j|d}|y|ddd}g}t|D]j}tjd}||d||j j ddk7sA|j|j j dl|S) zReturn the list of available backends for FlexiBLAS. If loaded is False, return the list of available backends from the FlexiBLAS configuration. If loaded is True, return the list of actually loaded backends. r_loadedrJNrrx __FALLBACK__)rLr,rangercreate_string_bufferrr{append)r3r func_nameget_backend_list_ n_backendsbackendsi backend_names r!rz%FlexiBLASController._get_backend_listfs %&Yb$AB #DKKDA  $&tQ2 z" DA!66t.rBr flexiblas_load_backend_librarycyrrrs r!rz4FlexiBLASController.switch_backend..rBr rxrzFailed to load backend zS. It must either be the name of a backend available in the FlexiBLAS configuration z' or the path to a valid shared library.flexiblas_switchcyrrrs r!rz4FlexiBLASController.switch_backend..rBr zFailed to switch to backend rN) rrrLr,strencode RuntimeErrorr&_load_librariesindex)r3r load_funcres switch_funcidxs r!switch_backendz"FlexiBLASController.switch_backends $.. .$111#DKK1I<X #KK!A< CL//89Cby"-g[9K..//VX KK ' ' )dkk+=|L ""((1# "9!=g[JK K r )F)rrrrOr7r8rrrPrrr?r2rDrGr0rrr __classcell__rs@r!rr*so(HL)M33++G7% <.- Lr rc>eZdZdZdZdZdZdZdZdZ dZ d Z d Z y ) MKLControllerzController class for MKLrSmkl) libmkl_rtmkl_rtrV)MKL_Get_Max_ThreadsMKL_Set_Num_ThreadsMKL_Get_Version_StringMKL_Set_Threading_Layerc.|j|_yrh)rjrkrAs r!r2z'MKLController.set_additional_attributess#88:r c@t|jdd}|S)Nrcyrhrrr r!rz/MKLController.get_num_threads..rBr rr3rs r!rDzMKLController.get_num_threads4;;(=|Lzr cBt|jdd}||S)Nrcyrhrrs r!rz/MKLController.set_num_threads..rBr rrs r!rGzMKLController.set_num_threads!4;;(=?WX $$r c>t|jdsytjd}|jj |d|j j d}tjd|}||jd}|jS)NrrxzVersion ([^ ]+) r) rfr,rrrrr{researchgroupsstrip)r3rr1groups r!r0zMKLController.get_versionst{{$<=))#. **34))""7+ -w7  llnQ'G}}r cZt|jdd}ddddddd }||d S) z!Return the threading layer of MKLrcyrr)layers r!rz4MKLController._get_threading_layer..rBr intel sequentialpgignutbbz not specified)rrwrrrr)r3set_threading_layer layer_maps r!rjz"MKLController._get_threading_layersJ & KK24D   ,R011r N) rrrrOr7r8rrr2rDrGr0rjrr r!rrs5"HL:M;% 2r rc2eZdZdZdZdZdZdZdZdZ dZ y) OpenMPControllerzController class for OpenMPr)libiomplibgomplibompvcomp)omp_get_max_threadsomp_get_num_threadsc@t|jdd}|S)Nr cyrhrrr r!rz2OpenMPController.get_num_threads..rBr rrs r!rDz OpenMPController.get_num_threadsrr cBt|jdd}||S)Nomp_set_num_threadscyrhrrs r!rz2OpenMPController.set_num_threads..rBr rrs r!rGz OpenMPController.set_num_threadsrr cyrhrrAs r!r0zOpenMPController.get_versionsr N) rrrrOr7r8rrrDrGr0rr r!rrs+%HLAM %r rc#4K|]}|jywrh)r7r]libs r!r_r_sC3#,,Cc#BK|]}|jD]}|ywrh)r)r]r*r%s r!r_r_s"O39N9NOvOOsrSctj|tj|jtj|j t j|jy)zRegister a new controllerN) _ALL_CONTROLLERSr_ALL_USER_APISr7_ALL_INTERNAL_APISr8 _ALL_PREFIXESextendr) controllers r!r r sLJ'*--.j556556r cfd}|S)Ncb|j!|jji|_|Srh)rOformat)oargskwargss r! decoratorz$_format_docstring..decorators/ 99 ( (($9&9AIr r)r8r9r:s`` r!_format_docstringr;s r i')maxsizec@tjj|S)zCSmall caching wrapper around os.path.realpath to limit system calls)ospathrealpathr$s r! _realpathrB!s 77  H %%r ) USER_APIS INTERNAL_APISc2tjS)aReturn the maximal number of threads for each detected library. Return a list with all the supported libraries that have been found. Each library is represented by a dict with the following information: - "user_api" : user API. Possible values are {USER_APIS}. - "internal_api": internal API. Possible values are {INTERNAL_APIS}. - "prefix" : filename prefix of the specific implementation. - "filepath": path to the loaded library. - "version": version of the library (if available). - "num_threads": the current thread limit. In addition, each library may contain internal_api specific entries. )r r?rr r!r r 's ! & & ((r c^eZdZdZddddZdZdZeddddZdZ e Z d Z d Z d Z y) _ThreadpoolLimiteraThe guts of ThreadpoolController.limit Refer to the docstring of ThreadpoolController.limit for more details. It will only act on the library controllers held by the provided `controller`. Using the default constructor sets the limits right away such that it can be used as a callable. Setting the limits can be delayed by using the `wrap` class method such that it can be used as a decorator. Nlimitsr7c||_|j||\|_|_|_|jj |_|jyrh) _controller _check_params_limits _user_api _prefixesr?_original_info_set_threadpool_limitsr3r3rIr7s r!r4z_ThreadpoolLimiter.__init__EsQ%7;7I7I H8 4 dndn#..335 ##%r c|SrhrrAs r! __enter__z_ThreadpoolLimiter.__enter__Ms r c$|jyrh)restore_original_limits)r3typer tracebacks r!__exit__z_ThreadpoolLimiter.__exit__Ps $$&r ct|||S)z@Return an instance of this class that can be used as a decorator)r3rIr7)_ThreadpoolLimiterDecorator)clsr3rIr7s r!wrapz_ThreadpoolLimiter.wrapSs+!&8  r ct|jj|jD]\}}|j |dy)z,Set the limits back to their original valuesr9N)ziprKlib_controllersrPrG)r3lib_controller original_infos r!rVz*_ThreadpoolLimiter.restore_original_limitsZsI-0    , ,d.A.A.  I )NM  * *=+G H Ir ci}g}|jD]{}|jDcgc]}|d|k(r|d}}t|}t|}|dk(r|j }n$|dk(rd}nt |}|j ||||<}|r*tjddj|zdz|Scc}w) zuOriginal num_threads from before calling threadpool_limits Return a dict `{user_api: num_threads}`. r7r9rwrNz1Multiple value possible for following user apis: , z. Returning the minimum.) rNrPsetlenpopminrwarningswarnjoin)r3r9 warning_apisr7lib_inforIn_limitslimits r!get_original_num_threadsz+_ThreadpoolLimiter.get_original_num_threadsds    *H!% 3 3J'83'F [F6{H1} QF ##H-$)K !# *&  MMC))L)*,-  3sB=ct|tr0|dk(r+|jjj \}}|t|t r@|t }n"|t vr|g}ntdt d|d||Dcic]}||}}g}nt|tr|Dcic] }|d|d }}n>t|tr.|jDcic]}|j|j}}t|tstdt|d|Dcgc] }|t vs |}}|Dcgc] }|t vs |}}|||fScc}wcc}wcc}wcc}wcc}w) zCSuitable values for the _limits, _user_api and _prefixes attributessequential_blas_under_openmpzuser_api must be either in z or None. Got z instead.r%r9zUlimits must either be an int, a list, a dict, or 'sequential_blas_under_openmp'. Got z instead) isinstancerrK,_get_params_for_sequential_blas_under_openmpvaluesintr/ ValueErrorlistr r`r%r9dict TypeErrorrWr1)r3rIr7apiprefixesrmrar%s r!rLz _ThreadpoolLimiter._check_paramss fc "v1O'O  MMOVVX  >Z4)^+$: 1.1Aj + !19:##v+::H&$'QWDLHX&(??F$89 +1*@*@&#))>+E+EE fd+;;?<.R.4O6v7NOHO'-G1FGHGx))9;  PGs* E'EE$ E$2E$< E) E)cF|jy|jjD]{}|j|jvr|j|j}n3|j|jvr|j|j}nh|k|j |}y)zChange the maximal number of threads in selected thread pools. Return a list with all the supported libraries that have been found matching `self._prefixes` and `self._user_api`. N)rMrKr`r%r7rG)r3rar9s r!rQz)_ThreadpoolLimiter._set_threadpool_limitss <<  "..>> +@+@A ((DLL8"ll>+B+BC &..{; Return a ThreadpoolController containing a subset of its current library controllers It will select all libraries matching at least one pair (key, value) from kwargs where key is an entry of the library info dict (like "user_api", "internal_api", "prefix", ...) and value is the value or a list of acceptable values for that entry. For instance, `ThreadpoolController().select(internal_api=["blis", "openblas"])` will select all library controllers whose internal_api is either "blis" or "openblas". c3BK|]\}}t|d|vywrh)rL)r]keyvalsras r!r_z.ThreadpoolController.select..Rs+CT2d:s)r;rsrxr`anyr r)r3r9rrrar`s ` r!selectzThreadpoolController.select?s  IIC(24(>4&DF3K I #'"6"6 !'   $55oFF s+BcP|jddjrdddSdddS)zReturn appropriate params to use for a sequential BLAS call in an OpenMP loop This function takes into account the unexpected behavior of OpenBLAS with the OpenMP threading layer. rTr)r8rkNrHrwrS)rr`rAs r!rtzAThreadpoolController._get_params_for_sequential_blas_under_openmpZs< ;;#X  / #5 500r rdc#>K|]}dj|ywz"{}"Nr6rs r!r_zThreadpoolController.gI3FMM#.IrNrHct|||S)aChange the maximal number of threads that can be used in thread pools. This function returns an object that can be used either as a callable (the construction of this object limits the number of threads) or as a context manager, in a `with` block to automatically restore the original state of the controlled libraries when exiting the block. Set the maximal number of threads that can be used in thread pools used in the supported libraries to `limits`. This function works for libraries that are already loaded in the interpreter and can be changed dynamically. This effect is global and impacts the whole Python process. There is no thread level isolation as these libraries do not offer thread-local APIs to configure the number of threads to use in nested parallel calls. Parameters ---------- limits : int, dict, 'sequential_blas_under_openmp' or None (default=None) The maximal number of threads that can be used in thread pools - If int, sets the maximum number of threads to `limits` for each library selected by `user_api`. - If it is a dictionary `{{key: max_threads}}`, this function sets a custom maximum number of threads for each `key` which can be either a `user_api` or a `prefix` for a specific library. - If 'sequential_blas_under_openmp', it will chose the appropriate `limits` and `user_api` parameters for the specific use case of sequential BLAS calls within an OpenMP parallel region. The `user_api` parameter is ignored. - If None, this function does not do anything. user_api : {USER_APIS} or None (default=None) APIs of libraries to limit. Used only if `limits` is an int. - If "blas", it will only limit BLAS supported libraries ({BLAS_LIBS}). - If "openmp", it will only limit OpenMP supported libraries ({OPENMP_LIBS}). Note that it can affect the number of threads used by the BLAS libraries if they rely on OpenMP. - If None, this function will apply to all supported libraries. rH)rGr3rIr7s r!rozThreadpoolController.limitfsf"$vIIr c#>K|]}dj|ywrrrs r!r_zThreadpoolController.rrc2tj|||S)aChange the maximal number of threads that can be used in thread pools. This function returns an object that can be used as a decorator. Set the maximal number of threads that can be used in thread pools used in the supported libraries to `limits`. This function works for libraries that are already loaded in the interpreter and can be changed dynamically. Parameters ---------- limits : int, dict or None (default=None) The maximal number of threads that can be used in thread pools - If int, sets the maximum number of threads to `limits` for each library selected by `user_api`. - If it is a dictionary `{{key: max_threads}}`, this function sets a custom maximum number of threads for each `key` which can be either a `user_api` or a `prefix` for a specific library. - If None, this function does not do anything. user_api : {USER_APIS} or None (default=None) APIs of libraries to limit. Used only if `limits` is an int. - If "blas", it will only limit BLAS supported libraries ({BLAS_LIBS}). - If "openmp", it will only limit OpenMP supported libraries ({OPENMP_LIBS}). Note that it can affect the number of threads used by the BLAS libraries if they rely on OpenMP. - If None, this function will apply to all supported libraries. rH)rGr]rs r!r]zThreadpoolController.wrapsN"&&tFX&NNr c,t|jSrh)rfr`rAs r!__len__zThreadpoolController.__len__s4''((r ctjdk(r|jytjdk(r|jydtjvr|j y|j y)zALoop through loaded shared libraries and store the supported onesdarwinwin32pyodideN)sysplatform_find_libraries_with_dyld+_find_libraries_with_enum_process_module_exmodules_find_libraries_pyodide$_find_libraries_with_dl_iterate_phdrrAs r!rz$ThreadpoolController._load_librariessV <<8 #  * * , \\W $  < < > #++ %  ( ( *  5 5 7r cj}t|dstjdtgSfd}t j t jt jtt jt j}||}t jd}|j||y)anLoop through loaded libraries and return binders on supported ones This function is expected to work on POSIX system only. This code is adapted from code by Intel developer @anton-malakhov available at https://github.com/IntelPython/smp Copyright (c) 2017, Intel Corporation published under the BSD 3-Clause license dl_iterate_phdrz9Could not find dl_iterate_phdr in the C standard library.cz|jj}|r"|jd}j|y)Nrxr)contentsrr{_make_controller_from_path)r?sizedatar$r3s r!match_library_callbackzYThreadpoolController._find_libraries_with_dl_iterate_phdr..match_library_callbacks6}}..H#??73//9r r N) _get_libcrfrirjRuntimeWarningr CFUNCTYPErPOINTERrc_size_trr)r3libcrc_func_signaturec_match_library_callbackrs` r!rz9ThreadpoolController._find_libraries_with_dl_iterate_phdrs~~t./ MMK I "++ LL NN= ) OO OO   $44J#K s# 5tgetpidOSErrorrrEnumProcessModulesExrrmapcreate_unicode_bufferGetModuleFileNameExWrfrirjrr CloseHandle)r3rrrPROCESS_QUERY_INFORMATIONPROCESS_VM_READLIST_LIBRARIES_ALLps_api kernel_32 h_process buf_countneededbufbuf_sizecount h_modulesmax_pathn_sizeh_moduler$s r!rz@ThreadpoolController._find_libraries_with_enum_process_module_exs  =<$*! !!!'*$$Z0 )) % 7  / }=> >1 -IWF*w*-!==-22LL%LL(& ""?@@v||+"LLX-BC LLX%:;EGS%[1I H}H..x8CWF% >22xc):FLL??99x=H,MMHIQ|U' 33H=% >(  ! !) ,I ! !) ,s >E)G::H c ddlm}|j j D]3}tjj|s#|j|5y#t$rtjdYywxYw)aPyodide specific implementation for finding loaded libraries. Adapted from suggestion in https://github.com/joblib/threadpoolctl/pull/169#issuecomment-1946696449. One day, we may have a simpler solution. libc dl_iterate_phdr needs to be implemented in Emscripten and exposed in Pyodide, see https://github.com/emscripten-core/emscripten/issues/21354 for more details. r)LDSOzHUnable to import LDSO from pyodide_js._module. This should never happen.N) pyodide_js._moduler ImportErrorrirjloadedLibsByName as_object_mapr>r?existsr)r3rr$s r!rz,ThreadpoolController._find_libraries_pyodide\sq  /--;;= :H ww~~h'//9  :  MM    sAA:9A:c:t|}tjj|j }t D]}|j ||j}|"|dk(rK|jdr9tj|ttfd|jDsqr|||||d|jDvrt|drtfd|jDs|jj!y) z:Store a library controller if it is supported and selectedNrV.dllc36K|]}t|ywrh)rf)r]funcrVs r!r_zBThreadpoolController._make_controller_from_path..s   .sr#c34K|]}|jywrhrAr)s r!r_zBThreadpoolController._make_controller_from_path..sISCLLIr+rc3JK|]}tj|ywrh)rfr,)r]rras r!r_zBThreadpoolController._make_controller_from_path..s(E--t4Es #)rBr>r?basenamelowerr. _check_prefixrendswithrr*r+rrr`rfr)r3r$filenamecontroller_classr%rarVs @@r!rz/ThreadpoolController._make_controller_from_pathwsX&77##H-335!1. < ''2B2T2TUF~ "$$V,$kk(LAG$4$B$B!.!&NID4H4HII+_=E,::EB$$++N;]. r rrrbrtypingrri ctypes.utilrabcrr functoolsr contextlibr __version____all__environ setdefaultr<c_uint64c_uint32rc_uint16r Structurer RTLD_NOLOADr+AttributeError DEFAULT_MODEr rRrrrrr.rxrer/r8r0r1r7r rr r r;rBr rGr[rkr r r(r)r*s0r!r:s $#'  ( ,f5#&++"5v6?? '*{{U':FOOF$$'>>L X CX vEEP<D]<D~}L-}L@52M52p}6 cC2BCCD2BC3c&&CO*OO !1CLLF4JC)::7 5&& T.1AST)U)$V<V