Commits

ariovistus committed 59060b0

fix deprecation warnings

update multi_index
python 3.3 dropped UCS2/UCS4 aliasing scheme
dmd is default compiler for posix.

  • Participants
  • Parent commits b2a96d8

Comments (0)

Files changed (13)

File dcompiler.py

         else:
             return '-L-l' + lib
     def compile(self, *args, **kwargs):
-        if not _isPlatWin:
+        if not _isPlatWin and not self.build_exe:
             output_dir = kwargs.get('output_dir', '')
             if not os.path.exists(output_dir):
                 os.makedirs(os.path.join(output_dir,'infra'))
             self._dmd_so_ctor = dsto
         return DCompiler.compile(self, *args, **kwargs)
     def link (self, *args, **kwargs):
-        if not _isPlatWin: 
+        if not _isPlatWin and not self.build_exe: 
             args[1].append(self._dmd_so_ctor)
         return DCompiler.link(self, *args, **kwargs)
 

File examples/deimos_unittests/makefile

 	     -version=Python_2_5_Or_Later \
 	     -version=Python_2_4_Or_Later \
 	     -L-lpython2.7
+PYTHON_3_3 = -version=Python_3_3_Or_Later \
+	     -version=Python_3_2_Or_Later \
+	     -version=Python_3_1_Or_Later \
+	     -version=Python_3_0_Or_Later \
+	     -version=Python_2_7_Or_Later \
+             -version=Python_2_6_Or_Later \
+	     -version=Python_2_5_Or_Later \
+	     -version=Python_2_4_Or_Later \
+	     -L-lpython3.3m
 PYTHON_2_7_LDC = -d-version=Python_2_7_Or_Later \
              -d-version=Python_2_6_Or_Later \
 	     -d-version=Python_2_5_Or_Later \
 	rm -f *.o
 
 %.x: %.d
-	$(DC) $(PYTHON_2_7) $< -of$@  -I$(PYD_DIR) -v
+	$(DC) $(PYTHON_3_3) $< -of$@  -I$(PYD_DIR) 
 	#$(LDC) -of $@ $(PYTHON_2_7_LDC) $< -I$(PYD_DIR) $(PYD_FILES)
 

