Changeset 113

Show
Ignore:
Timestamp:
07/05/07 16:51:15 (10 months ago)
Author:
KirkMcDonald
Message:

* Improved Pyd's handling of arrays.
* Added Repr
* Added arraytest

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/html_doc/class_wrapping.html

    r102 r113  
    5959 
    6060<dt><code>struct Init(<span class="t_arg">C</span> ...);</code></dt> 
    61 <dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
     61<dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of <code>Init</code>.</dd> 
     62 
     63<dt><code>struct Repr(alias <span class="t_arg">fn</span>);</code></dt> 
     64<dd>This allows you to expose a member function of the class as the Python type's <code>__repr__</code> function. The member function must have the signature <code>char[] function()</code>.</dd> 
    6265 
    6366<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
  • trunk/html_doc/conversion.html

    r86 r113  
    7070<tr><td><a href="class_wrapping.html">Wrapped class</a></td> <td>Wrapped class</td></tr> 
    7171<tr><td>Any callable</td>   <td>delegate</td>                           </tr> 
     72<tr><td>Any iterable</td>   <td>dynamic array</td>                      </tr> 
    7273<tr><td>str</td>            <td>char[]</td>                             </tr> 
    7374<tr><td>complex</td>        <td>cdouble</td>                            </tr> 
  • trunk/html_doc/index.html

    r105 r113  
    3434<p>Pyd includes the <code>meta.Nameof</code> package by Don Clugston. The source files meta.Nameof and meta.Demangle are copyright &copy; 2005-2006 Don Clugston.</p> 
    3535 
    36 <p>Pyd's Trac page can be found <a href="http://dsource.org/projects/pyd/wiki/">here</a>.</p> 
     36<p>Pyd's Trac page can be found <a href="http://dsource.org/projects/pyd/wiki">here</a>.</p> 
    3737 
    3838<p>A simple "hello, world" module might look like this:</p> 
  • trunk/html_doc/install.html

    r109 r113  
    3232<p>Pyd requires Python 2.4 or newer and the latest version of DMD (on Windows) or GDC (on Linux). At the time of this writing, those versions are DMD 1.00 and GDC 0.21.</p> 
    3333 
    34 <p>Pyd is supported on Windows using the <a href="http://digitalmars.com/d">DMD</a> compiler and on Linux using <a href="http://dgcc.sourceforge.net/">GDC</a>. Support for Derek Parnell's <code>bud</code> is also planned.</p> 
     34<p>Pyd is supported on Windows using the <a href="http://digitalmars.com/d/index.html">DMD</a> compiler and on Linux using <a href="http://dgcc.sourceforge.net/">GDC</a>. Support for Derek Parnell's <code>bud</code> is also planned.</p> 
    3535 
    3636<p>Release Candidate 1 of Pyd is available on dsource:</p> 
  • trunk/html_doc/struct_wrapping.html

    r102 r113  
    5555<dd>This wraps a property. It is the same <code>Property</code> struct template used to <a href="class_wrapping.html">wrap class properties</a>.</dd> 
    5656 
     57<dt><code>struct Repr(alias <span class="t_arg">fn</span>);</code></dt> 
     58<dd>This allows you to expose a member function of the struct as the Python type's <code>__repr__</code> function. The member function must have the signature <code>char[] function()</code>. It is the same <code>Repr</code> struct template used when <a href="class_wrapping.html">wrapping classes</a>.</dd> 
     59 
    5760<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
    5861<dd>This allows the user to specify a different overload of opApply than the default. (The default is always the one that is lexically first.) It is the same <code>Iter</code> struct template used in <a href="class_wrapping.html">class wrapping</a>.</dd> 
  • trunk/infrastructure/pyd/class_wrap.d

    r110 r113  
    177177    void wrapped_dealloc(PyObject* self) { 
    178178        exception_catcher(delegate void() { 
    179             WrapPyObject_SetObj(self, null); 
     179            WrapPyObject_SetObj(self, cast(T)null); 
    180180            self.ob_type.tp_free(self); 
    181181        }); 
     
    183183} 
    184184 
    185 template wrapped_repr(T) { 
     185template wrapped_repr(T, alias fn) { 
    186186    alias wrapped_class_object!(T) wrap_object; 
    187187    /// The default repr method calls the class's toString. 
    188188    extern(C) 
    189     PyObject* repr(PyObject* _self) { 
    190         return exception_catcher({ 
    191             wrap_object* self = cast(wrap_object*)_self; 
    192             char[] repr = objToStr(self.d_obj); 
    193             return _py(repr); 
     189    PyObject* repr(PyObject* self) { 
     190        return exception_catcher(delegate PyObject*() { 
     191            return method_wrap!(T, fn, char[] function()).func(self, null); 
    194192        }); 
    195193    } 
     
    430428 
    431429/** 
     430Wraps a method as the class's __repr__ in Python. 
     431*/ 
     432struct Repr(alias fn) { 
     433    static void call(T, shim)() { 
     434        alias wrapped_class_type!(T) type; 
     435        type.tp_repr = &wrapped_repr!(T, fn).repr; 
     436    } 
     437    template shim(uint i) { 
     438        const char[] shim = ""; 
     439    } 
     440} 
     441 
     442/** 
    432443Wraps the constructors of the class. 
    433444 
     
    722733    alias wrapped_class_type!(T) type; 
    723734    wrapped_object* self = cast(wrapped_object*)_self; 
    724     if (!is_wrapped!(T) || self is null || (is(T : Object) && cast(T)cast(Object)self.d_obj is null)) { 
     735    if (!is_wrapped!(T) || self is null || (is(T : Object) && cast(T)cast(Object)(self.d_obj) is null)) { 
    725736        throw new Exception("Error extracting D object from Python object..."); 
    726737    } 
  • trunk/infrastructure/pyd/func_wrap.d

    r110 r113  
    233233                return null; 
    234234            } 
    235             C instance = (cast(wrapped_class_object!(C)*)self).d_obj; 
     235            C instance = WrapPyObject_AsObject!(C)(self);//(cast(wrapped_class_object!(C)*)self).d_obj; 
    236236            if (instance is null) { 
    237237                PyErr_SetString(PyExc_ValueError, "Wrapped class instance is null!"); 
  • trunk/infrastructure/pyd/make_object.d

    r100 r113  
    9494        return PyComplex_FromDoubles(t.re, t.im); 
    9595    } else static if (is(T : char[])) { 
     96        if (t is null) { 
     97            Py_INCREF(Py_None); 
     98            return Py_None; 
     99        } 
    96100        return PyString_FromString((t ~ \0).ptr); 
    97101    } else static if (is(T : wchar[])) { 
     102        if (t is null) { 
     103            Py_INCREF(Py_None); 
     104            return Py_None; 
     105        } 
    98106        return PyUnicode_FromWideChar(t, t.length); 
    99107    // Converts any array (static or dynamic) to a Python list 
    100108    } else static if (isArray!(T) || isStaticArray!(T)) { 
     109        if (t is null) { 
     110            Py_INCREF(Py_None); 
     111            return Py_None; 
     112        } 
    101113        PyObject* lst = PyList_New(t.length); 
    102114        PyObject* temp; 
     
    114126    // Converts any associative array to a Python dict 
    115127    } else static if (isAA!(T)) { 
     128        if (t is null) { 
     129            Py_INCREF(Py_None); 
     130            return Py_None; 
     131        } 
    116132        PyObject* dict = PyDict_New(); 
    117133        PyObject* ktemp, vtemp; 
     
    137153        return dict; 
    138154    } else static if (is(T == delegate) || is(T == function)) { 
     155        if (t is null) { 
     156            Py_INCREF(Py_None); 
     157            return Py_None; 
     158        } 
    139159        PydWrappedFunc_Ready!(T)(); 
    140160        return WrapPyObject_FromObject(t); 
    141161    } else static if (is(T : PydObject)) { 
     162        if (t is null) { 
     163            Py_INCREF(Py_None); 
     164            return Py_None; 
     165        } 
    142166        PyObject* temp = t.ptr(); 
    143167        Py_INCREF(temp); 
     
    145169    // Convert wrapped type of a PyObject* 
    146170    } else static if (is(T == class)) { 
     171        if (t is null) { 
     172            Py_INCREF(Py_None); 
     173            return Py_None; 
     174        } 
    147175        // But only if it actually is a wrapped type. :-) 
    148176        PyTypeObject** type = t.classinfo in wrapped_classes; 
     
    161189    } else static if (is(typeof(*t) == struct)) { 
    162190        if (is_wrapped!(T)) { 
     191            if (t is null) { 
     192                Py_INCREF(Py_None); 
     193                return Py_None; 
     194            } 
    163195            return WrapPyObject_FromObject(t); 
    164196        } 
     
    248280        // We can only convert to a class if it has been wrapped, and of course 
    249281        // we can only convert the object if it is the wrapped type. 
    250         if (is_wrapped!(T) && cast(T)((cast(wrapped_class_object!(Object)*)o).d_obj) !is null) { 
     282        if ( 
     283            is_wrapped!(T) && 
     284            PyObject_IsInstance(o, cast(PyObject*)&wrapped_class_type!(T)) && 
     285            cast(T)((cast(wrapped_class_object!(Object)*)o).d_obj) !is null 
     286        ) { 
    251287            return WrapPyObject_AsObject!(T)(o); 
    252288        } 
     
    297333        if (result is null) handle_exception(); 
    298334        return .toString(result).dup; 
     335    } else static if (is(T E : E[])) { 
     336        // Dynamic arrays 
     337        PyObject* iter = PyObject_GetIter(o); 
     338        if (iter is null) { 
     339            PyErr_Clear(); 
     340            could_not_convert!(T)(o); 
     341        } 
     342        scope(exit) Py_DECREF(iter); 
     343        int len = PyObject_Length(o); 
     344        if (len == -1) { 
     345            PyErr_Clear(); 
     346            could_not_convert!(T)(o); 
     347        } 
     348        T array; 
     349        array.length = len; 
     350        int i = 0; 
     351        PyObject* item = PyIter_Next(iter); 
     352        while (item) { 
     353            try { 
     354                array[i] = d_type!(E)(item); 
     355            } catch(PydConversionException e) { 
     356                Py_DECREF(item); 
     357                // We re-throw the original conversion exception, rather than 
     358                // complaining about being unable to convert to an array. The 
     359                // partially constructed array is left to the GC. 
     360                throw e; 
     361            } 
     362            ++i; 
     363            Py_DECREF(item); 
     364            item = PyIter_Next(iter); 
     365        } 
     366        return array; 
    299367    } else static if (is(cdouble : T)) { 
    300368        double real_ = PyComplex_RealAsDouble(o); 
  • trunk/raw_html/class_wrapping.html

    r102 r113  
    4343 
    4444<dt><code>struct Init(<span class="t_arg">C</span> ...);</code></dt> 
    45 <dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
     45<dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of <code>Init</code>.</dd> 
     46 
     47<dt><code>struct Repr(alias <span class="t_arg">fn</span>);</code></dt> 
     48<dd>This allows you to expose a member function of the class as the Python type's <code>__repr__</code> function. The member function must have the signature <code>char[] function()</code>.</dd> 
    4649 
    4750<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
  • trunk/raw_html/conversion.html

    r62 r113  
    5454<tr><td><a href="class_wrapping.html">Wrapped class</a></td> <td>Wrapped class</td></tr> 
    5555<tr><td>Any callable</td>   <td>delegate</td>                           </tr> 
     56<tr><td>Any iterable</td>   <td>dynamic array</td>                      </tr> 
    5657<tr><td>str</td>            <td>char[]</td>                             </tr> 
    5758<tr><td>complex</td>        <td>cdouble</td>                            </tr> 
  • trunk/raw_html/struct_wrapping.html

    r102 r113  
    3939<dd>This wraps a property. It is the same <code>Property</code> struct template used to <a href="class_wrapping.html">wrap class properties</a>.</dd> 
    4040 
     41<dt><code>struct Repr(alias <span class="t_arg">fn</span>);</code></dt> 
     42<dd>This allows you to expose a member function of the struct as the Python type's <code>__repr__</code> function. The member function must have the signature <code>char[] function()</code>. It is the same <code>Repr</code> struct template used when <a href="class_wrapping.html">wrapping classes</a>.</dd> 
     43 
    4144<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
    4245<dd>This allows the user to specify a different overload of opApply than the default. (The default is always the one that is lexically first.) It is the same <code>Iter</code> struct template used in <a href="class_wrapping.html">class wrapping</a>.</dd>