Skip to content

Commit ccc0cdd

Browse files
committed
[GR-16805] [GR-16806] type.__base__ and GraalPythonVM env support
PullRequest: graalpython/572
2 parents afa6ab1 + 92afe4d commit ccc0cdd

File tree

6 files changed

+161
-7
lines changed

6 files changed

+161
-7
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
41+
def test_base():
42+
A = type('A', (), {})
43+
assert A.__base__ == object
44+
45+
# class B:
46+
# def ham(self):
47+
# return 'ham%d' % self
48+
#
49+
# class A(object):
50+
# pass
51+
#
52+
# class B(dict):
53+
# pass
54+
#
55+
# class C(A, B):
56+
# pass
57+
#
58+
# assert C.__base__ == B
59+
#
60+
# class A(object):
61+
# pass
62+
#
63+
# class B(object):
64+
# pass
65+
#
66+
# class C(A, B):
67+
# pass
68+
#
69+
# assert C.__base__ == A
70+
#
71+
# C = type('C', (B, int), {'spam': lambda self: 'spam%s' % self})
72+
# assert C.__base__ == int

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
package com.oracle.graal.python.builtins.objects.type;
2828

2929
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASES__;
30+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASE__;
3031
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__;
3132
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASS__;
3233
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__;
@@ -464,6 +465,16 @@ Object bases(LazyPythonClass self,
464465
}
465466
}
466467

468+
@Builtin(name = __BASE__, minNumOfPositionalArgs = 1, isGetter = true)
469+
@GenerateNodeFactory
470+
abstract static class BaseNode extends PythonBuiltinNode {
471+
@Specialization
472+
Object base(LazyPythonClass self,
473+
@Cached("create()") TypeNodes.GetBaseClassNode getBaseClassNode) {
474+
return getBaseClassNode.execute(self);
475+
}
476+
}
477+
467478
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, isGetter = true)
468479
@GenerateNodeFactory
469480
@ImportStatic(NativeMemberNames.class)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeNodes.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
4444
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
45+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
4546

4647
import java.util.ArrayList;
4748
import java.util.Collection;
@@ -66,6 +67,7 @@
6667
import com.oracle.graal.python.builtins.objects.dict.PDict;
6768
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
6869
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass.FlagsContainer;
70+
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassNodeGen;
6971
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetBaseClassesNodeGen;
7072
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetInstanceShapeNodeGen;
7173
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.GetMroStorageNodeGen;
@@ -574,6 +576,49 @@ private static PythonAbstractClass[] cast(Object[] arr) {
574576

575577
}
576578

