diff --git a/setup_mceditlib.py b/setup_mceditlib.py index e6e5e7e..0810962 100644 --- a/setup_mceditlib.py +++ b/setup_mceditlib.py @@ -23,7 +23,9 @@ include_dirs = [numpy.get_include()] mceditlib_ext_modules = cythonize([ "src/mceditlib/nbt.pyx", "src/mceditlib/relight/with_cython.pyx" -]) +], + compile_time_env={'IS_PY2': True}, + ) for m in mceditlib_ext_modules: m.include_dirs = include_dirs diff --git a/src/mceditlib/nbt.pyx b/src/mceditlib/nbt.pyx index 976ff25..55271f3 100644 --- a/src/mceditlib/nbt.pyx +++ b/src/mceditlib/nbt.pyx @@ -38,25 +38,42 @@ DEF UNICODE_NAMES = True # For each NBT file loaded, cache all of the unicode strings used for tag names. Saves some hundred kilobytes per # file since tag names often appear multiple times -DEF UNICODE_CACHE = True +# The value of the IS_PY2 macro is received from the build script +IF IS_PY2: + DEF UNICODE_CACHE = True +ELSE: + # This codepath is currently unsupported in the python3 version + DEF UNICODE_CACHE = False import collections import gzip import zlib -from cStringIO import StringIO -from cpython cimport PyTypeObject, PyUnicode_DecodeUTF8, PyList_Append, PyString_FromStringAndSize +from cpython cimport PyTypeObject, PyUnicode_DecodeUTF8, PyList_Append +IF IS_PY2: + from cStringIO import StringIO + from cpython cimport PyString_FromStringAndSize + binary_type = str +ELSE: + from io import BytesIO as StringIO + binary_type = bytes + import numpy -cdef extern from "cStringIO.h": - struct PycStringIO_CAPI: - int cwrite(object o, char * buf, Py_ssize_t len) - PyTypeObject * OutputType -cdef extern from "cobject.h": - void * PyCObject_Import(char * module_name, char * cobject_name) +IF IS_PY2: + cdef extern from "cStringIO.h": + struct PycStringIO_CAPI: + int cwrite(object o, char * buf, Py_ssize_t len) + PyTypeObject * OutputType + cdef extern from "cobject.h": + void * PyCObject_Import(char * module_name, char * cobject_name) -cdef PycStringIO_CAPI *PycStringIO = PyCObject_Import("cStringIO", "cStringIO_CAPI") -cdef PyTypeObject * StringO = PycStringIO.OutputType + cdef PycStringIO_CAPI *PycStringIO = PyCObject_Import("cStringIO", "cStringIO_CAPI") + cdef PyTypeObject * StringO = PycStringIO.OutputType +ELSE: + # The equivalent python3 code has not been written, so for now only reading + # is supported in python3 + pass # Tag IDs @@ -131,7 +148,7 @@ cdef class TAG_Value: def __set__(self, val): IF UNICODE_NAMES: - if isinstance(val, str): + if isinstance(val, binary_type): val = PyUnicode_DecodeUTF8(val, len(val), "strict") ELSE: if isinstance(val, unicode): @@ -327,7 +344,7 @@ cdef class TAG_String(TAG_Value): return self._value def __set__(self, value): - if isinstance(value, str): + if isinstance(value, binary_type): value = PyUnicode_DecodeUTF8(value, len(value), "strict") self._value = value @@ -509,7 +526,7 @@ cdef class _TAG_Compound(TAG_Value): return data if isinstance(filename_or_buf, basestring): - f = file(filename_or_buf, "wb") + f = open(filename_or_buf, "wb") f.write(data) else: filename_or_buf.write(data) @@ -545,7 +562,7 @@ def load(filename="", buf=None): :rtype: TAG_Compound """ if filename: - buf = file(filename, "rb") + buf = open(filename, "rb") if hasattr(buf, "read"): buf = buf.read() @@ -807,7 +824,10 @@ def hexdump(src, length=8): cdef void cwrite(obj, char *buf, size_t len): #print "cwrite %s %s %d" % (map(ord, buf[:min(4, len)]), buf[:min(4, len)].decode('ascii', 'replace'), len) - PycStringIO.cwrite(obj, buf, len) + IF IS_PY2: + PycStringIO.cwrite(obj, buf, len) + ELSE: + raise Exception("[nbt.pyx python3 port] cwrite was not ported to python3") cdef void save_tag_id(char tagID, object buf):