forked from VimPlug/jedi
Merge branch 'py314' of https://github.com/frenzymadness/jedi into py314
This commit is contained in:
@@ -477,22 +477,49 @@ class DirectObjectAccess:
|
|||||||
"""
|
"""
|
||||||
name = None
|
name = None
|
||||||
args = ()
|
args = ()
|
||||||
if safe_getattr(self._obj, '__module__', default='') == 'typing':
|
# Use getattr instead of safe_getattr for __module__ as getattr_static
|
||||||
|
# fails on typing types in Python 3.14+
|
||||||
|
module = getattr(self._obj, '__module__', '')
|
||||||
|
if module == 'typing':
|
||||||
|
import typing
|
||||||
|
# Try regex first (works for most types)
|
||||||
m = re.match(r'typing.(\w+)\[', repr(self._obj))
|
m = re.match(r'typing.(\w+)\[', repr(self._obj))
|
||||||
if m is not None:
|
if m is not None:
|
||||||
name = m.group(1)
|
name = m.group(1)
|
||||||
|
elif sys.version_info >= (3, 8):
|
||||||
|
# Fallback to get_origin() for Python 3.8+ when regex fails
|
||||||
|
# In Python 3.14+, Union/Optional repr changed to use | syntax
|
||||||
|
origin = typing.get_origin(self._obj)
|
||||||
|
if origin is typing.Union:
|
||||||
|
name = 'Union'
|
||||||
|
|
||||||
import typing
|
# Get args
|
||||||
if sys.version_info >= (3, 8):
|
if sys.version_info >= (3, 8):
|
||||||
args = typing.get_args(self._obj)
|
args = typing.get_args(self._obj)
|
||||||
else:
|
else:
|
||||||
args = safe_getattr(self._obj, '__args__', default=None)
|
args = safe_getattr(self._obj, '__args__', default=None)
|
||||||
|
if args is None:
|
||||||
|
args = ()
|
||||||
return name, tuple(self._create_access_path(arg) for arg in args)
|
return name, tuple(self._create_access_path(arg) for arg in args)
|
||||||
|
|
||||||
def needs_type_completions(self):
|
def needs_type_completions(self):
|
||||||
return inspect.isclass(self._obj) and self._obj != type
|
return inspect.isclass(self._obj) and self._obj != type
|
||||||
|
|
||||||
def _annotation_to_str(self, annotation):
|
def _annotation_to_str(self, annotation):
|
||||||
|
# In Python 3.14+, Union types are displayed as X | Y instead of Union[X, Y]
|
||||||
|
# We normalize to Union[X, Y] for consistency
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
import typing
|
||||||
|
origin = typing.get_origin(annotation)
|
||||||
|
if origin is typing.Union:
|
||||||
|
# Get the args and format them as Union[...]
|
||||||
|
args = typing.get_args(annotation)
|
||||||
|
formatted_args = ', '.join(
|
||||||
|
self._annotation_to_str(arg) if hasattr(arg, '__origin__')
|
||||||
|
else getattr(arg, '__name__', str(arg))
|
||||||
|
for arg in args
|
||||||
|
)
|
||||||
|
return f'Union[{formatted_args}]'
|
||||||
return inspect.formatannotation(annotation)
|
return inspect.formatannotation(annotation)
|
||||||
|
|
||||||
def get_signature_params(self):
|
def get_signature_params(self):
|
||||||
|
|||||||
@@ -90,7 +90,10 @@ def getattr_static(obj, attr, default=_sentinel):
|
|||||||
if not _is_type(obj):
|
if not _is_type(obj):
|
||||||
klass = type(obj)
|
klass = type(obj)
|
||||||
dict_attr = _shadowed_dict(klass)
|
dict_attr = _shadowed_dict(klass)
|
||||||
if (dict_attr is _sentinel or type(dict_attr) is types.MemberDescriptorType):
|
# In Python 3.15+, __dict__ is a GetSetDescriptorType instead of being _sentinel
|
||||||
|
if (dict_attr is _sentinel
|
||||||
|
or type(dict_attr) is types.MemberDescriptorType
|
||||||
|
or type(dict_attr) is types.GetSetDescriptorType):
|
||||||
instance_result = _check_instance(obj, attr)
|
instance_result = _check_instance(obj, attr)
|
||||||
else:
|
else:
|
||||||
klass = obj
|
klass = obj
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ def bar():
|
|||||||
({'return': 'typing.Union["str", int]'},
|
({'return': 'typing.Union["str", int]'},
|
||||||
['int', 'str'] if sys.version_info >= (3, 9) else ['int'], ''),
|
['int', 'str'] if sys.version_info >= (3, 9) else ['int'], ''),
|
||||||
({'return': 'typing.Union["str", 1]'},
|
({'return': 'typing.Union["str", 1]'},
|
||||||
['str'] if sys.version_info >= (3, 11) else [], ''),
|
[] if sys.version_info >= (3, 14) else (['str'] if sys.version_info >= (3, 11) else []), ''),
|
||||||
({'return': 'typing.Optional[str]'}, ['NoneType', 'str'], ''),
|
({'return': 'typing.Optional[str]'}, ['NoneType', 'str'], ''),
|
||||||
({'return': 'typing.Optional[str, int]'}, [], ''), # Takes only one arg
|
({'return': 'typing.Optional[str, int]'}, [], ''), # Takes only one arg
|
||||||
({'return': 'typing.Any'},
|
({'return': 'typing.Any'},
|
||||||
@@ -746,7 +746,8 @@ def test_complete_not_findable_class_source():
|
|||||||
def test_param_infer_default():
|
def test_param_infer_default():
|
||||||
abs_sig, = jedi.Interpreter('abs(', [{'abs': abs}]).get_signatures()
|
abs_sig, = jedi.Interpreter('abs(', [{'abs': abs}]).get_signatures()
|
||||||
param, = abs_sig.params
|
param, = abs_sig.params
|
||||||
assert param.name == 'x'
|
# Parameter name changed from 'x' to 'number' in Python 3.15
|
||||||
|
assert param.name in ('x', 'number')
|
||||||
assert param.infer_default() == []
|
assert param.infer_default() == []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ class TestSetupReadline(unittest.TestCase):
|
|||||||
'_', 'O_', 'EX_', 'EFD_', 'MFD_', 'TFD_',
|
'_', 'O_', 'EX_', 'EFD_', 'MFD_', 'TFD_',
|
||||||
'SF_', 'ST_', 'CLD_', 'POSIX_SPAWN_', 'P_',
|
'SF_', 'ST_', 'CLD_', 'POSIX_SPAWN_', 'P_',
|
||||||
'RWF_', 'CLONE_', 'SCHED_', 'SPLICE_',
|
'RWF_', 'CLONE_', 'SCHED_', 'SPLICE_',
|
||||||
|
# Python 3.15+ new constants
|
||||||
|
'AT_', 'PIDFD_', 'STATX_', 'GRND_', 'XATTR_',
|
||||||
|
'RTLD_', 'PRIO_', 'F_', 'SEEK_', 'NODEV',
|
||||||
]
|
]
|
||||||
difference = {
|
difference = {
|
||||||
x for x in difference
|
x for x in difference
|
||||||
|
|||||||
Reference in New Issue
Block a user