From 838e7f07ff3ae494fd39d42879e8c2daf933ae92 Mon Sep 17 00:00:00 2001 From: Atila Neves Date: Sun, 1 Dec 2019 12:44:19 +0100 Subject: [PATCH 1/4] Extremely hacky way to implement enums that only works for one case --- Makefile | 4 ++-- csharp/source/autowrap/csharp/csharp.d | 2 +- csharp/source/autowrap/csharp/dlang.d | 2 +- examples/simple/source/wrap_all.d | 7 +++++++ pynih/source/python/raw.dpp | 1 + pynih/source/python/type.d | 8 ++++++++ reflection/source/autowrap/reflection.d | 2 +- tests/test_simple.py | 19 +++++++++++++++++++ tests/ut/pynih/python/conv.d | 12 ++++++++++++ 9 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index dffd1338..ca6a472d 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ clean: git clean -xffd test_simple_pyd: tests/test_simple.py examples/simple/lib/pyd/simple.so - PYTHONPATH=$(PWD)/examples/simple/lib/pyd pytest -s -vv $< + PYTHONPATH=$(PWD)/examples/simple/lib/pyd PYD=1 pytest -s -vv $< examples/simple/lib/pyd/simple.so: examples/simple/lib/pyd/libsimple.so @cp $^ $@ @@ -47,7 +47,7 @@ test_simple_pynih_only: tests/test_simple_pynih_only.py examples/simple/lib/pyni PYTHONPATH=$(PWD)/examples/simple/lib/pynih pytest -s -vv $< test_simple_pynih: tests/test_simple.py examples/simple/lib/pynih/simple.so - PYTHONPATH=$(PWD)/examples/simple/lib/pynih pytest -s -vv $< + PYTHONPATH=$(PWD)/examples/simple/lib/pynih PYNIH=1 pytest -s -vv $< test_simple_cs: examples/simple/lib/csharp/libsimple.x64.so examples/simple/Simple.cs @cd tests/test_simple_cs && \ diff --git a/csharp/source/autowrap/csharp/csharp.d b/csharp/source/autowrap/csharp/csharp.d index fb7055c7..54cffe56 100644 --- a/csharp/source/autowrap/csharp/csharp.d +++ b/csharp/source/autowrap/csharp/csharp.d @@ -144,7 +144,7 @@ public string generateCSharp(Modules...)(LibraryName libraryName, RootNamespace static foreach(Agg; AllAggregates!Modules) { - static if(verifySupported!Agg && !isDateTimeType!Agg) + static if(verifySupported!Agg && !isDateTimeType!Agg && !is(Agg == enum)) { generateRangeDef!Agg(libraryName.value); generateConstructors!Agg(libraryName.value); diff --git a/csharp/source/autowrap/csharp/dlang.d b/csharp/source/autowrap/csharp/dlang.d index a73bfbfa..349a36f8 100644 --- a/csharp/source/autowrap/csharp/dlang.d +++ b/csharp/source/autowrap/csharp/dlang.d @@ -37,7 +37,7 @@ public string wrapDLang(Modules...)() if(allSatisfy!(isModule, Modules)) { static foreach(Agg; AllAggregates!Modules) { - static if(verifySupported!Agg && !isDateTimeType!Agg) + static if(verifySupported!Agg && !isDateTimeType!Agg && !is(Agg == enum)) { ret ~= generateSliceMethods!Agg(imports); ret ~= generateConstructors!Agg(imports); diff --git a/examples/simple/source/wrap_all.d b/examples/simple/source/wrap_all.d index ca10a54f..8d693d30 100644 --- a/examples/simple/source/wrap_all.d +++ b/examples/simple/source/wrap_all.d @@ -19,3 +19,10 @@ struct String { string otherStringAsParam(OtherString s) { return s.s ~ "quux"; } + + +enum MyEnum { + foo, + bar, + baz, +} diff --git a/pynih/source/python/raw.dpp b/pynih/source/python/raw.dpp index 2c9861b7..8136d01d 100644 --- a/pynih/source/python/raw.dpp +++ b/pynih/source/python/raw.dpp @@ -7,6 +7,7 @@ module python.raw; #include "Python.h" #include "datetime.h" #include "structmember.h" +#include "enumobject.h" enum isPython3 = is(PyModuleDef); diff --git a/pynih/source/python/type.d b/pynih/source/python/type.d index bc73684d..3184ed3b 100644 --- a/pynih/source/python/type.d +++ b/pynih/source/python/type.d @@ -190,6 +190,14 @@ struct PythonType(T) { } else static if(isCallable!T) { _pyType.tp_basicsize = PythonCallable!T.sizeof; _pyType.tp_call = &PythonCallable!T._py_call; + } else static if(is(T == enum)) { + import python.raw: PyEnum_Type; + _pyType.tp_basicsize = 0; + _pyType.tp_base = &PyEnum_Type; + import python.conv.d_to_python: toPython; + try + _pyType.tp_dict = ["foo": 0, "bar": 1, "baz": 2].toPython; + catch(Exception _) {} } else static assert(false, "Don't know what to do for type " ~ T.stringof); diff --git a/reflection/source/autowrap/reflection.d b/reflection/source/autowrap/reflection.d index b938f2da..2c6fc945 100644 --- a/reflection/source/autowrap/reflection.d +++ b/reflection/source/autowrap/reflection.d @@ -101,7 +101,7 @@ template isUserAggregate(A...) if(A.length == 1) { !is(Unqual!T == TimeOfDay) && !is(Unqual!T == Duration) && !isInstanceOf!(Tuple, T) && - (is(T == struct) || is(T == class)); + (is(T == struct) || is(T == class) || is(T == enum)); } diff --git a/tests/test_simple.py b/tests/test_simple.py index 15272f17..05decaa6 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -1,5 +1,9 @@ from datetime import date import pytest +import os + +is_pyd = os.environ.get('PYD') +is_pynih = os.environ.get('PYNIH') def test_adder(): @@ -261,3 +265,18 @@ def test_property_getter_setter(): assert obj.i == 42 obj.i = 33 # shouldn't throw assert obj.i == 33 + + +def test_enum(): + import pytest + if is_pyd: # FIXME + with pytest.raises(ImportError): + from simple import MyEnum + else: + from simple import MyEnum + assert MyEnum.foo == 0 + assert MyEnum.bar == 1 + assert MyEnum.baz == 2 + + with pytest.raises(AttributeError): # no quux + assert MyEnum.quux == 42 diff --git a/tests/ut/pynih/python/conv.d b/tests/ut/pynih/python/conv.d index 92c1aa40..762bad02 100644 --- a/tests/ut/pynih/python/conv.d +++ b/tests/ut/pynih/python/conv.d @@ -223,3 +223,15 @@ unittest { import core.time: seconds; backAndForth(1.seconds); } + + +@("enum") +unittest { + static enum Enum { + foo, + bar, + baz, + } + + backAndForth(Enum.bar); +} From 39c5f8eee36b4454250bacc4a048e93e77faba98 Mon Sep 17 00:00:00 2001 From: Atila Neves Date: Sun, 1 Dec 2019 13:00:38 +0100 Subject: [PATCH 2/4] Fix the hacky solution --- pynih/source/python/type.d | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/pynih/source/python/type.d b/pynih/source/python/type.d index 3184ed3b..b1983430 100644 --- a/pynih/source/python/type.d +++ b/pynih/source/python/type.d @@ -194,10 +194,13 @@ struct PythonType(T) { import python.raw: PyEnum_Type; _pyType.tp_basicsize = 0; _pyType.tp_base = &PyEnum_Type; - import python.conv.d_to_python: toPython; try - _pyType.tp_dict = ["foo": 0, "bar": 1, "baz": 2].toPython; - catch(Exception _) {} + _pyType.tp_dict = classDict; + catch(Exception e) { + import core.stdc.stdio; + enum msg = "Could not create class dict for " ~ T.stringof ~ "\n"; + printf(msg); + } } else static assert(false, "Don't know what to do for type " ~ T.stringof); @@ -213,6 +216,21 @@ struct PythonType(T) { } } + static if(is(T == enum)) { + private static PyObject* classDict() { + import python.conv.d_to_python: toPython; + import std.traits: EnumMembers, OriginalType; + + OriginalType!T[string] dict; + + static foreach(i; 0 .. EnumMembers!T.length) { + dict[__traits(identifier, EnumMembers!T[i])] = EnumMembers!T[i]; + } + + return dict.toPython; + } + } + static if(isUserAggregate!T) private static auto getsetDefs() { import python.raw: PyGetSetDef; From d7cabc55cf82e4ba0962c62859cb0af5acb4e786 Mon Sep 17 00:00:00 2001 From: Atila Neves Date: Sun, 1 Dec 2019 13:05:26 +0100 Subject: [PATCH 3/4] Phobos std.socket protocol test --- Makefile | 5 +++-- tests/test_phobos.py | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ca6a472d..2127ce5b 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ test: test_python test_cs test_python: test_python_pyd test_python_pynih test_python_pyd: test_simple_pyd test_pyd_pyd test_issues_pyd test_numpy_pyd test_python_pynih: test_simple_pynih test_pyd_pynih test_issues_pynih +test_python_phobos: test_phobos_pynih test_phobos_pyd test_cs: test_simple_cs clean: @@ -136,7 +137,7 @@ examples/numpy/lib/pynih/libnumpy.so: pynih/source/python/raw.d test_phobos_pyd: tests/test_phobos.py examples/phobos/lib/pyd/phobos.so - PYTHONPATH=$(PWD)/examples/phobos/lib/pyd pytest -s -vv $< + PYTHONPATH=$(PWD)/examples/phobos/lib/pyd PYD=1 pytest -s -vv $< examples/phobos/lib/pyd/phobos.so: examples/phobos/lib/pyd/libphobos.so @cp $^ $@ @@ -148,7 +149,7 @@ examples/phobos/dub.selections.json: @cd examples/phobos && dub upgrade -q test_phobos_pynih: tests/test_phobos.py examples/phobos/lib/pynih/phobos.so - PYTHONPATH=$(PWD)/examples/phobos/lib/pynih pytest -s -vv $< + PYTHONPATH=$(PWD)/examples/phobos/lib/pynih PYNIH=1 pytest -s -vv $< examples/phobos/lib/pynih/phobos.so: examples/phobos/lib/pynih/libphobos.so @cp $^ $@ diff --git a/tests/test_phobos.py b/tests/test_phobos.py index 555d7289..a0d162cb 100644 --- a/tests/test_phobos.py +++ b/tests/test_phobos.py @@ -1,2 +1,19 @@ +import os +import pytest + +is_pyd = os.environ.get('PYD') +is_pynih = os.environ.get('PYNIH') + + def test_protocol(): - from phobos import Protocol + if is_pyd: + with pytest.raises(ImportError): + from phobos import Protocol + else: + from phobos import Protocol, ProtocolType + + protocol = Protocol() + assert protocol.getProtocolByType(ProtocolType.TCP) + + assert protocol.name == "tcp" + assert protocol.aliases == ["TCP"] From 5f07f7c651a9fa4de9e87fa5ad7b0ce1c686ddc3 Mon Sep 17 00:00:00 2001 From: Atila Neves Date: Sun, 1 Dec 2019 13:06:52 +0100 Subject: [PATCH 4/4] Add phobos tests to test suite --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2127ce5b..424543e4 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ export PYD_D_VERSION_13 ?= Python_3_8_Or_Later all: test test: test_python test_cs test_python: test_python_pyd test_python_pynih -test_python_pyd: test_simple_pyd test_pyd_pyd test_issues_pyd test_numpy_pyd -test_python_pynih: test_simple_pynih test_pyd_pynih test_issues_pynih +test_python_pyd: test_simple_pyd test_pyd_pyd test_issues_pyd test_phobos_pyd test_numpy_pyd +test_python_pynih: test_simple_pynih test_pyd_pynih test_issues_pynih test_phobos_pynih test_python_phobos: test_phobos_pynih test_phobos_pyd test_cs: test_simple_cs