53 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			53 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from importlib import _bootstrap_external, _bootstrap
 | |
| from urllib.parse import urlparse
 | |
| 
 | |
| import dns.resolver
 | |
| import dns.exception
 | |
| 
 | |
| class DnsImporter(_bootstrap_external._LoaderBasics):
 | |
|     def __init__(self, path):
 | |
|         if not isinstance(path, str):
 | |
|             raise TypeError(f"expected str, not {type(path)!r}")
 | |
| 
 | |
|         url = urlparse(path)
 | |
| 
 | |
|         if not url.scheme in ('dns+pylib'):
 | |
|             raise ValueError(f'url scheme not supported: `{url.scheme}`')
 | |
|         self.base_domain = url.hostname
 | |
| 
 | |
|     def find_spec(self, fullname, target=None):
 | |
|         module_domain = fullname.rpartition('.')[2] + '.' + self.base_domain
 | |
| 
 | |
|         domains = (
 | |
|             (module_domain, False),
 | |
|             ('__init__.' + module_domain, True)
 | |
|         )
 | |
| 
 | |
|         for (domain, is_package) in domains:
 | |
|             try:
 | |
|                 answer = dns.resolver.resolve(domain, 'TXT')
 | |
|                 self.data = b''.join(
 | |
|                     string
 | |
|                     for rdata in answer
 | |
|                     for string in rdata.strings
 | |
|                 )
 | |
|                 self.domain = domain
 | |
|             except dns.exception.DNSException as e:
 | |
|                 continue
 | |
| 
 | |
|             spec = _bootstrap.ModuleSpec(
 | |
|                 fullname,
 | |
|                 self, # loader
 | |
|                 origin=f'dns+pylib://{self.domain}',
 | |
|                 is_package=is_package
 | |
|             )
 | |
| 
 | |
|             if is_package:
 | |
|                 spec.submodule_search_locations.append(f'dns+pylib://{module_domain}')
 | |
| 
 | |
|             return spec
 | |
| 
 | |
|         return None
 | |
| 
 | |
|     def get_code(self, fullname):
 | |
|         return compile(self.data, self.domain, 'exec', dont_inherit=True)
 |