diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index 933cfb918ce9..8328310eae53 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -136,6 +136,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { rtype = getReturnTypeByQName(overloadedQName, anchor); if (rtype != null) { boolean matched = true; + boolean notNullParameterMatch = false; for (Map.Entry entry : arguments.entrySet()) { final PyNamedParameter p = entry.getValue(); final String name = p.getName(); @@ -144,7 +145,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { } PyType argType = entry.getKey().getType(context); // Special case for the 'mode' argument of the 'open()' builtin - if (("__builtin__.open".equals(qname) || "io.open".equals(qname)) && "mode".equals(name)) { + if (("__builtin__.open".equals(qname) || "io.open".equals(qname) || "os.fdopen".equals(qname)) && "mode".equals(name)) { final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor); final LanguageLevel level = LanguageLevel.forElement(anchor); argType = cache.getUnicodeType(level); @@ -157,11 +158,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { } } final PyType paramType = getParameterTypeByQName(overloadedQName, name, anchor); - if (!PyTypeChecker.match(paramType, argType, context)) { + if (PyTypeChecker.match(paramType, argType, context)) { + if (argType != null && paramType != null) { + notNullParameterMatch = true; + } + } + else { matched = false; } } - if (matched) { + if (matched && notNullParameterMatch) { return rtype; } } diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties index 93600d7b721c..54912ad380d8 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties @@ -1822,6 +1822,934 @@ decimal.Decimal.__neg__ = \ :rtype: decimal.Decimal \n\ +# 10.1. os.path + +os.path.abspath = \ + :type path: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.abspath.1 = \ + :type path: bytes \n\ + :rtype: bytes \n\ + +os.path.abspath.2 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.path.basename = \ + :type p: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.basename.1 = \ + :type p: bytes \n\ + :rtype: bytes \n\ + +os.path.basename.2 = \ + :type p: unicode \n\ + :rtype: unicode \n\ + +os.path.commonprefix = \ + :type m: collections.Iterable of string \n\ + :rtype: bytes or unicode \n\ + +os.path.commonprefix.1 = \ + :type m: collections.Iterable of bytes \n\ + :rtype: bytes \n\ + +os.path.commonprefix.2 = \ + :type m: collections.Iterable of unicode \n\ + :rtype: unicode \n\ + +os.path.dirname = \ + :type p: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.dirname.1 = \ + :type p: bytes \n\ + :rtype: bytes \n\ + +os.path.dirname.2 = \ + :type p: unicode \n\ + :rtype: unicode \n\ + +os.path.exists = \ + :type path: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.lexists = \ + :type path: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.expanduser = \ + :type path: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.expanduser.1 = \ + :type path: bytes \n\ + :rtype: bytes \n\ + +os.path.expanduser.2 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.path.expandvars = \ + :type path: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.expandvars.1 = \ + :type path: bytes \n\ + :rtype: bytes \n\ + +os.path.expandvars.2 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.path.getatime = \ + :type filename: bytes or unicode \n\ + :rtype: int or float \n\ + +os.path.getmtime = \ + :type filename: bytes or unicode \n\ + :rtype: int or float \n\ + +os.path.getctime = \ + :type filename: bytes or unicode \n\ + :rtype: int or float \n\ + +os.path.getsize = \ + :type filename: bytes or unicode \n\ + :rtype: int or long \n\ + +os.path.isabs = \ + :type s: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.isfile = \ + :type path: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.isdir = \ + :type s: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.islink = \ + :type path: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.ismount = \ + :type path: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.join = \ + :type a: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.join.1 = \ + :type a: bytes \n\ + :rtype: bytes \n\ + +os.path.join.2 = \ + :type a: unicode \n\ + :rtype: unicode \n\ + +os.path.normcase = \ + :type s: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.normcase.1 = \ + :type s: bytes \n\ + :rtype: bytes \n\ + +os.path.normcase.2 = \ + :type s: unicode \n\ + :rtype: unicode \n\ + +os.path.normpath = \ + :type path: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.normpath.1 = \ + :type path: bytes \n\ + :rtype: bytes \n\ + +os.path.normpath.2 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.path.realpath = \ + :type filename: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.realpath.1 = \ + :type filename: bytes \n\ + :rtype: bytes \n\ + +os.path.realpath.2 = \ + :type filename: unicode \n\ + :rtype: unicode \n\ + +os.path.relpath = \ + :type path: bytes or unicode \n\ + :type start: bytes or unicode \n\ + :rtype: bytes or unicode \n\ + +os.path.relpath.1 = \ + :type path: bytes \n\ + :rtype: bytes \n\ + +os.path.relpath.2 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.path.samefile = \ + :type f1: bytes or unicode \n\ + :type f2: bytes or unicode \n\ + :rtype: bool \n\ + +os.path.sameopenfile = \ + :type fp1: int \n\ + :type fp2: int \n\ + :rtype: bool \n\ + +os.path.samestat = \ + :type s1: os.stat_result or tuple \n\ + :type s2: os.stat_result or tuple \n\ + :rtype: bool \n\ + +os.path.split = \ + :type p: bytes or unicode \n\ + :rtype: (bytes or unicode, bytes or unicode) \n\ + +os.path.split.1 = \ + :type p: bytes \n\ + :rtype: (bytes, bytes) \n\ + +os.path.split.2 = \ + :type p: unicode \n\ + :rtype: (unicode, unicode) \n\ + +os.path.splitdrive = \ + :type p: bytes or unicode \n\ + :rtype: (bytes or unicode, bytes or unicode) \n\ + +os.path.splitdrive.1 = \ + :type p: bytes \n\ + :rtype: (bytes, bytes) \n\ + +os.path.splitdrive.2 = \ + :type p: unicode \n\ + :rtype: (unicode, unicode) \n\ + +os.path.splitext = \ + :type p: bytes or unicode \n\ + :rtype: (bytes or unicode, bytes or unicode) \n\ + +os.path.splitext.1 = \ + :type p: bytes \n\ + :rtype: (bytes, bytes) \n\ + +os.path.splitext.2 = \ + :type p: unicode \n\ + :rtype: (unicode, unicode) \n\ + +os.path.splitunc = \ + :type p: bytes or unicode \n\ + :rtype: (bytes or unicode, bytes or unicode) \n\ + +os.path.splitunc.1 = \ + :type p: bytes \n\ + :rtype: (bytes, bytes) \n\ + +os.path.splitunc.2 = \ + :type p: unicode \n\ + :rtype: (unicode, unicode) \n\ + +os.path.walk = \ + :type top: bytes or unicode \n\ + :rtype: None \n\ + + +## 10.10. shutil + +shutil.copyfile = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.copymode = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.copystat = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.copy = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.copy2 = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.copytree = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :type symlinks: bool \n\ + :type ignore: collections.Callable or None \n\ + :rtype None \n\ + +shutil.rmtree = \ + :type path: bytes or unicode \n\ + :type ignore_errors: bool\n\ + :type onerror: collections.Callable or None \n\ + :rtype None \n\ + +shutil.move = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype None \n\ + +shutil.make_archive = \ + :type base_name: bytes or unicode \n\ + :type format: bytes or unicode \n\ + :type root_dir: bytes or unicode or None \n\ + :type base_dir: bytes or unicode or None \n\ + :type verbose: bool or int \n\ + :type dry_run: bool or int \n\ + :type owner: bytes or unicode or int or None \n\ + :type group: bytes or unicode or int or None \n\ + :rtype: bytes or unicode \n\ + +shutil.get_archive_formats = \ + :rtype: list of (string, string) \n\ + +shutil.register_archive_format = \ + :type name: bytes or unicode \n\ + :type function: collections.Callable \n\ + :type extra_args: None or collections.Sequence of (string, object) \n\ + :type description: bytes or unicode \n\ + :rtype: None + +shutil.unregister_archive_format = \ + :type name: bytes or unicode \n\ + :rtype: None \n\ + + +## 15.1. os + +os.ctermid = \ + :rtype: unicode \n\ + +os.getegid = \ + :rtype: int \n\ + +os.geteuid = \ + :rtype: int \n\ + +os.getgid = \ + :rtype: int \n\ + +os.getgroups = \ + :rtype: list of int \n\ + +os.initgroups = \ + :type username: string \n\ + :type gid: int \n\ + :rtype: None \n\ + +os.getlogin = \ + :rtype: unicode \n\ + +os.getpgid = \ + :type pid: int \n\ + :rtype: int \n\ + +os.getpgrp = \ + :rtype: int \n\ + +os.getpid = \ + :rtype: int \n\ + +os.getresuid = \ + :rtype: (int, int, int) \n\ + +os.getuid = \ + :rtype: int \n\ + +os.getenv = \ + :type key: string \n\ + :type default: object \n\ + :rtype: string \n\ + +os.putenv = \ + :type key: bytes or unicode \n\ + :type value: bytes or unicode \n\ + :rtype: None \n\ + +os.setegid = \ + :type gid: int \n\ + :rtype: None \n\ + +os.seteuid = \ + :type uid: int \n\ + :rtype: None \n\ + +os.setgid = \ + :type gid: int \n\ + :rtype: None \n\ + +os.setgroups = \ + :type p_list: list of int \n\ + :rtype: None \n\ + +os.setpgrp = \ + :rtype: None \n\ + +os.setpgid = \ + :type pid: int \n\ + :type pgrp: int \n\ + :rtype: None \n\ + +os.setregid = \ + :type rgid: int \n\ + :type egid: int \n\ + :rtype: None \n\ + +os.setresgid = \ + :type rgid: int \n\ + :type egid: int \n\ + :type sgid: int \n\ + :rtype: None \n\ + +os.setresuid = \ + :type ruid: int \n\ + :type euid: int \n\ + :type suid: int \n\ + :rtype: None \n\ + +os.setreuid = \ + :type ruid: int \n\ + :type euid: int \n\ + :rtype: None \n\ + +os.getsid = \ + :type pid: int \n\ + :rtype: int \n\ + +os.setsid = \ + :rtype: None \n\ + +os.setuid = \ + :type uid: int \n\ + :rtype: None \n\ + +os.strerror = \ + :type code: int \n\ + :rtype: unicode \n\ + +os.umask = \ + :type new_mask: int \n\ + :rtype: int \n\ + +os.uname = \ + :rtype: (unicode, unicode, unicode, unicode, unicode) \n\ + +os.unsetenv = \ + :type key: string \n\ + :rtype: None \n\ + +os.fdopen = \ + :type fd: int \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: file \n\ + +os.fdopen.1 = \ + :type mode: unicode \n\ + :rtype: io.TextIOWrapper \n\ + +os.fdopen.2 = \ + :type mode: bytes \n\ + :rtype: io.FileIO \n\ + +os.popen = \ + :type command: string \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: io.FileIO \n\ + +os.tmpfile = \ + :rtype: io.FileIO \n\ + +os.popen2 = \ + :type cmd: string \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: (io.FileIO, io.FileIO) \n\ + +os.popen3 = \ + :type cmd: string \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: (io.FileIO, io.FileIO, io.FileIO) \n\ + +os.popen4 = \ + :type cmd: string \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: (io.FileIO, io.FileIO) \n\ + +os.close = \ + :type fd: int \n\ + :rtype: None \n\ + +os.closerange = \ + :type fd_low: int \n\ + :type fd_high: int \n\ + :rtype: None \n\ + +os.dup = \ + :type fd: int \n\ + :rtype: int \n\ + +os.dup2 = \ + :type old_fd: int \n\ + :type new_fd: int \n\ + :rtype: None \n\ + +os.fchmod = \ + :type fd: int \n\ + :type mode: int \n\ + :rtype: None \n\ + +os.fchown = \ + :type fd: int \n\ + :type uid: int \n\ + :type gid: int \n\ + :rtype: None \n\ + +os.fdatasync = \ + :type fildes: int \n\ + :rtype: None \n\ + +os.fpathconf = \ + :type fd: int \n\ + :type name: int or string \n\ + +os.fstat = \ + :type fd: int \n\ + :rtype: os.stat_result \n\ + +os.fstatvfs = \ + :type fd: int \n\ + :rtype: os.statvfs_result \n\ + +os.fsync = \ + :type filedes: int \n\ + :rtype: None \n\ + +os.ftruncate = \ + :type fd: int \n\ + :type length: int or long \n\ + :rtype: None \n\ + +os.isatty = \ + :type fd: int \n\ + :rtype: bool \n\ + +os.lseek = \ + :type fd: int \n\ + :type pos: int or long \n\ + :type how: int \n\ + :rtype: None \n\ + +os.open = \ + :type filename: string \n\ + :type mode: string \n\ + :type bufsize: int \n\ + :rtype: int \n\ + +os.openpty = \ + :rtype: (int, int) \n\ + +os.pipe = \ + :rtype: (int, int) \n\ + +os.read = \ + :type fd: int \b\ + :type buffersize: int or long \n\ + :rtype: bytes \n\ + +os.tcgetpgrp = \ + :type fd: int \n\ + :rtype: int \n\ + +os.tcsetpgrp = \ + :type fd: int \n\ + :type pgid: int \n\ + :rtype: None \n\ + +os.ttyname = \ + :type fd: int \n\ + :rtype: unicode \n\ + +os.write = \ + :type fd: int \n\ + :type string: bytes \n\ + :rtype: int \n\ + +os.access = \ + :type path: bytes or unicode \n\ + :type mode: int \n\ + :rtype: bool \n\ + +os.chdir = \ + :type path: bytes or unicode \n\ + :rtype: None \n\ + +os.fchdir = \ + :type filedes: int \n\ + :rtype: None \n\ + +os.getcwd = \ + :rtype: bytes \n\ + +os.getcwdu = \ + :rtype: unicode \n\ + +os.chroot = \ + :type path: bytes or unicode \n\ + :rtype: None \n\ + +os.chmod = \ + :type path: bytes or unicode \n\ + :type mode: int \n\ + :rtype: None \n\ + +os.chown = \ + :type path: bytes or unicode \n\ + :type uid: int \n\ + :type gid: int \n\ + :rtype: None \n\ + +os.lchown = \ + :type path: bytes or unicode \n\ + :type uid: int \n\ + :type gid: int \n\ + :rtype: None \n\ + +os.link = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype: None \n\ + +os.listdir = \ + :type path: bytes or unicode \n\ + :rtype: list of string \n\ + +os.listdir.1 = \ + :type path: unicode \n\ + :rtype: list of unicode \n\ + +os.lstat = \ + :type path: bytes or unicode \n\ + :rtype: os.stat_result \n\ + +os.mkfifo = \ + :type filename: bytes or unicode \n\ + :type mode: int \n\ + :rtype: None \n\ + +os.mknod = \ + :type filename: bytes or unicode \n\ + :type mode: int \n\ + :type device: int \n\ + :rtype: None \n\ + +os.major = \ + :type device: int \n\ + :rtype: int \n\ + +os.minor = \ + :type device: int \n\ + :rtype: int \n\ + +os.makedev = \ + :type major: int \n\ + :type minor: int \n\ + :rtype: int \n\ + +os.mkdir = \ + :type path: bytes or unicode \n\ + :type mode: int \n\ + :rtype: None \n\ + +os.makedirs = \ + :type name: bytes or unicode \n\ + :type mode: int \n\ + :rtype: None \n\ + +os.pathconf = \ + :type path: bytes or unicode \n\ + :type name: int or string \n\ + +os.readlink = \ + :type path: bytes or unicode \n\ + :rtype: string \n\ + +os.readlink.1 = \ + :type path: unicode \n\ + :rtype: unicode \n\ + +os.remove = \ + :type path: bytes or unicode \n\ + :rtype: None \n\ + +os.removedirs = \ + :type name: bytes or unicode \n\ + :rtype: None \n\ + +os.rename = \ + :type old: bytes or unicode \n\ + :type new: bytes or unicode \n\ + :rtype: None \n\ + +os.renames = \ + :type old: bytes or unicode \n\ + :type new: bytes or unicode \n\ + :rtype: None \n\ + +os.rmdir = \ + :type path: bytes or unicode \n\ + :rtype: None \n\ + +os.stat = \ + :type path: bytes or unicode \n\ + :rtype: os.stat_result \n\ + +os.stat_float_times = \ + :type newval: bool or None \n\ + :rtype: bool \n\ + +os.statvfs = \ + :type path: bytes or unicode \n\ + :rtype: os.statvfs_result \n\ + +os.symlink = \ + :type src: bytes or unicode \n\ + :type dst: bytes or unicode \n\ + :rtype: None \n\ + +os.tempnam = \ + :type dir: bytes or unicode \n\ + :type prefix: bytes or unicode \n\ + :rtype: string \n\ + +os.tmpnam = \ + :rtype: string \n\ + +os.unlink = \ + :type path: bytes or unicode \n\ + :rtype: None \n\ + +os.utime = \ + :type path: bytes or unicode \n\ + :type atime: int or float \n\ + :type mtime: int or float \n\ + :rtype: None \n\ + +os.walk = \ + :type top: bytes or unicode \n\ + :type topdown: bool \n\ + :type followlinks: bool \n\ + :rtype: collections.Iterable of (string, list of string, list of string) \n\ + +os.walk.1 = \ + :type top: bytes \n\ + :type topdown: bool \n\ + :type followlinks: bool \n\ + :rtype: collections.Iterable of (bytes, list of bytes, list of bytes) \n\ + +os.walk.2 = \ + :type top: unicode \n\ + :type topdown: bool \n\ + :type followlinks: bool \n\ + :rtype: collections.Iterable of (unicode, list of unicode, list of unicode) \n\ + +os.execl = \ + :type file: bytes or unicode \n\ + :rtype: None \n\ + +os.execle = \ + :type file: bytes or unicode \n\ + :rtype: None \n\ + +os.execlp = \ + :type file: bytes or unicode \n\ + :rtype: None \n\ + +os.execlpe = \ + :type file: bytes or unicode \n\ + :rtype: None \n\ + +os.execv = \ + :type path: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :rtype: None \n\ + +os.execve = \ + :type path: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :type env: collections.Mapping of (string, string) \n\ + :rtype: None \n\ + +os.execvp = \ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :rtype: None \n\ + +os.execvpe = \ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :type env: collections.Mapping of (string, string) \n\ + :rtype: None \n\ + +os._exit = \ + :type status: int \n\ + :rtype: None \n\ + +os.fork = \ + :rtype: int \n\ + +os.forkpty = \ + :rtype: (int, int) \n\ + +os.kill = \ + :type pid: int \n\ + :type sig: int \n\ + :rtype: None \n\ + +os.killpg = \ + :type pgid: int \n\ + :type sig: int \n\ + :rtype: None \n\ + +os.nice = \ + :type inc: int \n\ + :rtype: int \n\ + +os.spawnl = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :rtype: int \n\ + +os.spawnle = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :rtype: int \n\ + +os.spawnlp = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :rtype: int \n\ + +os.spawnlpe = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :rtype: int \n\ + +os.spawnv = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :rtype: int \n\ + +os.spawnve = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :type env: collections.Mapping of (string, string) \n\ + :rtype: int \n\ + +os.spawnvp = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :rtype: int \n\ + +os.spawnvpe = \ + :type mode: int \n\ + :type file: bytes or unicode \n\ + :type args: collections.Iterable of string \n\ + :type env: collections.Mapping of (string, string) \n\ + :rtype: int \n\ + +os.system = \ + :type command: bytes or unicode \n\ + :rtype: int \n\ + +os.times = \ + :rtype: (float, float, float, float, float) \n\ + +os.wait = \ + :rtype: (int, int) \n\ + +os.waitpid = \ + :type pid: int \n\ + :type options: int \n\ + :rtype: (int, int) \n\ + +os.wait3 = \ + :type options: int \n\ + :rtype: (int, int, resource.struct_rusage) \n\ + +os.wait4 = \ + :type pid: int \n\ + :type options: int \n\ + :rtype: (int, int, resource.struct_rusage) \n\ + +os.WCOREDUMP = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WIFCONTINUED = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WIFSTOPPED = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WIFSIGNALED = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WIFEXITED = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WEXITSTATUS = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WSTOPSIG = \ + :type status: int \n\ + :rtype: bool \n\ + +os.WTERMSIG = \ + :type status: int \n\ + :rtype: bool \n\ + +os.urandom = \ + :type n: int \n\ + :rtype: bytes \n\ + + ## 15.2. io io.open = \ @@ -1948,6 +2876,13 @@ base64.b64decode = \ :rtype: bytes \n\ +## 27.1. sys + +sys.exit = \ + :type status: int \n\ + :rtype: None \n\ + + # 27.13. inspect # Fake diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties index 1734dc72ba4a..df60add6ffec 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes3.properties @@ -370,6 +370,12 @@ __builtin__.range.__init__ = \ :rtype: range of int \n\ +## 15.1. os + +os.getcwd = \ + :rtype: str \n\ + + ## 15.2. io io.IOBase.readlines = \ diff --git a/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java index 746a74d99ec4..7523382ec8ef 100644 --- a/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/DocumentationBuilder.java @@ -88,7 +88,7 @@ class DocumentationBuilder { if (property != null) { is_property = true; final AccessDirection dir = AccessDirection.of((PyElement)outer); - Maybe accessor = property.getByDirection(dir); + Maybe accessor = property.getByDirection(dir); myProlog .addItem("property ").addWith(TagBold, $().addWith(TagCode, $(element_name))) .addItem(" of ").add(PythonDocumentationProvider.describeClass(cls, TagCode, true, true)) @@ -97,10 +97,10 @@ class DocumentationBuilder { myBody.addItem(": ").addItem(property.getDoc()).addItem(BR); } else { - final PyFunction getter = property.getGetter().valueOrNull(); - if (getter != null && getter != myElement) { + final Callable getter = property.getGetter().valueOrNull(); + if (getter != null && getter != myElement && getter instanceof PyFunction) { // not in getter, getter's doc comment may be useful - PyStringLiteralExpression docstring = getter.getDocStringExpression(); + PyStringLiteralExpression docstring = ((PyFunction)getter).getDocStringExpression(); if (docstring != null) { myProlog .addItem(BR).addWith(TagItalic, $("Copied from getter:")).addItem(BR) diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java index cd49305e2ae1..6f36c9b516d5 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java @@ -90,7 +90,7 @@ public class PyPropertyAccessInspection extends PyInspection { } private void checkAccessor(PyExpression node, String name, AccessDirection dir, Property property) { - final Maybe accessor = property.getByDirection(dir); + final Maybe accessor = property.getByDirection(dir); if (accessor.isDefined() && accessor.value() == null) { final String message; if (dir == AccessDirection.WRITE) { diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java index 5e174b23caff..1733ba9c750c 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyDefinitionInspection.java @@ -119,8 +119,10 @@ public class PyPropertyDefinitionInspection extends PyInspection { else { // @property; we only check getter, others are checked by visitPyFunction // getter is always present with this form - final PyFunction function = property.getGetter().valueOrNull(); - checkGetter(function, getFunctionMarkingElement(function)); + final Callable callable = property.getGetter().valueOrNull(); + if (callable instanceof PyFunction) { + checkGetter(callable, getFunctionMarkingElement((PyFunction)callable)); + } } return false; // always want more } @@ -278,7 +280,7 @@ public class PyPropertyDefinitionInspection extends PyInspection { (element instanceof PyYieldExpression); } }); - hasReturns = returnStatements.length > 0; + hasReturns = returnStatements.length > 0; } else { PyReferenceExpression callSite = being_checked instanceof PyReferenceExpression ? (PyReferenceExpression) being_checked : null; diff --git a/python/src/com/jetbrains/python/psi/Property.java b/python/src/com/jetbrains/python/psi/Property.java index 5313ff37070f..aad101b0a575 100644 --- a/python/src/com/jetbrains/python/psi/Property.java +++ b/python/src/com/jetbrains/python/psi/Property.java @@ -18,19 +18,19 @@ public interface Property { * @return the setter: a method or null if defined, or something else callable if undefined. */ @NotNull - Maybe getSetter(); + Maybe getSetter(); /** * @return the getter: a method or null if defined, or something else callable if undefined. */ @NotNull - Maybe getGetter(); + Maybe getGetter(); /** * @return the deleter: a method or null if defined, or something else callable if undefined. */ @NotNull - Maybe getDeleter(); + Maybe getDeleter(); /** * @return doc string as known to property() call. If null, see getter's doc. @@ -39,7 +39,7 @@ public interface Property { String getDoc(); /** - * @return the target to which the result of property() call is assigned. For things defined via @property, it is null. + * @return the target to which the result of property() call is assigned. For things defined via @property, it is null. */ @Nullable PyTargetExpression getDefinitionSite(); @@ -49,6 +49,6 @@ public interface Property { * @return getter, setter, or deleter. */ @NotNull - Maybe getByDirection(@NotNull AccessDirection direction); + Maybe getByDirection(@NotNull AccessDirection direction); } diff --git a/python/src/com/jetbrains/python/psi/impl/PropertyBunch.java b/python/src/com/jetbrains/python/psi/impl/PropertyBunch.java index 34d50ca2f25c..ac3f339c11c2 100644 --- a/python/src/com/jetbrains/python/psi/impl/PropertyBunch.java +++ b/python/src/com/jetbrains/python/psi/impl/PropertyBunch.java @@ -49,8 +49,8 @@ public abstract class PropertyBunch { * @param ref a reference as an argument in property() call * @return value we want to store (resolved callable, name, etc) */ - protected abstract @Nullable MType translate(@NotNull PyReferenceExpression ref); - + @Nullable + protected abstract MType translate(@NotNull PyExpression ref); @Nullable public static PyCallExpression findPropertyCallSite(@Nullable PyExpression source) { @@ -140,10 +140,6 @@ public abstract class PropertyBunch { } private static Maybe translateIfSet(PropertyBunch target, PyExpression accessor) { - // TODO[yole] I don't quite understand this subtle distinction (why an accessor defined with lambda must be treated as defined=false) - if (accessor != null && !(accessor instanceof PyReferenceExpression)) { - return new Maybe(); - } - return new Maybe(accessor == null ? null : target.translate((PyReferenceExpression) accessor)); + return new Maybe(accessor == null ? null : target.translate(accessor)); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 543260805f80..6e22ce19aea1 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.ResolveState; -import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.*; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; @@ -42,6 +39,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.*; +import static com.jetbrains.python.psi.stubs.PyTargetExpressionStub.InitializerType.CallExpression; + /** * @author yole */ @@ -492,8 +491,8 @@ public class PyClassImpl extends PyPresentableElementImpl implement return proc.getResult(); } - private final static Maybe UNKNOWN_CALL = new Maybe(); // denotes _not_ a PyFunction, actually - private final static Maybe NONE = new Maybe(null); // denotes an explicit None + private final static Maybe UNKNOWN_CALL = new Maybe(); // denotes _not_ a PyFunction, actually + private final static Maybe NONE = new Maybe(null); // denotes an explicit None /** * @param name name of the property @@ -541,9 +540,9 @@ public class PyClassImpl extends PyPresentableElementImpl implement } } for (Map.Entry> entry: grouped.entrySet()) { - Maybe getter = NONE; - Maybe setter = NONE; - Maybe deleter = NONE; + Maybe getter = NONE; + Maybe setter = NONE; + Maybe deleter = NONE; String doc = null; final String decoratorName = entry.getKey(); for (PyFunction method : entry.getValue()) { @@ -553,13 +552,13 @@ public class PyClassImpl extends PyPresentableElementImpl implement final PyQualifiedName qname = deco.getQualifiedName(); if (qname != null) { if (qname.matches(PyNames.PROPERTY)) { - getter = new Maybe(method); + getter = new Maybe(method); } else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.SETTER)) { - setter = new Maybe(method); + setter = new Maybe(method); } else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.DELETER)) { - deleter = new Maybe(method); + deleter = new Maybe(method); } } } @@ -574,14 +573,14 @@ public class PyClassImpl extends PyPresentableElementImpl implement return null; } - private Maybe fromPacked(Maybe maybeName) { + private Maybe fromPacked(Maybe maybeName) { if (maybeName.isDefined()) { final String value = maybeName.value(); if (value == null || PyNames.NONE.equals(value)) { return NONE; } PyFunction method = findMethodByName(value, true); - if (method != null) return new Maybe(method); + if (method != null) return new Maybe(method); } return UNKNOWN_CALL; } @@ -595,15 +594,23 @@ public class PyClassImpl extends PyPresentableElementImpl implement final PyTargetExpressionStub targetStub = (PyTargetExpressionStub)substub; PropertyStubStorage prop = targetStub.getCustomStub(PropertyStubStorage.class); if (prop != null && (name == null || name.equals(targetStub.getName()))) { - Maybe getter = fromPacked(prop.getGetter()); - Maybe setter = fromPacked(prop.getSetter()); - Maybe deleter = fromPacked(prop.getDeleter()); + Maybe getter = fromPacked(prop.getGetter()); + Maybe setter = fromPacked(prop.getSetter()); + Maybe deleter = fromPacked(prop.getDeleter()); String doc = prop.getDoc(); if (getter != NONE || setter != NONE || deleter != NONE) { final PropertyImpl property = new PropertyImpl(targetStub.getName(), getter, setter, deleter, doc, targetStub.getPsi()); if (propertyProcessor == null || propertyProcessor.process(property)) return property; } } + final PyQualifiedName initializer = targetStub.getInitializer(); + if (targetStub.getInitializerType() == CallExpression && initializer != null && PyNames.PROPERTY.equals(initializer.toString())) { + final PropertyImpl property = new PropertyImpl(targetStub.getName(), UNKNOWN_CALL, UNKNOWN_CALL, UNKNOWN_CALL, + null, targetStub.getPsi()); + if (propertyProcessor == null || propertyProcessor.process(property)) { + return property; + } + } } } } @@ -702,10 +709,10 @@ public class PyClassImpl extends PyPresentableElementImpl implement return null; } - private static class PropertyImpl extends PropertyBunch implements Property { + private static class PropertyImpl extends PropertyBunch implements Property { private final String myName; - private PropertyImpl(String name, Maybe getter, Maybe setter, Maybe deleter, String doc, PyTargetExpression site) { + private PropertyImpl(String name, Maybe getter, Maybe setter, Maybe deleter, String doc, PyTargetExpression site) { myName = name; myDeleter = deleter; myGetter = getter; @@ -724,7 +731,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement @NotNull @Override - public Maybe getByDirection(@NotNull AccessDirection direction) { + public Maybe getByDirection(@NotNull AccessDirection direction) { switch (direction) { case READ: return myGetter; case WRITE: return mySetter; @@ -733,12 +740,19 @@ public class PyClassImpl extends PyPresentableElementImpl implement throw new IllegalArgumentException("Unknown direction " + PyUtil.nvl(direction)); } + @Nullable @Override - protected PyFunction translate(@NotNull PyReferenceExpression ref) { - if (PyNames.NONE.equals(ref.getName())) return null; // short-circuit a common case - PsiElement something = ref.getReference().resolve(); - if (something instanceof PyFunction) { - return (PyFunction)something; + protected Callable translate(@NotNull PyExpression expr) { + if (PyNames.NONE.equals(expr.getName())) return null; // short-circuit a common case + if (expr instanceof Callable) { + return (Callable)expr; + } + final PsiReference ref = expr.getReference(); + if (ref != null) { + PsiElement something = ref.resolve(); + if (something instanceof Callable) { + return (Callable)something; + } } return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyDecoratorListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDecoratorListImpl.java index 83ea5bd549d9..c923ee3b0e2f 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyDecoratorListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyDecoratorListImpl.java @@ -2,11 +2,10 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.jetbrains.python.PyElementTypes; -import com.jetbrains.python.psi.PyDecoratorList; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.stubs.PyDecoratorListStub; import com.jetbrains.python.psi.PyDecorator; +import com.jetbrains.python.psi.PyDecoratorList; import com.jetbrains.python.psi.PyElementVisitor; +import com.jetbrains.python.psi.stubs.PyDecoratorListStub; import org.jetbrains.annotations.NotNull; /** @@ -38,8 +37,8 @@ public class PyDecoratorListImpl extends PyBaseElementImpl public PyDecorator findDecorator(String name) { final PyDecorator[] decorators = getDecorators(); for (PyDecorator decorator : decorators) { - final PyExpression callee = decorator.getCallee(); - if (callee != null && name.equals(callee.getText())) { + final PyQualifiedName qName = decorator.getQualifiedName(); + if (qName != null && name.equals(qName.toString())) { return decorator; } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 371fcec7dc1c..743c61a0be8d 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -19,7 +19,9 @@ import com.jetbrains.python.console.PydevConsoleRunner; import com.jetbrains.python.console.completion.PydevConsoleReference; import com.jetbrains.python.console.pydev.ConsoleCommunication; import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.references.*; +import com.jetbrains.python.psi.impl.references.PyImportReference; +import com.jetbrains.python.psi.impl.references.PyQualifiedReference; +import com.jetbrains.python.psi.impl.references.PyReferenceImpl; import com.jetbrains.python.psi.resolve.*; import com.jetbrains.python.psi.types.*; import com.jetbrains.python.refactoring.PyDefUseUtil; @@ -218,24 +220,39 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere @Nullable public Ref getTypeOfProperty(@NotNull TypeEvalContext context) { - PyExpression qualifier = getQualifier(); + final PyExpression qualifier = getQualifier(); final String name = getName(); if (name != null && qualifier != null) { - PyType qualifierType = context.getType(qualifier); - if (qualifierType instanceof PyClassType) { - final PyClassType classType = (PyClassType)qualifierType; - PyClass pyClass = classType.getPyClass(); - if (pyClass != null) { - Property property = pyClass.findProperty(name); - if (property != null) { - if (classType.isDefinition()) { - return Ref.create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY)); - } - final Maybe accessor = property.getByDirection(AccessDirection.of(this)); - final PyFunction function = accessor.valueOrNull(); - final PyType type = (function != null) ? function.getReturnType(context, this) : null; - return Ref.create(type); + final PyType qualifierType = context.getType(qualifier); + return getTypeOfProperty(qualifierType, name, context); + } + return null; + } + + @Nullable + private Ref getTypeOfProperty(@Nullable PyType qualifierType, @NotNull String name, @NotNull TypeEvalContext context) { + if (qualifierType instanceof PyClassType) { + final PyClassType classType = (PyClassType)qualifierType; + PyClass pyClass = classType.getPyClass(); + if (pyClass != null) { + Property property = pyClass.findProperty(name); + if (property != null) { + if (classType.isDefinition()) { + return Ref.create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY)); } + final Maybe accessor = property.getByDirection(AccessDirection.of(this)); + final Callable callable = accessor.valueOrNull(); + final PyType type = (callable != null) ? callable.getReturnType(context, this) : null; + return Ref.create(type); + } + } + } + else if (qualifierType instanceof PyUnionType) { + final PyUnionType unionType = (PyUnionType)qualifierType; + for (PyType type : unionType.getMembers()) { + final Ref result = getTypeOfProperty(type, name, context); + if (result != null) { + return result; } } } diff --git a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java index 5fa0c29893c9..fd8649d0861b 100644 --- a/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java +++ b/python/src/com/jetbrains/python/psi/resolve/ResolveImportUtil.java @@ -549,6 +549,10 @@ public class ResolveImportUtil { components.set(0, "collections"); return PyQualifiedName.fromComponents(components); } + else if (head.equals("posix") || head.equals("nt")) { + components.set(0, "os"); + return PyQualifiedName.fromComponents(components); + } else if (head.equals("_functools")) { components.set(0, "functools"); return PyQualifiedName.fromComponents(components); @@ -565,7 +569,7 @@ public class ResolveImportUtil { components.set(0, "datetime"); return PyQualifiedName.fromComponents(components); } - else if (head.equals("ntpath") | head.equals("posixpath")) { + else if (head.equals("ntpath") || head.equals("posixpath") || head.equals("path")) { final List result = new ArrayList(); result.add("os"); components.set(0, "path"); diff --git a/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java b/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java index 69a17b166e73..1030bd1bdd20 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java +++ b/python/src/com/jetbrains/python/psi/stubs/PropertyStubStorage.java @@ -4,7 +4,6 @@ import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import com.intellij.util.io.StringRef; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyReferenceExpression; import com.jetbrains.python.psi.impl.PropertyBunch; import com.jetbrains.python.psi.impl.PyQualifiedName; import com.jetbrains.python.psi.impl.stubs.CustomTargetExpressionStub; @@ -23,11 +22,10 @@ import java.io.IOException; */ public class PropertyStubStorage extends PropertyBunch implements CustomTargetExpressionStub { + @Nullable @Override - protected String translate(@NotNull PyReferenceExpression ref) { - final String name = ref.getName(); - assert name != null; - return name; + protected String translate(@NotNull PyExpression ref) { + return ref.getName(); } private static final String IMPOSSIBLE_NAME = "#"; diff --git a/python/src/com/jetbrains/python/psi/types/PyClassType.java b/python/src/com/jetbrains/python/psi/types/PyClassType.java index c562c50421e4..e73bac12ed7b 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassType.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassType.java @@ -122,7 +122,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType { if (resolveContext.allowProperties()) { Property property = myClass.findProperty(name); if (property != null) { - Maybe accessor = property.getByDirection(direction); + Maybe accessor = property.getByDirection(direction); if (accessor.isDefined()) { Callable accessor_code = accessor.value(); ResolveResultList ret = new ResolveResultList(); diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index 6fb1e30fcc5c..e5062b6fb3cb 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -124,6 +124,12 @@ public class PyTypeChecker { return true; } } + if (actual instanceof PyFunctionType && expected instanceof PyClassType) { + final PyClass superClass = ((PyClassType)expected).getPyClass(); + if (superClass != null && PyNames.CALLABLE.equals(superClass.getName())) { + return true; + } + } final String superName = expected.getName(); final String subName = actual.getName(); // TODO: No inheritance check for builtin numerics at this moment @@ -376,7 +382,10 @@ public class PyTypeChecker { if (callSite == null) { return null; } - final PsiElement parent = callSite.getParent(); + PsiElement parent = callSite.getParent(); + while (parent instanceof PyParenthesizedExpression) { + parent = ((PyParenthesizedExpression)parent).getContainedExpression(); + } if (parent instanceof PyCallExpression) { return analyzeCall((PyCallExpression)parent, context); } diff --git a/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java b/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java index eefceb611661..72e8cf569d41 100644 --- a/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java @@ -6,6 +6,7 @@ import com.intellij.psi.PsiElement; import com.intellij.util.Processor; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; +import com.jetbrains.python.psi.Callable; import com.jetbrains.python.psi.Property; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; @@ -101,10 +102,10 @@ public class RenamePyFunctionProcessor extends RenamePyElementProcessor { } } - private static void addRename(Map renames, String newName, Maybe accessor) { - final PyFunction function = accessor.valueOrNull(); - if (function != null) { - renames.put(function, newName); + private static void addRename(Map renames, String newName, Maybe accessor) { + final Callable callable = accessor.valueOrNull(); + if (callable instanceof PyFunction) { + renames.put(callable, newName); } } } diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java index 332c586e594b..90de66323c72 100644 --- a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java @@ -16,7 +16,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV1() throws Exception { Property p; - Maybe accessor; + Maybe accessor; p = myClass.findProperty("v1"); assertNotNull(p); assertNull(p.getDoc()); @@ -40,7 +40,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV2() throws Exception { Property p; - Maybe accessor; + Maybe accessor; p = myClass.findProperty("v2"); assertNotNull(p); assertEquals("doc of v2", p.getDoc()); @@ -65,7 +65,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV3() throws Exception { Property p; - Maybe accessor; + Maybe accessor; p = myClass.findProperty("v3"); assertNotNull(p); assertNull(p.getDoc()); @@ -73,7 +73,7 @@ public class PyClassicPropertyTest extends PyTestCase { assertEquals("v3", site.getText()); accessor = p.getGetter(); - assertFalse(accessor.isDefined()); + assertTrue(accessor.isDefined()); accessor = p.getSetter(); assertTrue(accessor.isDefined()); @@ -88,7 +88,7 @@ public class PyClassicPropertyTest extends PyTestCase { /* NOTE: we don't support this yet public void testV4() throws Exception { Property p; - Maybe accessor; + Maybe accessor; p = myClass.findProperty("v4"); assertNotNull(p); assertEquals("otherworldly", p.getDoc()); diff --git a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java index f84887e367df..67414bcfbf5e 100644 --- a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java @@ -18,7 +18,7 @@ public class PyDecoratedPropertyTest extends PyTestCase { public void testW1() throws Exception { Property p; - Maybe accessor; + Maybe accessor; final String name = "w1"; p = myClass.findProperty(name); assertNotNull(p); @@ -43,7 +43,7 @@ public class PyDecoratedPropertyTest extends PyTestCase { public void testW2() throws Exception { Property p; - Maybe accessor; + Maybe accessor; final String name = "w2"; p = myClass.findProperty(name); assertNotNull(p); @@ -52,9 +52,11 @@ public class PyDecoratedPropertyTest extends PyTestCase { accessor = p.getGetter(); assertTrue(accessor.isDefined()); - assertNotNull(accessor.value()); - assertEquals("w2", accessor.value().getName()); - assertEquals("doc of "+name, accessor.value().getDocStringExpression().getStringValue()); + final Callable callable = accessor.value(); + assertNotNull(callable); + assertEquals("w2", callable.getName()); + assertInstanceOf(callable, PyFunction.class); + assertEquals("doc of " + name, ((PyFunction)callable).getDocStringExpression().getStringValue()); accessor = p.getSetter(); assertTrue(accessor.isDefined()); diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 62647916c668..3262bb3b1a47 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -104,12 +104,12 @@ public class PyStubsTest extends PyTestCase { assertEquals("BarClass", pyClass.getName()); Property prop = pyClass.findProperty("value"); - Maybe maybe_function = prop.getGetter(); + Maybe maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); assertEquals(pyClass.getMethods()[0], maybe_function.value()); Property setvalueProp = pyClass.findProperty("setvalue"); - Maybe setter = setvalueProp.getSetter(); + Maybe setter = setvalueProp.getSetter(); assertTrue(setter.isDefined()); assertEquals("__set", setter.value().getName()); diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index 24b6b9bcefe2..60b9f66241d9 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -371,6 +371,20 @@ public class PyTypeTest extends PyTestCase { "expr = h()\n"); } + public void testPropertyOfUnionType() { + PyExpression expr = parseExpr("def f():\n" + + " '''\n" + + " :rtype: int or slice\n" + + " '''\n" + + " raise NotImplementedError\n" + + "\n" + + "x = f()\n" + + "expr = x.start\n"); + TypeEvalContext context = TypeEvalContext.slow().withTracing(); + PyType actual = expr.getType(context); + assertNull(actual); + } + private PyExpression parseExpr(String text) { myFixture.configureByText(PythonFileType.INSTANCE, text); return myFixture.findElementByText("expr", PyExpression.class);