579+
@ImportStatic(NativeMemberNames.class)
580+
public abstract static class GetBaseClassNode extends PNodeWithContext {
581+
582+
public abstract PythonAbstractClass execute(Object obj);
583+
584+
@Specialization
585+
PythonAbstractClass doPythonClass(PythonManagedClass obj,
586+
@Cached PRaiseNode raise) {
587+
PythonAbstractClass[] baseClasses = obj.getBaseClasses();
588+
if (baseClasses.length == 1) {
589+
return baseClasses[0];
590+
}
591+
throw raise.raise(NotImplementedError, "get bestBase case not yet implemented");
592+
}
593+
594+
@Specialization
595+
PythonAbstractClass doPythonClass(PythonBuiltinClassType obj,
596+
@Cached PRaiseNode raise,
597+
@CachedContext(PythonLanguage.class) PythonContext context) {
598+
PythonAbstractClass[] baseClasses = context.getCore().lookupType(obj).getBaseClasses();
599+
if (baseClasses.length == 1) {
600+
return baseClasses[0];
601+
}
602+
throw raise.raise(NotImplementedError, "get bestBase case not yet implemented");
603+
}
604+
605+
@Specialization
606+
PythonAbstractClass doNative(PythonNativeClass obj,
607+
@Cached PRaiseNode raise,
608+
@Cached GetTypeMemberNode getTpBaseNode,
609+
@Cached("createClassProfile()") ValueProfile resultTypeProfile) {
610+
Object result = resultTypeProfile.profile(getTpBaseNode.execute(obj, NativeMemberNames.TP_BASE));
611+
if (result instanceof PythonAbstractClass) {
612+
return (PythonAbstractClass) result;
613+
}
614+
throw raise.raise(PythonBuiltinClassType.SystemError, "type does not provide __base__");
615+
}
616+
617+
public static GetBaseClassNode create() {
618+
return GetBaseClassNodeGen.create();
619+
}
620+
}
621+
577622
@ImportStatic(SpecialMethodNames.class)
578623
public abstract static class IsSameTypeNode extends PNodeWithContext {
579624

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public abstract class SpecialAttributeNames {
5353
public static final String __MODULE__ = "__module__";
5454
public static final String __DICT__ = "__dict__";
5555
public static final String __CLASS__ = "__class__";
56+
public static final String __BASE__ = "__base__";
5657
public static final String __BASES__ = "__bases__";
5758
public static final String __NAME__ = "__name__";
5859
public static final String __QUALNAME__ = "__qualname__";

graalpython/lib-graalpython/type.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0

mx.graalpython/mx_graalpython_benchmark.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import mx_benchmark
3434
from mx_benchmark import StdOutRule, java_vm_registry, Vm, GuestVm, VmBenchmarkSuite, AveragingBenchmarkMixin
3535
from mx_graalpython_bench_param import HARNESS_PATH
36+
from contextlib import contextmanager
3637

3738
# ----------------------------------------------------------------------------------------------------------------------
3839
#
@@ -75,6 +76,27 @@ def _check_vm_args(name, args):
7576
"got {} instead".format(args))
7677

7778

79+
@contextmanager
80+
def environ(env):
81+
def _handle_var((k, v)):
82+
if v is None:
83+
del os.environ[k]
84+
else:
85+
os.environ[k] = str(v)
86+
87+
if env:
88+
prev_env = {v: os.getenv(v) for v in env}
89+
map(_handle_var, env.items())
90+
else:
91+
prev_env = None
92+
93+
try:
94+
yield
95+
finally:
96+
if prev_env:
97+
map(_handle_var, prev_env.items())
98+
99+
78100
# ----------------------------------------------------------------------------------------------------------------------
79101
#
80102
# the vm definitions
@@ -194,14 +216,15 @@ def name(self):
194216

195217
class GraalPythonVm(GuestVm):
196218
def __init__(self, config_name=CONFIGURATION_DEFAULT, distributions=None, cp_suffix=None, cp_prefix=None,
197-
host_vm=None, extra_vm_args=None, extra_polyglot_args=None):
219+
host_vm=None, extra_vm_args=None, extra_polyglot_args=None, env=None):
198220
super(GraalPythonVm, self).__init__(host_vm=host_vm)
199221
self._config_name = config_name
200222
self._distributions = distributions
201223
self._cp_suffix = cp_suffix
202224
self._cp_prefix = cp_prefix
203225
self._extra_vm_args = extra_vm_args
204226
self._extra_polyglot_args = extra_polyglot_args
227+
self._env = env
205228

206229
def hosting_registry(self):
207230
return java_vm_registry
@@ -240,10 +263,11 @@ def run(self, cwd, args):
240263
cmd = truffle_options + vm_args + extra_polyglot_args + args
241264

242265
host_vm = self.host_vm()
243-
if hasattr(host_vm, 'run_lang'):
244-
return host_vm.run_lang('graalpython', extra_polyglot_args + args, cwd)
245-
else:
246-
return host_vm.run(cwd, cmd)
266+
with environ(self._env):
267+
if hasattr(host_vm, 'run_lang'):
268+
return host_vm.run_lang('graalpython', extra_polyglot_args + args, cwd)
269+
else:
270+
return host_vm.run(cwd, cmd)
247271

248272
def name(self):
249273
return VM_NAME_GRAALPYTHON
@@ -254,7 +278,8 @@ def config_name(self):
254278
def with_host_vm(self, host_vm):
255279
return self.__class__(config_name=self._config_name, distributions=self._distributions,
256280
cp_suffix=self._cp_suffix, cp_prefix=self._cp_prefix, host_vm=host_vm,
257-
extra_vm_args=self._extra_vm_args, extra_polyglot_args=self._extra_polyglot_args)
281+
extra_vm_args=self._extra_vm_args, extra_polyglot_args=self._extra_polyglot_args,
282+
env=self._env)
258283

259284

260285
# ----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)