Commit 0c1ec588 authored by Romain Casati's avatar Romain Casati
Browse files

hacked -> patched.

parent eb596af7
from . import kernel as __kernel__
from . import _hack_builtins
from . import _patch_builtins
__author__ = "Romain Casati"
......@@ -14,8 +14,8 @@ display = __kernel__.display
download = __kernel__.download
_hack_builtins.hack_all()
_patch_builtins.patch_all()
# avoid poluting __dict__
del _hack_builtins
del _patch_builtins
......@@ -136,7 +136,7 @@ class InteractiveConsole(_pyodide_console.InteractiveConsole):
pass
print(error, file=sys.stderr, flush=True)
return packages.load_and_hack(pkgs).catch(errorCallback).then(run)
return packages.load_and_patch(pkgs).catch(errorCallback).then(run)
def eval(self, code, stdout_callback, stderr_callback, data=None):
"""
......
......@@ -11,14 +11,14 @@ __license__ = "GNU GPL v3"
__email__ = "romain.casati@basthon.fr"
__all__ = ['hack_input', 'hack_help', 'hack_six']
__all__ = ['patch_input', 'patch_help', 'patch_six']
def hack_input():
""" Hacking Pyodide bugy input function. """
def patch_input():
""" Patching Pyodide bugy input function. """
_default_input = builtins.input
def _hacked_input(prompt=None):
def _patched_input(prompt=None):
if prompt is not None:
print(prompt, end='', flush=True)
res = window.prompt(prompt)
......@@ -28,16 +28,16 @@ def hack_input():
# copying all writable attributes (usefull to keep docstring and name)
for a in dir(_default_input):
try:
setattr(_hacked_input, a, getattr(_default_input, a))
setattr(_patched_input, a, getattr(_default_input, a))
except Exception:
pass
# replacing
builtins.input = _hacked_input
builtins.input = _patched_input
def hack_help():
""" Hacking help function.
def patch_help():
""" Patching help function.
See pydoc.py in cpython:
https://github.com/python/cpython/blob/master/Lib/pydoc.py
......@@ -47,7 +47,7 @@ def hack_help():
"""
_default_help = pydoc.help
def _hacked_help(*args, **kwargs):
def _patched_help(*args, **kwargs):
backup = sys.builtin_module_names
to_add = list(packages._all_pkgs)
to_add.append('js')
......@@ -56,10 +56,10 @@ def hack_help():
sys.builtin_module_names = backup
return res
pydoc.help = _hacked_help
pydoc.help = _patched_help
def hack_six():
def patch_six():
"""
In pyodide 0.16.1, six is installed under
/lib/python3.8/site-packages/six.py
......@@ -69,14 +69,14 @@ def hack_six():
To fix this, we move six.py under /lib/python3.8/
"""
path = Path('/lib/python3.8/site-packages/six.py')
assert path.exists(), "If you see this, hack_six should be useless."
assert path.exists(), "If you see this, patch_six should be useless."
path.rename('/lib/python3.8/six.py')
def hack_all():
def patch_all():
"""
Hack all builtins by calling all hack_* methods.
Patch all builtins by calling all patch_* methods.
"""
for name, method in globals().items():
if name.startswith('hack_') and name != 'hack_all':
if name.startswith('patch_') and name != 'patch_all':
method()
......@@ -7,24 +7,24 @@ __license__ = "GNU GPL v3"
__email__ = "romain.casati@basthon.fr"
def hack_matplotlib():
def patch_matplotlib():
"""
Hack the Wasm backend of matplotlib to render figures.
Patch the Wasm backend of matplotlib to render figures.
"""
from matplotlib.backends.wasm_backend import FigureCanvasWasm as wasm_backend
# already hacked?
# already patched?
if hasattr(wasm_backend, "_original_show"):
return
# hacking root node creation
# patching root node creation
def create_root_element(self):
self.root = document.createElement("div")
return self.root
wasm_backend.create_root_element = create_root_element
# hacking element getter carefuly addressing the case where the
# patching element getter carefuly addressing the case where the
# root node is not yet added to the DOM
def get_element(self, name):
if name == "" or not hasattr(self, "root"):
......@@ -35,7 +35,7 @@ def hack_matplotlib():
wasm_backend.get_element = get_element
# hacking show
# patching show
wasm_backend._original_show = wasm_backend.show
def show(self):
......@@ -48,13 +48,13 @@ def hack_matplotlib():
wasm_backend.show = show
def hack_turtle():
def patch_turtle():
"""
Hack Turtle to render figures.
Patch Turtle to render figures.
"""
from turtle import Screen
# hacking show_scene
# patching show_scene
if not hasattr(Screen, "_original_show_scene"):
Screen._original_show_scene = Screen.show_scene
......@@ -69,9 +69,9 @@ def hack_turtle():
Screen.show_scene = show_scene
def hack_sympy():
def patch_sympy():
"""
Hack Sympy to render expression using LaTeX (and probably MathJax).
Patch Sympy to render expression using LaTeX (and probably MathJax).
"""
import sympy
......@@ -86,9 +86,9 @@ def hack_sympy():
sympy.pretty_print = pretty_print
def hack_folium():
def patch_folium():
"""
Hack Folium to render maps.
Patch Folium to render maps.
"""
from folium import Map
......@@ -101,9 +101,9 @@ def hack_folium():
Map.display = display
def hack_pandas():
def patch_pandas():
"""
Hack Pandas to render data frames.
Patch Pandas to render data frames.
"""
from pandas import DataFrame
......@@ -116,7 +116,7 @@ def hack_pandas():
DataFrame.display = display
def hack_PIL():
def patch_PIL():
from PIL import Image, ImageShow
import io
from base64 import b64encode
......@@ -138,7 +138,7 @@ def hack_PIL():
ImageShow.register(basthonviewer)
def hack_scipy():
def patch_scipy():
"""
Add support for:
* scipy.integrate.solve_ivp from the Basthon's ivp module
......@@ -212,7 +212,7 @@ def hack_scipy():
scipy.integrate.odeint.__doc__ = scipy.integrate._odeint.__doc__
def hack_qrcode():
def patch_qrcode():
"""
* Adding `_repr_svg_` and `show` to qrcode svg images.
* Fix issue in `qrcode.image.svg.SvgPathImage._write`
......@@ -285,12 +285,12 @@ def hack_qrcode():
svg.SvgFragmentImage.download = meta_download('.svg')
def hack(modules):
""" Hack a list of modules. """
def patch(modules):
""" Patch a list of modules. """
if isinstance(modules, str):
modules = (modules,)
for module in modules:
hack_func = globals().get(f"hack_{module}")
if callable(hack_func):
hack_func()
patch_func = globals().get(f"patch_{module}")
if callable(patch_func):
patch_func()
......@@ -112,7 +112,7 @@ def put_module(filename, content):
file_finder.invalidate_caches()
pkgs = packages.find_imports(content)
return packages.load_and_hack(pkgs).then(callback)
return packages.load_and_patch(pkgs).then(callback)
def user_modules():
......
......@@ -6,7 +6,7 @@ It manage Pyodide and Basthon's modules load.
import pyodide
import js
from . import _hack_modules
from . import _patch_modules
from .utils import OrderedSet
......@@ -15,7 +15,7 @@ __license__ = "GNU GPL v3"
__email__ = "romain.casati@basthon.fr"
__all__ = ["find_imports", "load_and_hack"]
__all__ = ["find_imports", "load_and_patch"]
# Link to useful pyodide's dict
......@@ -69,7 +69,7 @@ _internal_pkgs_dict = {
},
"qrcode": {
"path": "qrcode", # loaded from PyPi
"deps": ["PIL"], # to force hacking
"deps": ["PIL"], # to force patching
},
}
......@@ -125,8 +125,8 @@ def _internal_dependencies(packages):
return OrderedSet.union(*(dependencies(p) for p in packages)) - packages
def load_and_hack(packages):
""" Load and hack modules (internal or Pyodide). """
def load_and_patch(packages):
""" Load and patch modules (internal or Pyodide). """
if isinstance(packages, str):
packages = [packages]
......@@ -136,7 +136,7 @@ def load_and_hack(packages):
if not packages:
return js.Promise.resolve()
# last dependencies first to ensure deps are resolved when hacking
# last dependencies first to ensure deps are resolved when patching
# the order is guarenteed by our OrderedSet
packages = reversed(packages | _internal_dependencies(packages))
pyodide_packages = packages & _pyodide_pkgs
......@@ -145,7 +145,7 @@ def load_and_hack(packages):
def callback(*args):
if packages:
_loaded.update(packages)
_hack_modules.hack(packages)
_patch_modules.patch(packages)
return getattr(js.Promise.all((_load_pyodide(pyodide_packages),
_load_internal(internal_packages))),
......
......@@ -88,10 +88,10 @@ def request(method, url, **kwargs):
cors_message = " Requested URL is not on this domain. You may have CORS issue."
raise ConnectionError(f"{error.js_error.toString()}{cors_message} Please check error message in browser console.")
req._hacked_send = send
req._hacked_onerror = onerror
req._patched_send = send
req._patched_onerror = onerror
# big hack since try/catch of JS code is not available on Python side
js.eval("try { __basthon_req._hacked_send(); } catch (e) { __basthon_req._hacked_onerror(e); }")
js.eval("try { __basthon_req._patched_send(); } catch (e) { __basthon_req._patched_onerror(e); }")
return Response(req)
......
......@@ -19,12 +19,12 @@ def test_all(selenium):
def test_turtle(selenium):
# already tested in test_hacked_modules
# already tested in test_patched_modules
assert True
def test_folium(selenium):
# already tested in test_hacked_modules
# already tested in test_patched_modules
assert True
......@@ -153,10 +153,10 @@ tutor()""")
def test__ivp(selenium):
# this is tested in test_hacked_modules.test_scipy via odeint
# this is tested in test_patched_modules.test_scipy via odeint
pass
def test_qrcode(selenium):
# already tested in test_hacked_modules
# already tested in test_patched_modules
assert True
......@@ -3,7 +3,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
def test_hack_input(selenium):
def test_patch_input(selenium):
selenium.run_basthon_detach("int(input('How old are you?'))")
driver = selenium.driver
wait = WebDriverWait(driver, 10)
......@@ -15,7 +15,7 @@ def test_hack_input(selenium):
assert result == "42"
def test_hack_modules(selenium):
def test_patch_modules(selenium):
data = selenium.run_basthon("help('modules')")
assert 'result' not in data['result'] and data['stderr'] == ""
# to easily update modules.txt in case a package is added
......@@ -25,7 +25,7 @@ def test_hack_modules(selenium):
assert data['stdout'] == f.read()
def test_hack_six(selenium):
def test_patch_six(selenium):
data = selenium.run_basthon("""
from pathlib import Path
......
......@@ -6,15 +6,15 @@ _test_data = Path(__file__).parent / "data"
def test_all(selenium):
# ensure all hacked modules are tested
# ensure all patched modules are tested
tested = set(g[len('test_'):] for g in globals()
if g.startswith('test_') and g != 'test_all')
result = selenium.run_basthon("""
from basthon import _hack_modules
set(g[len('hack_'):] for g in dir(_hack_modules)
if g.startswith('hack_'))""")['result']
hacked = eval(result['result']['text/plain'])
assert tested == hacked
from basthon import _patch_modules
set(g[len('patch_'):] for g in dir(_patch_modules)
if g.startswith('patch_'))""")['result']
patched = eval(result['result']['text/plain'])
assert tested == patched
def test_PIL(selenium):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment