From 4386ab9a8d127debd2da8a39d29f162b5e8581b8 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 2 Sep 2013 18:46:53 +0400 Subject: [PATCH 1/3] Search for user skeletons in PyCharm config --- .../userSkeletons/PyUserSkeletonsUtil.java | 26 ++++++++++++------- .../python/sdk/PythonSdkUpdater.java | 5 +++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java index 676b86f83ae6..e9ef7ebeee19 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java @@ -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 = "user-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 getPossibleUserSkeletonsPaths() { + final List result = new ArrayList(); + 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 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); } diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java index 69cfc3f42229..15dae82bf84f 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java @@ -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 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() { From cbed76ea3359df6764ae2e46f4ef6b3d437ca97e Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 2 Sep 2013 18:52:37 +0400 Subject: [PATCH 2/3] Renamed user-skeletons to python-skeletons --- python/helpers/python-skeletons/README.md | 139 +++++++ .../helpers/python-skeletons/__builtin__.py | 377 ++++++++++++++++++ .../helpers/python-skeletons/nose/__init__.py | 0 .../python-skeletons/nose/tools/__init__.py | 177 ++++++++ python/helpers/python-skeletons/re.py | 277 +++++++++++++ .../userSkeletons/PyUserSkeletonsUtil.java | 2 +- 6 files changed, 971 insertions(+), 1 deletion(-) create mode 100644 python/helpers/python-skeletons/README.md create mode 100644 python/helpers/python-skeletons/__builtin__.py create mode 100644 python/helpers/python-skeletons/nose/__init__.py create mode 100644 python/helpers/python-skeletons/nose/tools/__init__.py create mode 100644 python/helpers/python-skeletons/re.py diff --git a/python/helpers/python-skeletons/README.md b/python/helpers/python-skeletons/README.md new file mode 100644 index 000000000000..953a0d0a11d7 --- /dev/null +++ b/python/helpers/python-skeletons/README.md @@ -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 defintion 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 annoatations 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 + git clone https://github.com/JetBrains/python-skeletons.git + +where `` is: + +* Mac OS X: `~/Library/Prefernces/PyCharmXX/config` +* Linux: `~/.PyCharmXX/config` +* Windows: `\.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. diff --git a/python/helpers/python-skeletons/__builtin__.py b/python/helpers/python-skeletons/__builtin__.py new file mode 100644 index 000000000000..682c491c7367 --- /dev/null +++ b/python/helpers/python-skeletons/__builtin__.py @@ -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 xy. + + :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 diff --git a/python/helpers/python-skeletons/nose/__init__.py b/python/helpers/python-skeletons/nose/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/helpers/python-skeletons/nose/tools/__init__.py b/python/helpers/python-skeletons/nose/tools/__init__.py new file mode 100644 index 000000000000..143355fe3dbb --- /dev/null +++ b/python/helpers/python-skeletons/nose/tools/__init__.py @@ -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 diff --git a/python/helpers/python-skeletons/re.py b/python/helpers/python-skeletons/re.py new file mode 100644 index 000000000000..151ddc9b7257 --- /dev/null +++ b/python/helpers/python-skeletons/re.py @@ -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 diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java index e9ef7ebeee19..6aa350224a38 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java @@ -35,7 +35,7 @@ import java.util.List; * @author vlan */ public class PyUserSkeletonsUtil { - public static final String USER_SKELETONS_DIR = "user-skeletons"; + public static final String USER_SKELETONS_DIR = "python-skeletons"; @Nullable private static VirtualFile ourUserSkeletonsDirectory; @NotNull From 46199cb7f64a0b530aed14966fd7e669d9720de4 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Mon, 2 Sep 2013 18:53:35 +0400 Subject: [PATCH 3/3] Typos --- python/helpers/python-skeletons/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/helpers/python-skeletons/README.md b/python/helpers/python-skeletons/README.md index 953a0d0a11d7..e557a519e22e 100644 --- a/python/helpers/python-skeletons/README.md +++ b/python/helpers/python-skeletons/README.md @@ -21,7 +21,7 @@ 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 defintion code of libraries, +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. @@ -58,7 +58,7 @@ Conventions Skeletons should respect PEP-8 and PEP-257 style guides. The most simple way of specifying types in skeletons is Sphinx docstrings. -Function annoatations could be used for specifying types, but they are +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 @@ -121,7 +121,7 @@ repository into your PyCharm config directory: where `` is: -* Mac OS X: `~/Library/Prefernces/PyCharmXX/config` +* Mac OS X: `~/Library/Preferences/PyCharmXX/config` * Linux: `~/.PyCharmXX/config` * Windows: `\.PyCharmXX\config`