[clang] [libclang/python] Bump minimum compatibility to Python 3.6 (PR #77228)
Craig Hesling via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 6 23:13:48 PST 2024
https://github.com/linux4life798 created https://github.com/llvm/llvm-project/pull/77228
Remove Python 2 support and clean up code that conditions based on version.
Issue #76664.
>From 1ce6508ee1052c46c44a0f8f5dfd424df83ce209 Mon Sep 17 00:00:00 2001
From: Craig Hesling <craig at hesling.com>
Date: Sat, 2 Dec 2023 15:29:42 -0800
Subject: [PATCH 1/4] [libclang/python] Remove Python 2 support
This simply removes the Python 2 arm of this conditional logic
and unindents the Python 3 logic.
---
clang/bindings/python/README.txt | 2 +-
clang/bindings/python/clang/cindex.py | 78 ++++++++++++---------------
2 files changed, 34 insertions(+), 46 deletions(-)
diff --git a/clang/bindings/python/README.txt b/clang/bindings/python/README.txt
index 44c715e5de56f7..3e509662144fac 100644
--- a/clang/bindings/python/README.txt
+++ b/clang/bindings/python/README.txt
@@ -10,7 +10,7 @@ runner. For example:
--
$ env PYTHONPATH=$(echo ~/llvm/clang/bindings/python/) \
CLANG_LIBRARY_PATH=$(llvm-config --libdir) \
- python -m unittest discover -v
+ python3 -m unittest discover -v
tests.cindex.test_index.test_create ... ok
...
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index d780ee353a133c..81aefcc8db6234 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -69,59 +69,47 @@
import os
import sys
-if sys.version_info[0] == 3:
- # Python 3 strings are unicode, translate them to/from utf8 for C-interop.
- class c_interop_string(c_char_p):
- def __init__(self, p=None):
- if p is None:
- p = ""
- if isinstance(p, str):
- p = p.encode("utf8")
- super(c_char_p, self).__init__(p)
- def __str__(self):
- return self.value
-
- @property
- def value(self):
- if super(c_char_p, self).value is None:
- return None
- return super(c_char_p, self).value.decode("utf8")
-
- @classmethod
- def from_param(cls, param):
- if isinstance(param, str):
- return cls(param)
- if isinstance(param, bytes):
- return cls(param)
- if param is None:
- # Support passing null to C functions expecting char arrays
- return None
- raise TypeError(
- "Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__)
- )
+# Python 3 strings are unicode, translate them to/from utf8 for C-interop.
+class c_interop_string(c_char_p):
+ def __init__(self, p=None):
+ if p is None:
+ p = ""
+ if isinstance(p, str):
+ p = p.encode("utf8")
+ super(c_char_p, self).__init__(p)
- @staticmethod
- def to_python_string(x, *args):
- return x.value
+ def __str__(self):
+ return self.value
- def b(x):
- if isinstance(x, bytes):
- return x
- return x.encode("utf8")
+ @property
+ def value(self):
+ if super(c_char_p, self).value is None:
+ return None
+ return super(c_char_p, self).value.decode("utf8")
-elif sys.version_info[0] == 2:
- # Python 2 strings are utf8 byte strings, no translation is needed for
- # C-interop.
- c_interop_string = c_char_p
+ @classmethod
+ def from_param(cls, param):
+ if isinstance(param, str):
+ return cls(param)
+ if isinstance(param, bytes):
+ return cls(param)
+ if param is None:
+ # Support passing null to C functions expecting char arrays
+ return None
+ raise TypeError(
+ "Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__)
+ )
- def _to_python_string(x, *args):
- return x
+ @staticmethod
+ def to_python_string(x, *args):
+ return x.value
- c_interop_string.to_python_string = staticmethod(_to_python_string)
- def b(x):
+def b(x):
+ if isinstance(x, bytes):
return x
+ return x.encode("utf8")
# Importing ABC-s directly from collections is deprecated since Python 3.7,
>From 46638d89c359fc635d30059638fdc7e1517776c8 Mon Sep 17 00:00:00 2001
From: Craig Hesling <craig at hesling.com>
Date: Sat, 2 Dec 2023 15:25:24 -0800
Subject: [PATCH 2/4] [libclang/python] Remove inheritance from object
In Python3, inheriting from the object class is implicit.
---
clang/bindings/python/clang/cindex.py | 40 +++++++++++++--------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 81aefcc8db6234..563bd11db795e8 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -190,7 +190,7 @@ def __init__(self, enumeration, message):
### Structures and Utility Classes ###
-class CachedProperty(object):
+class CachedProperty:
"""Decorator that lazy-loads the value of a property.
The first time the property is accessed, the original property function is
@@ -380,7 +380,7 @@ def __repr__(self):
return "<SourceRange start %r, end %r>" % (self.start, self.end)
-class Diagnostic(object):
+class Diagnostic:
"""
A Diagnostic is a single instance of a Clang diagnostic. It includes the
diagnostic severity, the message, the location the diagnostic occurred, as
@@ -421,7 +421,7 @@ def spelling(self):
@property
def ranges(self):
- class RangeIterator(object):
+ class RangeIterator:
def __init__(self, diag):
self.diag = diag
@@ -437,7 +437,7 @@ def __getitem__(self, key):
@property
def fixits(self):
- class FixItIterator(object):
+ class FixItIterator:
def __init__(self, diag):
self.diag = diag
@@ -456,7 +456,7 @@ def __getitem__(self, key):
@property
def children(self):
- class ChildDiagnosticsIterator(object):
+ class ChildDiagnosticsIterator:
def __init__(self, diag):
self.diag_set = conf.lib.clang_getChildDiagnostics(diag)
@@ -520,7 +520,7 @@ def from_param(self):
return self.ptr
-class FixIt(object):
+class FixIt:
"""
A FixIt represents a transformation to be applied to the source to
"fix-it". The fix-it should be applied by replacing the given source range
@@ -535,7 +535,7 @@ def __repr__(self):
return "<FixIt range %r, value %r>" % (self.range, self.value)
-class TokenGroup(object):
+class TokenGroup:
"""Helper class to facilitate token management.
Tokens are allocated from libclang in chunks. They must be disposed of as a
@@ -591,7 +591,7 @@ def get_tokens(tu, extent):
yield token
-class TokenKind(object):
+class TokenKind:
"""Describes a specific type of a Token."""
_value_map = {} # int -> TokenKind
@@ -630,7 +630,7 @@ def register(value, name):
### Cursor Kinds ###
-class BaseEnumeration(object):
+class BaseEnumeration:
"""
Common base class for named enumerations held in sync with Index.h values.
@@ -2047,7 +2047,7 @@ def from_cursor_result(res, fn, args):
return res
-class StorageClass(object):
+class StorageClass:
"""
Describes the storage class of a declaration
"""
@@ -2596,7 +2596,7 @@ def __ne__(self, other):
# a void*.
-class ClangObject(object):
+class ClangObject:
"""
A helper for Clang objects. This class helps act as an intermediary for
the ctypes library and the Clang CIndex library.
@@ -2644,8 +2644,8 @@ class _CXUnsavedFile(Structure):
}
-class CompletionChunk(object):
- class Kind(object):
+class CompletionChunk:
+ class Kind:
def __init__(self, name):
self.name = name
@@ -2735,7 +2735,7 @@ def isKindResultType(self):
class CompletionString(ClangObject):
- class Availability(object):
+ class Availability:
def __init__(self, name):
self.name = name
@@ -2837,7 +2837,7 @@ def results(self):
@property
def diagnostics(self):
- class DiagnosticsItr(object):
+ class DiagnosticsItr:
def __init__(self, ccr):
self.ccr = ccr
@@ -3147,7 +3147,7 @@ def diagnostics(self):
Return an iterable (and indexable) object containing the diagnostics.
"""
- class DiagIterator(object):
+ class DiagIterator:
def __init__(self, tu):
self.tu = tu
@@ -3316,7 +3316,7 @@ def from_result(res, fn, args):
return res
-class FileInclusion(object):
+class FileInclusion:
"""
The FileInclusion class represents the inclusion of one source file by
another via a '#include' directive or as the input file for the translation
@@ -3365,7 +3365,7 @@ def __init__(self, enumeration, message):
Exception.__init__(self, "Error %d: %s" % (enumeration, message))
-class CompileCommand(object):
+class CompileCommand:
"""Represents the compile command used to build a file"""
def __init__(self, cmd, ccmds):
@@ -3397,7 +3397,7 @@ def arguments(self):
yield conf.lib.clang_CompileCommand_getArg(self.cmd, i)
-class CompileCommands(object):
+class CompileCommands:
"""
CompileCommands is an iterable object containing all CompileCommand
that can be used for building a specific file.
@@ -3853,7 +3853,7 @@ def register(item):
register(f)
-class Config(object):
+class Config:
library_path = None
library_file = None
compatibility_check = True
>From adce8f4f7de87707290d9328c17314c1a8d8d8fd Mon Sep 17 00:00:00 2001
From: Craig Hesling <craig at hesling.com>
Date: Sun, 7 Jan 2024 01:01:37 -0500
Subject: [PATCH 3/4] [libclang/python] Remove fallback for os.fspath
The LLVM minimum python version is 3.6. The os.fspath
function is always available in Python 3.6, so we
remove the unnecessary fallback.
https://docs.python.org/3/library/os.html#os.fspath
Issues #76664.
---
clang/bindings/python/clang/cindex.py | 40 ++++++++++++---------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 563bd11db795e8..c4dcbac5f93be5 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -120,16 +120,6 @@ def b(x):
else:
import collections as collections_abc
-# We only support PathLike objects on Python version with os.fspath present
-# to be consistent with the Python standard library. On older Python versions
-# we only support strings and we have dummy fspath to just pass them through.
-try:
- fspath = os.fspath
-except AttributeError:
-
- def fspath(x):
- return x
-
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
@@ -2991,13 +2981,13 @@ def from_source(
if hasattr(contents, "read"):
contents = contents.read()
contents = b(contents)
- unsaved_array[i].name = b(fspath(name))
+ unsaved_array[i].name = b(os.fspath(name))
unsaved_array[i].contents = contents
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(
index,
- fspath(filename) if filename is not None else None,
+ os.fspath(filename) if filename is not None else None,
args_array,
len(args),
unsaved_array,
@@ -3028,7 +3018,7 @@ def from_ast_file(cls, filename, index=None):
if index is None:
index = Index.create()
- ptr = conf.lib.clang_createTranslationUnit(index, fspath(filename))
+ ptr = conf.lib.clang_createTranslationUnit(index, os.fspath(filename))
if not ptr:
raise TranslationUnitLoadError(filename)
@@ -3181,7 +3171,7 @@ def reparse(self, unsaved_files=None, options=0):
if hasattr(contents, "read"):
contents = contents.read()
contents = b(contents)
- unsaved_files_array[i].name = b(fspath(name))
+ unsaved_files_array[i].name = b(os.fspath(name))
unsaved_files_array[i].contents = contents
unsaved_files_array[i].length = len(contents)
ptr = conf.lib.clang_reparseTranslationUnit(
@@ -3205,7 +3195,11 @@ def save(self, filename):
"""
options = conf.lib.clang_defaultSaveOptions(self)
result = int(
- conf.lib.clang_saveTranslationUnit(self, fspath(filename), options)
+ conf.lib.clang_saveTranslationUnit(
+ self,
+ os.fspath(filename),
+ options,
+ )
)
if result != 0:
raise TranslationUnitSaveError(result, "Error saving TranslationUnit.")
@@ -3249,12 +3243,12 @@ def codeComplete(
if hasattr(contents, "read"):
contents = contents.read()
contents = b(contents)
- unsaved_files_array[i].name = b(fspath(name))
+ unsaved_files_array[i].name = b(os.fspath(name))
unsaved_files_array[i].contents = contents
unsaved_files_array[i].length = len(contents)
ptr = conf.lib.clang_codeCompleteAt(
self,
- fspath(path),
+ os.fspath(path),
line,
column,
unsaved_files_array,
@@ -3288,7 +3282,9 @@ class File(ClangObject):
@staticmethod
def from_name(translation_unit, file_name):
"""Retrieve a file handle within the given translation unit."""
- return File(conf.lib.clang_getFile(translation_unit, fspath(file_name)))
+ return File(
+ conf.lib.clang_getFile(translation_unit, os.fspath(file_name)),
+ )
@property
def name(self):
@@ -3448,7 +3444,7 @@ def fromDirectory(buildDir):
errorCode = c_uint()
try:
cdb = conf.lib.clang_CompilationDatabase_fromDirectory(
- fspath(buildDir), byref(errorCode)
+ os.fspath(buildDir), byref(errorCode)
)
except CompilationDatabaseError as e:
raise CompilationDatabaseError(
@@ -3462,7 +3458,7 @@ def getCompileCommands(self, filename):
build filename. Returns None if filename is not found in the database.
"""
return conf.lib.clang_CompilationDatabase_getCompileCommands(
- self, fspath(filename)
+ self, os.fspath(filename)
)
def getAllCompileCommands(self):
@@ -3868,7 +3864,7 @@ def set_library_path(path):
"any other functionalities in libclang."
)
- Config.library_path = fspath(path)
+ Config.library_path = os.fspath(path)
@staticmethod
def set_library_file(filename):
@@ -3879,7 +3875,7 @@ def set_library_file(filename):
"any other functionalities in libclang."
)
- Config.library_file = fspath(filename)
+ Config.library_file = os.fspath(filename)
@staticmethod
def set_compatibility_check(check_status):
>From 89780022504368ae508044491a2b5b02de3eb69a Mon Sep 17 00:00:00 2001
From: Craig Hesling <craig at hesling.com>
Date: Sun, 7 Jan 2024 01:41:44 -0500
Subject: [PATCH 4/4] [libclang/python] Remove unnecessary versioned import
The LLVM minimum python version is 3.6. The abstract
base classes were copied from collections to
collections.abc in python 3.3. I believe the usage
of ABC from the original "collections" module or
"collections.abc" module were valid between 3.3 and
3.7, but was eventually dropped in 3.8. So, I believe
this method of import has been valid since 3.3.
https://docs.python.org/dev/library/collections.abc.html#module-collections.abc
Issues #76664.
---
clang/bindings/python/clang/cindex.py | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index c4dcbac5f93be5..754f03d718e882 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -66,8 +66,8 @@
import clang.enumerations
+import collections.abc
import os
-import sys
# Python 3 strings are unicode, translate them to/from utf8 for C-interop.
@@ -112,15 +112,6 @@ def b(x):
return x.encode("utf8")
-# Importing ABC-s directly from collections is deprecated since Python 3.7,
-# will stop working in Python 3.8.
-# See: https://docs.python.org/dev/whatsnew/3.7.html#id3
-if sys.version_info[:2] >= (3, 7):
- from collections import abc as collections_abc
-else:
- import collections as collections_abc
-
-
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
# integer and pass the wrong value on platforms where int != void*. Work around
@@ -2331,7 +2322,7 @@ def argument_types(self):
container is a Type instance.
"""
- class ArgumentsIterator(collections_abc.Sequence):
+ class ArgumentsIterator(collections.abc.Sequence):
def __init__(self, parent):
self.parent = parent
self.length = None
More information about the cfe-commits
mailing list