Skip to content

Instantly share code, notes, and snippets.

@vrthra
Last active September 23, 2021 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vrthra/66b514b0ec6aa12838e60bade230832d to your computer and use it in GitHub Desktop.
Save vrthra/66b514b0ec6aa12838e60bade230832d to your computer and use it in GitHub Desktop.
Import Module.
# ---
# 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