Last active
September 23, 2021 09:11
-
-
Save vrthra/66b514b0ec6aa12838e60bade230832d to your computer and use it in GitHub Desktop.
Import Module.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# --- | |
# published: true | |
# title: Importing Python Modules | |
# layout: post | |
# comments: true | |
# tags: python | |
# categories: post | |
# --- | |
# In the [previous post](/post/2018/09/06/peg-parsing/) I discussed how to | |
# implement simple parsing expression grammar based parsing, and I mentioned | |
# that the notebook is available in [runnable source form](https://github.com/rahulgopinath/rahulgopinath.github.io/blob/master/notebooks/2018-09-06-peg-parsing.py). | |
# This brings a question however. How do we make use of this notebook in later | |
# posts? | |
import sys, os, ast | |
import types | |
import importlib.abc | |
import importlib.machinery | |
class MetaPathFinderInWeb(importlib.abc.MetaPathFinder): | |
def __init__(self, loaders): self._loaders = loaders | |
def find_spec(self, fullname, path, target=None): | |
for loader in self._loaders: | |
if self._loaders[loader].has(fullname): | |
return importlib.machinery.ModuleSpec(fullname, self._loaders[loader]) | |
return None | |
class LocalLoader(importlib.abc.SourceLoader): | |
def __init__(self): | |
self.locations = {} | |
def get_data(self, m_loc): | |
#m_loc = './notebooks/%s' % m_loc | |
with open(m_loc, encoding='utf-8') as f: return f.read() | |
def get_filename(self, fullname): | |
return self.locations[fullname] | |
def has(self, fullname): return fullname in self.locations | |
class WebLoader(importlib.abc.SourceLoader): | |
def __init__(self): | |
self.locations = {} | |
def get_data(self, m_loc): | |
import urllib.request | |
github_repo = 'https://raw.githubusercontent.com/' | |
my_repo = 'rahulgopinath/rahulgopinath.github.io' | |
m_loc = github_repo + my_repo + '/master/notebooks/%s' % m_loc | |
return urllib.request.urlopen(m_loc).read() | |
def get_filename(self, fullname): | |
return self.locations[fullname] | |
def has(self, fullname): return fullname in self.locations | |
class PyodideLoader(importlib.abc.SourceLoader): | |
def __init__(self): | |
self.locations = {} | |
def get_data(self, m_loc): | |
if "pyodide" not in sys.modules: return None | |
import pyodide | |
github_repo = 'https://raw.githubusercontent.com/' | |
my_repo = 'rahulgopinath/rahulgopinath.github.io' | |
m_loc = github_repo + my_repo + '/master/notebooks/%s' % m_loc | |
return pyodide.open_url(m_loc).getvalue() | |
def get_filename(self, fullname): | |
return self.locations[fullname] | |
def has(self, fullname): return fullname in self.locations | |
class MyLoader(importlib.abc.Loader): | |
def __init__(self): | |
self.services = {} | |
def has(self, fullname): return fullname in self.services | |
def create_module(self, spec): return self.services[spec.name] | |
def exec_module(self, module): pass | |
def register(self, m_name, m_loc): | |
mod_name, module = self.make_module(m_name, m_loc) | |
if mod_name is None: | |
m_loc | |
self.services[mod_name] = module | |
def get_module_src(self, m_loc): | |
if "pyodide" in sys.modules: | |
import pyodide | |
github_repo = 'https://raw.githubusercontent.com/' | |
my_repo = 'rahulgopinath/rahulgopinath.github.io' | |
m_loc = github_repo + my_repo + '/master/notebooks/%s' % location | |
module_str = pyodide.open_url(m_loc).getvalue() | |
else: | |
m_loc = './notebooks/%s' % m_loc | |
with open(m_loc, encoding='utf-8') as f: return f.read() | |
def make_module(self, m_name, m_loc): | |
myast = ast.parse(self.get_module_src(m_loc), filename=m_loc, mode='exec') | |
assert myast.body[-1].targets[0].id == '__MODULE_NAME__' | |
mod_name = myast.body[-1].value.s | |
codeobj = compile(myast, m_loc, 'exec') | |
assert codeobj.co_consts[-1] == mod_name | |
newmodule = types.ModuleType(m_name) | |
#newmodule = imp.new_module(m_name) | |
exec(codeobj, newmodule.__dict__) | |
return newmodule.__dict__.get('__MODULE_NAME__', None), newmodule | |
class Importer: | |
def __init__(self): | |
self._loader = {'my':MyLoader(), 'local':LocalLoader(), 'web': WebLoader(), 'pyodide': PyodideLoader()} | |
sys.meta_path.append(MetaPathFinderInWeb(self._loader)) | |
def register(self, m_name, m_loc): | |
self._loader['my'].register(m_name, m_loc) | |
#if os.path.exists(m_loc): | |
# self._loader['local'].locations[m_name] = m_loc | |
#elif "pyodide" in sys.modules: | |
# self._loader['pyodide'].locations[m_name] = m_loc | |
#else: | |
# self._loader['web'].locations[m_name] = m_loc | |
importer = Importer() | |
importer.register("pegparser", '2018-09-06-peg-parsing.py') | |
import pegparser | |
print(pegparser.term_grammar) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment