Skip to content

Commit ecd9a8a

Browse files
aiskcclauss
andauthored
fix: pypy3 support (webpy#731)
* fix: pypy3 support * refactor: only override builtin in pypy * chore: fix github actions for pypy * fix: invalid overridden in pypy Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent c6b5656 commit ecd9a8a

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

.github/workflows/lint_python.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ jobs:
3131
strategy:
3232
fail-fast: false
3333
matrix:
34-
# TODO: (cclauss) add pypy3 https://github.com/webpy/webpy/issues/598
35-
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11-dev"] # , pypy3]
34+
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11-dev", "pypy-3.9"]
3635

3736
steps:
3837
- uses: actions/checkout@v3

tests/test_template.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ def testAttr(self):
3838
t("$code:\n foo = {'a': 1}.items()")()
3939
t("$code:\n bar = {k:0 for k in [1,2,3]}")()
4040

41+
def test_overridden(self):
42+
tpl = "$print('blah')"
43+
f = t(tpl, globals={"print": lambda x: x})
44+
assert repr(f()) == "'blah\\n'"
45+
4146

4247
class TestRender:
4348
def test_template_without_ext(self, tmpdir):

web/template.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@
2929
"""
3030

3131
import ast
32+
import builtins
3233
import glob
3334
import os
3435
import sys
3536
import tokenize
3637
from io import open
37-
import builtins
38+
from functools import partial
3839

3940
from .net import websafe
4041
from .utils import re_compile, safestr, safeunicode, storage
@@ -878,10 +879,21 @@ def __call__(self, *a, **kw):
878879
__hidetraceback__ = True # noqa: F841
879880
return self.t(*a, **kw)
880881

881-
def make_env(self, globals, builtins):
882+
def make_env(self, globals, builtins_):
883+
if sys.implementation.name == "pypy":
884+
# Pypy's `__builtins__` can't be overridden in exec. More details see issue #598.
885+
overridden_builtins = builtins.__dict__.keys() - builtins_.keys()
886+
887+
def f(name, *args, **kwargs):
888+
raise NameError("name '%s' is not defined" % name)
889+
890+
for name in overridden_builtins:
891+
if name not in globals:
892+
globals[name] = partial(f, name)
893+
882894
return dict(
883895
globals,
884-
__builtins__=builtins,
896+
__builtins__=builtins_,
885897
ForLoop=ForLoop,
886898
TemplateResult=TemplateResult,
887899
escape_=self._escape,

0 commit comments

Comments
 (0)