mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'python-skeletons'
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
Python Skeletons
|
||||
================
|
||||
|
||||
_This proposal is a draft._
|
||||
|
||||
Python skeletons are Python files that contain API definitions of existing
|
||||
libraries extended for static analysis tools.
|
||||
|
||||
Rationale
|
||||
---------
|
||||
|
||||
Python is a dynamic language less suitable for static code analysis than static
|
||||
languages like C or Java. Although Python static analysis tools can extract
|
||||
some information from Python source code without executing it, this information
|
||||
is often very shallow and incomplete.
|
||||
|
||||
Dynamic features of Python are very useful for user code. But using these
|
||||
features in APIs of third-party libraries and the standard library is not
|
||||
always a good idea. Tools (and users, in fact) need clear definitions of APIs.
|
||||
Often library API definitions are quite static and easy to grasp (defined
|
||||
using `class`, `def`), but types of function parameters and return values
|
||||
usually are not specified. Sometimes API definitions involve metaprogramming.
|
||||
|
||||
As there is not enough information in API definition code of libraries,
|
||||
developers of static analysis tools collect extended API data themselves and
|
||||
store it in their own formats. For example, PyLint uses imperative AST
|
||||
transformations of API modules in order to extend them with hard-coded data.
|
||||
PyCharm extends APIs via its proprietary database of declarative type
|
||||
annotations. The absence of a common extended API information format makes it
|
||||
hard for developers and users of tools to collect and share data.
|
||||
|
||||
|
||||
Proposal
|
||||
--------
|
||||
|
||||
The proposal is to create a common database of extended API definitions as a
|
||||
collection of Python files called skeletons. Static analysis tools already
|
||||
understand Python code, so it should be easy to start extracting API
|
||||
definitions from these Python skeleton files. Regular function and class
|
||||
definitions can be extended with additional docstrings and decorators, e.g. for
|
||||
providing types of function parameters and return values. Static analysis tools
|
||||
may use a subset of information contained in skeleton files needed for their
|
||||
operation. Using Python files instead of a custom API definition format will
|
||||
also make it easier for users to populate the skeletons database.
|
||||
|
||||
Declarative Python API definitions for static analysis tools cannot cover all
|
||||
dynamic tricks used in real APIs of libraries: some of them still require
|
||||
library-specific code analysis. Nevertheless the skeletons database is enough
|
||||
for many libraries.
|
||||
|
||||
The proposed [python-skeletons](https://github.com/JetBrains/python-skeletons)
|
||||
repository is hosted on GitHub.
|
||||
|
||||
|
||||
Conventions
|
||||
-----------
|
||||
|
||||
Skeletons should respect PEP-8 and PEP-257 style guides.
|
||||
|
||||
The most simple way of specifying types in skeletons is Sphinx docstrings.
|
||||
Function annotations could be used for specifying types, but they are
|
||||
available only for Python 3.
|
||||
|
||||
There is no standard notation for specifying types in Python code. We propose
|
||||
the following notation:
|
||||
|
||||
Foo # Class Foo visible in the current scope
|
||||
x.y.Bar # Class Bar from x.y module
|
||||
Foo | Bar # Foo or Bar
|
||||
(Foo, Bar) # Tuple of Foo and Bar
|
||||
list[Foo] # List of Foo elements
|
||||
dict[Foo, Bar] # Dict from Foo to Bar
|
||||
T # Generic type (T-Z are reserved for generics)
|
||||
T <= Foo # Generic type with upper bound Foo
|
||||
Foo[T] # Foo parameterized with T
|
||||
(Foo, Bar) -> Baz # Function of Foo and Bar that returns Baz
|
||||
|
||||
The formal syntax is defined in `pytypes` library (work in progress).
|
||||
|
||||
There are several shortcuts available:
|
||||
|
||||
unknown # Unknown type
|
||||
None # type(None)
|
||||
string # Py2: str | unicode, Py3: str
|
||||
bytestring # Py2: str | unicode, Py3: bytes
|
||||
bytes # Py2: str, Py3: bytes
|
||||
unicode # Py2: unicode, Py3: str
|
||||
|
||||
The syntax is a subject to change. It is almost compatible to Python (except
|
||||
function types), but its semantics differs from Python (no `|`, no implicitly
|
||||
visible names, no generic types). So you cannot use these expressions in
|
||||
Python 3 function annotations. See also `python-righarrow`, `typeannotations`.
|
||||
|
||||
The recommended way of checking the version of Python is:
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7) and sys.version_info < (3,):
|
||||
def from_27_until_30():
|
||||
pass
|
||||
|
||||
|
||||
PyCharm
|
||||
-------
|
||||
|
||||
PyCharm 3 can extract the following information from the skeletons:
|
||||
|
||||
* Parameters of functions and methods
|
||||
* Return types and parameter types of functions and methods
|
||||
* Types of assignment targets
|
||||
* Extra module members
|
||||
* TODO
|
||||
|
||||
PyCharm 3 comes with a snapshot of the Python skeletons repository. You
|
||||
should not modify it, because it will be updated with the PyCharm
|
||||
installation. If you want to change the skeletons, clone the skeletons GitHub
|
||||
repository into your PyCharm config directory:
|
||||
|
||||
cd <PyCharm config>
|
||||
git clone https://github.com/JetBrains/python-skeletons.git
|
||||
|
||||
where `<PyCharm config>` is:
|
||||
|
||||
* Mac OS X: `~/Library/Preferences/PyCharmXX/config`
|
||||
* Linux: `~/.PyCharmXX/config`
|
||||
* Windows: `<User home>\.PyCharmXX\config`
|
||||
|
||||
Please send your PyCharm-related bug reports and feature requests to
|
||||
[PyCharm issue tracker](http://youtrack.jetbrains.com/issues/PY).
|
||||
|
||||
|
||||
Feedback
|
||||
--------
|
||||
|
||||
If you want to contribute, send your pull requests to the Python skeletons
|
||||
repository on GitHub. Please make sure, that you follow the conventions above.
|
||||
|
||||
Use [code-quality](http://mail.python.org/mailman/listinfo/code-quality)
|
||||
mailing list to discuss Python skeletons.
|
||||
@@ -0,0 +1,377 @@
|
||||
"""Skeletons for built-in symbols."""
|
||||
|
||||
import sys as __sys
|
||||
|
||||
|
||||
def abs(number):
|
||||
"""Return the absolute value of the argument.
|
||||
|
||||
:type number: T
|
||||
:rtype: T | unknown
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def all(iterable):
|
||||
"""Return True if bool(x) is True for all values x in the iterable.
|
||||
|
||||
:type iterable: collections.Iterable
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def any(iterable):
|
||||
"""Return True if bool(x) is True for any x in the iterable.
|
||||
|
||||
:type iterable: collections.Iterable
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def bin(number):
|
||||
"""Return the binary representation of an integer or long integer.
|
||||
|
||||
:type number: numbers.Number
|
||||
:rtype: bytes
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def callable(object):
|
||||
"""Return whether the object is callable (i.e., some kind of function).
|
||||
Note that classes are callable, as are instances with a __call__() method.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def chr(i):
|
||||
"""Return a string of one character with ordinal i; 0 <= i < 256.
|
||||
|
||||
:type i: int
|
||||
:rtype: string
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def cmp(x, y):
|
||||
"""Return negative if x<y, zero if x==y, positive if x>y.
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def dir(object=None):
|
||||
"""If called without an argument, return the names in the current scope.
|
||||
Else, return an alphabetized list of names comprising (some of) the attributes
|
||||
of the given object, and of attributes reachable from it.
|
||||
|
||||
:rtype: list[string]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def divmod(x, y):
|
||||
"""Return the tuple ((x-x%y)/y, x%y).
|
||||
|
||||
:type x: numbers.Number
|
||||
:type y: numbers.Number
|
||||
:rtype: (int | long | float | unknown, int | long | float | unknown)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def filter(function_or_none, sequence):
|
||||
"""Return those items of sequence for which function(item) is true. If
|
||||
function is None, return the items that are true. If sequence is a tuple
|
||||
or string, return the same type, else return a list.
|
||||
|
||||
:type function_or_none: collections.Callable | None
|
||||
:type sequence: T <= list | collections.Iterable | bytes | unicode
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def getattr(object, name, default=None):
|
||||
"""Get a named attribute from an object; getattr(x, 'y') is equivalent to
|
||||
x.y. When a default argument is given, it is returned when the attribute
|
||||
doesn't exist; without it, an exception is raised in that case.
|
||||
|
||||
:type name: string
|
||||
:rtype: object | unknown
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def globals():
|
||||
"""Return the dictionary containing the current scope's global variables.
|
||||
|
||||
:rtype: dict[string, unknown]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def hasattr(object, name):
|
||||
"""Return whether the object has an attribute with the given name.
|
||||
|
||||
:type name: string
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def hash(object):
|
||||
"""Return a hash value for the object.
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def hex(number):
|
||||
"""Return the hexadecimal representation of an integer or long integer.
|
||||
|
||||
:type number: numbers.Integral
|
||||
:rtype: string
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def id(object):
|
||||
"""Return the identity of an object.
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def isinstance(object, class_or_type_or_tuple):
|
||||
"""Return whether an object is an instance of a class or of a subclass
|
||||
thereof.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def issubclass(C, B):
|
||||
"""Return whether class C is a subclass (i.e., a derived class) of class B.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def iter(source, sentinel=None):
|
||||
"""Get an iterator from an object. In the first form, the argument must
|
||||
supply its own iterator, or be a sequence. In the second form, the callable
|
||||
is called until it returns the sentinel.
|
||||
|
||||
:type source: collections.Iterable[T]
|
||||
:rtype: collections.Iterator[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def len(object):
|
||||
"""Return the number of items of a sequence or mapping.
|
||||
|
||||
:type object: collections.Sized
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def locals():
|
||||
"""Update and return a dictionary containing the current scope's local
|
||||
variables.
|
||||
|
||||
:rtype: dict[string, unknown]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def map(function, sequence, *sequence_1):
|
||||
"""Return a list of the results of applying the function to the items of
|
||||
the argument sequence(s).
|
||||
|
||||
:type function: ((T) -> V) | None
|
||||
:type sequence: collections.Iterable[T]
|
||||
:rtype: list[V] | bytes | unicode
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def next(iterator, default=None):
|
||||
"""Return the next item from the iterator.
|
||||
|
||||
:type iterator: collections.Iterator[T]
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def oct(number):
|
||||
"""Return the octal representation of an integer or long integer.
|
||||
|
||||
:type number: numbers.Integral
|
||||
:rtype: string
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def open(name, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=None, opener=None):
|
||||
"""Open a file, returns a file object.
|
||||
|
||||
:type name: string
|
||||
:type mode: string
|
||||
:type buffering: int
|
||||
:type encoding: string | None
|
||||
:type errors: string | None
|
||||
:rtype: file
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def ord(c):
|
||||
"""Return the integer ordinal of a one-character string.
|
||||
|
||||
:type c: string
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def pow(x, y, z=None):
|
||||
"""With two arguments, equivalent to x**y. With three arguments,
|
||||
equivalent to (x**y) % z, but may be more efficient (e.g. for longs).
|
||||
|
||||
:type x: numbers.Number
|
||||
:type y: numbers.Number
|
||||
:type z: numbers.Number | None
|
||||
:rtype: int | long | float | complex
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if __sys.version_info < (3,):
|
||||
def range(start, stop=None, step=None):
|
||||
"""Return a list containing an arithmetic progression of integers.
|
||||
|
||||
:type start: numbers.Integral
|
||||
:type stop: numbers.Integral | None
|
||||
:type step: numbers.Integral | None
|
||||
:rtype: list[int]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def reduce(function, sequence, initial=None):
|
||||
"""Apply a function of two arguments cumulatively to the items of a sequence,
|
||||
from left to right, so as to reduce the sequence to a single value.
|
||||
|
||||
:type function: collections.Callable
|
||||
:type sequence: collections.Iterable
|
||||
:type initial: T
|
||||
:rtype: T | unknown
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def repr(object):
|
||||
"""
|
||||
Return the canonical string representation of the object.
|
||||
|
||||
:rtype: string
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def round(number, ndigits=None):
|
||||
"""Round a number to a given precision in decimal digits (default 0 digits).
|
||||
|
||||
:type number: numbers.Real
|
||||
:type ndigits: numbers.Real | None
|
||||
:rtype: float
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class slice(object):
|
||||
def __init__(self, start, stop=None, step=None):
|
||||
"""Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).
|
||||
|
||||
:type start: numbers.Integral
|
||||
:type stop: numbers.Integral | None
|
||||
:type step: numbers.Integral | None
|
||||
"""
|
||||
return
|
||||
|
||||
|
||||
def vars(object=None):
|
||||
"""Without arguments, equivalent to locals(). With an argument, equivalent
|
||||
to object.__dict__.
|
||||
|
||||
:rtype: dict[string, unknown]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class object:
|
||||
""" The most base type."""
|
||||
|
||||
@staticmethod
|
||||
def __new__(cls, *more):
|
||||
"""Create a new object.
|
||||
|
||||
:type cls: T
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class enumerate(object):
|
||||
"""enumerate object."""
|
||||
|
||||
def __init__(self, iterable, start=0):
|
||||
"""Create an enumerate object.
|
||||
|
||||
:type iterable: collections.Iterable[T]
|
||||
:type start: int | long
|
||||
:rtype: enumerate[int, T]
|
||||
"""
|
||||
pass
|
||||
|
||||
def next(self):
|
||||
"""Return the next value, or raise StopIteration.
|
||||
|
||||
:rtype: (int, T)
|
||||
"""
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
"""x.__iter__() <==> iter(x).
|
||||
|
||||
:rtype: enumerate[int, T]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if __sys.version_info < (3,):
|
||||
class xrange(object):
|
||||
"""xrange object."""
|
||||
|
||||
def __init__(self, start, stop=None, step=None):
|
||||
"""Create an xrange object.
|
||||
|
||||
:type start: numbers.Integral
|
||||
:type stop: numbers.Integral | None
|
||||
:type step: numbers.Integral | None
|
||||
:rtype: xrange[int]
|
||||
"""
|
||||
pass
|
||||
@@ -0,0 +1,177 @@
|
||||
"""Skeleton for 'nose.tools' module."""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def assert_equal(first, second, msg=None):
|
||||
"""Fail if the two objects are unequal as determined by the '==' operator.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def assert_not_equal(first, second, msg=None):
|
||||
"""Fail if the two objects are equal as determined by the '==' operator.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def assert_true(expr, msg=None):
|
||||
"""Check that the expression is true."""
|
||||
pass
|
||||
|
||||
|
||||
def assert_false(expr, msg=None):
|
||||
"""Check that the expression is false."""
|
||||
pass
|
||||
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
def assert_is(expr1, expr2, msg=None):
|
||||
"""Just like assert_true(a is b), but with a nicer default message."""
|
||||
pass
|
||||
|
||||
def assert_is_not(expr1, expr2, msg=None):
|
||||
"""Just like assert_true(a is not b), but with a nicer default message.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_is_none(obj, msg=None):
|
||||
"""Same as assert_true(obj is None), with a nicer default message.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_is_not_none(obj, msg=None):
|
||||
"""Included for symmetry with assert_is_none."""
|
||||
pass
|
||||
|
||||
def assert_in(member, container, msg=None):
|
||||
"""Just like assert_true(a in b), but with a nicer default message."""
|
||||
pass
|
||||
|
||||
def assert_not_in(member, container, msg=None):
|
||||
"""Just like assert_true(a not in b), but with a nicer default message.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_is_instance(obj, cls, msg=None):
|
||||
"""Same as assert_true(isinstance(obj, cls)), with a nicer default
|
||||
message.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_not_is_instance(obj, cls, msg=None):
|
||||
"""Included for symmetry with assert_is_instance."""
|
||||
pass
|
||||
|
||||
|
||||
def assert_raises(excClass, callableObj=None, *args, **kwargs):
|
||||
"""Fail unless an exception of class excClass is thrown by callableObj when
|
||||
invoked with arguments args and keyword arguments kwargs.
|
||||
|
||||
If called with callableObj omitted or None, will return a
|
||||
context object used like this::
|
||||
|
||||
with assert_raises(SomeException):
|
||||
do_something()
|
||||
|
||||
:rtype: unittest.case._AssertRaisesContext | None
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
def assert_raises_regexp(expected_exception, expected_regexp,
|
||||
callable_obj=None, *args, **kwargs):
|
||||
"""Asserts that the message in a raised exception matches a regexp.
|
||||
|
||||
:rtype: unittest.case._AssertRaisesContext | None
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def assert_almost_equal(first, second, places=None, msg=None, delta=None):
|
||||
"""Fail if the two objects are unequal as determined by their difference
|
||||
rounded to the given number of decimal places (default 7) and comparing to
|
||||
zero, or by comparing that the between the two objects is more than the
|
||||
given delta.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def assert_not_almost_equal(first, second, places=None, msg=None, delta=None):
|
||||
"""Fail if the two objects are equal as determined by their difference
|
||||
rounded to the given number of decimal places (default 7) and comparing to
|
||||
zero, or by comparing that the between the two objects is less than the
|
||||
given delta.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
def assert_greater(a, b, msg=None):
|
||||
"""Just like assert_true(a > b), but with a nicer default message."""
|
||||
pass
|
||||
|
||||
def assert_greater_equal(a, b, msg=None):
|
||||
"""Just like assert_true(a >= b), but with a nicer default message."""
|
||||
pass
|
||||
|
||||
def assert_less(a, b, msg=None):
|
||||
"""Just like assert_true(a < b), but with a nicer default message."""
|
||||
pass
|
||||
|
||||
def assert_less_equal(a, b, msg=None):
|
||||
"""Just like self.assertTrue(a <= b), but with a nicer default
|
||||
message.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_regexp_matches(text, expected_regexp, msg=None):
|
||||
"""Fail the test unless the text matches the regular expression."""
|
||||
pass
|
||||
|
||||
def assert_not_regexp_matches(text, unexpected_regexp, msg=None):
|
||||
"""Fail the test if the text matches the regular expression."""
|
||||
pass
|
||||
|
||||
def assert_items_equal(expected_seq, actual_seq, msg=None):
|
||||
"""An unordered sequence specific comparison. It asserts that
|
||||
actual_seq and expected_seq have the same element counts.
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_dict_contains_subset(expected, actual, msg=None):
|
||||
"""Checks whether actual is a superset of expected."""
|
||||
pass
|
||||
|
||||
def assert_multi_line_equal(first, second, msg=None):
|
||||
"""Assert that two multi-line strings are equal."""
|
||||
pass
|
||||
|
||||
def assert_sequence_equal(seq1, seq2, msg=None, seq_type=None):
|
||||
"""An equality assertion for ordered sequences (like lists and tuples).
|
||||
"""
|
||||
pass
|
||||
|
||||
def assert_list_equal(list1, list2, msg=None):
|
||||
"""A list-specific equality assertion."""
|
||||
pass
|
||||
|
||||
def assert_tuple_equal(tuple1, tuple2, msg=None):
|
||||
"""A tuple-specific equality assertion."""
|
||||
pass
|
||||
|
||||
def assert_set_equal(set1, set2, msg=None):
|
||||
"""A set-specific equality assertion."""
|
||||
pass
|
||||
|
||||
def assert_dict_equal(d1, d2, msg=None):
|
||||
"""A dict-specific equality assertion."""
|
||||
pass
|
||||
|
||||
|
||||
assert_equals = assert_equal
|
||||
assert_not_equals = assert_not_equal
|
||||
assert_almost_equals = assert_almost_equal
|
||||
assert_not_almost_equals = assert_not_almost_equal
|
||||
@@ -0,0 +1,277 @@
|
||||
"""Skeleton for 're' stdlib module."""
|
||||
|
||||
|
||||
def compile(pattern, flags=0):
|
||||
"""Compile a regular expression pattern, returning a pattern object.
|
||||
|
||||
:type pattern: bytes | unicode
|
||||
:type flags: int
|
||||
:rtype: __Regex
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def search(pattern, string, flags=0):
|
||||
"""Scan through string looking for a match, and return a corresponding
|
||||
match instance. Return None if no position in the string matches.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type string: T <= bytes | unicode
|
||||
:type flags: int
|
||||
:rtype: __Match[T] | None
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def match(pattern, string, flags=0):
|
||||
"""Matches zero or more characters at the beginning of the string.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type string: T <= bytes | unicode
|
||||
:type flags: int
|
||||
:rtype: __Match[T] | None
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def split(pattern, string, maxsplit=0, flags=0):
|
||||
"""Split string by the occurrences of pattern.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type string: T <= bytes | unicode
|
||||
:type maxsplit: int
|
||||
:type flags: int
|
||||
:rtype: list[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def findall(pattern, string, flags=0):
|
||||
"""Return a list of all non-overlapping matches of pattern in string.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type string: T <= bytes | unicode
|
||||
:type flags: int
|
||||
:rtype: list[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def finditer(pattern, string, flags=0):
|
||||
"""Return an iterator over all non-overlapping matches for the pattern in
|
||||
string. For each match, the iterator returns a match object.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type string: T <= bytes | unicode
|
||||
:type flags: int
|
||||
:rtype: collections.Iterable[__Match[T]]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def sub(pattern, repl, string, count=0, flags=0):
|
||||
"""Return the string obtained by replacing the leftmost non-overlapping
|
||||
occurrences of pattern in string by the replacement repl.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type repl: bytes | unicode | collections.Callable
|
||||
:type string: T <= bytes | unicode
|
||||
:type count: int
|
||||
:type flags: int
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def subn(pattern, repl, string, count=0, flags=0):
|
||||
"""Return the tuple (new_string, number_of_subs_made) found by replacing
|
||||
the leftmost non-overlapping occurrences of pattern with the
|
||||
replacement repl.
|
||||
|
||||
:type pattern: bytes | unicode | __Regex
|
||||
:type repl: bytes | unicode | collections.Callable
|
||||
:type string: T <= bytes | unicode
|
||||
:type count: int
|
||||
:type flags: int
|
||||
:rtype: (T, int)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def escape(string):
|
||||
"""Escape all the characters in pattern except ASCII letters and numbers.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type: T
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class __Regex(object):
|
||||
"""Mock class for a regular expression pattern object."""
|
||||
|
||||
def __init__(self, flags, groups, groupindex, pattern):
|
||||
"""Create a new pattern object.
|
||||
|
||||
:type flags: int
|
||||
:type groups: int
|
||||
:type groupindex: dict[bytes | unicode, int]
|
||||
:type pattern: bytes | unicode
|
||||
"""
|
||||
self.flags = flags
|
||||
self.groups = groups
|
||||
self.groupindex = groupindex
|
||||
self.pattern = pattern
|
||||
|
||||
def search(self, string, pos=0, endpos=-1):
|
||||
"""Scan through string looking for a match, and return a corresponding
|
||||
match instance. Return None if no position in the string matches.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type pos: int
|
||||
:type endpos: int
|
||||
:rtype: __Match[T] | None
|
||||
"""
|
||||
pass
|
||||
|
||||
def match(self, string, pos=0, endpos=-1):
|
||||
"""Matches zero | more characters at the beginning of the string.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type pos: int
|
||||
:type endpos: int
|
||||
:rtype: __Match[T] | None
|
||||
"""
|
||||
pass
|
||||
|
||||
def split(self, string, maxsplit=0):
|
||||
"""Split string by the occurrences of pattern.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type maxsplit: int
|
||||
:rtype: list[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
def findall(self, string, pos=0, endpos=-1):
|
||||
"""Return a list of all non-overlapping matches of pattern in string.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type pos: int
|
||||
:type endpos: int
|
||||
:rtype: list[T]
|
||||
"""
|
||||
pass
|
||||
|
||||
def finditer(self, string, pos=0, endpos=-1):
|
||||
"""Return an iterator over all non-overlapping matches for the
|
||||
pattern in string. For each match, the iterator returns a
|
||||
match object.
|
||||
|
||||
:type string: T <= bytes | unicode
|
||||
:type pos: int
|
||||
:type endpos: int
|
||||
:rtype: collections.Iterable[__Match[T]]
|
||||
"""
|
||||
pass
|
||||
|
||||
def sub(self, repl, string, count=0):
|
||||
"""Return the string obtained by replacing the leftmost non-overlapping
|
||||
occurrences of pattern in string by the replacement repl.
|
||||
|
||||
:type repl: bytes | unicode | collections.Callable
|
||||
:type string: T <= bytes | unicode
|
||||
:type count: int
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
def subn(self, repl, string, count=0):
|
||||
"""Return the tuple (new_string, number_of_subs_made) found by replacing
|
||||
the leftmost non-overlapping occurrences of pattern with the
|
||||
replacement repl.
|
||||
|
||||
:type repl: bytes | unicode | collections.Callable
|
||||
:type string: T <= bytes | unicode
|
||||
:type count: int
|
||||
:rtype: (T, int)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class __Match(object):
|
||||
"""Mock class for a match object."""
|
||||
|
||||
def __init__(self, pos, endpos, lastindex, lastgroup, re, string):
|
||||
"""Create a new match object.
|
||||
|
||||
:type pos: int
|
||||
:type endpos: int
|
||||
:type lastindex: int | None
|
||||
:type lastgroup: int | bytes | unicode | None
|
||||
:type re: __Regex
|
||||
:type string: bytes | unicode
|
||||
:rtype: __Match[T]
|
||||
"""
|
||||
self.pos = pos
|
||||
self.endpos = endpos
|
||||
self.lastindex = lastindex
|
||||
self.lastgroup = lastgroup
|
||||
self.re = re
|
||||
self.string = string
|
||||
|
||||
def expand(self, template):
|
||||
"""Return the string obtained by doing backslash substitution on the
|
||||
template string template.
|
||||
|
||||
:type template: T
|
||||
:rtype: T
|
||||
"""
|
||||
pass
|
||||
|
||||
def group(self, *args):
|
||||
"""Return one or more subgroups of the match.
|
||||
|
||||
:rtype: T | tuple
|
||||
"""
|
||||
pass
|
||||
|
||||
def groups(self, default=None):
|
||||
"""Return a tuple containing all the subgroups of the match, from 1 up
|
||||
to however many groups are in the pattern.
|
||||
|
||||
:rtype: tuple
|
||||
"""
|
||||
pass
|
||||
|
||||
def groupdict(self, default=None):
|
||||
"""Return a dictionary containing all the named subgroups of the match,
|
||||
keyed by the subgroup name.
|
||||
|
||||
:rtype: dict[bytes | unicode, T]
|
||||
"""
|
||||
pass
|
||||
|
||||
def start(self, group=0):
|
||||
"""Return the index of the start of the substring matched by group.
|
||||
|
||||
:type group: int | bytes | unicode
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
def end(self, group=0):
|
||||
"""Return the index of the end of the substring matched by group.
|
||||
|
||||
:type group: int | bytes | unicode
|
||||
:rtype: int
|
||||
"""
|
||||
pass
|
||||
|
||||
def span(self, group=0):
|
||||
"""Return a 2-tuple (start, end) for the substring matched by group.
|
||||
|
||||
:type group: int | bytes | unicode
|
||||
:rtype: (int, int)
|
||||
"""
|
||||
pass
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,21 +35,28 @@ import java.util.List;
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyUserSkeletonsUtil {
|
||||
public static final String USER_SKELETONS_DIR = "python-skeletons";
|
||||
@Nullable private static VirtualFile ourUserSkeletonsDirectory;
|
||||
|
||||
@NotNull
|
||||
public static String getUserSkeletonsPath() {
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
return StringUtil.join(new String[] {PathManager.getHomePath(), "python", "helpers", "user-skeletons"}, File.separator);
|
||||
}
|
||||
// TODO: Add the possibility to put skeletons into PathManager.getSystemPath() + "/user-skeletons"
|
||||
return PythonHelpersLocator.getHelperPath("user-skeletons");
|
||||
private static List<String> getPossibleUserSkeletonsPaths() {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
result.add(PathManager.getConfigPath() + File.separator + USER_SKELETONS_DIR);
|
||||
result.add(ApplicationManager.getApplication().isInternal()
|
||||
? StringUtil.join(new String[]{PathManager.getHomePath(), "python", "helpers", USER_SKELETONS_DIR}, File.separator)
|
||||
: PythonHelpersLocator.getHelperPath(USER_SKELETONS_DIR));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile getUserSkeletonsDirectory() {
|
||||
if (ourUserSkeletonsDirectory == null) {
|
||||
ourUserSkeletonsDirectory = LocalFileSystem.getInstance().findFileByPath(getUserSkeletonsPath());
|
||||
for (String path : getPossibleUserSkeletonsPaths()) {
|
||||
ourUserSkeletonsDirectory = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
|
||||
if (ourUserSkeletonsDirectory != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ourUserSkeletonsDirectory;
|
||||
}
|
||||
@@ -75,7 +83,7 @@ public class PyUserSkeletonsUtil {
|
||||
if (sdk != null) {
|
||||
final Project project = foothold.getProject();
|
||||
final PythonSdkPathCache cache = PythonSdkPathCache.getInstance(project, sdk);
|
||||
final PyQualifiedName cacheQName = PyQualifiedName.fromDottedString("user-skeletons." + qName);
|
||||
final PyQualifiedName cacheQName = PyQualifiedName.fromDottedString(USER_SKELETONS_DIR + "." + qName);
|
||||
final List<PsiElement> results = cache.get(cacheQName);
|
||||
if (results != null) {
|
||||
final PsiElement element = results.isEmpty() ? null : results.get(0);
|
||||
@@ -101,7 +109,7 @@ public class PyUserSkeletonsUtil {
|
||||
}
|
||||
|
||||
public static void addUserSkeletonsRoot(@NotNull SdkModificator sdkModificator) {
|
||||
final VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByPath(getUserSkeletonsPath());
|
||||
final VirtualFile root = getUserSkeletonsDirectory();
|
||||
if (root != null) {
|
||||
sdkModificator.addRoot(root, OrderRootType.CLASSES);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,10 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
private static void updateSysPath(final Sdk sdk) throws InvalidSdkException {
|
||||
long start_time = System.currentTimeMillis();
|
||||
final List<String> sysPath = PythonSdkType.getSysPath(sdk.getHomePath());
|
||||
sysPath.add(PyUserSkeletonsUtil.getUserSkeletonsPath());
|
||||
final VirtualFile file = PyUserSkeletonsUtil.getUserSkeletonsDirectory();
|
||||
if (file != null) {
|
||||
sysPath.add(file.getPath());
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
Reference in New Issue
Block a user