Skip to content

Commit e615cc3

Browse files
committed
Merge pull request libdynd#449 from izaid/array_functions
Updates to match libdynd
2 parents 67f65f1 + 1ae97d2 commit e615cc3

File tree

7 files changed

+140
-121
lines changed

7 files changed

+140
-121
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ before_install:
2424
- export CXX=g++-4.9
2525

2626
install:
27-
- travis_retry pip install --install-option="--no-cython-compile" Cython==0.21
27+
- travis_retry pip install --install-option="--no-cython-compile" Cython==0.23
2828
- mkdir libraries
2929
- pushd libraries
3030
- git clone --depth=1 https://github.com/libdynd/libdynd.git
@@ -42,7 +42,7 @@ matrix:
4242
python: 2.6
4343
compiler: gcc
4444
install:
45-
- travis_retry pip install --install-option="--no-cython-compile" Cython==0.21
45+
- travis_retry pip install --install-option="--no-cython-compile" Cython==0.23
4646
- travis_retry pip install -I numpy==1.7.2
4747
- travis_retry pip install unittest2
4848
- python -c "import numpy; print numpy.__version__"

dynd/cpp/array.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ..config cimport translate_exception
22
from libc.stdint cimport intptr_t
3+
from libcpp cimport bool
34
from .type cimport type
45

56
cdef extern from 'dynd/array.hpp' namespace 'dynd::nd' nogil:
@@ -16,6 +17,8 @@ cdef extern from 'dynd/array.hpp' namespace 'dynd::nd' nogil:
1617

1718
array view_scalars(type&) except +translate_exception
1819

20+
bool is_null()
21+
1922
array operator<(array &)
2023
array operator<=(array &)
2124
array operator==(array &)

dynd/cpp/func/callable.pxd

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
from libcpp cimport bool
2+
3+
from ..array cimport array
14
from ..type cimport type
25

36
cdef extern from 'dynd/func/callable.hpp' namespace 'dynd::nd' nogil:
47
cdef cppclass callable:
58
callable()
69

710
type get_array_type()
11+
12+
bool is_null()
13+
14+
array operator()(...)

dynd/cpp/type.pxd

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
1+
from libcpp cimport bool
2+
from libcpp.map cimport map
13
from libcpp.string cimport string
24

35
from .types.type_id cimport type_id_t
46

57
from ..config cimport translate_exception
68
from .array cimport array
9+
from .func.callable cimport callable
10+
11+
cdef extern from 'dynd/types/base_type.hpp' namespace 'dynd::ndt' nogil:
12+
cdef cppclass base_type:
13+
void get_dynamic_array_properties(map[string, callable] &)
14+
void get_dynamic_array_functions(map[string, callable] &)
15+
16+
cdef extern from 'dynd/types/builtin_type_properties.hpp' namespace 'dynd' nogil:
17+
void get_builtin_type_dynamic_array_properties(type_id_t, map[string, callable] &)
718

819
cdef extern from 'dynd/type.hpp' namespace 'dynd::ndt' nogil:
920
cdef cppclass type:
1021
type()
1122
type(type_id_t) except +translate_exception
1223
type(string&) except +translate_exception
1324

25+
base_type *get()
26+
1427
size_t get_data_size()
1528
size_t get_default_data_size() except +translate_exception
1629
size_t get_data_alignment()
1730
size_t get_arrmeta_size()
1831
type get_canonical_type()
1932

33+
bool is_builtin()
34+
2035
bint operator==(type&)
2136
bint operator!=(type&)
2237

dynd/nd/array.pyx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GE, Py_GT
44
from libcpp.string cimport string
5+
from libcpp.map cimport map
6+
from cython.operator import dereference
57

68
from ..cpp.array cimport groupby as dynd_groupby
7-
from ..cpp.type cimport type as _type
9+
from ..cpp.func.callable cimport callable as _callable
10+
from ..cpp.type cimport type as _type, get_builtin_type_dynamic_array_properties
811
from ..cpp.types.categorical_type cimport dynd_make_categorical_type
912
from ..cpp.types.datashape_formatter cimport format_datashape as dynd_format_datashape
1013

@@ -72,7 +75,6 @@ cdef extern from 'array_functions.hpp' namespace 'pydynd':
7275
int array_releasebuffer_pep3118(object ndo, Py_buffer *buffer) except -1
7376

7477
cdef extern from 'gfunc_callable_functions.hpp' namespace 'pydynd':
75-
object get_array_dynamic_property(_array&, object) except +translate_exception
7678
void add_array_names_to_dir_dict(_array&, object) except +translate_exception
7779
void set_array_dynamic_property(_array&, object, object) except +translate_exception
7880

@@ -201,7 +203,30 @@ cdef class array(object):
201203
return result.keys()
202204

203205
def __getattr__(self, name):
204-
return get_array_dynamic_property(self.v, name)
206+
if self.v.is_null():
207+
raise AttributeError(name)
208+
209+
cdef map[string, _callable] properties
210+
211+
cdef _type dt = self.v.get_type()
212+
if (not dt.is_builtin()):
213+
dt.get().get_dynamic_array_properties(properties)
214+
else:
215+
get_builtin_type_dynamic_array_properties(dt.get_type_id(), properties);
216+
217+
cdef _callable p = properties[name]
218+
if (not p.is_null()):
219+
return wrap(p(self.v))
220+
221+
cdef map[string, _callable] functions
222+
if (not dt.is_builtin()):
223+
dt.get().get_dynamic_array_functions(functions)
224+
225+
cdef _callable f = functions[name]
226+
if (not f.is_null()):
227+
return wrap(f(self.v))
228+
229+
raise AttributeError(name)
205230

