diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000..1c8799d --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,15 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an issue is closed for lack of response +daysUntilClose: 28 + +# Label requiring a response +responseRequiredLabel: more-information-needed + +# Comment to post when closing an issue for lack of response. Set to `false` to disable. +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..16f1825 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: ci +on: + - pull_request + - push + +jobs: + Test: + if: "!contains(github.event.head_commit.message, '[skip ci]')" + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + atom_channel: + - stable + - nightly + steps: + - uses: actions/checkout@v2 + - name: Cache + uses: actions/cache@v2 + with: + path: | + 'node_modules' + 'C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/v140' + key: ${{ runner.os }}-${{ matrix.atom_channel }}-${{ hashFiles('package.json') }} + + - uses: UziTech/action-setup-atom@v1 + with: + channel: ${{ matrix.atom_channel }} + + - name: Install Visual Studio 2015 on Windows + if: ${{ contains(matrix.os, 'windows') }} + run: | + choco install visualcpp-build-tools --version=14.0.25420.1 --ignore-dependencies -y --params "'/IncludeRequired'" + echo ::set-env name=VCTargetsPath::'C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\v140' + + - name: Install dependencies + run: apm install + + - name: Run tests + run: apm test + + Skip: + if: contains(github.event.head_commit.message, '[skip ci]') + runs-on: ubuntu-latest + steps: + - name: Skip CI 🚫 + run: echo skip ci diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 47ee9a1..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -### Project specific config ### -language: generic - -env: - global: - - APM_TEST_PACKAGES="" - - ATOM_LINT_WITH_BUNDLED_NODE="true" - - matrix: - - ATOM_CHANNEL=stable - - ATOM_CHANNEL=beta - -### Generic setup follows ### -script: - - curl -s -O https://raw.githubusercontent.com/atom/ci/master/build-package.sh - - chmod u+x build-package.sh - - ./build-package.sh - -notifications: - email: - on_success: never - on_failure: change - -branches: - only: - - master - -git: - depth: 10 - -sudo: false - -dist: trusty - -addons: - apt: - packages: - - build-essential - - fakeroot - - git - - libsecret-1-dev diff --git a/README.md b/README.md index e646780..4def7c0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Python language support in Atom -[![macOS Build Status](https://travis-ci.org/atom/language-python.svg?branch=master)](https://travis-ci.org/atom/language-python) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/hmxrb9jttjh41es9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-python/branch/master) +##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) + # Python language support in Atom +![ci](https://github.com/atom/language-python/workflows/ci/badge.svg) [![Dependency Status](https://david-dm.org/atom/language-python.svg)](https://david-dm.org/atom/language-python) Adds syntax highlighting and snippets to Python files in Atom. diff --git a/appveyor.yml b/appveyor.yml index 2b0fde4..795da41 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,27 +1,6 @@ -version: "{build}" - -platform: x64 +# empty appveyor +build: off branches: - only: - - master - -clone_depth: 10 - -skip_tags: true - -environment: - APM_TEST_PACKAGES: - - matrix: - - ATOM_CHANNEL: stable - - ATOM_CHANNEL: beta - -install: - - ps: Install-Product node 4 - -build_script: - - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1')) - -test: off -deploy: off + only: + - non-existing diff --git a/grammars/python.cson b/grammars/python.cson index dc84094..71cb6d4 100644 --- a/grammars/python.cson +++ b/grammars/python.cson @@ -848,7 +848,7 @@ 'generic_names': 'match': '[A-Za-z_][A-Za-z0-9_]*' 'illegal_names': - 'match': '\\b(and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield|await)\\b' + 'match': '\\b(and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield|await|async)\\b' 'name': 'invalid.illegal.name.python' 'keyword_arguments': 'begin': '\\b([a-zA-Z_][a-zA-Z_0-9]*)\\s*(=)(?!=)' @@ -1643,7 +1643,7 @@ 'name': 'string.quoted.double.block.python' 'patterns': [ { - 'begin': '(?=\\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH))' + 'begin': '(?=\\s*(SELECT|INSERT|UPDATE|DELETE(?! \/)|CREATE|REPLACE|ALTER|WITH))' 'name': 'meta.embedded.sql' 'end': '(?=\\s*""")' 'patterns': [ @@ -1655,7 +1655,7 @@ ] } { - 'begin': '(")(?=\\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH))' + 'begin': '(")(?=\\s*(SELECT|INSERT|UPDATE|DELETE(?! \/)|CREATE|REPLACE|ALTER|WITH))' 'beginCaptures': '1': 'name': 'punctuation.definition.string.begin.python' @@ -2214,7 +2214,7 @@ 'name': 'string.quoted.single.block.python' 'patterns': [ { - 'begin': '(?=\\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH))' + 'begin': '(?=\\s*(SELECT|INSERT|UPDATE|DELETE(?! \/)|CREATE|REPLACE|ALTER|WITH))' 'end': '(?=\\s*\'\'\')' 'name': 'meta.embedded.sql' 'patterns': [ @@ -2226,7 +2226,7 @@ ] } { - 'begin': '(\')(?=\\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH))' + 'begin': '(\')(?=\\s*(SELECT|INSERT|UPDATE|DELETE(?! \/)|CREATE|REPLACE|ALTER|WITH))' 'beginCaptures': '1': 'name': 'punctuation.definition.string.begin.python' diff --git a/grammars/regular expressions (python).cson b/grammars/regular expressions (python).cson index fabcd80..18d1438 100644 --- a/grammars/regular expressions (python).cson +++ b/grammars/regular expressions (python).cson @@ -14,6 +14,10 @@ 'match': '\\\\[1-9][0-9]?' 'name': 'keyword.other.back-reference.regexp' } + { + 'match': '\\\\.' + 'name': 'constant.character.escape.backslash.regexp' + } { 'match': '[?+*][?+]?|\\{(\\d+,\\d+|\\d+,|,\\d+|\\d+)\\}\\??' 'name': 'keyword.operator.quantifier.regexp' diff --git a/grammars/tree-sitter-python.cson b/grammars/tree-sitter-python.cson index ee5db99..4490d74 100644 --- a/grammars/tree-sitter-python.cson +++ b/grammars/tree-sitter-python.cson @@ -1,8 +1,15 @@ -id: 'python' name: 'Python' +scopeName: 'source.python' type: 'tree-sitter' parser: 'tree-sitter-python' -legacyScopeName: 'source.python' + +firstLineRegex: [ + # shebang line + '^#![ \\t]*/.*\\bpython[\\d\\.]*\\b' + + # vim modeline + 'vim\\b.*\\bset\\b.*\\b(filetype|ft|syntax)=python' +] fileTypes: [ 'py' @@ -18,9 +25,16 @@ fileTypes: [ ] folds: [ + { + type: ['if_statement'] + start: {type: ':'} + end: {type: ['elif_clause', 'else_clause']} + }, { type: [ 'if_statement' + 'elif_clause' + 'else_clause' 'for_statement' 'try_statement' 'with_statement' @@ -30,7 +44,7 @@ folds: [ 'async_function_definition' ] start: {type: ':'} - } + }, { start: {type: '(', index: 0} end: {type: ')', index: -1} @@ -53,12 +67,28 @@ scopes: 'comment': 'comment.line' 'string': 'string.quoted' + 'escape_sequence': 'constant.character.escape' + 'interpolation': 'meta.embedded' + 'interpolation > "{"': 'punctuation.section.embedded' + 'interpolation > "}"': 'punctuation.section.embedded' 'class_definition > identifier': 'entity.name.type.class' - 'function_definition > identifier': 'entity.name.function' - 'call > identifier:nth-child(0)': 'entity.name.function' + 'function_definition > identifier': 'entity.name.function.definition' + 'call > identifier:nth-child(0)': [ + {match: '^(abs|all|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|vars|zip|__import__)$', + scopes: 'support.function.call'}, + {match: '^[A-Z]', scopes: 'support.type.contructor'} + 'entity.name.function.call' + ] 'call > attribute > identifier:nth-child(2)': 'entity.name.function' + 'identifier': [ + {match: + '^(BaseException|Exception|TypeError|StopAsyncIteration|StopIteration|ImportError|ModuleNotFoundError|OSError|ConnectionError|BrokenPipeError|ConnectionAbortedError|ConnectionRefusedError|ConnectionResetError|BlockingIOError|ChildProcessError|FileExistsError|FileNotFoundError|IsADirectoryError|NotADirectoryError|InterruptedError|PermissionError|ProcessLookupError|TimeoutError|EOFError|RuntimeError|RecursionError|NotImplementedError|NameError|UnboundLocalError|AttributeError|SyntaxError|IndentationError|TabError|LookupError|IndexError|KeyError|ValueError|UnicodeError|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|AssertionError|ArithmeticError|FloatingPointError|OverflowError|ZeroDivisionError|SystemError|ReferenceError|BufferError|MemoryError|Warning|UserWarning|DeprecationWarning|PendingDeprecationWarning|SyntaxWarning|RuntimeWarning|FutureWarning|ImportWarning|UnicodeWarning|BytesWarning|ResourceWarning|GeneratorExit|SystemExit|KeyboardInterrupt)$' + scopes: 'support.type.exception'}, + {match: '^(self)', scopes: 'entity.name.variable.self'} + ] + 'attribute > identifier:nth-child(2)': 'variable.other.object.property' 'decorator': 'entity.name.function.decorator' @@ -66,15 +96,33 @@ scopes: 'none': 'constant.language' 'true': 'constant.language' 'false': 'constant.language' - 'integer': 'constant.language' - 'float': 'constant.language' + 'integer': 'constant.numeric' + 'float': 'constant.numeric' 'type > identifier': 'support.storage.type' + 'class_definition > argument_list > attribute': 'entity.other.inherited-class' + 'class_definition > argument_list > identifier': 'entity.other.inherited-class' + 'class_definition > argument_list > keyword_argument > attribute': 'entity.other.inherited-class' + 'class_definition > argument_list > keyword_argument > identifier:nth-child(2)': 'entity.other.inherited-class' + '"class"': 'storage.type.class' '"def"': 'storage.type.function' '"lambda"': 'storage.type.function' + '"global"': 'storage.modifier.global' + '"nonlocal"': 'storage.modifier.nonlocal' + + 'parameters > identifier': 'variable.parameter.function' + 'parameters > list_splat > identifier': 'variable.parameter.function' + 'parameters > dictionary_splat > identifier': 'variable.parameter.function' + 'default_parameter > identifier:nth-child(0)': 'variable.parameter.function' + 'keyword_argument > identifier:nth-child(0)': 'variable.parameter.function' + 'lambda_parameters > identifier': 'variable.parameter.function' + 'typed_parameter > identifier': 'variable.parameter.function' + + 'argument_list': 'meta.method-call.python' + '"if"': 'keyword.control' '"else"': 'keyword.control' '"elif"': 'keyword.control' @@ -83,6 +131,7 @@ scopes: '"return"': 'keyword.control' '"break"': 'keyword.control' '"continue"': 'keyword.control' + '"pass"': 'keyword.control' '"raise"': 'keyword.control' '"yield"': 'keyword.control' '"await"': 'keyword.control' @@ -94,16 +143,53 @@ scopes: '"finally"': 'keyword.control' '"import"': 'keyword.control' '"from"': 'keyword.control' - '"print"': 'keyword.control' - '"assert"': 'keyword.control' + + '"print"': 'keyword.other' + '"assert"': 'keyword.other' + '"exec"': 'keyword.other' + '"del"': 'keyword.other' '"+"': 'keyword.operator' '"-"': 'keyword.operator' '"*"': 'keyword.operator' '"/"': 'keyword.operator' '"%"': 'keyword.operator' + '"**"': 'keyword.operator' + '"//"': 'keyword.operator' + '"=="': 'keyword.operator' + '"!="': 'keyword.operator' + '"<>"': 'keyword.operator' + '">"': 'keyword.operator' + '"<"': 'keyword.operator' + '">="': 'keyword.operator' + '"<="': 'keyword.operator' + '"="': 'keyword.operator' + '"+="': 'keyword.operator' + '"-="': 'keyword.operator' + '"*="': 'keyword.operator' + '"/="': 'keyword.operator' + '"%="': 'keyword.operator' + '"**="': 'keyword.operator' + '"//="': 'keyword.operator' + '"&"': 'keyword.operator' + '"|"': 'keyword.operator' + '"^"': 'keyword.operator' + '"~"': 'keyword.operator' + '"<<"': 'keyword.operator' + '">>"': 'keyword.operator' + 'binary_operator > "@"': 'keyword.operator' + 'binary_operator > "@="': 'keyword.operator' '"in"': 'keyword.operator.logical.python' '"and"': 'keyword.operator.logical.python' '"or"': 'keyword.operator.logical.python' '"not"': 'keyword.operator.logical.python' '"is"': 'keyword.operator.logical.python' + '"->"': 'keyword.control.return' + + '"["': 'punctuation.definition.begin.bracket.square' + '"]"': 'punctuation.definition.end.bracket.square' + '","': 'punctuation.separator.delimiter' + '"{"': 'punctuation.section.block.begin.bracket.curly' + '"}"': 'punctuation.section.block.end.bracket.curly' + '"("': 'punctuation.section.parens.begin.bracket.round' + '")"': 'punctuation.section.parens.end.bracket.round' diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d77eb13 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,188 @@ +{ + "name": "language-python", + "version": "0.53.6", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "atom-grammar-test": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/atom-grammar-test/-/atom-grammar-test-0.6.4.tgz", + "integrity": "sha1-2KU1A9H+k5mX9Ji3SirDEARKfU4=", + "requires": { + "chevrotain": "^0.18.0", + "escape-string-regexp": "^1.0.5" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chevrotain": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-0.18.0.tgz", + "integrity": "sha1-sodxTjFZC64sXR4vYRZz7+xHnYA=" + }, + "coffee-script": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.11.1.tgz", + "integrity": "sha1-vxxHrWREOg2V0S3ysUfMCk2q1uk=", + "dev": true + }, + "coffeelint": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-1.16.2.tgz", + "integrity": "sha512-6mzgOo4zb17WfdrSui/cSUEgQ0AQkW3gXDht+6lHkfkqGUtSYKwGdGcXsDfAyuScVzTlTtKdfwkAlJWfqul7zg==", + "dev": true, + "requires": { + "coffee-script": "~1.11.0", + "glob": "^7.0.6", + "ignore": "^3.0.9", + "optimist": "^0.6.1", + "resolve": "^0.6.3", + "strip-json-comments": "^1.0.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "tree-sitter-python": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.17.0.tgz", + "integrity": "sha512-6HaqF/1GHB0/qrkcIxYqEELsQq6bXdQxx2KnGLZhoGn5ipbAibncSuQT9f8HYbmqLZ4dIGleQzsXreY1mx2lig==", + "requires": { + "nan": "^2.4.0" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index d8d1107..6a079e3 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,14 @@ { "name": "language-python", - "version": "0.49.5", + "version": "0.53.6", "engines": { "atom": "*", "node": "*" }, "description": "Python language support in Atom", + "keywords": [ + "tree-sitter" + ], "homepage": "https://atom.github.io/language-python", "repository": { "type": "git", @@ -17,7 +20,7 @@ }, "dependencies": { "atom-grammar-test": "^0.6.4", - "tree-sitter-python": "^0.11.3" + "tree-sitter-python": "^0.17.0" }, "devDependencies": { "coffeelint": "^1.10.1" diff --git a/settings/language-python.cson b/settings/language-python.cson index 001e981..8538f10 100644 --- a/settings/language-python.cson +++ b/settings/language-python.cson @@ -4,5 +4,6 @@ 'softTabs': true 'tabLength': 4 'commentStart': '# ' + 'foldEndPattern': '^\\s*[}\\])]' 'increaseIndentPattern': '^\\s*(class|def|elif|else|except|finally|for|if|try|with|while|async\\s+(def|for|with))\\b.*:\\s*$' 'decreaseIndentPattern': '^\\s*(elif|else|except|finally)\\b.*:\\s*$' diff --git a/snippets/language-python.cson b/snippets/language-python.cson index 6962bb7..3dee6ee 100644 --- a/snippets/language-python.cson +++ b/snippets/language-python.cson @@ -55,7 +55,7 @@ 'body': 'self.fail(\'${1:message}\')$0' 'New Class': 'prefix': 'class' - 'body': 'class ${1:ClassName}(${2:object}):\n\t"""${3:docstring for $1.}"""\n\tdef __init__(self, ${4:arg}):\n\t\t${5:super($1, self).__init__()}\n\t\tself.arg = arg\n\t\t$0' + 'body': 'class ${1:ClassName}(${2:object}):\n\t"""${3:docstring for $1.}"""\n\n\tdef __init__(self, ${4:arg}):\n\t\t${5:super($1, self).__init__()}\n\t\tself.arg = arg\n\t\t$0' 'New Method': 'prefix': 'defs' 'body': 'def ${1:mname}(self, ${2:arg}):\n\t${3:pass}' @@ -94,7 +94,7 @@ 'body': '[${1:value} for ${2:value} in ${3:variable}]' 'List Comprehension If Else': 'prefix': 'lcie' - 'body': '[${1:value} if ${2:condition} else ${3:condition} for ${4:value} in ${5:variable}]' + 'body': '[${1:value} if ${2:condition} else ${3:value} for ${4:value} in ${5:variable}]' 'Dictionary Comprehension': 'prefix': 'dc' 'body': '{${1:key}: ${2:value} for ${3:key}, ${4:value} in ${5:variable}}' @@ -119,7 +119,3 @@ 'if __name__ == \'__main__\'': 'prefix': 'ifmain' 'body': 'if __name__ == \'__main__\':\n\t${1:main()}$0' -'.source.python:not(.string)': - 'self': - 'prefix': '.' - 'body': 'self.' diff --git a/spec/language-python-spec.coffee b/spec/language-python-spec.coffee index e5b431e..e21fb82 100644 --- a/spec/language-python-spec.coffee +++ b/spec/language-python-spec.coffee @@ -5,6 +5,8 @@ describe 'Python settings', -> editor.destroy() beforeEach -> + atom.config.set('core.useTreeSitterParsers', false) + waitsForPromise -> atom.workspace.open().then (o) -> editor = o diff --git a/spec/python-regex-spec.coffee b/spec/python-regex-spec.coffee index cb11eee..d1cb81a 100644 --- a/spec/python-regex-spec.coffee +++ b/spec/python-regex-spec.coffee @@ -2,6 +2,8 @@ describe 'Python regular expression grammar', -> grammar = null beforeEach -> + atom.config.set('core.useTreeSitterParsers', false) + waitsForPromise -> atom.packages.activatePackage('language-python') @@ -28,3 +30,23 @@ describe 'Python regular expression grammar', -> expect(tokens[1]).toEqual value: '^', scopes: ['source.regexp.python', 'constant.other.character-class.set.regexp', 'keyword.operator.negation.regexp'] expect(tokens[2]).toEqual value: '][', scopes: ['source.regexp.python', 'constant.other.character-class.set.regexp'] expect(tokens[3]).toEqual value: ']', scopes: ['source.regexp.python', 'constant.other.character-class.set.regexp', 'punctuation.definition.character-class.end.regexp'] + + it 'escapes the character following any backslash', -> + {tokens} = grammar.tokenizeLine '''\\q\\(\\[\\'\\"\\?\\^\\-\\*\\.\\#''' + expect(tokens[0]).toEqual value: '\\q', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[1]).toEqual value: '\\(', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[2]).toEqual value: '\\[', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[3]).toEqual value: '\\\'', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[4]).toEqual value: '\\"', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[5]).toEqual value: '\\?', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[6]).toEqual value: '\\^', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[7]).toEqual value: '\\-', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[8]).toEqual value: '\\*', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[9]).toEqual value: '\\.', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + expect(tokens[10]).toEqual value: '\\#', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] + + {tokens} = grammar.tokenizeLine '''(\\()\\)''' + expect(tokens[0]).toEqual value: '(', scopes: ['source.regexp.python', 'meta.group.regexp', 'punctuation.definition.group.regexp'] + expect(tokens[1]).toEqual value: '\\(', scopes: ['source.regexp.python', 'meta.group.regexp', 'constant.character.escape.backslash.regexp'] + expect(tokens[2]).toEqual value: ')', scopes: ['source.regexp.python', 'meta.group.regexp', 'punctuation.definition.group.regexp'] + expect(tokens[3]).toEqual value: '\\)', scopes: ['source.regexp.python', 'constant.character.escape.backslash.regexp'] diff --git a/spec/python-spec.coffee b/spec/python-spec.coffee index 3f5eeba..423f8c1 100644 --- a/spec/python-spec.coffee +++ b/spec/python-spec.coffee @@ -5,6 +5,8 @@ describe "Python grammar", -> grammar = null beforeEach -> + atom.config.set('core.useTreeSitterParsers', false) + waitsForPromise -> atom.packages.activatePackage("language-python") @@ -748,3 +750,10 @@ describe "Python grammar", -> expect(tokens[13]).toEqual value: ')', scopes: ['source.python', 'string.quoted.double.single-line.sql.python', 'meta.embedded.sql', 'punctuation.definition.section.bracket.round.end.sql'] expect(tokens[15]).toEqual value: '"', scopes: ['source.python', 'string.quoted.double.single-line.sql.python', 'punctuation.definition.string.end.python'] expect(tokens[17]).toEqual value: '%', scopes: ['source.python', 'keyword.operator.arithmetic.python'] + + it "recognizes DELETE as an HTTP method", -> + {tokens} = grammar.tokenizeLine('"DELETE /api/v1/endpoint"') + + expect(tokens[0]).toEqual value: '"', scopes: ['source.python', 'string.quoted.double.single-line.python', 'punctuation.definition.string.begin.python'] + expect(tokens[1]).toEqual value: 'DELETE /api/v1/endpoint', scopes: ['source.python', 'string.quoted.double.single-line.python'] + expect(tokens[2]).toEqual value: '"', scopes: ['source.python', 'string.quoted.double.single-line.python', 'punctuation.definition.string.end.python']