jbcoe created this revision.
jbcoe added reviewers: eliben, compnerd, nemanjai, skalinichev.
jbcoe added a subscriber: cfe-commits.
jbcoe set the repository for this revision to rL LLVM.
This is incomplete and I'm in need of some input.
Some test pass in Python 3 now. Python 2 tests pass as before.
Work so far:
`map` in Python 3 is lazily evaluated so the method by which functions are
registered needed updating.
Strings are unicode in Python 3 not UTF-8, I've tried to create an new
c_types-like class (c_string_p) to automate the conversion. It mostly works but
I may have overlooked things.
Once we can get all Python 3 tests to pass then I'd like to get this merged.
Repository:
rL LLVM
https://reviews.llvm.org/D26082
Files:
bindings/python/clang/cindex.py
Index: bindings/python/clang/cindex.py
===================================================================
--- bindings/python/clang/cindex.py
+++ bindings/python/clang/cindex.py
@@ -73,6 +73,30 @@
# this by marshalling object arguments as void**.
c_object_p = POINTER(c_void_p)
+# Python 3 strings are unicode, translate them to/from utf8 for C-interop
+if type(u"") == str:
+ class c_string_p(c_char_p):
+ def __init__(self, p=None):
+ if p is None:
+ p = ""
+ if type(p) == str:
+ p = p.encode("utf8")
+ super(c_char_p, self).__init__(p)
+
+ def __str__(self):
+ return self.value
+
+ @property
+ def value(self):
+ return super(c_char_p, self).value.decode("utf8")
+
+ @classmethod
+ def from_param(cls, param):
+ return cls(param)
+else:
+ c_string_p = c_char_p
+
+
callbacks = {}
### Exception Classes ###
@@ -147,7 +171,7 @@
class _CXString(Structure):
"""Helper for transforming CXString results."""
- _fields_ = [("spelling", c_char_p), ("free", c_int)]
+ _fields_ = [("spelling", c_string_p), ("free", c_int)]
def __del__(self):
conf.lib.clang_disposeString(self)
@@ -554,8 +578,8 @@
if value >= len(self.__class__._kinds):
self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1)
if self.__class__._kinds[value] is not None:
- raise ValueError,'{0} value {1} already loaded'.format(
- str(self.__class__), value)
+ raise ValueError('{0} value {1} already loaded'.format(
+ str(self.__class__), value))
self.value = value
self.__class__._kinds[value] = self
self.__class__._name_map = None
@@ -577,7 +601,7 @@
@classmethod
def from_id(cls, id):
if id >= len(cls._kinds) or cls._kinds[id] is None:
- raise ValueError,'Unknown template argument kind %d' % id
+ raise ValueError('Unknown template argument kind %d' % id)
return cls._kinds[id]
def __repr__(self):
@@ -1775,7 +1799,7 @@
if value >= len(StorageClass._kinds):
StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1)
if StorageClass._kinds[value] is not None:
- raise ValueError,'StorageClass already loaded'
+ raise ValueError('StorageClass already loaded')
self.value = value
StorageClass._kinds[value] = self
StorageClass._name_map = None
@@ -1796,7 +1820,7 @@
@staticmethod
def from_id(id):
if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]:
- raise ValueError,'Unknown storage class %d' % id
+ raise ValueError('Unknown storage class %d' % id)
return StorageClass._kinds[id]
def __repr__(self):
@@ -2125,7 +2149,7 @@
"""
Retrieve the offset of a field in the record.
"""
- return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname))
+ return conf.lib.clang_Type_getOffsetOf(self, c_string_p(fieldname))
def get_ref_qualifier(self):
"""
@@ -2184,7 +2208,7 @@
class _CXUnsavedFile(Structure):
"""Helper for passing unsaved file arguments."""
- _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
+ _fields_ = [("name", c_string_p), ("contents", c_string_p), ('length', c_ulong)]
# Functions calls through the python interface are rather slow. Fortunately,
# for most symboles, we do not need to perform a function call. Their spelling
@@ -2539,17 +2563,19 @@
args_array = None
if len(args) > 0:
- args_array = (c_char_p * len(args))(* args)
+ args_array = (c_string_p * len(args))()
+ for i,a in enumerate(args):
+ args_array[i] = c_string_p(a)
unsaved_array = None
if len(unsaved_files) > 0:
unsaved_array = (_CXUnsavedFile * len(unsaved_files))()
for i, (name, contents) in enumerate(unsaved_files):
if hasattr(contents, "read"):
contents = contents.read()
- unsaved_array[i].name = name
- unsaved_array[i].contents = contents
+ unsaved_array[i].name = c_string_p(name)
+ unsaved_array[i].contents = c_string_p(contents)
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
@@ -2727,9 +2753,9 @@
# FIXME: It would be great to support an efficient version
# of this, one day.
value = value.read()
- print value
+ print(value)
if not isinstance(value, str):
- raise TypeError,'Unexpected unsaved file contents.'
+ raise TypeError('Unexpected unsaved file contents.')
unsaved_files_array[i].name = name
unsaved_files_array[i].contents = value
unsaved_files_array[i].length = len(value)
@@ -2791,9 +2817,9 @@
# FIXME: It would be great to support an efficient version
# of this, one day.
value = value.read()
- print value
+ print(value)
if not isinstance(value, str):
- raise TypeError,'Unexpected unsaved file contents.'
+ raise TypeError('Unexpected unsaved file contents.')
unsaved_files_array[i].name = name
unsaved_files_array[i].contents = value
unsaved_files_array[i].length = len(value)
@@ -3061,7 +3087,7 @@
[c_object_p]),
("clang_CompilationDatabase_fromDirectory",
- [c_char_p, POINTER(c_uint)],
+ [c_string_p, POINTER(c_uint)],
c_object_p,
CompilationDatabase.from_result),
@@ -3071,7 +3097,7 @@
CompileCommands.from_result),
("clang_CompilationDatabase_getCompileCommands",
- [c_object_p, c_char_p],
+ [c_object_p, c_string_p],
c_object_p,
CompileCommands.from_result),
@@ -3106,7 +3132,7 @@
c_uint),
("clang_codeCompleteAt",
- [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int],
+ [TranslationUnit, c_string_p, c_int, c_int, c_void_p, c_int, c_int],
POINTER(CCRStructure)),
("clang_codeCompleteGetDiagnostic",
@@ -3122,7 +3148,7 @@
c_object_p),
("clang_createTranslationUnit",
- [Index, c_char_p],
+ [Index, c_string_p],
c_object_p),
("clang_CXXConstructor_isConvertingConstructor",
@@ -3272,7 +3298,7 @@
("clang_getCString",
[_CXString],
- c_char_p),
+ c_string_p),
("clang_getCursor",
[TranslationUnit, SourceLocation],
@@ -3419,7 +3445,7 @@
Type.from_result),
("clang_getFile",
- [TranslationUnit, c_char_p],
+ [TranslationUnit, c_string_p],
c_object_p),
("clang_getFileName",
@@ -3548,7 +3574,7 @@
("clang_getTUResourceUsageName",
[c_uint],
- c_char_p),
+ c_string_p),
("clang_getTypeDeclaration",
[Type],
@@ -3643,15 +3669,15 @@
bool),
("clang_parseTranslationUnit",
- [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int],
+ [Index, c_string_p, c_void_p, c_int, c_void_p, c_int, c_int],
c_object_p),
("clang_reparseTranslationUnit",
[TranslationUnit, c_int, c_void_p, c_int],
c_int),
("clang_saveTranslationUnit",
- [TranslationUnit, c_char_p, c_uint],
+ [TranslationUnit, c_string_p, c_uint],
c_int),
("clang_tokenize",
@@ -3723,7 +3749,7 @@
Type.from_result),
("clang_Type_getOffsetOf",
- [Type, c_char_p],
+ [Type, c_string_p],
c_longlong),
("clang_Type_getSizeOf",
@@ -3782,7 +3808,8 @@
def register(item):
return register_function(lib, item, ignore_errors)
- map(register, functionList)
+ for f in functionList:
+ register(f)
class Config:
library_path = None
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits