From 6aab8e27fa7832fd73bf8e1e27ff356490e9dd94 Mon Sep 17 00:00:00 2001 From: Alexander Grooff Date: Fri, 8 Jan 2021 15:32:51 +0100 Subject: [PATCH 1/2] Reify object from base type The currect assumption that `object` can be used to create a new object is not always valid. One example is the issue I'm currently facing: ``` >>> reify(ast.Num(n=var('x')), {var('x'): 123}) ... 55 def _reify_object_dict(o, s): ---> 56 obj = object.__new__(type(o)) 57 58 d = yield _reify(o.__dict__, s) TypeError: object.__new__(Num) is not safe, use Num.__new__() ``` --- tests/test_more.py | 8 ++++++++ unification/more.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_more.py b/tests/test_more.py index 30e5a6a..38c5923 100644 --- a/tests/test_more.py +++ b/tests/test_more.py @@ -1,3 +1,4 @@ +from ast import Num from collections.abc import Mapping from unification import var @@ -29,6 +30,13 @@ def test_unify_object(): assert stream_eval(_unify_object(Foo(1, 2), Foo(1, x), {})) == {x: 2} +def test_unify_nonstandard_object(): + x = var() + assert stream_eval(_unify_object(Num(n=1), Num(n=1), {})) == {} + assert stream_eval(_unify_object(Num(n=1), Num(n=2), {})) is False + assert stream_eval(_unify_object(Num(n=1), Num(n=x), {})) == {x: 1} + + def test_reify_object(): x = var() obj = stream_eval(_reify_object(Foo(1, x), {x: 4})) diff --git a/unification/more.py b/unification/more.py index 0922284..071e638 100644 --- a/unification/more.py +++ b/unification/more.py @@ -53,7 +53,7 @@ def _reify_object(o, s): def _reify_object_dict(o, s): - obj = object.__new__(type(o)) + obj = type(o).__new__(type(o)) d = yield _reify(o.__dict__, s) From 50f326c0b9fa9ee0dbd7d47573d98c3a1f02b4e2 Mon Sep 17 00:00:00 2001 From: Alexander Grooff Date: Sat, 9 Jan 2021 11:05:05 +0100 Subject: [PATCH 2/2] Test both unify and reifying nonstandard objects Change from the previous commit only affects reifying nonstandard objects, so this change better reflects the new situation. Use the base `unify` and `reify` functions to test instead of the private functions. --- tests/test_more.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/test_more.py b/tests/test_more.py index 38c5923..440c1be 100644 --- a/tests/test_more.py +++ b/tests/test_more.py @@ -1,4 +1,4 @@ -from ast import Num +import ast from collections.abc import Mapping from unification import var @@ -31,10 +31,11 @@ def test_unify_object(): def test_unify_nonstandard_object(): + _unify.add((ast.AST, ast.AST, Mapping), _unify_object) x = var() - assert stream_eval(_unify_object(Num(n=1), Num(n=1), {})) == {} - assert stream_eval(_unify_object(Num(n=1), Num(n=2), {})) is False - assert stream_eval(_unify_object(Num(n=1), Num(n=x), {})) == {x: 1} + assert unify(ast.Num(n=1), ast.Num(n=1), {}) == {} + assert unify(ast.Num(n=1), ast.Num(n=2), {}) is False + assert unify(ast.Num(n=1), ast.Num(n=x), {}) == {x: 1} def test_reify_object(): @@ -47,6 +48,14 @@ def test_reify_object(): assert stream_eval(_reify_object(f, {})) is f +def test_reify_nonstandard_object(): + _reify.add((ast.AST, Mapping), _reify_object) + x = var() + assert reify(ast.Num(n=1), {}).n == 1 + assert reify(ast.Num(n=x), {}).n == x + assert reify(ast.Num(n=x), {x: 2}).n == 2 + + def test_reify_slots(): class SlotsObject(object): __slots__ = ["myattr"]