1cdef struct Point:
2    double x
3    double y
4    int color
5
6def test_constructor(x, y, int color):
7    """
8    >>> sorted(test_constructor(1,2,255).items())
9    [('color', 255), ('x', 1.0), ('y', 2.0)]
10    >>> try: test_constructor(1,None,255)
11    ... except TypeError: pass
12    """
13    cdef Point p = Point(x, y, color)
14    return p
15
16
17def return_constructor(x, y, int color):
18    """
19    >>> sorted(return_constructor(1,2,255).items())
20    [('color', 255), ('x', 1.0), ('y', 2.0)]
21    >>> try: return_constructor(1, None, 255)
22    ... except TypeError: pass
23    """
24    return Point(x, y, color)
25
26
27def test_constructor_kwds(x, y, color):
28    """
29    >>> sorted(test_constructor_kwds(1.25, 2.5, 128).items())
30    [('color', 128), ('x', 1.25), ('y', 2.5)]
31    >>> test_constructor_kwds(1.25, 2.5, None)
32    Traceback (most recent call last):
33    ...
34    TypeError: an integer is required
35    """
36    cdef Point p = Point(x=x, y=y, color=color)
37    return p
38
39
40def return_constructor_kwds(double x, y, color):
41    """
42    >>> sorted(return_constructor_kwds(1.25, 2.5, 128).items())
43    [('color', 128), ('x', 1.25), ('y', 2.5)]
44    >>> return_constructor_kwds(1.25, 2.5, None)
45    Traceback (most recent call last):
46    ...
47    TypeError: an integer is required
48    """
49    return Point(x=x, y=y, color=color)
50
51
52def test_dict_construction(x, y, color):
53    """
54    >>> sorted(test_dict_construction(4, 5, 64).items())
55    [('color', 64), ('x', 4.0), ('y', 5.0)]
56    >>> try: test_dict_construction("foo", 5, 64)
57    ... except TypeError: pass
58    """
59    cdef Point p = {'color': color, 'x': x, 'y': y}
60    return p
61
62def test_list_construction(x, y, color):
63    """
64    >>> sorted(test_list_construction(4, 5, 64).items())
65    [('color', 64), ('x', 4.0), ('y', 5.0)]
66    >>> try: test_list_construction("foo", 5, 64)
67    ... except TypeError: pass
68    """
69    cdef Point p = [x, y, color]
70    return p
71
72'''
73# FIXME: make this work
74def test_tuple_construction(x, y, color):
75    """
76    >>> sorted(test_tuple_construction(4, 5, 64).items())
77    [('color', 64), ('x', 4.0), ('y', 5.0)]
78    >>> try: test_tuple_construction("foo", 5, 64)
79    ... except TypeError: pass
80    """
81    cdef Point p = (x, y, color)
82    return p
83'''
84
85cdef union int_or_float:
86    int n
87    double x
88
89def test_union_constructor(n,x):
90    """
91    >>> test_union_constructor(1, None)
92    1
93    >>> test_union_constructor(None, 2.0)
94    2.0
95    """
96    cdef int_or_float u
97    if n is None:
98        u = int_or_float(x=x)
99        return u.x
100    else:
101        u = int_or_float(n=n)
102        return u.n
103
104cdef struct with_pointers:
105    bint is_integral
106    int_or_float data
107    void* ptr
108
109def test_pointers(int n, double x):
110    """
111    >>> test_pointers(100, 2.71828)
112    100
113    2.71828
114    True
115    """
116    cdef with_pointers a = [True, {'n': n}, NULL]
117    cdef with_pointers b = with_pointers(False, {'x': x}, NULL)
118    print a.data.n
119    print b.data.x
120    print a.ptr == b.ptr == NULL
121
122cdef struct MyStruct:
123    char c
124    int i
125    float f
126    char *s
127
128bhello = b"hello"  # must hold a C reference in PyPy
129
130def test_obj_to_struct(MyStruct mystruct):
131    """
132    >>> test_obj_to_struct(dict(c=10, i=20, f=6.7, s=bhello))
133    c=10 i=20 f=6.70 s=hello
134    >>> test_obj_to_struct(None)
135    Traceback (most recent call last):
136       ...
137    TypeError: Expected a mapping, got NoneType
138    >>> test_obj_to_struct(dict(s=b"world"))
139    Traceback (most recent call last):
140       ...
141    ValueError: No value specified for struct attribute 'c'
142    >>> test_obj_to_struct(dict(c=b"world"))
143    Traceback (most recent call last):
144       ...
145    TypeError: an integer is required
146    """
147    print 'c=%d i=%d f=%.2f s=%s' % (mystruct.c, mystruct.i, mystruct.f, mystruct.s.decode('ascii'))
148
149cdef struct NestedStruct:
150    MyStruct mystruct
151    double d
152
153def test_nested_obj_to_struct(NestedStruct nested):
154    """
155    >>> test_nested_obj_to_struct(dict(mystruct=dict(c=10, i=20, f=6.7, s=bhello), d=4.5))
156    c=10 i=20 f=6.70 s=hello d=4.50
157    >>> test_nested_obj_to_struct(dict(d=7.6))
158    Traceback (most recent call last):
159       ...
160    ValueError: No value specified for struct attribute 'mystruct'
161    >>> test_nested_obj_to_struct(dict(mystruct={}, d=7.6))
162    Traceback (most recent call last):
163       ...
164    ValueError: No value specified for struct attribute 'c'
165    """
166    print 'c=%d i=%d f=%.2f s=%s d=%.2f' % (nested.mystruct.c,
167                                            nested.mystruct.i,
168                                            nested.mystruct.f,
169                                            nested.mystruct.s.decode('UTF-8'),
170                                            nested.d)
171
172