File examples/pyd_unittests/func_wrap.d

 
 unittest {
     static assert(getparams!foo1 == "int i, int j");
-    static assert(getparams!foo2 == "int i, double j = 2");
+    static assert(getparams!foo2.startsWith("int i, double j = 2"));
     static assert(getparams!foo3 == "...");
     static assert(getparams!foo4 == "int[] i...");
     auto fn = &call_ctor!(Foo2, Init!(int, double)).func;

File examples/pyd_unittests/func_wrap3.d

 
 unittest {
     static assert(getparams!foo1 == "int i, int j");
-    static assert(getparams!foo2 == "int i, double j = 2");
+    static assert(getparams!foo2.startsWith("int i, double j = 2"));
     static assert(getparams!foo3 == "...");
     static assert(getparams!foo4 == "int[] i...");
     auto fn = &call_ctor!(Foo2, Init!(int, double)).func;

File infrastructure/deimos/python/unicodeobject.d

    Unicode 3.0. */
 enum Py_UNICODE Py_UNICODE_REPLACEMENT_CHARACTER = 0xFFFD;
 
-version(Python_Unicode_UCS2) {
+version(Python_3_3_Or_Later) {
+    enum PyUnicode_ = "PyUnicode_";
+}else version(Python_Unicode_UCS2) {
     enum PyUnicode_ = "PyUnicodeUCS2_";
 }else{
     enum PyUnicode_ = "PyUnicodeUCS4_";
 // oh, well. this is probably faster anyways.
 // following code is generated by substitute_and_alias. 
 // don't modify it; modify unicode_funs!
-version(Python_Unicode_UCS2) {
+version(Python_3_3_Or_Later) {
+    version(Python_2_6_Or_Later) {
+
+    /** Create a Unicode Object from the Py_UNICODE buffer u of the given
+       size.
+
+       u may be NULL which causes the contents to be undefined. It is the
+       user's responsibility to fill in the needed data afterwards. Note
+       that modifying the Unicode object contents after construction is
+       only allowed if u was set to NULL.
+
+       The buffer is copied into the new object. */
+        /// Availability: >= 2.6
+        PyObject* PyUnicode_FromUnicode(Py_UNICODE* u, Py_ssize_t size);
+
+      /** Similar to PyUnicode_FromUnicode(), but u points to Latin-1 encoded bytes */
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_FromStringAndSize(
+              const(char)*u,        /* char buffer */
+              Py_ssize_t size       /* size of buffer */
+              );
+
+      /** Similar to PyUnicode_FromUnicode(), but u points to null-terminated
+         Latin-1 encoded bytes */
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_FromString(
+              const(char)*u        /* string */
+              );
+
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_FromFormatV(const(char)*, va_list);
+
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_FromFormat(const(char)*, ...);
+
+      /** Format the object based on the format_spec, as defined in PEP 3101
+         (Advanced String Formatting). */
+        /// Availability: >= 2.6
+      PyObject* _PyUnicode_FormatAdvanced(PyObject *obj,
+              Py_UNICODE *format_spec,
+              Py_ssize_t format_spec_len);
+
+        /// Availability: >= 2.6
+      int PyUnicode_ClearFreeList();
+
+      /**
+Params:
+string = UTF-7 encoded string
+length = size of string
+error = error handling
+consumed = bytes consumed 
+*/
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_DecodeUTF7Stateful(
+              const(char)* string,         
+              Py_ssize_t length,          
+              const(char)*errors,         
+              Py_ssize_t *consumed        
+              );
+
+      /**
+Params:
+string = UTF-32 encoded string
+length = size of string
+error = error handling
+byteorder = pointer to byteorder to use 0=native;-1=LE,1=BE; updated on exit 
+*/
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_DecodeUTF32(
+              const(char)* string,
+              Py_ssize_t length, 
+              const(char)*errors,
+              int *byteorder              
+              );
+
+      /**
+Params:
+string = UTF-32 encoded string
+length = size of string
+error = error handling
+byteorder = pointer to byteorder to use 0=native;-1=LE,1=BE; updated on exit 
+*/
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_DecodeUTF32Stateful(
+              const(char)*string,
+              Py_ssize_t length, 
+              const(char)*errors,
+              int *byteorder,    
+              Py_ssize_t *consumed
+              );
+
+      /** Returns a Python string using the UTF-32 encoding in native byte
+         order. The string always starts with a BOM mark.  */
+        /// Availability: >= 2.6
+
+      PyObject* PyUnicode_AsUTF32String(
+              PyObject *unicode
+              );
+
+      /** Returns a Python string object holding the UTF-32 encoded value of
+         the Unicode data.
+
+         If byteorder is not 0, output is written according to the following
+         byte order:
+
+         byteorder == -1: little endian
+         byteorder == 0:  native byte order (writes a BOM mark)
+         byteorder == 1:  big endian
+
+         If byteorder is 0, the output string will always start with the
+         Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is
+         prepended.
+Params:
+data = Unicode char buffer 
+length = number of Py_UNICODE chars to encode 
+errors = error handling
+byteorder = byteorder to use 0=BOM+native;-1=LE,1=BE 
+
+       */
+        /// Availability: >= 2.6
+      PyObject* PyUnicode_EncodeUTF32(
+              const Py_UNICODE *data,     
+              Py_ssize_t length,
+              const(char)* errors,
+              int byteorder
+              );
+
+      }
+
+    /** Return a read-only pointer to the Unicode object's internal
+      Py_UNICODE buffer. */
+    Py_UNICODE* PyUnicode_AsUnicode(PyObject* unicode);
+
+    /** Get the length of the Unicode object. */
+    Py_ssize_t PyUnicode_GetSize(PyObject* unicode);
+
+    /** Get the maximum ordinal for a Unicode character. */
+    Py_UNICODE PyUnicode_GetMax();
+
+    /** Resize an already allocated Unicode object to the new size length.
+
+   _*unicode is modified to point to the new (resized) object and 0
+   returned on success.
+
+   This API may only be called by the function which also called the
+   Unicode constructor. The refcount on the object must be 1. Otherwise,
+   an error is returned.
+
+   Error handling is implemented as follows: an exception is set, -1
+   is returned and *unicode left untouched.
+Params:
+unicode = pointer to the new unicode object.
+length = New length.
+
+*/
+    int PyUnicode_Resize(PyObject** unicode, Py_ssize_t length);
+
+    /** Coerce obj to an Unicode object and return a reference with
+     _*incremented* refcount.
+
+     Coercion is done in the following way:
+
+     1. String and other char buffer compatible objects are decoded
+     under the assumptions that they contain data using the current
+     default encoding. Decoding is done in "strict" mode.
+
+     2. All other objects (including Unicode objects) raise an
+     exception.
+
+     The API returns NULL in case of an error. The caller is responsible
+     for decref'ing the returned objects.
+
+     */
+    PyObject* PyUnicode_FromEncodedObject(
+            PyObject* obj, 
+            const(char)* encoding, 
+            const(char)* errors);
+
+    /** Coerce obj to an Unicode object and return a reference with
+     _*incremented* refcount.
+
+     Unicode objects are passed back as-is (subclasses are converted to
+     true Unicode objects), all other objects are delegated to
+     PyUnicode_FromEncodedObject(obj, NULL, "strict") which results in
+     using the default encoding as basis for decoding the object.
+
+     The API returns NULL in case of an error. The caller is responsible
+     for decref'ing the returned objects.
+
+     */
+    PyObject* PyUnicode_FromObject(PyObject* obj);
+
+    /** Create a Unicode Object from the whcar_t buffer w of the given
+      size.
+
+      The buffer is copied into the new object. */
+    PyObject* PyUnicode_FromWideChar(const(wchar)* w, Py_ssize_t size);
+
+    /** Copies the Unicode Object contents into the wchar_t buffer w.  At
+      most size wchar_t characters are copied.
+
+      Note that the resulting wchar_t string may or may not be
+      0-terminated.  It is the responsibility of the caller to make sure
+      that the wchar_t string is 0-terminated in case this is required by
+      the application.
+
+      Returns the number of wchar_t characters copied (excluding a
+      possibly trailing 0-termination character) or -1 in case of an
+      error. */
+    Py_ssize_t PyUnicode_AsWideChar(
+            PyUnicodeObject* unicode, 
+            const(wchar)* w, 
+            Py_ssize_t size);
+
+    /** Create a Unicode Object from the given Unicode code point ordinal.
+
+       The ordinal must be in range(0x10000) on narrow Python builds
+       (UCS2), and range(0x110000) on wide builds (UCS4). A ValueError is
+       raised in case it is not.
+
+     */
+    PyObject* PyUnicode_FromOrdinal(int ordinal);
+
+    /** Return a Python string holding the default encoded value of the
+      Unicode object.
+
+      The resulting string is cached in the Unicode object for subsequent
+      usage by this function. The cached version is needed to implement
+      the character buffer interface and will live (at least) as long as
+      the Unicode object itself.
+
+      The refcount of the string is *not* incremented.
+
+     _*** Exported for internal use by the interpreter only !!! ***
+
+     */
+    PyObject* _PyUnicode_AsDefaultEncodedString(PyObject *, const(char)*);
+
+    /** Returns the currently active default encoding.
+
+      The default encoding is currently implemented as run-time settable
+      process global.  This may change in future versions of the
+      interpreter to become a parameter which is managed on a per-thread
+      basis.
+
+     */
+    const(char)* PyUnicode_GetDefaultEncoding();
+
+    /** Sets the currently active default encoding.
+
+       Returns 0 on success, -1 in case of an error.
+
+     */
+    int PyUnicode_SetDefaultEncoding(const(char)*encoding);
+
+    /** Create a Unicode object by decoding the encoded string s of the
+      given size. 
+Params:
+s = encoded string 
+size = size of buffer 
+encoding = encoding 
+errors = error handling 
+     */
+    PyObject* PyUnicode_Decode(
+            const(char)* s, 
+            Py_ssize_t size, 
+            const(char)* encoding, 
+            const(char)* errors);
+
+    version(Python_3_0_Or_Later) {
+    /** Decode a Unicode object unicode and return the result as Python
+      object. */
+        /// Availability: 3.*
+
+    PyObject* PyUnicode_AsDecodedObject(
+            PyObject* unicode, 
+            const(char)* encoding, 
+            const(char)* errors 
+            );
+
+    /** Decode a Unicode object unicode and return the result as Unicode
+      object. */
+        /// Availability: 3.*
+
+    PyObject* PyUnicode_AsDecodedUnicode(
+            PyObject* unicode, 
+            const(char)* encoding, 
+            const(char)* errors 
+            );
+
+    }
+
+    /** Encodes a Py_UNICODE buffer of the given size and returns a
+      Python string object. 
+Params:
+s = Unicode char buffer 
+size = number of Py_UNICODE chars to encode 
+encoding = encoding 
+errors = error handling 
+     */
+    PyObject* PyUnicode_Encode(
+            Py_UNICODE* s, 
+            Py_ssize_t size, 
+            const(char)* encoding, 
+            const(char)* errors);
+
+    /** Encodes a Unicode object and returns the result as Python object. 
+     */
+    PyObject* PyUnicode_AsEncodedObject(
+            PyObject* unicode, 
+            const(char)* encoding, 
+            const(char)* errors);
+
+    /** Encodes a Unicode object and returns the result as Python string
+      object. */
+    PyObject* PyUnicode_AsEncodedString(
+            PyObject* unicode, 
+            const(char)* encoding, 
+            const(char)* errors);
+
+    version(Python_3_0_Or_Later) {
+        /** Encodes a Unicode object and returns the result as Unicode
+           object. */
+        /// Availability: >= 3.*
+        PyObject* PyUnicode_AsEncodedUnicode(
+                PyObject* unicode,
+                const(char)* encoding,
+                const(char)* errors  
+                );
+
+    }
+
+    /**
+Params:
+    string = UTF-7 encoded string 
+    length = size of string 
+    errors = error handling 
+    */
+    PyObject* PyUnicode_DecodeUTF7(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /**
+Params:
+    data = Unicode char buffer 
+    length = number of Py_UNICODE chars to encode 
+    base64SetO = Encode RFC2152 Set O characters in base64 
+    base64WhiteSpace = Encode whitespace (sp, ht, nl, cr) in base64 
+    errors = error handling 
+    */
+    PyObject* PyUnicode_EncodeUTF7(
+            Py_UNICODE* data, 
+            Py_ssize_t length,
+            int encodeSetO, 
+            int encodeWhiteSpace, 
+            const(char)* errors
+      );
+
+    /// _
+    PyObject* PyUnicode_DecodeUTF8(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /// _
+    PyObject* PyUnicode_DecodeUTF8Stateful(
+            const(char)* string, 
+            Py_ssize_t length,
+            const(char)* errors, 
+            Py_ssize_t* consumed
+      );
+
+    /// _
+    PyObject* PyUnicode_AsUTF8String(PyObject* unicode);
+
+    /// _
+    PyObject* PyUnicode_EncodeUTF8(
+            Py_UNICODE* data, 
+            Py_ssize_t length, 
+            const(char) *errors);
+
+
+
+    /** Decodes length bytes from a UTF-16 encoded buffer string and returns
+      the corresponding Unicode object.
+
+      errors (if non-NULL) defines the error handling. It defaults
+      to "strict".
+
+      If byteorder is non-NULL, the decoder starts decoding using the
+      given byte order:
+
+     *byteorder == -1: little endian
+     *byteorder == 0:  native order
+     *byteorder == 1:  big endian
+
+     In native mode, the first two bytes of the stream are checked for a
+     BOM mark. If found, the BOM mark is analysed, the byte order
+     adjusted and the BOM skipped.  In the other modes, no BOM mark
+     interpretation is done. After completion, *byteorder is set to the
+     current byte order at the end of input data.
+
+     If byteorder is NULL, the codec starts in native order mode.
+
+     */
+    PyObject* PyUnicode_DecodeUTF16(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors, 
+            int* byteorder);
+
+
+    /**
+Params:
+string = UTF-16 encoded string 
+length = size of string 
+errors = error handling 
+byteorder = pointer to byteorder to use 0=native;-1=LE,1=BE; updated on exit 
+consumed = bytes consumed 
+        */
+    PyObject* PyUnicode_DecodeUTF16Stateful(
+            const(char)* string, 
+            Py_ssize_t length,
+            const(char)* errors, 
+            int* byteorder, 
+            Py_ssize_t* consumed
+      );
+
+
+    /** Returns a Python string using the UTF-16 encoding in native byte
+       order. The string always starts with a BOM mark.  */
+    PyObject* PyUnicode_AsUTF16String(PyObject *unicode);
+
+
+    /** Returns a Python string object holding the UTF-16 encoded value of
+       the Unicode data.
+
+       If byteorder is not 0, output is written according to the following
+       byte order:
+
+       byteorder == -1: little endian
+       byteorder == 0:  native byte order (writes a BOM mark)
+       byteorder == 1:  big endian
+
+       If byteorder is 0, the output string will always start with the
+       Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is
+       prepended.
+
+       Note that Py_UNICODE data is being interpreted as UTF-16 reduced to
+       UCS-2. This trick makes it possible to add full UTF-16 capabilities
+       at a later point without compromising the APIs.
+
+     */
+    PyObject* PyUnicode_EncodeUTF16(
+            Py_UNICODE* data, 
+            Py_ssize_t length,
+            const(char)* errors, 
+            int byteorder
+      );
+
+
+
+    /// _
+    PyObject* PyUnicode_DecodeUnicodeEscape(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+
+    /// _
+    PyObject* PyUnicode_AsUnicodeEscapeString(
+            PyObject* unicode);
+
+
+    /// _
+    PyObject* PyUnicode_EncodeUnicodeEscape(
+            Py_UNICODE* data, 
+            Py_ssize_t length);
+
+
+    /**
+Params:
+string = Raw-Unicode-Escape encoded string 
+length = size of string 
+errors = error handling 
+    */
+    PyObject* PyUnicode_DecodeRawUnicodeEscape(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /// _
+    PyObject* PyUnicode_AsRawUnicodeEscapeString(PyObject* unicode);
+
+    /// _
+    PyObject* PyUnicode_EncodeRawUnicodeEscape(
+            Py_UNICODE* data, Py_ssize_t length);
+
+    /// _
+    PyObject* _PyUnicode_DecodeUnicodeInternal(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /**
+Params:
+string = Latin-1 encoded string 
+length = size of string 
+errors = error handling 
+     */
+    PyObject* PyUnicode_DecodeLatin1(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /// _
+    PyObject* PyUnicode_AsLatin1String(PyObject *unicode);
+
+    /**
+Params:
+data = Unicode char buffer 
+length = Number of Py_UNICODE chars to encode 
+errors = error handling 
+    */
+    PyObject* PyUnicode_EncodeLatin1(
+            Py_UNICODE* data, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /**
+Params:
+    data = Unicode char buffer 
+    length = Number of Py_UNICODE chars to encode 
+    errors = error handling 
+    */
+    PyObject* PyUnicode_DecodeASCII(
+            const(char)* string, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /// _
+    PyObject* PyUnicode_AsASCIIString(PyObject *unicode);
+
+    /**
+Params:
+    data = Unicode char buffer 
+    length = Number of Py_UNICODE chars to encode 
+    errors = error handling 
+      */
+    PyObject* PyUnicode_EncodeASCII(
+            Py_UNICODE* data, 
+            Py_ssize_t length, 
+            const(char)* errors);
+
+    /**
+Params:
+    string = Encoded string 
+    length = size of string 
+    mapping = character mapping (char ordinal -> unicode ordinal) 
+    errors = error handling 
+      */
+    PyObject* PyUnicode_DecodeCharmap(
+            const(char)* string, 
+            Py_ssize_t length,
+            PyObject* mapping, 
+            const(char)* errors
+      );
+
+    /**
+Params:
+    unicode = Unicode object 
+    mapping = character mapping (unicode ordinal -> char ordinal) 
+      */
+    PyObject* PyUnicode_AsCharmapString(
+            PyObject* unicode, 
+            PyObject* mapping);
+
+    /**
+Params:
+    data = Unicode char buffer 
+    length = Number of Py_UNICODE chars to encode 
+    mapping = character mapping (unicode ordinal -> char ordinal) 
+    errors = error handling 
+      */
+    PyObject* PyUnicode_EncodeCharmap(
+            Py_UNICODE* data, 
+            Py_ssize_t length,
+            PyObject* mapping, 
+            const(char)* errors
+      );
+
+    /** Translate a Py_UNICODE buffer of the given length by applying a
+      character mapping table to it and return the resulting Unicode
+      object.
+
+      The mapping table must map Unicode ordinal integers to Unicode
+      ordinal integers or None (causing deletion of the character).
+
+      Mapping tables may be dictionaries or sequences. Unmapped character
+      ordinals (ones which cause a LookupError) are left untouched and
+      are copied as-is.
+
+     */
+    PyObject* PyUnicode_TranslateCharmap(
+            Py_UNICODE* data, 
+            Py_ssize_t length,
+            PyObject* table, 
+            const(char)* errors
+      );
+
+    version (Windows) {
+        /// Availability: Windows only
+      PyObject* PyUnicode_DecodeMBCS(
+              const(char)* string, 
+              Py_ssize_t length, 
+              const(char)* errors);
+
+        /// Availability: Windows only
+      PyObject* PyUnicode_AsMBCSString(PyObject* unicode);
+
+        /// Availability: Windows only
+      PyObject* PyUnicode_EncodeMBCS(
+              Py_UNICODE* data, 
+              Py_ssize_t length, 
+              const(char)* errors);
+
+    }
+    /** Takes a Unicode string holding a decimal value and writes it into
+      an output buffer using standard ASCII digit codes.
+
+      The output buffer has to provide at least length+1 bytes of storage
+      area. The output string is 0-terminated.
+
+      The encoder converts whitespace to ' ', decimal characters to their
+      corresponding ASCII digit and all other Latin-1 characters except
+      \0 as-is. Characters outside this range (Unicode ordinals 1-256)
+      are treated as errors. This includes embedded NULL bytes.
+
+      Error handling is defined by the errors argument:
+
+      NULL or "strict": raise a ValueError
+      "ignore": ignore the wrong characters (these are not copied to the
+      output buffer)
+      "replace": replaces illegal characters with '?'
+
+      Returns 0 on success, -1 on failure.
+
+     */
+    int PyUnicode_EncodeDecimal(
+            Py_UNICODE* s, 
+            Py_ssize_t length, 
+            char* output, 
+            const(char)* errors);
+
+    /** Concat two strings giving a new Unicode string. */
+    PyObject* PyUnicode_Concat(
+            PyObject* left, 
+            PyObject* right);
+
+    version(Python_3_0_Or_Later) {
+        /** Concat two strings and put the result in *pleft
+           (sets *pleft to NULL on error) 
+Params:
+pleft = Pointer to left string 
+right = Right string 
+         */
+        /// Availability: 3.*
+
+        void PyUnicode_Append(
+                PyObject** pleft,
+                PyObject* right 
+                );
+
+        /** Concat two strings, put the result in *pleft and drop the right object
+           (sets *pleft to NULL on error) 
+Params:
+pleft = Pointer to left string 
+         */
+        /// Availability: 3.*
+        void PyUnicode_AppendAndDel(
+                PyObject** pleft,
+                PyObject* right 
+                );
+
+    }
+
+    /** Split a string giving a list of Unicode strings.
+
+      If sep is NULL, splitting will be done at all whitespace
+      substrings. Otherwise, splits occur at the given separator.
+
+      At most maxsplit splits will be done. If negative, no limit is set.
+
+      Separators are not included in the resulting list.
+
+     */
+    PyObject* PyUnicode_Split(
+            PyObject* s, 
+            PyObject* sep, 
+            Py_ssize_t maxsplit);
+
+    /** Ditto PyUnicode_Split, but split at line breaks.
+
+       CRLF is considered to be one line break. Line breaks are not
+       included in the resulting list. */
+    PyObject* PyUnicode_Splitlines(
+            PyObject* s, 
+            int keepends);
+
+    version(Python_2_5_Or_Later) {
+        /** Partition a string using a given separator. */
+        /// Availability: >= 2.5
+        PyObject* PyUnicode_Partition(
+                PyObject* s,
+                PyObject* sep 
+                );
+
+
+        /** Partition a string using a given separator, searching from the end 
+          of the string. */
+
+        PyObject* PyUnicode_RPartition(
+                PyObject* s,
+                PyObject* sep 
+                );
+
+    }
+
+    /** Split a string giving a list of Unicode strings.
+
+       If sep is NULL, splitting will be done at all whitespace
+       substrings. Otherwise, splits occur at the given separator.
+
+       At most maxsplit splits will be done. But unlike PyUnicode_Split
+       PyUnicode_RSplit splits from the end of the string. If negative,
+       no limit is set.
+
+       Separators are not included in the resulting list.
+
+     */
+    PyObject* PyUnicode_RSplit(
+            PyObject* s, 
+            PyObject* sep, 
+            Py_ssize_t maxsplit);
+
+
+    /** Translate a string by applying a character mapping table to it and
+      return the resulting Unicode object.
+
+      The mapping table must map Unicode ordinal integers to Unicode
+      ordinal integers or None (causing deletion of the character).
+
+      Mapping tables may be dictionaries or sequences. Unmapped character
+      ordinals (ones which cause a LookupError) are left untouched and
+      are copied as-is.
+
+     */
+    PyObject* PyUnicode_Translate(
+            PyObject* str, 
+            PyObject* table, 
+            const(char)* errors);
+
+    /** Join a sequence of strings using the given separator and return
+      the resulting Unicode string. */
+    PyObject* PyUnicode_Join(
+            PyObject* separator, 
+            PyObject* seq);
+
+    /** Return 1 if substr matches str[start:end] at the given tail end, 0
+      otherwise. */
+    Py_ssize_t PyUnicode_Tailmatch(
+            PyObject* str, 
+            PyObject* substr,
+            Py_ssize_t start, 
+            Py_ssize_t end, 
+            int direction
+      );
+
+
+    /** Return the first position of substr in str[start:end] using the
+      given search direction or -1 if not found. -2 is returned in case
+      an error occurred and an exception is set. */
+    Py_ssize_t PyUnicode_Find(
+            PyObject* str, 
+            PyObject* substr,
+            Py_ssize_t start, 
+            Py_ssize_t end, 
+            int direction
+      );
+
+    /** Count the number of occurrences of substr in str[start:end]. */
+    Py_ssize_t PyUnicode_Count(
+            PyObject* str, 
+            PyObject* substr, 
+            Py_ssize_t start, 
+            Py_ssize_t end);
+
+    /** Replace at most maxcount occurrences of substr in str with replstr
+       and return the resulting Unicode object. */
+    PyObject* PyUnicode_Replace(
+            PyObject* str, 
+            PyObject* substr,
+            PyObject* replstr, 
+            Py_ssize_t maxcount
+      );
+
+    /** Compare two strings and return -1, 0, 1 for less than, equal,
+      greater than resp. */
+    int PyUnicode_Compare(PyObject* left, PyObject* right);
+
+    version(Python_3_0_Or_Later) {
+        /** Compare two strings and return -1, 0, 1 for less than, equal,
+          greater than resp. 
+Params:
+left =
+right = ASCII-encoded string
+         */
+        /// Availability: 3.*
+        int PyUnicode_CompareWithASCIIString(
+                PyObject* left,
+                const(char)* right
+                );
+    }
+
+    version(Python_2_5_Or_Later) {
+        /** Rich compare two strings and return one of the following:
+
+          - NULL in case an exception was raised
+          - Py_True or Py_False for successfuly comparisons
+          - Py_NotImplemented in case the type combination is unknown
+
+          Note that Py_EQ and Py_NE comparisons can cause a UnicodeWarning in
+          case the conversion of the arguments to Unicode fails with a
+          UnicodeDecodeError.
+
+          Possible values for op:
+
+          Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE
+
+         */
+        /// Availability: >= 2.5
+        PyObject* PyUnicode_RichCompare(
+                PyObject* left,
+                PyObject* right,
+                int op
+                );
+    }
+
+    /** Apply a argument tuple or dictionary to a format string and return
+      the resulting Unicode string. */
+    PyObject* PyUnicode_Format(PyObject* format, PyObject* args);
+
+    /** Checks whether element is contained in container and return 1/0
+       accordingly.
+
+       element has to coerce to an one element Unicode string. -1 is
+       returned in case of an error. */
+    int PyUnicode_Contains(PyObject* container, PyObject* element);
+
+    version(Python_3_0_Or_Later) {
+        /** Checks whether argument is a valid identifier. */
+        /// Availability: 3.*
+        int PyUnicode_IsIdentifier(PyObject* s);
+    }
+
+
+    /// _
+    int _PyUnicode_IsLowercase(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsUppercase(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsTitlecase(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsWhitespace(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsLinebreak(Py_UNICODE ch);
+
+    /// _
+    Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch);
+
+    /// _
+    Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch);
+
+    /// _
+    Py_UNICODE _PyUnicode_ToTitlecase(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_ToDecimalDigit(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_ToDigit(Py_UNICODE ch);
+
+    /// _
+    double _PyUnicode_ToNumeric(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsDecimalDigit(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsDigit(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsNumeric(Py_UNICODE ch);
+
+    /// _
+    int _PyUnicode_IsAlpha(Py_UNICODE ch);
+
+}else version(Python_Unicode_UCS2) {
 
     version(Python_2_6_Or_Later) {
 

File infrastructure/pyd/class_wrap.d

 import std.functional;
 import std.metastrings;
 import std.typetuple;
-import std.string: format = xformat;
+import std.string: format;
 import std.typecons: Tuple;
 import util.typelist;
 import util.multi_index;

File infrastructure/pyd/exception.d

 module pyd.exception;
 
 import std.conv;
-import std.string: format = xformat;
+import std.string: format;
 import std.string;
 import deimos.python.Python;
 import meta.Nameof : prettytypeof;

File infrastructure/pyd/make_object.d

     } else static if (is(Unqual!T _unused : Complex!F, F)) {
         return PyComplex_FromDoubles(t.re, t.im);
     } else static if(is(T == std.bigint.BigInt)) {
-        import std.string: format = xformat;
+        import std.string: format;
         string num_str = format("%s\0",t);
         return PyLong_FromString(num_str.dup.ptr, null, 10);
     } else static if(is(Unqual!T _unused : PydInputRange!E, E)) {
                     format("length mismatch: %s vs %s", count, T.length));
     }
     // copy data, don't take slice
-    memcpy(_array.ptr, arr_o.ob_item, count*itemsize);
+    static if(isPointer!(typeof(_array))) {
+        memcpy((*_array).ptr, arr_o.ob_item, count*itemsize);
+    }else{
+        memcpy(_array.ptr, arr_o.ob_item, count*itemsize);
+    }
     //_array[] = cast(E[]) arr_o.ob_item[0 .. count*itemsize];
     return cast(T) _array;
 }

File infrastructure/pyd/op_wrap.d

 import std.algorithm: startsWith, endsWith;
 import std.traits;
 import std.exception: enforce;
-import std.string: format = xformat;
+import std.string: format;
 import std.conv: to;
 import pyd.class_wrap;
 import pyd.func_wrap;

File infrastructure/util/multi_index.d

-/**
-A port of Joaquín M López Muñoz' 
-<a 
-href="http://www.boost.org/doc/libs/1_48_0/libs/multi_index/doc/index.html"> 
-_multi_index </a>
-library.
-
-
-compilation options: $(BR)
-<b>version=PtrHackery</b> - In boost::_multi_index, Muñoz stores the color of a RB 
-Tree Node in the low bit of one of the pointers with the rationale that on 
-'many' architectures, pointers only point to even addresses.
-
-Source: $(LINK https://bitbucket.org/ariovistus/multi_index/src/)
-Macros: 
-TEXTWITHCOMMAS = $0
-Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. 
-Other code copyright 2011- Ellery Newcomer. 
-All rights reserved by the respective holders.
-
-License: Distributed under the Boost Software License, Version 1.0.
-(See accompanying file LICENSE_1_0.txt or copy at $(WEB
-boost.org/LICENSE_1_0.txt)).
-
-Authors: Steven Schveighoffer, Ellery Newcomer
-
-Introduction:
-A standard container maintains its elements in a specific structure which 
-allows it to offer interesting or useful access to its elements. However,
-sometimes a programmer needs functionality which is not offered by a single
-collection type. Faced with such a need, a programmer must maintain auxiliary 
-containers, either of duplicated elements or of pointers to elements of the 
-primary container.
-In either solution, keeping the parallel containers synchronized quickly 
-becomes a pain, and may introduce inefficiencies in time or memory complexity.
-
-Into this use case steps multi_index. It allows the user to specify multiple
-<i>indeces</i> on the container elements, each of which provides interesting
-access functionality. A multi_index container will automatically keep all 
-indeces synchronized over insertion, removal, or replacement operations 
-performed on any one index.  
-
-Each index will typically require ($(D N * ptrsize * k)) additional bytes of 
-memory, for some k < 4
-
-$(B Quick Start):
-
-A MultiIndexContainer needs two things: a value type and a list of indeces. Put the list of indeces inside $(D IndexedBy). That way we can give MultiIndexContainer other lists, like signals and tags [later].
-
------
-alias MultiIndexContainer!(int, IndexedBy!(Sequenced!())) MyContainer;
-
-MyContainer c = new MyContainer;
------
-
-Generally you do not perform operations on a MultiIndexContainer, but on one of
-its indeces. MultiIndexContainer does define $(D empty) and $(D length), and 
-all indeces support these operations.
------
-// erg, not feeling inspired ..
-auto seq_index = c.get_index!0;
-writeln(seq_index.empty);
-seq_index.insert([1,2,3]); 
-writeln(seq_index.empty);
-writeln(seq_index.front);
------
-The following index types are provided:
-$(BOOKTABLE,
-
-$(TR $(TH $(D Sequenced)))
-
-$(TR  $(TD Provides a doubly linked list view - exposes 
-fast access to the front and back of the index.  Default insertion inserts to 
-the back of the index $(BR)
-
-$(TEXTWITHCOMMAS Complexities:)
-$(BOOKTABLE, $(TR $(TH) $(TH))
-$(TR $(TD Insertion) $(TD $(TEXTWITHCOMMAS 
-i(n) = 1 for front and back insertion
-))) 
-$(TR $(TD Removal) $(TD $(TEXTWITHCOMMAS 
-d(n) = 1 for front, back, and auxiliary removal
-)))
-$(TR $(TD Replacement) $(TD $(TEXTWITHCOMMAS 
-r(n) = 1 for auxiliary replacement 
-))))
-
-$(TEXTWITHCOMMAS Supported Operations:)
-$(BOOKTABLE, 
-$(TR  $(TD $(D
-C.Range
-))$(TD $(TEXTWITHCOMMAS 
-Sequenced Range type.
-)))
-$(TR  $(TD $(D
-c[]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a bidirectional range iterating over the index.
-)))
-$(TR  $(TD $(D
-c.front
-))$(TD $(TEXTWITHCOMMAS 
-Returns the first element inserted into the index
-)))
-$(TR  $(TD $(D
-c.front = value
-))$(TD $(TEXTWITHCOMMAS 
-Replaces the front element in the index with value
-)))
-$(TR  $(TD $(D
-c.back
-))$(TD $(TEXTWITHCOMMAS 
-Returns the last element inserted into the index
-)))
-$(TR  $(TD $(D
-c.back = value
-))$(TD $(TEXTWITHCOMMAS 
-Replaces the last element in the index with value
-)))
-$(TR  $(TD $(D
-c.modify(r, mod)
-))$(TD $(TEXTWITHCOMMAS 
-Executes $(D mod(r.front)) and performs any necessary fixups to the 
-container's indeces. If the result of mod violates any index' invariant, 
-r.front is removed from the container.
-)))
-$(TR  $(TD $(D
-c.replace(r, value)
-))$(TD $(TEXTWITHCOMMAS 
-Replaces $(D r.front) with $(D value).
-)))
-$(TR  $(TD $(D
-c.insertFront(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the front of the index.
-)))
-$(TR  $(TD $(D
-c.insertBack(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the back of the index.
-)))
-$(TR  $(TD $(D
-c.insert(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the back of the index.
-)))
-$(TR  $(TD $(D
-c.removeFront()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the front of the index.
-)))
-$(TR  $(TD $(D
-c.removeBack()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.removeAny()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.remove(r)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the values in range $(D r) from the container.
-)))
-)
-
-))
-
-$(TR $(TH $(D RandomAccess)))
-$(TR $(TD Provides a random access view - exposes an
-array-like access to container elements. Default insertion inserts to the back of the index $(BR)
-
-$(TEXTWITHCOMMAS Complexities:)
-$(BOOKTABLE, $(TR $(TH) $(TH))
-$(TR $(TD Insertion) $(TD $(TEXTWITHCOMMAS 
-i(n) = 1 (amortized) for back insertion, n otherwise 
-))) 
-$(TR $(TD Removal) $(TD $(TEXTWITHCOMMAS 
-d(n) = 1 for back removal, n otherwise 
-)))
-$(TR $(TD Replacement) $(TD $(TEXTWITHCOMMAS 
-r(n) = 1 
-))))
-
-$(TEXTWITHCOMMAS Supported Operations:)
-$(BOOKTABLE, 
-$(TR  $(TD $(D
-C.Range
-))$(TD $(TEXTWITHCOMMAS 
-RandomAccess Range type.
-)))
-$(TR  $(TD $(D
-c[]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a random access range iterating over the index.
-)))
-$(TR  $(TD $(D
-c[a,b]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a random access range iterating over the subrange of the index.
-)))
-$(TR  $(TD $(D
-c.capacity
-))$(TD $(TEXTWITHCOMMAS 
-Returns the length of the underlying store of the index.
-)))
-$(TR  $(TD $(D
-c.reserve(c)
-))$(TD $(TEXTWITHCOMMAS 
-Ensures sufficient capacity to accommodate $(D c) elements
-)))
-$(TR  $(TD $(D
-c.front
-))$(TD $(TEXTWITHCOMMAS 
-Returns the first element inserted into the index
-)))
-$(TR  $(TD $(D
-c.front = value
-))$(TD $(TEXTWITHCOMMAS 
-Replaces the front element in the index with value
-)))
-$(TR  $(TD $(D
-c.back
-))$(TD $(TEXTWITHCOMMAS 
-Returns the last element inserted into the index
-)))
-$(TR  $(TD $(D
-c.back = value
-))$(TD $(TEXTWITHCOMMAS 
-Replaces the last element in the index with value
-)))
-$(TR  $(TD $(D
-c[i]
-))$(TD $(TEXTWITHCOMMAS 
-Provides const view random access to elements of the index.
-)))
-$(TR  $(TD $(D
-c[i] = value
-))$(TD $(TEXTWITHCOMMAS 
-Sets element $(D i) to $(D value), unless another index refuses it.
-)))
-$(TR  $(TD $(D
-c.swapAt(i,j)
-))$(TD $(TEXTWITHCOMMAS 
-Swaps elements' positions in this index only. This can be done without checks!
-)))
-$(TR  $(TD $(D
-c.modify(r, mod)
-))$(TD $(TEXTWITHCOMMAS 
-Executes $(D mod(r.front)) and performs any necessary fixups to the 
-container's indeces. If the result of mod violates any index' invariant, 
-r.front is removed from the container.
-)))
-$(TR  $(TD $(D
-c.replace(r, value)
-))$(TD $(TEXTWITHCOMMAS 
-Replaces $(D r.front) with $(D value).
-)))
-$(TR  $(TD $(D
-c.insertFront(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the front of the index.
-)))
-$(TR  $(TD $(D
-c.insertBack(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the back of the index.
-)))
-$(TR  $(TD $(D
-c.insert(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff to the back of the index.
-)))
-$(TR  $(TD $(D
-c.removeFront()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the front of the index.
-)))
-$(TR  $(TD $(D
-c.removeBack()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.removeAny()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.linearRemove(r)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the values in range $(D r) from the container.
-)))
-)
-
-))
-
-$(TR $(TH $(D Ordered, OrderedUnique, OrderedNonUnique))) 
-$(TR $(TD Provides a 
-red black tree view - keeps container elements in order defined by predicates 
-KeyFromValue and Compare. 
-Unique variant will cause the container to refuse 
-insertion of an item if an equivalent item already exists in the container.
-
-$(TEXTWITHCOMMAS Complexities:)
-$(BOOKTABLE, $(TR $(TH) $(TH))
-$(TR $(TD Insertion) $(TD $(TEXTWITHCOMMAS 
-i(n) = log(n) $(BR)
-))) 
-$(TR $(TD Removal) $(TD $(TEXTWITHCOMMAS 
-d(n) = log(n) $(BR)
-)))
-$(TR $(TD Replacement) $(TD $(TEXTWITHCOMMAS 
-r(n) = 1 if the element's position does not change, log(n) otherwise 
-))))
-
-$(TEXTWITHCOMMAS Supported Operations:)
-$(BOOKTABLE, 
-$(TR  $(TD $(D
-C.Range
-))$(TD $(TEXTWITHCOMMAS 
-Ordered Range type.
-)))
-$(TR  $(TD $(D
-c[]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a bidirectional range iterating over the index.
-)))
-$(TR  $(TD $(D
-c.front
-))$(TD $(TEXTWITHCOMMAS 
-Returns the first element inserted into the index
-)))
-$(TR  $(TD $(D
-c.back
-))$(TD $(TEXTWITHCOMMAS 
-Returns the last element inserted into the index
-)))
-$(TR  $(TD $(D
-k in c
-))$(TD $(TEXTWITHCOMMAS 
-Checks if $(D k) is in the index, where $(D k) is either an element or a key
-)))
-$(TR  $(TD $(D
-c[k]
-))$(TD $(TEXTWITHCOMMAS 
-Provides const view indexed access to elements of the index. Available for Unique variant.
-)))
-$(TR  $(TD $(D
-c.modify(r, mod)
-))$(TD $(TEXTWITHCOMMAS 
-Executes $(D mod(r.front)) and performs any necessary fixups to the 
-container's indeces. If the result of mod violates any index' invariant, 
-r.front is removed from the container.
-)))
-$(TR  $(TD $(D
-c.replace(r, value)
-))$(TD $(TEXTWITHCOMMAS 
-Replaces $(D r.front) with $(D value).
-)))
-$(TR  $(TD $(D
-c.insert(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff into the index.
-)))
-$(TR  $(TD $(D
-c.removeFront()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the front of the index.
-)))
-$(TR  $(TD $(D
-c.removeBack()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.removeAny()
-))$(TD $(TEXTWITHCOMMAS 
-Removes the value at the back of the index.
-)))
-$(TR  $(TD $(D
-c.remove(r)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the values in range $(D r) from the container.
-)))
-$(TR  $(TD $(D
-c.removeKey(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Removes values equivalent to the given values or keys. 
-)))
-$(TR  $(TD $(D
-c.upperBound(k)
-))$(TD $(TEXTWITHCOMMAS 
-Get a range with all elements $(D e) such that $(D e < k)
-)))
-$(TR  $(TD $(D
-c.lowerBound(k)
-))$(TD $(TEXTWITHCOMMAS 
-Get a range with all elements $(D e) such that $(D e > k)
-)))
-$(TR  $(TD $(D
-c.equalRange(k)
-))$(TD $(TEXTWITHCOMMAS 
-Get a range with all elements $(D e) such that $(D e == k)
-)))
-$(TR  $(TD $(D
-c.bounds!("[]")(lo,hi)
-))$(TD $(TEXTWITHCOMMAS 
-Get a range with all elements $(D e) such that $(D lo <= e <= hi). Boundaries parameter a la <a href="http://www.d-programming-language.org/phobos/std_random.html#uniform">std.random.uniform</a>!
-)))
-)
-
-))
-
-$(TR $(TH $(D Hashed, HashedUnique, HashedNonUnique))) 
-$(TR $(TD Provides a 
-hash table view - exposes fast access to every element of the container, 
-given key defined by predicates KeyFromValue, Hash, and Eq.
-Unique variant will cause the container to refuse 
-insertion of an item if an equivalent item already exists in the container.
-
-$(TEXTWITHCOMMAS Complexities:)
-$(BOOKTABLE, $(TR $(TH) $(TH))
-$(TR $(TD Insertion) $(TD $(TEXTWITHCOMMAS 
-i(n) = 1 average, n worst case $(BR)
-))) 
-$(TR $(TD Removal) $(TD $(TEXTWITHCOMMAS 
-d(n) = 1 for auxiliary removal, otherwise 1 average, n worst case $(BR)
-)))
-$(TR $(TD Replacement) $(TD $(TEXTWITHCOMMAS 
-r(n) = 1 if the element's position does not change, log(n) otherwise 
-))))
-
-$(TEXTWITHCOMMAS Supported Operations:)
-$(BOOKTABLE, 
-$(TR  $(TD $(D
-C.Range
-))$(TD $(TEXTWITHCOMMAS 
-Hashed Range type.
-)))
-$(TR  $(TD $(D
-c[]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a forward range iterating over the index.
-)))
-$(TR  $(TD $(D
-c.front
-))$(TD $(TEXTWITHCOMMAS 
-Returns the first element in the hash. No, this isn't helpful.
-)))
-$(TR  $(TD $(D
-k in c
-))$(TD $(TEXTWITHCOMMAS 
-Checks if $(D k) is in the index, where $(D k) is either an element or a key
-)))
-$(TR  $(TD $(D
-c.contains(value)
-))$(TD $(TEXTWITHCOMMAS 
-Checks if $(D value) is in the index. $(BR) EMN: Wat? Wat is this doing in here?
-)))
-$(TR  $(TD $(D
-c[k]
-))$(TD $(TEXTWITHCOMMAS 
-Provides const view indexed access to elements of the index. Available for Unique variant.
-)))
-$(TR  $(TD $(D
-c.modify(r, mod)
-))$(TD $(TEXTWITHCOMMAS 
-Executes $(D mod(r.front)) and performs any necessary fixups to the 
-container's indeces. If the result of mod violates any index' invariant, 
-r.front is removed from the container.
-)))
-$(TR  $(TD $(D
-c.replace(r, value)
-))$(TD $(TEXTWITHCOMMAS 
-Replaces $(D r.front) with $(D value).
-)))
-$(TR  $(TD $(D
-c.insert(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff into the index.
-)))
-$(TR  $(TD $(D
-c.remove(r)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the values in range $(D r) from the container.
-)))
-$(TR  $(TD $(D
-c.removeKey(key)
-))$(TD $(TEXTWITHCOMMAS 
-Removes values equivalent to $(D key). 
-)))
-$(TR  $(TD $(D
-c.equalRange(k)
-))$(TD $(TEXTWITHCOMMAS 
-Get a range with all elements $(D e) such that $(D e == k)
-)))
-)
-
-))
-
-$(TR $(TH $(D Heap))) 
-$(TR $(TD Provides a max heap view - exposes fast access to 
-the largest element in the container as defined by predicates KeyFromValue 
-and Compare.
-
-$(TEXTWITHCOMMAS Complexities:)
-$(BOOKTABLE, $(TR $(TH) $(TH))
-$(TR $(TD Insertion) $(TD $(TEXTWITHCOMMAS 
-i(n) = log(n) 
-))) 
-$(TR $(TD Removal) $(TD $(TEXTWITHCOMMAS 
-d(n) = log(n)
-)))
-$(TR $(TD Replacement) $(TD $(TEXTWITHCOMMAS 
-r(n) = log(n) if the element's position does not change, log(n) otherwise 
-))))
-$(TEXTWITHCOMMAS Supported Operations:)
-$(BOOKTABLE, 
-$(TR  $(TD $(D
-C.Range
-))$(TD $(TEXTWITHCOMMAS 
-Heap Range type.
-)))
-$(TR  $(TD $(D
-c[]
-))$(TD $(TEXTWITHCOMMAS 
-Returns a bidirectional (EMN: wat? why?!) range iterating over the index.
-)))
-$(TR  $(TD $(D
-c.front
-))$(TD $(TEXTWITHCOMMAS 
-Returns the max element in the heap. 
-)))
-$(TR  $(TD $(D
-c.back
-))$(TD $(TEXTWITHCOMMAS 
-Returns some element of the heap.. probably not the max element...
-)))
-$(TR  $(TD $(D
-c.modify(r, mod)
-))$(TD $(TEXTWITHCOMMAS 
-Executes $(D mod(r.front)) and performs any necessary fixups to the 
-container's indeces. If the result of mod violates any index' invariant, 
-r.front is removed from the container.
-)))
-$(TR  $(TD $(D
-c.replace(r, value)
-))$(TD $(TEXTWITHCOMMAS 
-Replaces $(D r.front) with $(D value).
-)))
-$(TR  $(TD $(D
-c.capacity
-))$(TD $(TEXTWITHCOMMAS 
-Returns the length of the underlying store of the index.
-)))
-$(TR  $(TD $(D
-c.reserve(c)
-))$(TD $(TEXTWITHCOMMAS 
-Ensures sufficient capacity to accommodate $(D c) elements
-)))
-$(TR  $(TD $(D
-c.insert(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Inserts stuff into the index.
-)))
-$(TR  $(TD $(D
-c.removeFront(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the max element in the heap.
-)))
-$(TR  $(TD $(D
-c.removeAny(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the max element in the heap.
-)))
-$(TR  $(TD $(D
-c.removeBack(stuff)
-))$(TD $(TEXTWITHCOMMAS 
-Removes the back element in the heap. $(BR) EMN: what the heck was I smoking?
-)))
-)
-
-))
-
-)
-
-Mutability:
-Providing multiple indeces to the same data does introduce some complexities, 
-though. Consider:
------
-alias MultiIndexContainer!(Tuple!(int,string), IndexedBy!(RandomAccess!(), OrderedUnique!("a[1]"))) C;
-
-C c = new C;
-
-c.insert(tuple(1,"a"));
-c.insert(tuple(2,"b"));
-
-c[1][1] = "a"; // bad! index 1 now contains duplicates and is in invalid state! 
------
-In general, the container must either require the user 
-not to perform any damning operation on its elements (which likely will entail 
-paranoid and continual checking of the validity of its indeces), or else not 
-provide a mutable view of its elements. By default, multi_index chooses the 
-latter (with controlled exceptions). 
-
-Thus you are limited to modification operations for which the 
-indeces can detect and perform any fixups (or possibly reject). You can use 
-a remove/modify/insert workflow here, or functions modify and replace, which
-each index implements. 
-
-For modifications which are sure not to invalidate any index, you might simply 
-cast away the constness of the returned element. This will work, 
-but it is not recommended on the grounds of aesthetics (it's ew) and 
-maintainability (if the code changes, it's a ticking time bomb).
-
-Finally, if you just have to have a mutable view, include
-MutableView in the MultiIndexContainer specification. This is
-the least safe option (but see Signals and Slots), and you might make liberal
-use of the convenience function check provided by MultiIndexContainer, 
-which asserts the validity of each index.
-
-Efficiency:
-
-To draw on an example from boost::_multi_index, suppose a collection of 
-Tuple!(int,int) needs to be kept in sorted order by both elements of the tuple.
-This might be accomplished by the following:
-------
-import std.container;
-alias RedBlackTree!(Tuple!(int,int), "a[0] < b[0]") T1;
-alias RedBlackTree!(Tuple!(int,int)*, "(*a)[1] < (*b)[1]") T2;
-
-T1 tree1 = new T1;
-T2 tree2 = new T2;
-------
-
-Insertion remains straightforward
-------
-tree1.insert(item);
-tree2.insert(&item);
-------
-However removal introduces some inefficiency
-------
-tree1.remove(item);
-tree2.remove(&item); // requires a log(n) search, followed by a potential log(n) rebalancing
-------
-Muñoz suggests making the element type of T2 an iterator of T1 for to obviate
-the need for the second search. However, this is not possible in D, as D 
-espouses ranges rather than indeces. (As a side note, Muñoz proceeds to point 
-out that the iterator solution will require at minimum (N * ptrsize) more bytes 
-of memory than will _multi_index, so we needn't lament over this fact.)
-
-Our approach:
-------
-alias MultiIndexContainer!(Tuple!(int,int), 
-        IndexedBy!(OrderedUnique!("a[0]"), 
-            OrderedUnique!("a[1]"))) T;
-
-T t = new T;
-------
-
-makes insertion and removal somewhat simpler:
-
-------
-t.insert(item);
-t.remove(item);
-------
-
-and removal will not perform a log(n) search on the second index 
-(rebalancing can't be avoided).
-
-Signals and Slots:
-
-An experimental feature of multi_index. You can design your value type
-to be a signal, a la std.signals, and hook it up to your 
-MultiIndexContainer. (Note: std.signals won't work with multi_index,
-so don't bother trying)
-
-Example:
--------
-
-import multi_index;
-import std.algorithm: moveAll;
-
-class MyRecord{
-    int _i;
-
-    @property int i()const{ return _i; }
-    @property void i(int i1){
-        _i = i1;
-        emit(); // MultiIndexContainer is notified that this record's 
-                // position in indeces may need to be fixed
-    }
-
-    // signal impl - MultiIndexContainer will use these
-    // to connect. In this example, we actually only need
-    // a single slot. For a value type with M signals 
-    // (differentiated with mixin aliases), there will be 
-    // M slots connected.
-    void delegate()[] slots;
-
-    void connect(void delegate() slot){
-        slots ~= slot;
-    }
-    void disconnect(void delegate() slot){
-        size_t index = slots.length;
-        foreach(i, slot1; slots){
-            if(slot is slot1){
-                index = i;
-                moveAll(slots[i+1 .. $], slots[i .. $-1]);
-                slots.length-=1;
-                break;
-            }
-        }
-    }
-    void emit(){
-        foreach(slot; slots){
-            slot();
-        }
-    }
-}
-
-alias MultiIndexContainer!(MyRecord,
-    IndexedBy!(OrderedUnique!("a.i")),
-    SignalOnChange!(ValueSignal!(0)), // this tells MultiIndexContainer that you want
-                                      // it to use the signal defined in MyRecord.
-                                      // you just need to pass in the index number.
-    MutableView,
-) MyContainer;
-
-MyContainer c = new MyContainer;
-
-// populate c
-
-MyRecord v = c.front();
-
-v.i = 22; // v's position in c is automatically fixed
--------
-
-Thus, MultiIndexContainers can be kept valid automatically PROVIDED no
-modifications occur other than those which call emit.
-
-But what happens if a modification breaks, for example, a uniqueness 
-constraint? Well, you have two options: remove the offending element 
-silently, or remove it loudly (throw an exception). multi_index chooses
-the latter in this case.
-
-$(B Thread Safety):
-
-multi_index is not designed to be used in multithreading.
-Find yourself a relational database.
-
-$(B Memory Allocation)
-
-In C++, memory allocators are used to control how a container allocates memory. D does not have this (but will soon). Until it does, multi_index will use a
-simple allocator protocol to regulate allocation of container structures. 
-Define a struct with two static methods:
-
-------
-struct MyAllocator{
- T* allocate(T)(size_t i); // return pointer to chunk of memory containing i*T.sizeof bytes 
- void deallocate(T)(T* t); // release chunk of memory at t
-}
-------
-Pass the struct type in to MultiIndexContainer:
-------
-alias MultiIndexContainer!(int,IndexedBy!(Sequenced!()), MyAllocator) G;
-------
-Two allocators are predefined in multi_index: $(B GCAllocator) (default), and $(B MallocAllocator)
-
-
- */
 module util.multi_index;
 
 /**
  * TODO:
- *  ordered index
- *   compatible sorting criteria
- *   special constructor for SortedRange?
  *  random access index
  *   insertAfter ? insertBefore ?
  *  fix BitHackery
  *  make MutableView a per index thing?
  *  modify(r, mod, rollback)
- *  tagging
+ *  contain const/immutable value types
  *  other indeces? 
  *  dup
  *  make reserve perform reserve on all appropriate indeces?
- *  
+ *  ensure MultiIndexContainer is strongly exception safe.  
  */
 
 version = BucketHackery;
 import std.range;
 import std.exception: enforce;
 import std.algorithm: find, swap, copy, fill, max, startsWith, moveAll;
+import std.algorithm: move, sort, map;
 import std.traits: isImplicitlyConvertible, isDynamicArray;
-import std.metastrings: Format, toStringNow;
 import util.replace: Replace;
-import std.typetuple: TypeTuple, staticMap, NoDuplicates, staticIndexOf;
+import std.typetuple: TypeTuple, staticMap, NoDuplicates, staticIndexOf, allSatisfy;
 import std.functional: unaryFun, binaryFun;
 import std.string: format;
-import std.typetuple: allSatisfy;
 version(PtrHackery){
     import core.bitop: bt, bts, btr;
 }
 Defines the index' primary range, which embodies a
 bidirectional range 
 */
-        struct Range{
-            ThisContainer c;
-            ThisNode* _front, _back;
-            alias _front node;
+        struct SequencedRange(bool is_const) {
+            static if(is_const) {
+                alias const(ThisNode) Node;
+                alias const(ThisContainer) Container;
+            }else {
+                alias ThisContainer Container;
+                alias ThisNode Node;
+            }
+            Container c;
+            Node* _front, _back;
+            alias _front front_node;
+            alias _back back_node;
+
+            this(Container _c, Node* f, Node* b) {
+                c = _c;
+                _front = f;
+                _back = b;
+            }
 
             @property bool empty() {
                 return 
                     _front !is _back.index!N.next &&
                     _back !is _front.index!N.prev);
             }
-            @property ValueView front(){
+            @property front(){
                 return _front.value;
             }
-            @property ValueView back(){
+            @property back(){
                 return _back.value;
             }
 
-            Range save(){ return this; }
+            @property save(){ return this; }
 
             void popFront()
             in{
             void popBack(){
                 _back = _back.index!N.prev;
             }
-
-/**
-Pops front and removes it from the container.
-Does not invalidate this range.
-Preconditions: !empty
-Complexity: $(BIGOH d(n)), $(BR) $(BIGOH 1) for this index
-*/
-            void removeFront(){
-                ThisNode* node = _front;
-                popFront();
-                c._RemoveAll(node);
-            }
-
-/**
-Pops back and removes it from the container.
-Does not invalidate this range.
-Preconditions: !empty
-Complexity: $(BIGOH d(n)), $(BR) $(BIGOH 1) for this index
-*/
-            void removeBack(){
-                ThisNode* node = _back;
-                popBack();
-                c._RemoveAll(node);
-            }
         }
 
-        alias TypeTuple!(N,Range) IndexTuple;
+        alias TypeTuple!(N,SequencedRange) IndexTuple;
         alias TypeTuple!(N) NodeTuple;
 
         // node implementation 
                 }
         }
 
- /// index implementation 
+ /// Sequenced index implementation 
  ///
  /// Requirements: the following symbols must be  
  /// defined in the scope in which this index is mixed in:
  // dangit, ddoc, show my single starting underscore!
  /// ThisNode, Value, __InsertAllBut!N, __InsertAll,  __Replace, 
  /// __RemoveAllBut!N, node_count
-        mixin template IndexMixin(size_t N, Range_0){
+        mixin template IndexMixin(size_t N, alias Range_0){
             ThisNode* _front, _back;
-            alias Range_0 Range;
+            alias Range_0!false SeqRange;
+            alias Range_0!true ConstSeqRange;
+
+            template IsMyRange(T) {
+                enum bool IsMyRange = 
+                    is(T == SeqRange) || 
+                    is(T == ConstSeqRange);
+            }
 
 /**
 Returns the number of elements in the container.
 
 Complexity: $(BIGOH 1)
 */
-            @property bool empty(){
+            @property bool empty() const{
                 return node_count == 0;
             }
 
 
 Complexity: $(BIGOH 1)
 */