| 1 |
/* |
|---|
| 2 |
Copyright (c) 2006 Kirk McDonald |
|---|
| 3 |
|
|---|
| 4 |
Permission is hereby granted, free of charge, to any person obtaining a copy of |
|---|
| 5 |
this software and associated documentation files (the "Software"), to deal in |
|---|
| 6 |
the Software without restriction, including without limitation the rights to |
|---|
| 7 |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
|---|
| 8 |
of the Software, and to permit persons to whom the Software is furnished to do |
|---|
| 9 |
so, subject to the following conditions: |
|---|
| 10 |
|
|---|
| 11 |
The above copyright notice and this permission notice shall be included in all |
|---|
| 12 |
copies or substantial portions of the Software. |
|---|
| 13 |
|
|---|
| 14 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|---|
| 15 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|---|
| 16 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|---|
| 17 |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|---|
| 18 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|---|
| 19 |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|---|
| 20 |
SOFTWARE. |
|---|
| 21 |
*/ |
|---|
| 22 |
module pyd.pydobject; |
|---|
| 23 |
|
|---|
| 24 |
//private import std.c.stdio; |
|---|
| 25 |
import python; |
|---|
| 26 |
import pyd.exception; |
|---|
| 27 |
import pyd.make_object; |
|---|
| 28 |
//import std.string; |
|---|
| 29 |
|
|---|
| 30 |
/** |
|---|
| 31 |
* Wrapper class for a Python/C API PyObject. |
|---|
| 32 |
* |
|---|
| 33 |
* Nearly all of these member functions may throw a PythonException if the |
|---|
| 34 |
* underlying Python API raises a Python exception. |
|---|
| 35 |
* |
|---|
| 36 |
* Authors: $(LINK2 mailto:kirklin.mcdonald@gmail.com, Kirk McDonald) |
|---|
| 37 |
* Date: June 18, 2006 |
|---|
| 38 |
* See_Also: |
|---|
| 39 |
* $(LINK2 http://docs.python.org/api/api.html, The Python/C API) |
|---|
| 40 |
*/ |
|---|
| 41 |
class PydObject { |
|---|
| 42 |
protected: |
|---|
| 43 |
PyObject* m_ptr; |
|---|
| 44 |
public: |
|---|
| 45 |
/** |
|---|
| 46 |
* Wrap around a passed PyObject*. |
|---|
| 47 |
* Params: |
|---|
| 48 |
* o = The PyObject to wrap. |
|---|
| 49 |
* borrowed = Whether o is a _borrowed reference. Instances |
|---|
| 50 |
* of PydObject always own their references. |
|---|
| 51 |
* Therefore, Py_INCREF will be called if borrowed is |
|---|
| 52 |
* $(D_KEYWORD true). |
|---|
| 53 |
*/ |
|---|
| 54 |
this(PyObject* o, bool borrowed=false) { |
|---|
| 55 |
if (o is null) handle_exception(); |
|---|
| 56 |
// PydObject always owns its references |
|---|
| 57 |
if (borrowed) Py_INCREF(o); |
|---|
| 58 |
m_ptr = o; |
|---|
| 59 |
} |
|---|
| 60 |
|
|---|
| 61 |
/// The default constructor constructs an instance of the Py_None PydObject. |
|---|
| 62 |
this() { this(Py_None, true); } |
|---|
| 63 |
|
|---|
| 64 |
/// Destructor. Calls Py_DECREF on owned PyObject reference. |
|---|
| 65 |
~this() { |
|---|
| 66 |
Py_DECREF(m_ptr); |
|---|
| 67 |
} |
|---|
| 68 |
|
|---|
| 69 |
/** |
|---|
| 70 |
* Returns a borrowed reference to the PyObject. |
|---|
| 71 |
*/ |
|---|
| 72 |
PyObject* ptr() { return m_ptr; } |
|---|
| 73 |
|
|---|
| 74 |
/* |
|---|
| 75 |
* Prints PyObject to a C FILE* object. |
|---|
| 76 |
* Params: |
|---|
| 77 |
* fp = The file object to _print to. std.c.stdio.stdout by default. |
|---|
| 78 |
* raw = If $(D_KEYWORD true), prints the "str" representation of the |
|---|
| 79 |
* PydObject, and uses the "repr" otherwise. Defaults to |
|---|
| 80 |
* $(D_KEYWORD false). |
|---|
| 81 |
* Bugs: This does not seem to work, raising an AccessViolation. Meh. |
|---|
| 82 |
* Use toString. |
|---|
| 83 |
*/ |
|---|
| 84 |
/+ |
|---|
| 85 |
void print(FILE* fp=stdout, bool raw=false) { |
|---|
| 86 |
if (PyObject_Print(m_ptr, fp, raw ? Py_PRINT_RAW : 0) == -1) |
|---|
| 87 |
handle_exception(); |
|---|
| 88 |
} |
|---|
| 89 |
+/ |
|---|
| 90 |
|
|---|
| 91 |
/// Same as _hasattr(this, attr_name) in Python. |
|---|
| 92 |
bool hasattr(char[] attr_name) { |
|---|
| 93 |
return PyObject_HasAttrString(m_ptr, (attr_name ~ \0).ptr) == 1; |
|---|
| 94 |
} |
|---|
| 95 |
|
|---|
| 96 |
/// Same as _hasattr(this, attr_name) in Python. |
|---|
| 97 |
bool hasattr(PydObject attr_name) { |
|---|
| 98 |
return PyObject_HasAttr(m_ptr, attr_name.m_ptr) == 1; |
|---|
| 99 |
} |
|---|
| 100 |
|
|---|
| 101 |
/// Same as _getattr(this, attr_name) in Python. |
|---|
| 102 |
PydObject getattr(char[] attr_name) { |
|---|
| 103 |
return new PydObject(PyObject_GetAttrString(m_ptr, (attr_name ~ \0).ptr)); |
|---|
| 104 |
} |
|---|
| 105 |
|
|---|
| 106 |
/// Same as _getattr(this, attr_name) in Python. |
|---|
| 107 |
PydObject getattr(PydObject attr_name) { |
|---|
| 108 |
return new PydObject(PyObject_GetAttr(m_ptr, attr_name.m_ptr)); |
|---|
| 109 |
} |
|---|
| 110 |
|
|---|
| 111 |
/** |
|---|
| 112 |
* Same as _setattr(this, attr_name, v) in Python. |
|---|
| 113 |
*/ |
|---|
| 114 |
void setattr(char[] attr_name, PydObject v) { |
|---|
| 115 |
if (PyObject_SetAttrString(m_ptr, (attr_name ~ \0).ptr, v.m_ptr) == -1) |
|---|
| 116 |
handle_exception(); |
|---|
| 117 |
} |
|---|
| 118 |
|
|---|
| 119 |
/** |
|---|
| 120 |
* Same as _setattr(this, attr_name, v) in Python. |
|---|
| 121 |
*/ |
|---|
| 122 |
void setattr(PydObject attr_name, PydObject v) { |
|---|
| 123 |
if (PyObject_SetAttr(m_ptr, attr_name.m_ptr, v.m_ptr) == -1) |
|---|
| 124 |
handle_exception(); |
|---|
| 125 |
} |
|---|
| 126 |
|
|---|
| 127 |
/** |
|---|
| 128 |
* Same as del this.attr_name in Python. |
|---|
| 129 |
*/ |
|---|
| 130 |
void delattr(char[] attr_name) { |
|---|
| 131 |
if (PyObject_DelAttrString(m_ptr, (attr_name ~ \0).ptr) == -1) |
|---|
| 132 |
handle_exception(); |
|---|
| 133 |
} |
|---|
| 134 |
|
|---|
| 135 |
/** |
|---|
| 136 |
* Same as del this.attr_name in Python. |
|---|
| 137 |
*/ |
|---|
| 138 |
void delattr(PydObject attr_name) { |
|---|
| 139 |
if (PyObject_DelAttr(m_ptr, attr_name.m_ptr) == -1) |
|---|
| 140 |
handle_exception(); |
|---|
| 141 |
} |
|---|
| 142 |
|
|---|
| 143 |
/** |
|---|
| 144 |
* Exposes Python object comparison to D. Same as cmp(this, rhs) in Python. |
|---|
| 145 |
*/ |
|---|
| 146 |
int opCmp(PydObject rhs) { |
|---|
| 147 |
// This function happily maps exactly to opCmp |
|---|
| 148 |
int res = PyObject_Compare(m_ptr, rhs.m_ptr); |
|---|
| 149 |
// Check for possible error |
|---|
| 150 |
handle_exception(); |
|---|
| 151 |
return res; |
|---|
| 152 |
} |
|---|
| 153 |
|
|---|
| 154 |
/** |
|---|
| 155 |
* Exposes Python object equality check to D. |
|---|
| 156 |
*/ |
|---|
| 157 |
bool opEquals(PydObject rhs) { |
|---|
| 158 |
int res = PyObject_Compare(m_ptr, rhs.m_ptr); |
|---|
| 159 |
handle_exception(); |
|---|
| 160 |
return res == 0; |
|---|
| 161 |
} |
|---|
| 162 |
|
|---|
| 163 |
/// Same as _repr(this) in Python. |
|---|
| 164 |
PydObject repr() { |
|---|
| 165 |
return new PydObject(PyObject_Repr(m_ptr)); |
|---|
| 166 |
} |
|---|
| 167 |
|
|---|
| 168 |
/// Same as _str(this) in Python. |
|---|
| 169 |
PydObject str() { |
|---|
| 170 |
return new PydObject(PyObject_Str(m_ptr)); |
|---|
| 171 |
} |
|---|
| 172 |
version (Tango) { |
|---|
| 173 |
/// Allows PydObject to be formatted. |
|---|
| 174 |
char[] toUtf8() { |
|---|
| 175 |
return d_type!(char[])(m_ptr); |
|---|
| 176 |
} |
|---|
| 177 |
} else { |
|---|
| 178 |
/// Allows use of PydObject in writef via %s |
|---|
| 179 |
char[] toString() { |
|---|
| 180 |
return d_type!(char[])(m_ptr); |
|---|
| 181 |
} |
|---|
| 182 |
} |
|---|
| 183 |
|
|---|
| 184 |
/// Same as _unicode(this) in Python. |
|---|
| 185 |
PydObject unicode() { |
|---|
| 186 |
return new PydObject(PyObject_Unicode(m_ptr)); |
|---|
| 187 |
} |
|---|
| 188 |
|
|---|
| 189 |
/// Same as isinstance(this, cls) in Python. |
|---|
| 190 |
bool isInstance(PydObject cls) { |
|---|
| 191 |
int res = PyObject_IsInstance(m_ptr, cls.m_ptr); |
|---|
| 192 |
if (res == -1) handle_exception(); |
|---|
| 193 |
return res == 1; |
|---|
| 194 |
} |
|---|
| 195 |
|
|---|
| 196 |
/// Same as issubclass(this, cls) in Python. Only works if this is a class. |
|---|
| 197 |
bool isSubclass(PydObject cls) { |
|---|
| 198 |
int res = PyObject_IsSubclass(m_ptr, cls.m_ptr); |
|---|
| 199 |
if (res == -1) handle_exception(); |
|---|
| 200 |
return res == 1; |
|---|
| 201 |
} |
|---|
| 202 |
|
|---|
| 203 |
/// Same as _callable(this) in Python. |
|---|
| 204 |
bool callable() { |
|---|
| 205 |
return PyCallable_Check(m_ptr) == 1; |
|---|
| 206 |
} |
|---|
| 207 |
|
|---|
| 208 |
/** |
|---|
| 209 |
* Calls the PydObject with the PyTuple args. |
|---|
| 210 |
* Params: |
|---|
| 211 |
* args = Should be a PydTuple of the arguments to pass. Omit to |
|---|
| 212 |
* call with no arguments. |
|---|
| 213 |
* Returns: Whatever the function PydObject returns. |
|---|
| 214 |
*/ |
|---|
| 215 |
PydObject unpackCall(PydObject args=null) { |
|---|
| 216 |
return new PydObject(PyObject_CallObject(m_ptr, args is null ? null : args.m_ptr)); |
|---|
| 217 |
} |
|---|
| 218 |
|
|---|
| 219 |
/** |
|---|
| 220 |
* Calls the PydObject with positional and keyword arguments. |
|---|
| 221 |
* Params: |
|---|
| 222 |
* args = Positional arguments. Should be a PydTuple. Pass an empty |
|---|
| 223 |
* PydTuple for no positional arguments. |
|---|
| 224 |
* kw = Keyword arguments. Should be a PydDict. |
|---|
| 225 |
* Returns: Whatever the function PydObject returns. |
|---|
| 226 |
*/ |
|---|
| 227 |
PydObject unpackCall(PydObject args, PydObject kw) { |
|---|
| 228 |
return new PydObject(PyObject_Call(m_ptr, args.m_ptr, kw.m_ptr)); |
|---|
| 229 |
} |
|---|
| 230 |
|
|---|
| 231 |
/** |
|---|
| 232 |
* Calls the PydObject with any convertible D items. |
|---|
| 233 |
*/ |
|---|
| 234 |
PydObject opCall(T ...) (T t) { |
|---|
| 235 |
PyObject* tuple = PyTuple_FromItems(t); |
|---|
| 236 |
if (tuple is null) handle_exception(); |
|---|
| 237 |
PyObject* result = PyObject_CallObject(m_ptr, tuple); |
|---|
| 238 |
Py_DECREF(tuple); |
|---|
| 239 |
if (result is null) handle_exception(); |
|---|
| 240 |
return new PydObject(result); |
|---|
| 241 |
} |
|---|
| 242 |
|
|---|
| 243 |
/** |
|---|
| 244 |
* |
|---|
| 245 |
*/ |
|---|
| 246 |
PydObject methodUnpack(char[] name, PydObject args=null) { |
|---|
| 247 |
// Get the method PydObject |
|---|
| 248 |
PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); |
|---|
| 249 |
PyObject* result; |
|---|
| 250 |
// If this method doesn't exist (or other error), throw exception |
|---|
| 251 |
if (m is null) handle_exception(); |
|---|
| 252 |
// Call the method, and decrement the refcounts on the temporaries. |
|---|
| 253 |
result = PyObject_CallObject(m, args is null ? null : args.m_ptr); |
|---|
| 254 |
Py_DECREF(m); |
|---|
| 255 |
// Return the result. |
|---|
| 256 |
return new PydObject(result); |
|---|
| 257 |
} |
|---|
| 258 |
|
|---|
| 259 |
PydObject methodUnpack(char[] name, PydObject args, PydObject kw) { |
|---|
| 260 |
// Get the method PydObject |
|---|
| 261 |
PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); |
|---|
| 262 |
PyObject* result; |
|---|
| 263 |
// If this method doesn't exist (or other error), throw exception. |
|---|
| 264 |
if (m is null) handle_exception(); |
|---|
| 265 |
// Call the method, and decrement the refcounts on the temporaries. |
|---|
| 266 |
result = PyObject_Call(m, args.m_ptr, kw.m_ptr); |
|---|
| 267 |
Py_DECREF(m); |
|---|
| 268 |
// Return the result. |
|---|
| 269 |
return new PydObject(result); |
|---|
| 270 |
} |
|---|
| 271 |
|
|---|
| 272 |
/** |
|---|
| 273 |
* Calls a method of the object with any convertible D items. |
|---|
| 274 |
*/ |
|---|
| 275 |
PydObject method(T ...) (char[] name, T t) { |
|---|
| 276 |
PyObject* mthd = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); |
|---|
| 277 |
if (mthd is null) handle_exception(); |
|---|
| 278 |
PyObject* tuple = PyTuple_FromItems(t); |
|---|
| 279 |
if (tuple is null) { |
|---|
| 280 |
Py_DECREF(mthd); |
|---|
| 281 |
handle_exception(); |
|---|
| 282 |
} |
|---|
| 283 |
PyObject* result = PyObject_CallObject(mthd, tuple); |
|---|
| 284 |
Py_DECREF(mthd); |
|---|
| 285 |
Py_DECREF(tuple); |
|---|
| 286 |
if (result is null) handle_exception(); |
|---|
| 287 |
return new PydObject(result); |
|---|
| 288 |
} |
|---|
| 289 |
|
|---|
| 290 |
/// Same as _hash(this) in Python. |
|---|
| 291 |
int hash() { |
|---|
| 292 |
int res = PyObject_Hash(m_ptr); |
|---|
| 293 |
if (res == -1) handle_exception(); |
|---|
| 294 |
return res; |
|---|
| 295 |
} |
|---|
| 296 |
|
|---|
| 297 |
T toDItem(T)() { |
|---|
| 298 |
return d_type!(T)(m_ptr); |
|---|
| 299 |
} |
|---|
| 300 |
|
|---|
| 301 |
/// Same as "not not this" in Python. |
|---|
| 302 |
bool toBool() { |
|---|
| 303 |
return d_type!(bool)(m_ptr); |
|---|
| 304 |
} |
|---|
| 305 |
|
|---|
| 306 |
/// Same as "_not this" in Python. |
|---|
| 307 |
bool not() { |
|---|
| 308 |
int res = PyObject_Not(m_ptr); |
|---|
| 309 |
if (res == -1) handle_exception(); |
|---|
| 310 |
return res == 1; |
|---|
| 311 |
} |
|---|
| 312 |
|
|---|
| 313 |
/** |
|---|
| 314 |
* Gets the _type of this PydObject. Same as _type(this) in Python. |
|---|
| 315 |
* Returns: The _type PydObject of this PydObject. |
|---|
| 316 |
*/ |
|---|
| 317 |
PydObject type() { |
|---|
| 318 |
return new PydObject(PyObject_Type(m_ptr)); |
|---|
| 319 |
} |
|---|
| 320 |
|
|---|
| 321 |
/** |
|---|
| 322 |
* The _length of this PydObject. Same as _len(this) in Python. |
|---|
| 323 |
*/ |
|---|
| 324 |
int length() { |
|---|
| 325 |
int res = PyObject_Length(m_ptr); |
|---|
| 326 |
if (res == -1) handle_exception(); |
|---|
| 327 |
return res; |
|---|
| 328 |
} |
|---|
| 329 |
/// Same as length() |
|---|
| 330 |
int size() { return length(); } |
|---|
| 331 |
|
|---|
| 332 |
/// Same as _dir(this) in Python. |
|---|
| 333 |
PydObject dir() { |
|---|
| 334 |
return new PydObject(PyObject_Dir(m_ptr)); |
|---|
| 335 |
} |
|---|
| 336 |
|
|---|
| 337 |
//---------- |
|---|
| 338 |
// Indexing |
|---|
| 339 |
//---------- |
|---|
| 340 |
/// Equivalent to o[_key] in Python. |
|---|
| 341 |
PydObject opIndex(PydObject key) { |
|---|
| 342 |
return new PydObject(PyObject_GetItem(m_ptr, key.m_ptr)); |
|---|
| 343 |
} |
|---|
| 344 |
/** |
|---|
| 345 |
* Equivalent to o['_key'] in Python; usually only makes sense for |
|---|
| 346 |
* mappings. |
|---|
| 347 |
*/ |
|---|
| 348 |
PydObject opIndex(char[] key) { |
|---|
| 349 |
return new PydObject(PyMapping_GetItemString(m_ptr, (key ~ \0).ptr)); |
|---|
| 350 |
} |
|---|
| 351 |
/// Equivalent to o[_i] in Python; usually only makes sense for sequences. |
|---|
| 352 |
PydObject opIndex(int i) { |
|---|
| 353 |
return new PydObject(PySequence_GetItem(m_ptr, i)); |
|---|
| 354 |
} |
|---|
| 355 |
|
|---|
| 356 |
/// Equivalent to o[_key] = _value in Python. |
|---|
| 357 |
void opIndexAssign(PydObject value, PydObject key) { |
|---|
| 358 |
if (PyObject_SetItem(m_ptr, key.m_ptr, value.m_ptr) == -1) |
|---|
| 359 |
handle_exception(); |
|---|
| 360 |
} |
|---|
| 361 |
/** |
|---|
| 362 |
* Equivalent to o['_key'] = _value in Python. Usually only makes sense for |
|---|
| 363 |
* mappings. |
|---|
| 364 |
*/ |
|---|
| 365 |
void opIndexAssign(PydObject value, char[] key) { |
|---|
| 366 |
if (PyMapping_SetItemString(m_ptr, (key ~ \0).ptr, value.m_ptr) == -1) |
|---|
| 367 |
handle_exception(); |
|---|
| 368 |
} |
|---|
| 369 |
/** |
|---|
| 370 |
* Equivalent to o[_i] = _value in Python. Usually only makes sense for |
|---|
| 371 |
* sequences. |
|---|
| 372 |
*/ |
|---|
| 373 |
void opIndexAssign(PydObject value, int i) { |
|---|
| 374 |
if (PySequence_SetItem(m_ptr, i, value.m_ptr) == -1) |
|---|
| 375 |
handle_exception(); |
|---|
| 376 |
} |
|---|
| 377 |
|
|---|
| 378 |
/// Equivalent to del o[_key] in Python. |
|---|
| 379 |
void delItem(PydObject key) { |
|---|
| 380 |
if (PyObject_DelItem(m_ptr, key.m_ptr) == -1) |
|---|
| 381 |
handle_exception(); |
|---|
| 382 |
} |
|---|
| 383 |
/** |
|---|
| 384 |
* Equivalent to del o['_key'] in Python. Usually only makes sense for |
|---|
| 385 |
* mappings. |
|---|
| 386 |
*/ |
|---|
| 387 |
void delItem(char[] key) { |
|---|
| 388 |
if (PyMapping_DelItemString(m_ptr, (key ~ \0).ptr) == -1) |
|---|
| 389 |
handle_exception(); |
|---|
| 390 |
} |
|---|
| 391 |
/** |
|---|
| 392 |
* Equivalent to del o[_i] in Python. Usually only makes sense for |
|---|
| 393 |
* sequences. |
|---|
| 394 |
*/ |
|---|
| 395 |
void delItem(int i) { |
|---|
| 396 |
if (PySequence_DelItem(m_ptr, i) == -1) |
|---|
| 397 |
handle_exception(); |
|---|
| 398 |
} |
|---|
| 399 |
|
|---|
| 400 |
//--------- |
|---|
| 401 |
// Slicing |
|---|
| 402 |
//--------- |
|---|
| 403 |
/// Equivalent to o[_i1:_i2] in Python. |
|---|
| 404 |
PydObject opSlice(int i1, int i2) { |
|---|
| 405 |
return new PydObject(PySequence_GetSlice(m_ptr, i1, i2)); |
|---|
| 406 |
} |
|---|
| 407 |
/// Equivalent to o[:] in Python. |
|---|
| 408 |
PydObject opSlice() { |
|---|
| 409 |
return this.opSlice(0, this.length()); |
|---|
| 410 |
} |
|---|
| 411 |
/// Equivalent to o[_i1:_i2] = _v in Python. |
|---|
| 412 |
void opSliceAssign(PydObject v, int i1, int i2) { |
|---|
| 413 |
if (PySequence_SetSlice(m_ptr, i1, i1, v.m_ptr) == -1) |
|---|
| 414 |
handle_exception(); |
|---|
| 415 |
} |
|---|
| 416 |
/// Equivalent to o[:] = _v in Python. |
|---|
| 417 |
void opSliceAssign(PydObject v) { |
|---|
| 418 |
this.opSliceAssign(v, 0, this.length()); |
|---|
| 419 |
} |
|---|
| 420 |
/// Equivalent to del o[_i1:_i2] in Python. |
|---|
| 421 |
void delSlice(int i1, int i2) { |
|---|
| 422 |
if (PySequence_DelSlice(m_ptr, i1, i2) == -1) |
|---|
| 423 |
handle_exception(); |
|---|
| 424 |
} |
|---|
| 425 |
/// Equivalent to del o[:] in Python. |
|---|
| 426 |
void delSlice() { |
|---|
| 427 |
this.delSlice(0, this.length()); |
|---|
| 428 |
} |
|---|
| 429 |
|
|---|
| 430 |
//----------- |
|---|
| 431 |
// Iteration |
|---|
| 432 |
//----------- |
|---|
| 433 |
|
|---|
| 434 |
/** |
|---|
| 435 |
* Iterates over the items in a collection, be they the items in a |
|---|
| 436 |
* sequence, keys in a dictionary, or some other iteration defined for the |
|---|
| 437 |
* PydObject's type. |
|---|
| 438 |
*/ |
|---|
| 439 |
int opApply(int delegate(inout PydObject) dg) { |
|---|
| 440 |
PyObject* iterator = PyObject_GetIter(m_ptr); |
|---|
| 441 |
PyObject* item; |
|---|
| 442 |
int result = 0; |
|---|
| 443 |
PydObject o; |
|---|
| 444 |
|
|---|
| 445 |
if (iterator == null) { |
|---|
| 446 |
handle_exception(); |
|---|
| 447 |
} |
|---|
| 448 |
|
|---|
| 449 |
item = PyIter_Next(iterator); |
|---|
| 450 |
while (item) { |
|---|
| 451 |
o = new PydObject(item); |
|---|
| 452 |
result = dg(o); |
|---|
| 453 |
Py_DECREF(item); |
|---|
| 454 |
if (result) break; |
|---|
| 455 |
item = PyIter_Next(iterator); |
|---|
| 456 |
} |
|---|
| 457 |
Py_DECREF(iterator); |
|---|
| 458 |
|
|---|
| 459 |
// Just in case an exception occured |
|---|
| 460 |
handle_exception(); |
|---|
| 461 |
|
|---|
| 462 |
return result; |
|---|
| 463 |
} |
|---|
| 464 |
|
|---|
| 465 |
/** |
|---|
| 466 |
* Iterate over (key, value) pairs in a dictionary. If the PydObject is not |
|---|
| 467 |
* a dict, this simply does nothing. (It iterates over no items.) You |
|---|
| 468 |
* should not attempt to modify the dictionary while iterating through it, |
|---|
| 469 |
* with the exception of modifying values. Adding or removing items while |
|---|
| 470 |
* iterating through it is an especially bad idea. |
|---|
| 471 |
*/ |
|---|
| 472 |
int opApply(int delegate(inout PydObject, inout PydObject) dg) { |
|---|
| 473 |
PyObject* key, value; |
|---|
| 474 |
version(Python_2_5_Or_Later) { |
|---|
| 475 |
Py_ssize_t pos = 0; |
|---|
| 476 |
} else { |
|---|
| 477 |
int pos = 0; |
|---|
| 478 |
} |
|---|
| 479 |
int result = 0; |
|---|
| 480 |
PydObject k, v; |
|---|
| 481 |
|
|---|
| 482 |
while (PyDict_Next(m_ptr, &pos, &key, &value)) { |
|---|
| 483 |
k = new PydObject(key, true); |
|---|
| 484 |
v = new PydObject(value, true); |
|---|
| 485 |
result = dg(k, v); |
|---|
| 486 |
if (result) break; |
|---|
| 487 |
} |
|---|
| 488 |
|
|---|
| 489 |
return result; |
|---|
| 490 |
} |
|---|
| 491 |
|
|---|
| 492 |
//------------ |
|---|
| 493 |
// Arithmetic |
|---|
| 494 |
//------------ |
|---|
| 495 |
/// |
|---|
| 496 |
PydObject opAdd(PydObject o) { |
|---|
| 497 |
return new PydObject(PyNumber_Add(m_ptr, o.m_ptr)); |
|---|
| 498 |
} |
|---|
| 499 |
/// |
|---|
| 500 |
PydObject opSub(PydObject o) { |
|---|
| 501 |
return new PydObject(PyNumber_Subtract(m_ptr, o.m_ptr)); |
|---|
| 502 |
} |
|---|
| 503 |
/// |
|---|
| 504 |
PydObject opMul(PydObject o) { |
|---|
| 505 |
return new PydObject(PyNumber_Multiply(m_ptr, o.m_ptr)); |
|---|
| 506 |
} |
|---|
| 507 |
/// Sequence repetition |
|---|
| 508 |
PydObject opMul(int count) { |
|---|
| 509 |
return new PydObject(PySequence_Repeat(m_ptr, count)); |
|---|
| 510 |
} |
|---|
| 511 |
/// |
|---|
| 512 |
PydObject opDiv(PydObject o) { |
|---|
| 513 |
return new PydObject(PyNumber_Divide(m_ptr, o.m_ptr)); |
|---|
| 514 |
} |
|---|
| 515 |
/// |
|---|
| 516 |
PydObject floorDiv(PydObject o) { |
|---|
| 517 |
return new PydObject(PyNumber_FloorDivide(m_ptr, o.m_ptr)); |
|---|
| 518 |
} |
|---|
| 519 |
/// |
|---|
| 520 |
PydObject opMod(PydObject o) { |
|---|
| 521 |
return new PydObject(PyNumber_Remainder(m_ptr, o.m_ptr)); |
|---|
| 522 |
} |
|---|
| 523 |
/// |
|---|
| 524 |
PydObject divmod(PydObject o) { |
|---|
| 525 |
return new PydObject(PyNumber_Divmod(m_ptr, o.m_ptr)); |
|---|
| 526 |
} |
|---|
| 527 |
/// |
|---|
| 528 |
PydObject pow(PydObject o1, PydObject o2=null) { |
|---|
| 529 |
return new PydObject(PyNumber_Power(m_ptr, o1.m_ptr, (o2 is null) ? Py_None : o2.m_ptr)); |
|---|
| 530 |
} |
|---|
| 531 |
/// |
|---|
| 532 |
PydObject opPos() { |
|---|
| 533 |
return new PydObject(PyNumber_Positive(m_ptr)); |
|---|
| 534 |
} |
|---|
| 535 |
/// |
|---|
| 536 |
PydObject opNeg() { |
|---|
| 537 |
return new PydObject(PyNumber_Negative(m_ptr)); |
|---|
| 538 |
} |
|---|
| 539 |
/// |
|---|
| 540 |
PydObject abs() { |
|---|
| 541 |
return new PydObject(PyNumber_Absolute(m_ptr)); |
|---|
| 542 |
} |
|---|
| 543 |
/// |
|---|
| 544 |
PydObject opCom() { |
|---|
| 545 |
return new PydObject(PyNumber_Invert(m_ptr)); |
|---|
| 546 |
} |
|---|
| 547 |
/// |
|---|
| 548 |
PydObject opShl(PydObject o) { |
|---|
| 549 |
return new PydObject(PyNumber_Lshift(m_ptr, o.m_ptr)); |
|---|
| 550 |
} |
|---|
| 551 |
/// |
|---|
| 552 |
PydObject opShr(PydObject o) { |
|---|
| 553 |
return new PydObject(PyNumber_Rshift(m_ptr, o.m_ptr)); |
|---|
| 554 |
} |
|---|
| 555 |
/// |
|---|
| 556 |
PydObject opAnd(PydObject o) { |
|---|
| 557 |
return new PydObject(PyNumber_And(m_ptr, o.m_ptr)); |
|---|
| 558 |
} |
|---|
| 559 |
/// |
|---|
| 560 |
PydObject opXor(PydObject o) { |
|---|
| 561 |
return new PydObject(PyNumber_Xor(m_ptr, o.m_ptr)); |
|---|
| 562 |
} |
|---|
| 563 |
/// |
|---|
| 564 |
PydObject opOr(PydObject o) { |
|---|
| 565 |
return new PydObject(PyNumber_Or(m_ptr, o.m_ptr)); |
|---|
| 566 |
} |
|---|
| 567 |
|
|---|
| 568 |
//--------------------- |
|---|
| 569 |
// In-place arithmetic |
|---|
| 570 |
//--------------------- |
|---|
| 571 |
private extern(C) |
|---|
| 572 |
alias PyObject* function(PyObject*, PyObject*) op_t; |
|---|
| 573 |
|
|---|
| 574 |
// A useful wrapper for most of the in-place operators |
|---|
| 575 |
private PydObject |
|---|
| 576 |
inplace(op_t op, PydObject rhs) { |
|---|
| 577 |
if (PyType_HasFeature(m_ptr.ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)) { |
|---|
| 578 |
op(m_ptr, rhs.m_ptr); |
|---|
| 579 |
handle_exception(); |
|---|
| 580 |
} else { |
|---|
| 581 |
PyObject* result = op(m_ptr, rhs.m_ptr); |
|---|
| 582 |
if (result is null) handle_exception(); |
|---|
| 583 |
Py_DECREF(m_ptr); |
|---|
| 584 |
m_ptr = result; |
|---|
| 585 |
} |
|---|
| 586 |
return this; |
|---|
| 587 |
} |
|---|
| 588 |
/// |
|---|
| 589 |
PydObject opAddAssign(PydObject o) { |
|---|
| 590 |
return inplace(&PyNumber_InPlaceAdd, o); |
|---|
| 591 |
} |
|---|
| 592 |
/// |
|---|
| 593 |
PydObject opSubAssign(PydObject o) { |
|---|
| 594 |
return inplace(&PyNumber_InPlaceSubtract, o); |
|---|
| 595 |
} |
|---|
| 596 |
/// |
|---|
| 597 |
PydObject opMulAssign(PydObject o) { |
|---|
| 598 |
return inplace(&PyNumber_InPlaceMultiply, o); |
|---|
| 599 |
} |
|---|
| 600 |
/// In-place sequence repetition |
|---|
| 601 |
PydObject opMulAssign(int count) { |
|---|
| 602 |
if (PyType_HasFeature(m_ptr.ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)) { |
|---|
| 603 |
PySequence_InPlaceRepeat(m_ptr, count); |
|---|
| 604 |
handle_exception(); |
|---|
| 605 |
} else { |
|---|
| 606 |
PyObject* result = PySequence_InPlaceRepeat(m_ptr, count); |
|---|
| 607 |
if (result is null) handle_exception(); |
|---|
| 608 |
Py_DECREF(m_ptr); |
|---|
| 609 |
m_ptr = result; |
|---|
| 610 |
} |
|---|
| 611 |
return this; |
|---|
| 612 |
} |
|---|
| 613 |
/// |
|---|
| 614 |
PydObject opDivAssign(PydObject o) { |
|---|
| 615 |
return inplace(&PyNumber_InPlaceDivide, o); |
|---|
| 616 |
} |
|---|
| 617 |
/// |
|---|
| 618 |
PydObject floorDivAssign(PydObject o) { |
|---|
| 619 |
return inplace(&PyNumber_InPlaceFloorDivide, o); |
|---|
| 620 |
} |
|---|
| 621 |
/// |
|---|
| 622 |
PydObject opModAssign(PydObject o) { |
|---|
| 623 |
return inplace(&PyNumber_InPlaceRemainder, o); |
|---|
| 624 |
} |
|---|
| 625 |
/// |
|---|
| 626 |
PydObject powAssign(PydObject o1, PydObject o2=null) { |
|---|
| 627 |
if (PyType_HasFeature(m_ptr.ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)) { |
|---|
| 628 |
PyNumber_InPlacePower(m_ptr, o1.m_ptr, (o2 is null) ? Py_None : o2.m_ptr); |
|---|
| 629 |
handle_exception(); |
|---|
| 630 |
} else { |
|---|
| 631 |
PyObject* result = PyNumber_InPlacePower(m_ptr, o1.m_ptr, (o2 is null) ? Py_None : o2.m_ptr); |
|---|
| 632 |
if (result is null) handle_exception(); |
|---|
| 633 |
Py_DECREF(m_ptr); |
|---|
| 634 |
m_ptr = result; |
|---|
| 635 |
} |
|---|
| 636 |
return this; |
|---|
| 637 |
} |
|---|
| 638 |
/// |
|---|
| 639 |
PydObject opShlAssign(PydObject o) { |
|---|
| 640 |
return inplace(&PyNumber_InPlaceLshift, o); |
|---|
| 641 |
} |
|---|
| 642 |
/// |
|---|
| 643 |
PydObject opShrAssign(PydObject o) { |
|---|
| 644 |
return inplace(&PyNumber_InPlaceRshift, o); |
|---|
| 645 |
} |
|---|
| 646 |
/ |
|---|