Random access iterators, and sequence protocol.
Hi, I have a container class that defines an operator [] (std::size_t) and also has a size function that returns the number of elements in the container. It does not provide access to an internal iterator. To get the '[]' wrapped with Pyste I need to rename the function as __getitem__ of course. I also renamed size to __len__. However, I would like to do this: for i in container: i.something() To do this __getitem__ needs to generate an IndexError when the index is greater than or equal to size. Do I _have_ to register an exception translator from something like std::range_error? Is there an easier way to do this? The docs don't reveal any easier solutions. It would be nice if this were also as easy as doing it via range, or iterator. :) Thanks. cheers, prabhu
Hi Prabhu, Prabhu Ramachandran wrote:
Hi,
I have a container class that defines an operator [] (std::size_t) and also has a size function that returns the number of elements in the container. It does not provide access to an internal iterator. To get the '[]' wrapped with Pyste I need to rename the function as __getitem__ of course. I also renamed size to __len__. However, I would like to do this:
for i in container: i.something()
To do this __getitem__ needs to generate an IndexError when the index is greater than or equal to size. Do I _have_ to register an exception translator from something like std::range_error? Is there an easier way to do this? The docs don't reveal any easier solutions. It would be nice if this were also as easy as doing it via range, or iterator. :)
Make a wrapper for your __getitem__, that throws IndexError when an invalid index is passed (untested): Object my__getitem__(Container& c, int index) { if (index < 0) { // allow negative indexes index = c.size() + index; } if (index >= c.size()) { PyErr_SetString(PyExc_IndexError, "index out of range"); boost::python::throw_error_already_set(); } return c[index]; } If you want to be able to set items in your container in Python with the [] operator, you will have to define also a __setitem__. 8) Then in your pyste file: Include('mywrappers.hpp') Container = Class(...) add_method(Container, 'my__getitem__') add_method(Container, 'my__setitem__') HTH, Nicodemus.
"N" == nicodemus <nicodemus@globalite.com.br> writes:
>> To do this __getitem__ needs to generate an IndexError when the >> index is greater than or equal to size. Do I _have_ to >> register an exception translator from something like >> std::range_error? Is there an easier way to do this? The docs >> don't reveal any easier solutions. It would be nice if this >> were also as easy as doing it via range, or iterator. :) N> Make a wrapper for your __getitem__, that throws IndexError N> when an invalid index is passed (untested): [snip example] Thanks. I was aware of that. I wanted to know if there were an easier way. :) I guess this should be a fairly common requirement anyway so having some boilerplate code would be useful. It struck me that since Pyste files are pure Python files it would certainly be useful if a *user* could share common functions that generate code that is common across Pyste files that they have. To this end it would be nice if 'import' could work in the directory where the .pyste file exists. So perhaps something like this would be useful in pyste.py::ParseArguments(): for file in files: d = os.path.dirname(os.path.abspath(file)) if d not in sys.path: sys.path.append(d) That way any of the .pyste files could import others in their directory without having to resort to doing it in each of their source files. Thanks! cheers, prabhu
Prabhu Ramachandran <prabhu@aero.iitm.ernet.in> writes:
Thanks. I was aware of that. I wanted to know if there were an easier way. :) I guess this should be a fairly common requirement anyway so having some boilerplate code would be useful.
Joel de Guzman is almost finished with a library facility which makes it easier, but it will probably be a week before it's in the library. -- Dave Abrahams Boost Consulting www.boost-consulting.com
"DA" == David Abrahams <dave@boost-consulting.com> writes:
DA> Prabhu Ramachandran <prabhu@aero.iitm.ernet.in> writes: >> Thanks. I was aware of that. I wanted to know if there were >> an easier way. :) I guess this should be a fairly common >> requirement anyway so having some boilerplate code would be >> useful. DA> Joel de Guzman is almost finished with a library facility DA> which makes it easier, but it will probably be a week before DA> it's in the library. Great! Thanks. prabhu
To do this __getitem__ needs to generate an IndexError when the index is greater than or equal to size. Do I _have_ to register an exception translator from something like std::range_error? Is there an easier way to do this?
I don't think you can do it any easier than that. And besides, if you export std::range_error this will automatically apply to your future container exports.
"NM" == Nikolay Mladenov <nickm@sitius.com> writes:
>> To do this __getitem__ needs to generate an IndexError when the >> index is greater than or equal to size. Do I _have_ to >> register an exception translator from something like >> std::range_error? Is there an easier way to do this? NM> I don't think you can do it any easier than that. And besides, NM> if you export std::range_error this will automatically apply NM> to your future container exports. True, but if you don't want to add the size related checks in the C++ library that you are wrapping (for whatever reason) and instead want to do it in the wrapper functions then you'd need to write the wrapper for each container. Anyway, since .pyste files can import .py files it should be easy to share code that does this internally and one would merely have to write one function that does the job. Thanks. cheers, prabhu
Ok. Than may be you could write an index_check<container> call policy that does the index checking in the precall... Prabhu Ramachandran wrote:
"NM" == Nikolay Mladenov <nickm@sitius.com> writes:
>> To do this __getitem__ needs to generate an IndexError when the >> index is greater than or equal to size. Do I _have_ to >> register an exception translator from something like >> std::range_error? Is there an easier way to do this?
NM> I don't think you can do it any easier than that. And besides, NM> if you export std::range_error this will automatically apply NM> to your future container exports.
True, but if you don't want to add the size related checks in the C++ library that you are wrapping (for whatever reason) and instead want to do it in the wrapper functions then you'd need to write the wrapper for each container. Anyway, since .pyste files can import .py files it should be easy to share code that does this internally and one would merely have to write one function that does the job.
Thanks.
cheers, prabhu
participants (4)
-
David Abrahams -
Nicodemus -
Nikolay Mladenov -
Prabhu Ramachandran