206231
def __setattr__(self, name, value):
207232
set_array_dynamic_property(self.v, name, value)

dynd/src/gfunc_callable_functions.cpp

Lines changed: 16 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,11 @@ void pydynd::add_array_names_to_dir_dict(const dynd::nd::array &n,
9797
{
9898
ndt::type dt = n.get_type();
9999
if (!dt.is_builtin()) {
100-
const std::pair<std::string, nd::callable> *properties;
101-
size_t count;
100+
std::map<std::string, nd::callable> properties;
102101
// Add the array properties
103-
dt.extended()->get_dynamic_array_properties(&properties, &count);
104-
for (size_t i = 0; i < count; ++i) {
105-
if (PyDict_SetItemString(dict, properties[i].first.c_str(), Py_None) <
106-
0) {
102+
dt.extended()->get_dynamic_array_properties(properties);
103+
for (const auto &pair : properties) {
104+
if (PyDict_SetItemString(dict, pair.first.c_str(), Py_None) < 0) {
107105
throw runtime_error("");
108106
}
109107
}
@@ -116,96 +114,37 @@ void pydynd::add_array_names_to_dir_dict(const dynd::nd::array &n,
116114
}
117115
}
118116
else {
119-
const std::pair<std::string, nd::callable> *properties;
120-
size_t count;
117+
std::map<std::string, nd::callable> properties;
121118
// Add the array properties
122-
get_builtin_type_dynamic_array_properties(dt.get_type_id(), &properties,
123-
&count);
124-
for (size_t i = 0; i < count; ++i) {
125-
if (PyDict_SetItemString(dict, properties[i].first.c_str(), Py_None) <
126-
0) {
119+
get_builtin_type_dynamic_array_properties(dt.get_type_id(), properties);
120+
for (const auto &pair : properties) {
121+
if (PyDict_SetItemString(dict, pair.first.c_str(), Py_None) < 0) {
127122
throw runtime_error("");
128123
}
129124
}
130125
// TODO: Add the array functions
131126
}
132127
}
133128

134-
PyObject *pydynd::get_array_dynamic_property(const dynd::nd::array &n,
135-
PyObject *name)
136-
{
137-
if (n.is_null()) {
138-
PyErr_SetObject(PyExc_AttributeError, name);
139-
return NULL;
140-
}
141-
ndt::type dt = n.get_type();
142-
const std::pair<std::string, nd::callable> *properties;
143-
size_t count;
144-
// Search for a property
145-
if (!dt.is_builtin()) {
146-
dt.extended()->get_dynamic_array_properties(&properties, &count);
147-
}
148-
else {
149-
get_builtin_type_dynamic_array_properties(dt.get_type_id(), &properties,
150-
&count);
151-
}
152-
153-
// TODO: We probably want to make some kind of acceleration structure for the
154-
// name lookup
155-
if (count > 0) {
156-
std::string nstr = pystring_as_string(name);
157-
for (size_t i = 0; i < count; ++i) {
158-
if (properties[i].first == nstr) {
159-
return DyND_PyWrapper_New(const_cast<dynd::nd::callable &>(
160-
properties[i].second)(dynd::kwds("self", n)));
161-
}
162-
}
163-
}
164-
165-
// Search for a function
166-
std::map<std::string, nd::callable> functions;
167-
if (!dt.is_builtin()) {
168-
dt.extended()->get_dynamic_array_functions(functions);
169-
}
170-
else {
171-
count = 0;
172-
}
173-
std::string nstr = pystring_as_string(name);
174-
nd::callable c = functions[nstr];
175-
if (!c.is_null()) {
176-
return DyND_PyWrapper_New(c(n));
177-
}
178-
179-
PyErr_SetObject(PyExc_AttributeError, name);
180-
return NULL;
181-
}
182-
183129
void pydynd::set_array_dynamic_property(const dynd::nd::array &n,
184130
PyObject *name, PyObject *value)
185131
{
186132
ndt::type dt = n.get_type();
187-
const std::pair<std::string, nd::callable> *properties;
188-
size_t count;
133+
std::map<std::string, nd::callable> properties;
189134
// Search for a property
190135
if (!dt.is_builtin()) {
191-
dt.extended()->get_dynamic_array_properties(&properties, &count);
136+
dt.extended()->get_dynamic_array_properties(properties);
192137
}
193138
else {
194-
get_builtin_type_dynamic_array_properties(dt.get_type_id(), &properties,
195-
&count);
139+
get_builtin_type_dynamic_array_properties(dt.get_type_id(), properties);
196140
}
141+
197142
// TODO: We probably want to make some kind of acceleration structure for
198143
// the name lookup
199-
if (count > 0) {
200-
std::string nstr = pystring_as_string(name);
201-
for (size_t i = 0; i < count; ++i) {
202-
if (properties[i].first == nstr) {
203-
nd::array p = const_cast<dynd::nd::callable &>(properties[i].second)(
204-
dynd::kwds("self", n));
205-
array_broadcast_assign_from_py(p, value, &eval::default_eval_context);
206-
return;
207-
}
208-
}
144+
std::string nstr = pystring_as_string(name);
145+
nd::callable p = properties[nstr];
146+
if (!p.is_null()) {
147+
array_broadcast_assign_from_py(p(n), value, &eval::default_eval_context);
209148
}
210149

211150
PyErr_SetObject(PyExc_AttributeError, name);

0 commit comments

Comments
 (0)