diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index fadcc7ec1f20..1d6d6a97d1df 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -12,33 +12,33 @@ Otherwise **please** fill in the requested details below. "XXX" markers should n
## Environment data
-- VS Code version: < XXX >
-- Extension version (available under the Extensions sidebar): < XXX >
-- OS and version: < XXX >
-- Python version: < XXX; include the distribution details if applicable, e.g. Anaconda >
-- Type of virtual environment used (if applicable): < XXX: N/A | venv | virtualenv | conda | ... >
-- Relevant/affected Python packages and their versions: < XXX >
+- VS Code version: XXX
+- Extension version (available under the Extensions sidebar): XXX
+- OS and version: XXX
+- Python version (& distribution if applicable, e.g. Anaconda): XXX
+- Type of virtual environment used (N/A | venv | virtualenv | conda | ...): XXX
+- Relevant/affected Python packages and their versions: XXX
## Actual behavior
-< XXX >
+XXX
## Expected behavior
-< XXX >
+XXX
## Steps to reproduce:
-1. < XXX >
+1. XXX
## Logs
Output for `Python` in the `Output` panel (`View`→`Output`, change the drop-down the upper-right of the `Output` panel to `Python`)
```
-< XXX >
+XXX
```
Output from `Console` under the `Developer Tools` panel (toggle Developer Tools on under `Help`)
```
-< XXX >
+XXX
```
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000000..ecc2a4026baf
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,9 @@
+Fixes #
+
+- [ ] Title summarizes what is changing
+- [ ] Includes a [news entry](https://github.com/Microsoft/vscode-python/tree/master/news) file (remember to thank yourself!)
+- [ ] Unit tests & [code coverage](https://codecov.io/gh/Microsoft/vscode-python) are not adversely affected (within reason)
+- [ ] Works on all [actively maintained versions of Python](https://devguide.python.org/#status-of-python-branches) (e.g. Python 2.7 & the latest Python 3 release)
+- [ ] Works on Windows 10, macOS, and Linux (e.g. considered file system case-sensitivity)
+- [ ] Dependencies are pinned (e.g. `"1.2.3"`, not `"^1.2.3"`)
+- [ ] `package-lock.json` has been regenerated if dependencies have changed
diff --git a/.github/lock.yml b/.github/lock.yml
new file mode 100644
index 000000000000..dde77291a4ef
--- /dev/null
+++ b/.github/lock.yml
@@ -0,0 +1,3 @@
+daysUntilLock: 28
+lockComment: false
+only: issues
diff --git a/.github/release_plan.md b/.github/release_plan.md
new file mode 100644
index 000000000000..e6ae17fd41bf
--- /dev/null
+++ b/.github/release_plan.md
@@ -0,0 +1,92 @@
+# Week of Monday, XXX
+
+- [ ] Review the state of the current [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Go through telemetry for GDPR
+- [ ] Go through all [merged pull requests](https://github.com/Microsoft/vscode-python/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Amerged) and add the [`validate fix` label](https://github.com/Microsoft/vscode-python/labels/validate%20fix) as appropriate as well as checking for news entries
+- [ ] Validate [fixed issues](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+- [ ] Triage [unverified issues](https://github.com/Microsoft/vscode-python/labels/needs%20verification)
+- [ ] Update pre-existing dependencies as appropriate (npm, Python, git submodule, or otherwise; requires updating CELA)
+
+## Planning
+- [ ] Evaluate if TypeScript usage needs updating to sync with VS Code's usage
+- [ ] Evaluate [projects](https://github.com/Microsoft/vscode-python/projects) & [`meta` issues](https://github.com/Microsoft/vscode-python/labels/meta)
+- [ ] Go through [`needs PR` issues](https://github.com/Microsoft/vscode-python/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3A%22needs+PR%22+-label%3A%22help+wanted%22+-label%3A%22good+first+issue%22+no%3Amilestone) to see if there's anything we want to add to this milestone
+- [ ] Finalize the initial set of issues for the [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Close issues that have [needed more info](https://github.com/Microsoft/vscode-python/issues?q=is%3Aopen+label%3A%22needs+more+info%22+sort%3Aupdated-asc) for over a month
+
+# Week of Monday, XXX
+
+- [ ] Review the state of the current [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Go through telemetry for GDPR
+- [ ] Go through all [merged pull requests](https://github.com/Microsoft/vscode-python/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Amerged) and add the [`validate fix` label](https://github.com/Microsoft/vscode-python/labels/validate%20fix) as appropriate as well as checking for news entries
+- [ ] Validate [fixed issues](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+- [ ] Triage [unverified issues](https://github.com/Microsoft/vscode-python/labels/needs%20verification)
+
+## Planning
+- [ ] Check if there have been no performance regressions
+- [ ] Read through [VS Code's iteration plan](https://github.com/Microsoft/vscode/labels/iteration-plan) (it may still be a [draft](https://github.com/Microsoft/vscode/labels/iteration-plan-draft))
+
+# Week of Monday, XXX
+
+- [ ] Review the state of the current [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Go through telemetry for GDPR
+- [ ] Go through all [merged pull requests](https://github.com/Microsoft/vscode-python/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Amerged) and add the [`validate fix` label](https://github.com/Microsoft/vscode-python/labels/validate%20fix) as appropriate as well as checking for news entries
+- [ ] Validate [fixed issues](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+- [ ] Triage [unverified issues](https://github.com/Microsoft/vscode-python/labels/needs%20verification)
+
+## Legal
+- [ ] Announce the lock-down of dependencies for this release
+- [ ] Notify CELA of all changes to the [repository](https://github.com/Microsoft/vscode-python/tree/master/pythonFiles), [distribution dependencies](https://github.com/Microsoft/vscode-python/blob/master/package.json) (including [ptvsd](https://pypi.org/project/ptvsd/), and [git submodules](https://github.com/Microsoft/vscode-python) (e.g. Typeshed)
+
+## Release a beta version for testing
+- [ ] Update the [version](https://github.com/Microsoft/vscode-python/blob/master/package.json) to be a `beta` & update the [changelog](https://github.com/Microsoft/vscode-python/blob/master/CHANGELOG.md)
+- [ ] Announce the beta [development build](https://github.com/Microsoft/vscode-python/blob/master/CONTRIBUTING.md#development-build) (along with how to help [validate fixes](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed))
+- [ ] Open appropriate [documentation issues](https://github.com/microsoft/vscode-docs/issues?q=is%3Aissue+is%3Aopen+label%3Apython)
+
+# Week of Monday, XXX
+
+- [ ] Review the state of the current [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Go through telemetry for GDPR
+- [ ] Merge any last-minute [pull requests](https://github.com/Microsoft/vscode-python/pulls)
+- [ ] Go through all [merged pull requests](https://github.com/Microsoft/vscode-python/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Amerged) and add the [`validate fix` label](https://github.com/Microsoft/vscode-python/labels/validate%20fix) as appropriate as well as checking for news entries
+- [ ] Validate [fixed issues](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+- [ ] Triage [unverified issues](https://github.com/Microsoft/vscode-python/labels/needs%20verification)
+
+## Prep for the release candidate
+- [ ] Announce feature freeze
+- [ ] Make sure the [repo](https://github.com/Microsoft/vscode-python/blob/master/ThirdPartyNotices-Repository.txt) and [distribution TPNs](https://github.com/Microsoft/vscode-python/blob/master/ThirdPartyNotices-Distribution.txt) have been updated appropriately
+
+## Test the release candidate code
+- [ ] Update the [version](https://github.com/Microsoft/vscode-python/blob/master/package.json) to be an `rc` & update the [changelog](https://github.com/Microsoft/vscode-python/blob/master/CHANGELOG.md)
+- [ ] Announce the release candidate [development build](https://github.com/Microsoft/vscode-python/blob/master/CONTRIBUTING.md#development-build)
+- [ ] Open appropriate [documentation issues](https://github.com/microsoft/vscode-docs/issues?q=is%3Aissue+is%3Aopen+label%3Apython)
+- [ ] Begin drafting a [blog](http://aka.ms/pythonblog) post
+
+## Prep the release
+- [ ] Ensure all new feature usages are tracked via telemetry
+- [ ] Make sure no extraneous files are being included in the `.vsix` file (make sure to check for hidden files)
+- [ ] Make sure the [appropriate pull requests](https://github.com/microsoft/vscode-docs/pulls) for the [documentation](https://code.visualstudio.com/docs/python/python-tutorial) -- including the [WOW](https://code.visualstudio.com/docs/languages/python) page -- are ready
+
+## Release
+- [ ] Update the [changelog](https://github.com/Microsoft/vscode-python/blob/master/CHANGELOG.md) (including the names of external contributors & projects)
+- [ ] Update the [version](https://github.com/Microsoft/vscode-python/blob/master/package.json) number to be final
+- [ ] Make sure [CI](https://github.com/Microsoft/vscode-python/blob/master/CONTRIBUTING.md) is passing
+- [ ] Generate the final `.vsix` file
+- [ ] Upload the final `.vsix` file to the [marketplace](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
+- [ ] Publish [documentation](https://code.visualstudio.com/docs/python/python-tutorial) [changes](https://github.com/microsoft/vscode-docs/pulls)
+- [ ] Publish the [blog](http://aka.ms/pythonblog) post
+- [ ] Create a [release](https://github.com/Microsoft/vscode-python/releases) on GitHub (which creates an appropriate git tag)
+- [ ] Determine if a hotfix is needed
+- [ ] Create the `release-` [branch](https://github.com/Microsoft/vscode-python/)
+
+## Prep for the _next_ release
+- [ ] Bump the [version](https://github.com/Microsoft/vscode-python/blob/master/package.json) number to the next `alpha`
+- [ ] Make sure the next **two** [milestones](https://github.com/Microsoft/vscode-python/milestones) exist
+- [ ] Lift the feature freeze
+- [ ] Create a new [release plan](https://github.com/Microsoft/vscode-python/edit/master/.github/release_plan.md)
+
+## Clean up after _this_ release
+- [ ] Clean up any straggling [fixed issues needing validation](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+- [ ] Close the (now) old [milestone](https://github.com/Microsoft/vscode-python/milestones)
+- [ ] Delete the previous releases' [branch](https://github.com/Microsoft/vscode-python/branches)
+- [ ] Go through [`needs more info` issues](https://github.com/Microsoft/vscode-python/issues?q=is%3Aopen+label%3A%22needs+more+info%22+sort%3Aupdated-asc) and close any that have no activity for over a month
diff --git a/.github/test_plan.md b/.github/test_plan.md
new file mode 100644
index 000000000000..a98b21fea0b6
--- /dev/null
+++ b/.github/test_plan.md
@@ -0,0 +1,283 @@
+# Test plan
+
+## Environment
+
+- OS: XXX (Windows, macOS, latest Ubuntu LTS)
+ - Shell: XXX (Command Prompt, PowerShell, bash, fish)
+- Python
+ - Distribution: XXX (CPython, miniconda)
+ - Version: XXX (2.7, latest 3.x)
+- VS Code: XXX (Insiders)
+
+## Tests
+
+**ALWAYS**:
+- Check the `Output` window under `Python` for logged errors
+- Have `Developer Tools` open to detect any errors
+- Consider running the tests in a multi-folder workspace
+- Focus on in-development features (i.e. experimental debugger and language server)
+
+
+ Scenarios
+
+### [Environment](https://code.visualstudio.com/docs/python/environments)
+#### Interpreters
+
+- [ ] Interpreter is [shown in the status bar](https://code.visualstudio.com/docs/python/environments#_choosing-an-environment)
+- [ ] An interpreter can be manually specified using the [`Select Interpreter` command](https://code.visualstudio.com/docs/python/environments#_choosing-an-environment)
+- [ ] Detected system-installed interpreters
+- [ ] Detected an Anaconda installation
+- [ ] (Linux/macOS) Detected all interpreters installed w/ [pyenv](https://github.com/pyenv/pyenv) detected
+- [ ] [`"python.pythonPath"`](https://code.visualstudio.com/docs/python/environments#_manually-specifying-an-interpreter) triggers an update in the status bar
+- [ ] `Run Python File in Terminal`
+- [ ] `Run Selection/Line in Python Terminal`
+ - [ ] Right-click
+ - [ ] Command
+ - [ ] `Shift+Enter`
+
+#### Virtual environments
+
+**ALWAYS**:
+- Use the latest version of Anaconda
+- Realize that `conda` is slow
+- Create an environment with a space in their path somewhere
+- Make sure that you do not have `python.pythonPath` specified in your `settings.json` when testing automatic detection
+- Do note that the `Select Interpreter` drop-down window scrolls
+
+- [ ] Detected a single virtual environment at the top-level of the workspace folder (if you created this _after_ opening VS Code, then run `Reload Window` to pick up the new environment)
+ - [ ] Appropriate suffix label specified in status bar (e.g. `(venv)`)
+ - [ ] [`Create Terminal`](https://code.visualstudio.com/docs/python/environments#_activating-an-environment-in-the-terminal) works
+ - [ ] Steals focus
+ - [ ] `"python.terminal.activateEnvironment": false` deactivates automatically running the activation script in the terminal
+ - [ ] After the language server downloads it is able to complete its analysis of the environment w/o requiring a restart
+- [ ] Detect multiple virtual environments contained in the directory specified in `"python.venvPath"`
+- [ ] Detected all [conda environments created with an interpreter](https://code.visualstudio.com/docs/python/environments#_conda-environments)
+ - [ ] Appropriate suffix label specified in status bar (e.g. `(condaenv)`)
+ - [ ] Prompted to install Pylint
+ - [ ] Asked whether to install using conda or pip
+ - [ ] Installs into environment
+ - [ ] [`Create Terminal`](https://code.visualstudio.com/docs/python/environments#_activating-an-environment-in-the-terminal) works
+ - [ ] `"python.terminal.activateEnvironment": false` deactivates automatically running the activation script in the terminal
+ - [ ] After the language server downloads it is able to complete its analysis of the environment w/o requiring a restart
+- [ ] (Linux/macOS until [`-m` is supported](https://github.com/Microsoft/vscode-python/issues/978)) Detected the virtual environment created by [pipenv](https://docs.pipenv.org/)
+ - [ ] Appropriate suffix label specified in status bar (e.g. `(pipenv)`)
+ - [ ] Prompt to install Pylint uses `pipenv install --dev`
+ - [ ] [`Create Terminal`](https://code.visualstudio.com/docs/python/environments#_activating-an-environment-in-the-terminal) works
+ - [ ] `"python.terminal.activateEnvironment": false` deactivates automatically running the activation script in the terminal
+ - [ ] After the language server downloads it is able to complete its analysis of the environment w/o requiring a restart
+- [ ] (Linux/macOS) Virtual environments created under `{workspaceFolder}/.direnv/python-{python_version}` are detected (for [direnv](https://direnv.net/) and its [`layout python3`](https://github.com/direnv/direnv/blob/master/stdlib.sh) support)
+ - [ ] Appropriate suffix label specified in status bar (e.g. `(venv)`)
+
+#### [Environment files](https://code.visualstudio.com/docs/python/environments#_environment-variable-definitions-file)
+Sample files:
+```python
+# example.py
+import os
+print('Hello,', os.environ.get('WHO'), '!')
+```
+```
+# .env
+WHO=world
+PYTHONPATH=some/path/somewhere
+````
+
+**ALWAYS**:
+- Make sure to use `Reload Window` between tests to reset your environment
+- Note that environment files only apply under the debugger and Jedi
+
+- [ ] Environment variables in a `.env` file are exposed when running under the debugger
+- [ ] `"python.envFile"` allows for specifying an environment file manually (e.g. Jedi picks up `PYTHONPATH` changes)
+- [ ] `envFile` in a `launch.json` configuration works
+
+#### [Debugging](https://code.visualstudio.com/docs/python/environments#_python-interpreter-for-debugging)
+
+- [ ] `pythonPath` setting in your `launch.json` overrides your `python.pythonPath` default setting
+
+### [Linting](https://code.visualstudio.com/docs/python/linting)
+
+**ALWAYS**:
+- Check under the `Problems` tab to see e.g. if a linter is raising errors
+
+#### Pylint/default linting
+[Prompting to install Pylint is covered under `Environments` above]
+
+For testing the disablement of the default linting rules for Pylint:
+```ini
+# pylintrc
+[MESSAGES CONTROL]
+enable=bad-names
+```
+```python3
+# example.py
+foo = 42 # Marked as a blacklisted name.
+```
+- [ ] Installation via the prompt installs Pylint as appropriate
+ - [ ] Uses `--user` for system-install of Python
+ - [ ] Installs into a virtual environment environment directly
+- [ ] Pylint works
+- [ ] `"python.linting.pylintUseMinimalCheckers": false` turns off the default rules w/ no `pylintrc` file present
+- [ ] The existence of a `pylintrc` file turns off the default rules
+
+#### Other linters
+
+**Note**:
+- You can use the `Run Linting` command to run a newly installed linter
+- When the extension installs a new linter, it turns off all other linters
+
+- [ ] flake8 works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] mypy works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] pep8 works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] prospector works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] pydocstyle works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] pylama works
+ - [ ] `Select linter` lists the linter and installs it if necessary
+- [ ] 3 or more linters work simultaneously (make sure you have turned on the linters in your `settings.json`)
+ - [ ] `Run Linting` runs all activated linters
+ - [ ] `"python.linting.enabled": false` disables all linters
+ - [ ] The `Enable Linting` command changes `"python.linting.enabled"`
+- [ ] `"python.linting.lintOnSave` works
+
+### [Editing](https://code.visualstudio.com/docs/python/editing)
+
+#### [IntelliSense](https://code.visualstudio.com/docs/python/editing#_autocomplete-and-intellisense)
+
+Please also test for general accuracy on the most "interesting" code you can find.
+
+- [ ] `"python.autoComplete.extraPaths"` works
+- [ ] `"python.autoComplete.preloadModules"` works (e.g. listing `numpy` should visibly speed up completing on the module's contents)
+- [ ] `"python.autocomplete.addBrackets": true` causes auto-completion of functions to append `()`
+
+#### [Formatting](https://code.visualstudio.com/docs/python/editing#_formatting)
+Sample file:
+```python
+# There should be _some_ change after running `Format Document`.
+def foo():pass
+```
+
+- [ ] Prompted to install a formatter if none installed and `Format Document` is run
+ - [ ] Installing `autopep8` works
+ - [ ] Installing `black` works
+ - [ ] Installing `yapf` works
+- [ ] autopep8 works
+- [ ] black works
+- [ ] yapf works
+- [ ] `"editor.formatOnType": true` works and has expected results
+
+#### [Refactoring](https://code.visualstudio.com/docs/python/editing#_refactoring)
+
+- [ ] [`Extract Variable`](https://code.visualstudio.com/docs/python/editing#_extract-variable) works
+ - [ ] You are prompted to install `rope` if it is not already available
+- [ ] [`Extract method`](https://code.visualstudio.com/docs/python/editing#_extract-method) works
+ - [ ] You are prompted to install `rope` if it is not already available
+- [ ] [`Sort Imports`](https://code.visualstudio.com/docs/python/editing#_sort-imports) works
+
+### [Debugging](https://code.visualstudio.com/docs/python/debugging)
+
+**ALWAYS**:
+- Test the current debugger
+- Test the experimental debugger (and note whether it is _at least_ as fast as the old debugger)
+
+- [ ] [Configurations](https://code.visualstudio.com/docs/python/debugging#_debugging-specific-app-types) work
+ - [ ] `Current File`
+ - [ ] `Module`
+ - [ ] `Attach`
+ - [ ] `Terminal (integrated)`
+ - [ ] `Terminal (external)`
+ - [ ] `Django`
+ - [ ] `Flask`
+ - [ ] `Pyramid`
+ - [ ] `Watson`
+ - [ ] `Scrapy`
+ - [ ] `PySpark`
+ - [ ] `All debug Options` with [appropriate values](https://code.visualstudio.com/docs/python/debugging#_standard-configuration-and-options) edited to make values valid
+- [ ] Running code from start to finish w/ no special debugging options (e.g. no breakpoints)
+- [ ] Breakpoints
+ - [ ] Set
+ - [ ] Hit
+ - [ ] Conditional
+ - [ ] Expression
+ - [ ] Hit count
+ - [ ] Log points (experimental debugger only)
+- [ ] Stepping
+ - [ ] Over
+ - [ ] Into
+ - [ ] Out
+- [ ] Can inspect variables
+ - [ ] Through hovering over variable in code
+ - [ ] `Variables` section of debugger sidebar
+- [ ] [Remote debugging](https://code.visualstudio.com/docs/python/debugging#_remote-debugging) works
+ - [ ] ... over SSH
+- [ ] [App Engine](https://code.visualstudio.com/docs/python/debugging#_google-app-engine-debugging)
+
+### [Unit testing](https://code.visualstudio.com/docs/python/unit-testing)
+
+#### [`unittest`](https://code.visualstudio.com/docs/python/unit-testing#_unittest-configuration-settings)
+```python
+import unittest
+
+class PassingTests(unittest.TestCase):
+
+ def test_passing(self):
+ self.assertEqual(42, 42)
+
+ def test_passing_still(self):
+ self.assertEqual("silly walk", "silly walk")
+
+
+class FailingTests(unittest.TestCase):
+
+ def test_failure(self):
+ self.assertEqual(42, -13)
+
+ def test_failure_still(self):
+ self.assertEqual("I'm right!", "no, I am!")
+```
+- [ ] `Run All Unit Tests` triggers the prompt to configure the test runner
+- [ ] Tests are discovered (as shown by code lenses on each test)
+
+#### [`pytest`](https://code.visualstudio.com/docs/python/unit-testing#_pytest-configuration-settings)
+```python
+def test_passing():
+ assert 42 == 42
+
+def test_failure():
+ assert 42 == -13
+```
+
+- [ ] `Run All Unit Tests` triggers the prompt to configure the test runner
+ - [ ] `pytest` gets installed
+- [ ] Tests are discovered (as shown by code lenses on each test)
+
+#### [`nose`](https://code.visualstudio.com/docs/python/unit-testing#_nose-configuration-settings)
+```python
+def test_passing():
+ assert 42 == 42
+
+def test_failure():
+ assert 42 == -13
+```
+
+- [ ] `Run All Unit Tests` triggers the prompt to configure the test runner
+ - [ ] Nose gets installed
+- [ ] Tests are discovered (as shown by code lenses on each test)
+
+#### General
+
+- [ ] Code lenses appears
+ - [ ] `Run Test` lens works (and status bar updates as appropriate)
+ - [ ] `Debug Test` lens works
+ - [ ] Appropriate ✔/❌ shown for each test
+- [ ] Status bar is functioning
+ - [ ] Appropriate test results displayed
+ - [ ] `Run All Unit Tests` works
+ - [ ] `Discover Unit Tests` works (resets tests result display in status bar)
+ - [ ] `Run Unit Test Method ...` works
+ - [ ] `View Unit Test Output` works
+ - [ ] After having at least one failure, `Run Failed Tests` works
+
+
diff --git a/.gitignore b/.gitignore
index 466b005af61d..c6cd087c91ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,10 @@ coverage/
.vscode-test/**
.venv
pythonFiles/experimental/ptvsd/**
+debug_coverage*/**
+languageServer/**
+bin/**
+obj/**
+.pytest_cache
+tmp/**
+.python-version
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000000..a57bae098756
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "typeshed"]
+ path = typeshed
+ url = https://github.com/python/typeshed.git
+ branch = master
\ No newline at end of file
diff --git a/.mocha-reporter/mocha-vsts-reporter.js b/.mocha-reporter/mocha-vsts-reporter.js
new file mode 100644
index 000000000000..7ac83371527c
--- /dev/null
+++ b/.mocha-reporter/mocha-vsts-reporter.js
@@ -0,0 +1,63 @@
+'use-strict';
+
+var mocha = require('mocha');
+var MochaJUnitReporter = require('mocha-junit-reporter');
+module.exports = MochaVstsReporter;
+
+function MochaVstsReporter(runner, options) {
+ MochaJUnitReporter.call(this, runner, options);
+ var INDENT_BASE = ' ';
+ var indenter = '';
+ var indentLevel = 0;
+ var passes = 0;
+ var failures = 0;
+ var skipped = 0;
+
+ runner.on('suite', function(suite){
+ if (suite.root === true){
+ console.log('Begin test run.............');
+ indentLevel++;
+ indenter = INDENT_BASE.repeat(indentLevel);
+ } else {
+ console.log('%sStart "%s"', indenter, suite.title);
+ indentLevel++;
+ indenter = INDENT_BASE.repeat(indentLevel);
+ }
+ });
+
+ runner.on('suite end', function(suite){
+ if (suite.root === true) {
+ indentLevel=0;
+ indenter = '';
+ console.log('.............End test run.');
+ } else {
+ console.log('%sEnd "%s"', indenter, suite.title);
+ indentLevel--;
+ indenter = INDENT_BASE.repeat(indentLevel);
+ // ##vso[task.setprogress]current operation
+ }
+ });
+
+ runner.on('pass', function(test){
+ passes++;
+ console.log('%s✓ %s (%dms)', indenter, test.title, test.duration);
+ });
+
+ runner.on('pending', function(test){
+ skipped++;
+ console.log('%s- %s', indenter, test.title);
+ console.log('##vso[task.logissue type=warning;sourcepath=%s;]SKIPPED TEST %s :: %s', test.file, test.parent.title, test.title);
+ });
+
+ runner.on('fail', function(test, err){
+ failures++;
+ console.log('%s✖ %s -- error: %s', indenter, test.title, err.message);
+ console.log('##vso[task.logissue type=error;sourcepath=%s;]FAILED %s :: %s', test.file, test.parent.title, test.title);
+ });
+
+ runner.on('end', function(){
+ console.log('SUMMARY: %d/%d passed, %d skipped', passes, passes + failures, skipped);
+ });
+}
+
+mocha.utils.inherits(MochaVstsReporter, MochaJUnitReporter);
diff --git a/.travis.yml b/.travis.yml
index f81ec0a06242..52cf8962505f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,57 +5,133 @@ matrix:
include:
- os: linux
python: "2.7"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "2.7"
+ env: DEBUGGER_TEST_RELEASE=true
+ - os: linux
+ python: "2.7"
+ env: SINGLE_WORKSPACE_TEST=true
+ - os: linux
+ python: "2.7"
+ env: MULTIROOT_WORKSPACE_TEST=true
+ - os: linux
+ python: "3.6-dev"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "3.6-dev"
+ env: DEBUGGER_TEST_RELEASE=true
+ - os: linux
+ python: "3.6-dev"
+ env: SINGLE_WORKSPACE_TEST=true
+ - os: linux
+ python: "3.6-dev"
+ env: MULTIROOT_WORKSPACE_TEST=true
+ - os: linux
+ python: "3.6-dev"
+ env: PERFORMANCE_TEST=true
+ - os: linux
+ python: "3.7-dev"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "3.7-dev"
+ env: DEBUGGER_TEST_RELEASE=true
+ - os: linux
+ python: "3.7-dev"
+ env: SINGLE_WORKSPACE_TEST=true
+ - os: linux
+ python: "3.7-dev"
+ env: MULTIROOT_WORKSPACE_TEST=true
+ allow_failures:
+ - os: linux
+ python: "2.7"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "2.7"
+ env: DEBUGGER_TEST_RELEASE=true
- os: linux
python: "3.6-dev"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "3.6-dev"
+ env: DEBUGGER_TEST_RELEASE=true
+ - os: linux
+ python: "3.7-dev"
+ env: DEBUGGER_TEST=true
+ - os: linux
+ python: "3.7-dev"
+ env: DEBUGGER_TEST_RELEASE=true
before_install: |
if [ $TRAVIS_OS_NAME == "linux" ]; then
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
sh -e /etc/init.d/xvfb start;
sleep 3;
fi
- git submodule update --init --recursive
git clone https://github.com/creationix/nvm.git ./.nvm
source ./.nvm/nvm.sh
nvm install 8.9.1
nvm use 8.9.1
- yarn global add vsce
- yarn global add azure-cli
- export TRAVIS_PYTHON_PATH=`which python`
+ npm install npm@latest -g
+ npm install -g vsce
+ npm install -g azure-cli
+ export CI_PYTHON_PATH=`which python`
install:
- - pip install --upgrade -r requirements.txt
- - pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/
- - yarn
+ - python -m pip install --upgrade -r requirements.txt
+ - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/
+ - npm ci
script:
- - yarn run clean
- - yarn run vscode:prepublish
- - yarn run cover:enable
- - yarn run testDebugger --silent
+ - if [ $DEBUGGER_TEST == "true" ]; then
+ npm run clean;
+ npm run vscode:prepublish;
+ npm run cover:enable;
+ npm run testDebugger --silent;
+ fi
+ - npm run debugger-coverage
- if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then
bash <(curl -s https://codecov.io/bash);
fi
- - rm -rf ./pythonFiles/experimental/ptvsd
- - yarn run clean
- - yarn run vscode:prepublish
- - yarn run cover:enable
- - yarn run testSingleWorkspace --silent
+ - npm run clean:ptvsd
+ - pip install -t ./pythonFiles/experimental/ptvsd ptvsd --pre --no-cache-dir;
+ - if [ $DEBUGGER_TEST_RELEASE == "true" ]; then
+ npm run clean;
+ npm run vscode:prepublish;
+ npm run cover:enable;
+ npm run testDebugger --silent;
+ fi
+ - npm run debugger-coverage
- if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then
bash <(curl -s https://codecov.io/bash);
fi
- - yarn run clean
- - yarn run vscode:prepublish
- - yarn run cover:enable
- - yarn run testMultiWorkspace --silent
+ - if [ $SINGLE_WORKSPACE_TEST == "true" ]; then
+ npm run clean;
+ npm run vscode:prepublish;
+ npm run cover:enable;
+ npm run testSingleWorkspace --silent;
+ fi
- if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then
bash <(curl -s https://codecov.io/bash);
fi
- - if [ "$TRAVIS_PYTHON_VERSION" != "2.7" ]; then
- python3 -m pip install --upgrade -r news/requirements.txt;
- python3 news/announce.py --dry-run;
+ - if [ $MULTIROOT_WORKSPACE_TEST == "true" ]; then
+ npm run clean;
+ npm run vscode:prepublish;
+ npm run cover:enable;
+ npm run testMultiWorkspace --silent;
fi
-after_success:
- - if [ $AZURE_STORAGE_ACCOUNT ]; then
+ - if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then
+ bash <(curl -s https://codecov.io/bash);
+ fi
+ - if [[ "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == "false" && "$PERFORMANCE_TEST" == "true" ]]; then
yarn run clean;
+ yarn run vscode:prepublish;
+ yarn run testPerformance --silent;
+ fi
+ - if [ "$TRAVIS_PYTHON_VERSION" == "3.7" ]; then
+ python3 -m pip install --upgrade -r news/requirements.txt;
+ python3 news/announce.py --dry_run;
+ fi
+ - if [[ $AZURE_STORAGE_ACCOUNT && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_PULL_REQUEST" == "false" ]]; then
+ npm run clean;
vsce package;
- azure storage blob upload --container $AZURE_STORAGE_CONTAINER --blob ms-python-insiders.vsix --account-name $AZURE_STORAGE_ACCOUNT --account-key $AZURE_STORAGE_ACCESS_KEY --file python*.vsix --quiet;
+ azure storage blob upload python*.vsix $AZURE_STORAGE_CONTAINER ms-python-insiders.vsix --account-name $AZURE_STORAGE_ACCOUNT --account-key $AZURE_STORAGE_ACCESS_KEY --quiet;
fi
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 264d49e34f11..4a1a1f9bd12a 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -11,9 +11,10 @@
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
+ "smartStep": true,
"sourceMaps": true,
"outFiles": [
- "${workspaceFolder}/out/**/*.js"
+ "${workspaceFolder}/out/**/*"
],
"preLaunchTask": "Compile"
},
@@ -23,6 +24,7 @@
"request": "launch",
"program": "${workspaceFolder}/out/client/debugger/Main.js",
"stopOnEntry": false,
+ "smartStep": true,
"args": [
"--server=4711"
],
@@ -39,6 +41,7 @@
"request": "launch",
"program": "${workspaceFolder}/out/client/debugger/mainV2.js",
"stopOnEntry": false,
+ "smartStep": true,
"args": [
"--server=4711"
],
@@ -66,6 +69,22 @@
],
"preLaunchTask": "Compile"
},
+ {
+ "name": "Debug Unit Tests",
+ "type": "node",
+ "request": "launch",
+ "program": "${workspaceFolder}/out/test/unittests.js",
+ "stopOnEntry": false,
+ "sourceMaps": true,
+ "args": [
+ "timeout=60000",
+ "grep="
+ ],
+ "outFiles": [
+ "${workspaceFolder}/out/**/*.js"
+ ],
+ "preLaunchTask": "Compile"
+ },
{
"name": "Launch Multiroot Tests",
"type": "extensionHost",
@@ -78,11 +97,32 @@
],
"stopOnEntry": false,
"sourceMaps": true,
+ "smartStep": true,
"outFiles": [
- "${workspaceFolder}/out/**/*.js"
+ "${workspaceFolder}/out/**/*"
],
"preLaunchTask": "Compile"
},
+ {
+ "name": "Launch Language Server Tests",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": [
+ "${workspaceFolder}/src/test",
+ "--extensionDevelopmentPath=${workspaceFolder}",
+ "--extensionTestsPath=${workspaceFolder}/out/test"
+ ],
+ "stopOnEntry": false,
+ "sourceMaps": true,
+ "outFiles": [
+ "${workspaceFolder}/out/**/*.js"
+ ],
+ "preLaunchTask": "Compile",
+ "env": {
+ "VSC_PYTHON_LANGUAGE_SERVER": "1"
+ }
+ },
{
"name": "Launch Tests (with code coverage)",
"type": "extensionHost",
@@ -94,6 +134,7 @@
"--extensionTestsPath=${workspaceFolder}/out/test"
],
"stopOnEntry": false,
+ "smartStep": true,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
diff --git a/.vscode/settings.json b/.vscode/settings.json
index be66f967c5c4..7ce29c7c0813 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,6 +3,8 @@
"files.exclude": {
"out": true, // set this to true to hide the "out" folder with the compiled JS files
"**/*.pyc": true,
+ "obj": true,
+ "bin": true,
"**/__pycache__": true,
"node_modules": true,
".vscode-test": true,
@@ -19,4 +21,4 @@
"python.unitTest.promptToConfigure": false,
"python.workspaceSymbols.enabled": false,
"python.formatting.provider": "none"
-}
\ No newline at end of file
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index f4384e2537bf..6165d465d00f 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -9,6 +9,32 @@
"tasks": [
{
"label": "Compile",
+ "type": "npm",
+ "script": "compile",
+ "isBackground": true,
+ "problemMatcher": [
+ "$tsc-watch",
+ {
+ "base": "$tslint5",
+ "fileLocation": "relative"
+ }
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ },
+ {
+ "label": "Run Unit Tests",
+ "type": "npm",
+ "script": "test:unittests",
+ "group": {
+ "kind": "test",
+ "isDefault": true
+ }
+ },
+ {
+ "label": "Hygiene",
"type": "gulp",
"task": "watch",
"isBackground": true,
@@ -18,6 +44,24 @@
"focus": false,
"panel": "dedicated"
},
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "problemMatcher": []
+ },
+ {
+ // Use this to run hygiene and display errors in problems window (very slow on Windows)
+ "label": "Hygiene (Problems Window)",
+ "type": "gulp",
+ "task": "watchProblems",
+ "isBackground": true,
+ "presentation": {
+ "echo": true,
+ "reveal": "never",
+ "focus": false,
+ "panel": "dedicated"
+ },
"problemMatcher": [
{
"applyTo": "allDocuments",
diff --git a/.vscodeignore b/.vscodeignore
index a9397c1a60b1..4037e6fc7e54 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -1,37 +1,58 @@
-.vscode/**
-.vscode-test/**
-.github/**
-.nvm/**
-typings/**
-out/test/**
-out/src/**
-out/pythonFiles/**
-out/testMultiRootWkspc/**
-out/coverconfig.json
-test/**
-src/**
-scripts/**
**/*.map
-.gitignore
-.gitmodules
+.appveyor.yml
.editorconfig
.eslintrc
.gitattributes
-images/**/*.gif
-images/**/*.png
-tsconfig.json
-typings.json
+.gitignore
+.gitmodules
+.npmrc
+.travis.yml
+CODE_OF_CONDUCT.md
+CODING_STANDARDS.md
+CONTRIBUTING.md
+CONTRIBUTING - LANGUAGE SERVER.md
coverconfig.json
-tslint.json
-tsfmt.json
gulpfile.js
-pythonFiles/**/*.pyc
-requirements.txt
-vsc-extension-quickstart.md
-.travis.yml
+packageExtension.cmd
+tsconfig.json
+tsfmt.json
+tslint.json
+typings.json
+vscode-python-signing.*
webpack.config.js
yarn.lock
+
+.github/**
+.nvm/**
+.vscode/**
+.vscode-test/**
+languageServer/**
+bin/**
+BuildOutput/**
coverage/**
-CODE_OF_CONDUCT.md
-CODING_STANDARDS.md
-CONTRIBUTING.md
+debug_coverage*/**
+images/**/*.gif
+images/**/*.png
+news/**
+obj/**
+out/coverconfig.json
+out/pythonFiles/**
+out/src/**
+out/test/**
+out/testMultiRootWkspc/**
+pythonFiles/**/*.pyc
+requirements.txt
+scripts/**
+src/**
+test/**
+tmp/**
+typeshed/tests/**
+typeshed/.flake8
+typeshed/.git
+typeshed/.gitignore
+typeshed/.travis.yml
+typeshed/CONTRIBUTING.md
+typeshed/README.md
+typeshed/*.txt
+typings/**
+vsc-extension-quickstart.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d746daec36e..bc8c712281b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,662 @@
# Changelog
+## 2018.7.1 (23 July 2018)
+
+### Fixes
+
+1. Update the language server to code as of
+ [651468731500ec1cc644029c3666c57b82f77d76](https://github.com/Microsoft/PTVS/commit/651468731500ec1cc644029c3666c57b82f77d76).
+ ([#2233](https://github.com/Microsoft/vscode-python/issues/2233))
+
+
+## 2018.7.0 (18 July 2018)
+
+### Thanks
+
+Thanks to the following projects which we fully rely on to provide some of
+our features:
+- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/)
+- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/)
+ and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/)
+- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/)
+- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed)
+- [rope](https://pypi.org/project/rope/) (user-installed)
+
+Also thanks to the various projects we provide integrations with which help
+make this extension useful:
+- Debugging support:
+ [Django](https://pypi.org/project/Django/),
+ [Flask](https://pypi.org/project/Flask/),
+ [gevent](https://pypi.org/project/gevent/),
+ [Jinja](https://pypi.org/project/Jinja/),
+ [Pyramid](https://pypi.org/project/pyramid/),
+ [PySpark](https://pypi.org/project/pyspark/),
+ [Scrapy](https://pypi.org/project/Scrapy/),
+ [Watson](https://pypi.org/project/Watson/)
+- Formatting:
+ [autopep8](https://pypi.org/project/autopep8/),
+ [black](https://pypi.org/project/black/),
+ [yapf](https://pypi.org/project/yapf/)
+- Interpreter support:
+ [conda](https://conda.io/),
+ [direnv](https://direnv.net/),
+ [pipenv](https://pypi.org/project/pipenv/),
+ [pyenv](https://github.com/pyenv/pyenv),
+ [venv](https://docs.python.org/3/library/venv.html#module-venv),
+ [virtualenv](https://pypi.org/project/virtualenv/)
+- Linting:
+ [flake8](https://pypi.org/project/flake8/),
+ [mypy](https://pypi.org/project/mypy/),
+ [prospector](https://pypi.org/project/prospector/),
+ [pylint](https://pypi.org/project/pylint/),
+ [pydocstyle](https://pypi.org/project/pydocstyle/),
+ [pylama](https://pypi.org/project/pylama/)
+- Testing:
+ [nose](https://pypi.org/project/nose/),
+ [pytest](https://pypi.org/project/pytest/),
+ [unittest](https://docs.python.org/3/library/unittest.html#module-unittest)
+
+And finally thanks to the [Python](https://www.python.org/) development team and
+community for creating a fantastic programming language and community to be a
+part of!
+
+### Enhancements
+
+1. Language server now reports code analysis progress in the status bar.
+ ([#1591](https://github.com/Microsoft/vscode-python/issues/1591))
+1. Only report Language Server download progress once.
+ ([#2000](https://github.com/Microsoft/vscode-python/issues/2000))
+1. Messages changes to reflect name of the language server: 'Microsoft Python Language Server';
+ folder name changed from `analysis` to `languageServer`.
+ ([#2107](https://github.com/Microsoft/vscode-python/issues/2107))
+1. Set default analysis for language server to open files only.
+ ([#2113](https://github.com/Microsoft/vscode-python/issues/2113))
+1. Add two popups to the extension: one to ask users to move to the new language server, the other to request feedback from users of that language server.
+ ([#2127](https://github.com/Microsoft/vscode-python/issues/2127))
+
+### Fixes
+
+1. Ensure dunder variables are always displayed in code completion when using the new language server.
+ ([#2013](https://github.com/Microsoft/vscode-python/issues/2013))
+1. Store testId for files & suites during unittest discovery.
+ ([#2044](https://github.com/Microsoft/vscode-python/issues/2044))
+1. `editor.formatOnType` no longer adds space after `*` in multi-line arguments.
+ ([#2048](https://github.com/Microsoft/vscode-python/issues/2048))
+1. Fix bug where tooltips would popup whenever a comma is typed within a string.
+ ([#2057](https://github.com/Microsoft/vscode-python/issues/2057))
+1. Change keyboard shortcut for `Run Selection/Line in Python Terminal` to not
+ interfere with the Find/Replace dialog box.
+ ([#2068](https://github.com/Microsoft/vscode-python/issues/2068))
+1. Relax validation of the environment `Path` variable.
+ ([#2076](https://github.com/Microsoft/vscode-python/issues/2076))
+1. `editor.formatOnType` is more reliable handling floating point numbers.
+ ([#2079](https://github.com/Microsoft/vscode-python/issues/2079))
+1. Change the default port used in remote debugging using `Experimental` debugger to `5678`.
+ ([#2146](https://github.com/Microsoft/vscode-python/issues/2146))
+1. Register test manager when using the new language server.
+ ([#2186](https://github.com/Microsoft/vscode-python/issues/2186))
+
+### Code Health
+
+1. Removed pre-commit hook that ran unit tests.
+ ([#1986](https://github.com/Microsoft/vscode-python/issues/1986))
+1. Pass OS type to the debugger.
+ ([#2128](https://github.com/Microsoft/vscode-python/issues/2128))
+1. Ensure 'languageServer' directory is excluded from the build output.
+ ([#2150](https://github.com/Microsoft/vscode-python/issues/2150))
+1. Change the download links of the language server files.
+ ([#2180](https://github.com/Microsoft/vscode-python/issues/2180))
+
+
+
+## 2018.6.0 (20 June 2018)
+
+### Thanks
+
+Thanks to the following projects which we fully rely on to provide some of
+our features:
+- [isort 4.3.4](https://pypi.org/project/isort/4.3.4/)
+- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/)
+ and [parso 0.2.1](https://pypi.org/project/parso/0.2.1/)
+- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.11a5](https://pypi.org/project/ptvsd/4.1.11a5/)
+- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed)
+- [rope](https://pypi.org/project/rope/) (user-installed)
+
+Also thanks to the various projects we provide integrations with which help
+make this extension useful:
+- Debugging support:
+ [Django](https://pypi.org/project/Django/),
+ [Flask](https://pypi.org/project/Flask/),
+ [gevent](https://pypi.org/project/gevent/),
+ [Jinja](https://pypi.org/project/Jinja/),
+ [Pyramid](https://pypi.org/project/pyramid/),
+ [PySpark](https://pypi.org/project/pyspark/),
+ [Scrapy](https://pypi.org/project/Scrapy/),
+ [Watson](https://pypi.org/project/Watson/)
+- Formatting:
+ [autopep8](https://pypi.org/project/autopep8/),
+ [black](https://pypi.org/project/black/),
+ [yapf](https://pypi.org/project/yapf/)
+- Interpreter support:
+ [conda](https://conda.io/),
+ [direnv](https://direnv.net/),
+ [pipenv](https://pypi.org/project/pipenv/),
+ [pyenv](https://github.com/pyenv/pyenv),
+ [venv](https://docs.python.org/3/library/venv.html#module-venv),
+ [virtualenv](https://pypi.org/project/virtualenv/)
+- Linting:
+ [flake8](https://pypi.org/project/flake8/),
+ [mypy](https://pypi.org/project/mypy/),
+ [prospector](https://pypi.org/project/prospector/),
+ [pylint](https://pypi.org/project/pylint/),
+ [pydocstyle](https://pypi.org/project/pydocstyle/),
+ [pylama](https://pypi.org/project/pylama/)
+- Testing:
+ [nose](https://pypi.org/project/nose/),
+ [pytest](https://pypi.org/project/pytest/),
+ [unittest](https://docs.python.org/3/library/unittest.html#module-unittest)
+
+And finally thanks to the [Python](https://www.python.org/) development team and
+community for creating a fantastic programming language and community to be a
+part of!
+
+### Enhancements
+
+1. Add setting to control automatic test discovery on save, `python.unitTest.autoTestDiscoverOnSaveEnabled`.
+ (thanks [Lingyu Li](http://github.com/lingyv-li/))
+ ([#1037](https://github.com/Microsoft/vscode-python/issues/1037))
+1. Add `gevent` launch configuration option to enable debugging of gevent monkey patched code.
+ (thanks [Bence Nagy](https://github.com/underyx))
+ ([#127](https://github.com/Microsoft/vscode-python/issues/127))
+1. Add support for the `"source.organizeImports"` setting for `"editor.codeActionsOnSave"` (thanks [Nathan Gaberel](https://github.com/n6g7)); you can turn this on just for Python using:
+ ```json
+ "[python]": {
+ "editor.codeActionsOnSave": {
+ "source.organizeImports": true
+ }
+ }
+ ```
+ ([#156](https://github.com/Microsoft/vscode-python/issues/156))
+1. Added Spanish translation.
+ (thanks [Mario Rubio](https://github.com/mario-mra/))
+ ([#1902](https://github.com/Microsoft/vscode-python/issues/1902))
+1. Add a French translation (thanks to [Jérémy](https://github.com/PixiBixi) for
+ the initial patch, and thanks to [Nathan Gaberel](https://github.com/n6g7),
+ [Bruno Alla](https://github.com/browniebroke), and
+ [Tarek Ziade](https://github.com/tarekziade) for reviews).
+ ([#1959](https://github.com/Microsoft/vscode-python/issues/1959))
+1. Add syntax highlighting for [Pipenv](http://pipenv.readthedocs.io/en/latest/)-related
+ files (thanks [Nathan Gaberel](https://github.com/n6g7)).
+ ([#995](https://github.com/Microsoft/vscode-python/issues/995))
+
+### Fixes
+
+1. Modified to change error message displayed when path to a tool (`linter`, `formatter`, etc) is invalid.
+ ([#1064](https://github.com/Microsoft/vscode-python/issues/1064))
+1. Improvements to the logic used to parse the arguments passed into the test frameworks.
+ ([#1070](https://github.com/Microsoft/vscode-python/issues/1070))
+1. Ensure navigation to definitons follows imports and is transparent to decoration.
+ (thanks [Peter Law](https://github.com/PeterJCLaw))
+ ([#1638](https://github.com/Microsoft/vscode-python/issues/1638))
+1. Fix for intellisense failing when using the new `Outline` feature.
+ ([#1721](https://github.com/Microsoft/vscode-python/issues/1721))
+1. When debugging unit tests, use the `env` file configured in `settings.json` under `python.envFile`.
+ ([#1759](https://github.com/Microsoft/vscode-python/issues/1759))
+1. Fix to display all interpreters in the interpreter list when a workspace contains a `Pipfile`.
+ ([#1800](https://github.com/Microsoft/vscode-python/issues/1800))
+1. Use file system API to perform file path comparisons when performing code navigation.
+ (thanks to [bstaint](https://github.com/bstaint) for the problem diagnosis)
+ ([#1811](https://github.com/Microsoft/vscode-python/issues/1811))
+1. Automatically add path mappings for remote debugging when attaching to the localhost.
+ ([#1829](https://github.com/Microsoft/vscode-python/issues/1829))
+1. Change keyboard shortcut for `Run Selection/Line in Python Terminal` to `Shift+Enter`.
+ ([#1875](https://github.com/Microsoft/vscode-python/issues/1875))
+1. Fix unhandled rejected promises in unit tests.
+ ([#1919](https://github.com/Microsoft/vscode-python/issues/1919))
+1. Fix debugger issue that causes the debugger to hang and silently exit stepping over a line of code instantiating an ITK vector object.
+ ([#459](https://github.com/Microsoft/vscode-python/issues/459))
+
+### Code Health
+
+1. Add telemetry to capture type of python interpreter used in workspace.
+ ([#1237](https://github.com/Microsoft/vscode-python/issues/1237))
+1. Enabled multi-thrreaded debugger tests for the `experimental` debugger.
+ ([#1250](https://github.com/Microsoft/vscode-python/issues/1250))
+1. Log relevant environment information when the existence of `pipenv` cannot be determined.
+ ([#1338](https://github.com/Microsoft/vscode-python/issues/1338))
+1. Use [dotenv](https://www.npmjs.com/package/dotenv) package to parse [environment variables definition files](https://code.visualstudio.com/docs/python/environments#_environment-variable-definitions-file).
+ ([#1376](https://github.com/Microsoft/vscode-python/issues/1376))
+1. Move from yarn to npm.
+ ([#1402](https://github.com/Microsoft/vscode-python/issues/1402))
+1. Fix django and flask debugger tests when using the experimental debugger.
+ ([#1407](https://github.com/Microsoft/vscode-python/issues/1407))
+1. Capture telemetry for the usage of the `Create Terminal` command along with other instances when a terminal is created implicitly.
+ ([#1542](https://github.com/Microsoft/vscode-python/issues/1542))
+1. Add telemetry to capture availability of Python 3, version of Python used in workspace and the number of workspace folders.
+ ([#1545](https://github.com/Microsoft/vscode-python/issues/1545))
+1. Ensure all CI tests (except for debugger) are no longer allowed to fail.
+ ([#1614](https://github.com/Microsoft/vscode-python/issues/1614))
+1. Capture telemetry for the usage of the feature that formats a line as you type (`editor.formatOnType`).
+ ([#1766](https://github.com/Microsoft/vscode-python/issues/1766))
+1. Capture telemetry for the new debugger.
+ ([#1767](https://github.com/Microsoft/vscode-python/issues/1767))
+1. Capture telemetry for usage of the setting `python.autocomplete.addBrackets`
+ ([#1770](https://github.com/Microsoft/vscode-python/issues/1770))
+1. Speed up githook by skipping commits not containing any `.ts` files.
+ ([#1803](https://github.com/Microsoft/vscode-python/issues/1803))
+1. Update typescript package to 2.9.1.
+ ([#1815](https://github.com/Microsoft/vscode-python/issues/1815))
+1. Log Conda not existing message as an information instead of an error.
+ ([#1817](https://github.com/Microsoft/vscode-python/issues/1817))
+1. Make use of `ILogger` to log messages instead of using `console.error`.
+ ([#1821](https://github.com/Microsoft/vscode-python/issues/1821))
+1. Update `parso` package to 0.2.1.
+ ([#1833](https://github.com/Microsoft/vscode-python/issues/1833))
+1. Update `isort` package to 4.3.4.
+ ([#1842](https://github.com/Microsoft/vscode-python/issues/1842))
+1. Add better exception handling when parsing responses received from the Jedi language service.
+ ([#1867](https://github.com/Microsoft/vscode-python/issues/1867))
+1. Resolve warnings in CI Tests and fix some broken CI tests.
+ ([#1885](https://github.com/Microsoft/vscode-python/issues/1885))
+1. Reduce sample count used to capture performance metrics in order to reduce time taken to complete the tests.
+ ([#1887](https://github.com/Microsoft/vscode-python/issues/1887))
+1. Ensure workspace information is passed into installer when determining whether a product/tool is installed.
+ ([#1893](https://github.com/Microsoft/vscode-python/issues/1893))
+1. Add JUnit file output to enable CI integration with VSTS.
+ ([#1897](https://github.com/Microsoft/vscode-python/issues/1897))
+1. Log unhandled rejected promises when running unit tests.
+ ([#1918](https://github.com/Microsoft/vscode-python/issues/1918))
+1. Add ability to run tests without having to launch VS Code.
+ ([#1922](https://github.com/Microsoft/vscode-python/issues/1922))
+1. Fix rename refactoring unit tests.
+ ([#1953](https://github.com/Microsoft/vscode-python/issues/1953))
+1. Fix failing test on Mac when validating the path of a python interperter.
+ ([#1957](https://github.com/Microsoft/vscode-python/issues/1957))
+1. Display banner prompting user to complete a survey for the use of the `Experimental Debugger`.
+ ([#1968](https://github.com/Microsoft/vscode-python/issues/1968))
+1. Use a glob pattern to look for `conda` executables.
+ ([#256](https://github.com/Microsoft/vscode-python/issues/256))
+1. Create tests to measure activation times for the extension.
+ ([#932](https://github.com/Microsoft/vscode-python/issues/932))
+
+
+
+
+
+## 2018.5.0 (05 Jun 2018)
+
+Thanks to the following projects which we fully rely on to provide some of
+our features:
+- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/)
+- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/)
+ and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/)
+- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a5](https://pypi.org/project/ptvsd/4.1.1a5/)
+- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed)
+- [rope](https://pypi.org/project/rope/) (user-installed)
+
+And thanks to the many other projects which users can optionally choose from
+and install to work with the extension. Without them the extension would not be
+nearly as feature-rich and useful as it is.
+
+### Enhancements
+
+1. Add support for the [Black formatter](https://pypi.org/project/black/)
+ (thanks to [Josh Smeaton](https://github.com/jarshwah) for the initial patch)
+ ([#1153](https://github.com/Microsoft/vscode-python/issues/1153))
+1. Add the command `Discover Unit Tests`.
+ ([#1474](https://github.com/Microsoft/vscode-python/issues/1474))
+1. Auto detect `*.jinja2` and `*.j2` extensions as Jinja templates, to enable debugging of Jinja templates.
+ ([#1484](https://github.com/Microsoft/vscode-python/issues/1484))
+
+### Fixes
+
+1. Ensure debugger breaks on `assert` failures.
+ ([#1194](https://github.com/Microsoft/vscode-python/issues/1194))
+1. Ensure debugged program is terminated when `Stop` debugging button is clicked.
+ ([#1345](https://github.com/Microsoft/vscode-python/issues/1345))
+1. Fix indentation when function contains type hints.
+ ([#1461](https://github.com/Microsoft/vscode-python/issues/1461))
+1. Ensure python environment activation works as expected within a multi-root workspace.
+ ([#1476](https://github.com/Microsoft/vscode-python/issues/1476))
+1. Close communication channel before exiting the test runner.
+ ([#1529](https://github.com/Microsoft/vscode-python/issues/1529))
+1. Allow for negative column numbers in messages returned by `pylint`.
+ ([#1628](https://github.com/Microsoft/vscode-python/issues/1628))
+1. Modify the `FLASK_APP` environment variable in the flask debug configuration to include just the name of the application file.
+ ([#1634](https://github.com/Microsoft/vscode-python/issues/1634))
+1. Ensure the display name of an interpreter does not get prefixed twice with the words `Python`.
+ ([#1651](https://github.com/Microsoft/vscode-python/issues/1651))
+1. Enable code refactoring when using the new Analysis Engine.
+ ([#1774](https://github.com/Microsoft/vscode-python/issues/1774))
+1. `editor.formatOnType` no longer breaks numbers formatted with underscores.
+ ([#1779](https://github.com/Microsoft/vscode-python/issues/1779))
+1. `editor.formatOnType` now better handles multiline function arguments
+ ([#1796](https://github.com/Microsoft/vscode-python/issues/1796))
+1. `Go to Definition` now works for functions which have numbers that use `_` as a separator (as part of our Jedi 0.12.0 upgrade).
+ ([#180](https://github.com/Microsoft/vscode-python/issues/180))
+1. Display documentation for auto completion items when the feature to automatically insert of brackets for selected item is turned on.
+ ([#452](https://github.com/Microsoft/vscode-python/issues/452))
+1. Ensure empty paths do not get added into `sys.path` by the Jedi language server. (this was fixed in the previous release in [#1471](https://github.com/Microsoft/vscode-python/pull/1471))
+ ([#677](https://github.com/Microsoft/vscode-python/issues/677))
+1. Resolves rename refactor issue that remvoes the last line of the source file when the line is being refactored and source does not end with an EOL.
+ ([#695](https://github.com/Microsoft/vscode-python/issues/695))
+1. Ensure the prompt to install missing packages is not displayed more than once.
+ ([#980](https://github.com/Microsoft/vscode-python/issues/980))
+
+### Code Health
+
+1. Add syntax highlighting to `constraints.txt` files to match that of `requirements.txt` files.
+ (thanks [Waleed Sehgal](https://github.com/waleedsehgal))
+ ([#1053](https://github.com/Microsoft/vscode-python/issues/1053))
+1. Refactor unit testing functionality to improve testability of individual components.
+ ([#1068](https://github.com/Microsoft/vscode-python/issues/1068))
+1. Add unit tests for evaluating expressions in the experimental debugger.
+ ([#1109](https://github.com/Microsoft/vscode-python/issues/1109))
+1. Add tests to ensure custom arguments get passed into python program when using the experimental debugger.
+ ([#1280](https://github.com/Microsoft/vscode-python/issues/1280))
+1. Ensure custom environment variables are always used when spawning any process from within the extension.
+ ([#1339](https://github.com/Microsoft/vscode-python/issues/1339))
+1. Add tests for hit count breakpoints for the experimental debugger.
+ ([#1410](https://github.com/Microsoft/vscode-python/issues/1410))
+1. Ensure none of the npm packages (used by the extension) rely on native dependencies.
+ ([#1416](https://github.com/Microsoft/vscode-python/issues/1416))
+1. Remove explicit initialization of `PYTHONPATH` with the current workspace path in unit testing of modules with the experimental debugger.
+ ([#1465](https://github.com/Microsoft/vscode-python/issues/1465))
+1. Flag `program` in `launch.json` configuration items as an optional attribute.
+ ([#1503](https://github.com/Microsoft/vscode-python/issues/1503))
+1. Remove unused setting `disablePromptForFeatures`.
+ ([#1551](https://github.com/Microsoft/vscode-python/issues/1551))
+1. Remove unused Unit Test setting `debugHost`.
+ ([#1552](https://github.com/Microsoft/vscode-python/issues/1552))
+1. Create a new API to retrieve interpreter details with the ability to cache the details.
+ ([#1569](https://github.com/Microsoft/vscode-python/issues/1569))
+1. Add tests for log points in the experimental debugger.
+ ([#1582](https://github.com/Microsoft/vscode-python/issues/1582))
+1. Update typescript package to 2.8.3.
+ ([#1604](https://github.com/Microsoft/vscode-python/issues/1604))
+1. Fix typescript compilation error.
+ ([#1623](https://github.com/Microsoft/vscode-python/issues/1623))
+1. Fix unit tests used to test flask template debugging on AppVeyor for the experimental debugger.
+ ([#1640](https://github.com/Microsoft/vscode-python/issues/1640))
+1. Change yarn install script to include the keyword `--lock-file`.
+ (thanks [Lingyu Li](https://github.com/lingyv-li/))
+ ([#1682](https://github.com/Microsoft/vscode-python/issues/1682))
+1. Run unit tests as a pre-commit hook.
+ ([#1703](https://github.com/Microsoft/vscode-python/issues/1703))
+1. Update debug capabilities to add support for the setting `supportTerminateDebuggee` due to an upstream update from [PTVSD](https://github.com/Microsoft/ptvsd/issues).
+ ([#1719](https://github.com/Microsoft/vscode-python/issues/1719))
+1. Build and upload development build of the extension to the Azure blob store even if CI tests fail on the `master` branch.
+ ([#1730](https://github.com/Microsoft/vscode-python/issues/1730))
+1. Changes to the script used to upload the extension to the Azure blob store.
+ ([#1732](https://github.com/Microsoft/vscode-python/issues/1732))
+1. Prompt user to reload Visual Studio Code when toggling between the analysis engines.
+ ([#1747](https://github.com/Microsoft/vscode-python/issues/1747))
+1. Fix typo in unit test.
+ ([#1794](https://github.com/Microsoft/vscode-python/issues/1794))
+1. Fix failing Prospector unit tests and add more tests for linters (with and without workspaces).
+ ([#1836](https://github.com/Microsoft/vscode-python/issues/1836))
+1. Ensure `Outline` view doesn't overload the language server with too many requets, while user is editing text in the editor.
+ ([#1856](https://github.com/Microsoft/vscode-python/issues/1856))
+
+
+
+
+
+## 2018.4.0 (2 May 2018)
+
+Thanks to the following projects which we fully rely on to provide some of
+our features:
+- [isort 4.2.15](https://pypi.org/project/isort/4.2.15/)
+- [jedi 0.12.0](https://pypi.org/project/jedi/0.12.0/)
+ and [parso 0.2.0](https://pypi.org/project/parso/0.2.0/)
+- [ptvsd 3.0.0](https://pypi.org/project/ptvsd/3.0.0/) and [4.1.1a1](https://pypi.org/project/ptvsd/4.1.1a1/)
+- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed)
+- [rope](https://pypi.org/project/rope/) (user-installed)
+
+And a special thanks to [Patryk Zawadzki](https://github.com/patrys) for all of
+his help on [our issue tracker](https://github.com/Microsoft/vscode-python)!
+
+### Enhancements
+
+1. Enable debugging of Jinja templates in the experimental debugger.
+ This is made possible with the addition of the `jinja` setting in the `launch.json` file as follows:
+ ```json
+ "request": "launch or attach",
+ ...
+ "jinja": true
+ ```
+ ([#1206](https://github.com/Microsoft/vscode-python/issues/1206))
+1. Remove empty spaces from the selected text of the active editor when executing in a terminal.
+ ([#1207](https://github.com/Microsoft/vscode-python/issues/1207))
+1. Add prelimnary support for remote debugging using the experimental debugger.
+ Attach to a Python program started using the command `python -m ptvsd --server --port 9091 --file pythonFile.py`
+ ([#1229](https://github.com/Microsoft/vscode-python/issues/1229))
+1. Add support for [logpoints](https://code.visualstudio.com/docs/editor/debugging#_logpoints) in the experimental debugger.
+ ([#1306](https://github.com/Microsoft/vscode-python/issues/1306))
+1. Set focus to the terminal upon creation of a terminal using the `Python: Create Terminal` command.
+ ([#1315](https://github.com/Microsoft/vscode-python/issues/1315))
+1. Save the python file before running it in the terminal using the command/menu `Run Python File in Terminal`.
+ ([#1316](https://github.com/Microsoft/vscode-python/issues/1316))
+1. Added support for source references (remote debugging without having the source code locally) in the experimental debugger.
+ ([#1333](https://github.com/Microsoft/vscode-python/issues/1333))
+1. Add `Ctrl+Enter` keyboard shortcut for `Run Selection/Line in Python Terminal`.
+ ([#1349](https://github.com/Microsoft/vscode-python/issues/1349))
+1. Settings configured within the `debugOptions` property of `launch.json` for the old debugger are now defined as individual (boolean) properties in the new experimental debugger (e.g. `"debugOptions": ["RedirectOutput"]` becomes `"redirectOutput": true`).
+ ([#1395](https://github.com/Microsoft/vscode-python/issues/1395))
+1. Intergrate Jedi 0.12. See https://github.com/davidhalter/jedi/issues/1063#issuecomment-381417297 for details.
+ ([#1400](https://github.com/Microsoft/vscode-python/issues/1400))
+1. Enable Jinja template debugging as a default behaivour when using the Watson debug configuration for debugging of Watson applications.
+ ([#1480](https://github.com/Microsoft/vscode-python/issues/1480))
+1. Enable Jinja template debugging as a default behavior when debugging Pyramid applications.
+ ([#1492](https://github.com/Microsoft/vscode-python/issues/1492))
+1. Add prelimnary support for remote debugging using the experimental debugger.
+ Attach to a Python program after having imported `ptvsd` and enabling the debugger to attach as follows:
+ ```python
+ import ptvsd
+ ptvsd.enable_attach(('0.0.0.0', 5678))
+ ```
+ Additional capabilities:
+ * `ptvsd.break_into_debugger()` to break into the attached debugger.
+ * `ptvsd.wait_for_attach(timeout)` to cause the program to wait untill a debugger attaches.
+ * `ptvsd.is_attached()` to determine whether a debugger is attached to the program.
+ ([#907](https://github.com/Microsoft/vscode-python/issues/907))
+
+### Fixes
+
+1. Use an existing method to identify the active interpreter.
+ ([#1015](https://github.com/Microsoft/vscode-python/issues/1015))
+1. Fix `go to definition` functionality across files.
+ ([#1033](https://github.com/Microsoft/vscode-python/issues/1033))
+1. IntelliSense under Python 2 for inherited attributes works again (thanks to an upgraded Jedi).
+ ([#1072](https://github.com/Microsoft/vscode-python/issues/1072))
+1. Reverted change that ended up considering symlinked interpreters as duplicate interpreter.
+ ([#1192](https://github.com/Microsoft/vscode-python/issues/1192))
+1. Display errors returned by the PipEnv command when identifying the corresonding environment.
+ ([#1254](https://github.com/Microsoft/vscode-python/issues/1254))
+1. When `editor.formatOnType` is on, don't add a space for `*args` or `**kwargs`
+ ([#1257](https://github.com/Microsoft/vscode-python/issues/1257))
+1. When `editor.formatOnType` is on, don't add a space between a string type specifier and the string literal
+ ([#1257](https://github.com/Microsoft/vscode-python/issues/1257))
+1. Reduce the frequency within which the memory usage of the language server is checked, also ensure memory usage is not checked unless language server functionality is used.
+ ([#1277](https://github.com/Microsoft/vscode-python/issues/1277))
+1. Ensure interpreter file exists on the file system before including into list of interpreters.
+ ([#1305](https://github.com/Microsoft/vscode-python/issues/1305))
+1. Do not have the formatter consider single-quoted string multiline even if it is not terminated.
+ ([#1364](https://github.com/Microsoft/vscode-python/issues/1364))
+1. IntelliSense works in module-level `if` statements (thanks to Jedi 0.12.0 upgrade).
+ ([#142](https://github.com/Microsoft/vscode-python/issues/142))
+1. Clicking the codelens `Run Test` on a test class should run that specific test class instead of all tests in the file.
+ ([#1472](https://github.com/Microsoft/vscode-python/issues/1472))
+1. Clicking the codelens `Run Test` on a test class or method should run that specific test instead of all tests in the file.
+ ([#1473](https://github.com/Microsoft/vscode-python/issues/1473))
+1. Check whether the selected python interpreter is valid before starting the language server. Failing to do so could result in the extension failing to load.
+ ([#1487](https://github.com/Microsoft/vscode-python/issues/1487))
+1. Fixes the issue where Conda environments created using the latest version of Anaconda are not activated in Powershell.
+ ([#1520](https://github.com/Microsoft/vscode-python/issues/1520))
+1. Increase the delay for the activation of environments in Powershell terminals.
+ ([#1533](https://github.com/Microsoft/vscode-python/issues/1533))
+1. Fix activation of environments with spaces in the python path when using Powershell.
+ ([#1534](https://github.com/Microsoft/vscode-python/issues/1534))
+1. Ensure Flask application is launched with multi-threading disabled, when run in the CI tests.
+ ([#1535](https://github.com/Microsoft/vscode-python/issues/1535))
+1. IntelliSense works appropriately when a project contains multiple files with the same name (thanks to Jedi 0.12.0 update).
+ ([#178](https://github.com/Microsoft/vscode-python/issues/178))
+1. Add blank lines to separate blocks of indented code (function defs, classes, and the like) so as to ensure the code can be run within a Python interactive prompt.
+ ([#259](https://github.com/Microsoft/vscode-python/issues/259))
+1. Provide type details appropriate for the iterable in a `for` loop when the line has a `# type` comment.
+ ([#338](https://github.com/Microsoft/vscode-python/issues/338))
+1. Parameter hints following an f-string work again.
+ ([#344](https://github.com/Microsoft/vscode-python/issues/344))
+1. When `editor.formatOnType` is on, don't indent after a single-line statement block
+ ([#726](https://github.com/Microsoft/vscode-python/issues/726))
+1. Fix debugging of Pyramid applications on Windows.
+ ([#737](https://github.com/Microsoft/vscode-python/issues/737))
+
+### Code Health
+
+1. Improved developer experience of the Python Extension on Windows.
+ ([#1216](https://github.com/Microsoft/vscode-python/issues/1216))
+1. Parallelize jobs (unit tests) on CI server.
+ ([#1247](https://github.com/Microsoft/vscode-python/issues/1247))
+1. Run CI tests against the release version and master branch of PTVSD (experimental debugger), allowing tests to fail against the master branch of PTVSD.
+ ([#1253](https://github.com/Microsoft/vscode-python/issues/1253))
+1. Only trigger the extension for `file` and `untitled` in preparation for
+ [Visual Studio Live Share](https://aka.ms/vsls)
+ (thanks to [Jonathan Carter](https://github.com/lostintangent))
+ ([#1298](https://github.com/Microsoft/vscode-python/issues/1298))
+1. Ensure all unit tests run on Travis use the right Python interpreter.
+ ([#1318](https://github.com/Microsoft/vscode-python/issues/1318))
+1. Pin all production dependencies.
+ ([#1374](https://github.com/Microsoft/vscode-python/issues/1374))
+1. Add support for [hit count breakpoints](https://code.visualstudio.com/docs/editor/debugging#_advanced-breakpoint-topics) in the experimental debugger.
+ ([#1409](https://github.com/Microsoft/vscode-python/issues/1409))
+1. Ensure custom environment variables defined in `.env` file are passed onto the `pipenv` command.
+ ([#1428](https://github.com/Microsoft/vscode-python/issues/1428))
+1. Remove unwanted python packages no longer used in unit tests.
+ ([#1494](https://github.com/Microsoft/vscode-python/issues/1494))
+1. Register language server functionality in the extension against specific resource types supporting the python language.
+ ([#1530](https://github.com/Microsoft/vscode-python/issues/1530))
+
+
+## 2018.3.1 (29 Mar 2018)
+
+### Fixes
+
+1. Fixes issue that causes linter to fail when file path contains spaces.
+([#1239](https://github.com/Microsoft/vscode-python/issues/1239))
+
+## 2018.3.0 (28 Mar 2018)
+
+### Enhancements
+
+1. Add a PySpark debug configuration for the experimental debugger.
+ ([#1029](https://github.com/Microsoft/vscode-python/issues/1029))
+1. Add a Pyramid debug configuration for the experimental debugger.
+ ([#1030](https://github.com/Microsoft/vscode-python/issues/1030))
+1. Add a Watson debug configuration for the experimental debugger.
+ ([#1031](https://github.com/Microsoft/vscode-python/issues/1031))
+1. Add a Scrapy debug configuration for the experimental debugger.
+ ([#1032](https://github.com/Microsoft/vscode-python/issues/1032))
+1. When using pipenv, install packages (such as linters, test frameworks) in dev-packages.
+ ([#1110](https://github.com/Microsoft/vscode-python/issues/1110))
+1. Added commands translation for italian locale.
+(thanks [Dotpys](https://github.com/Dotpys/)) ([#1152](https://github.com/Microsoft/vscode-python/issues/1152))
+1. Add support for Django Template debugging in experimental debugger.
+ ([#1189](https://github.com/Microsoft/vscode-python/issues/1189))
+1. Add support for Flask Template debugging in experimental debugger.
+ ([#1190](https://github.com/Microsoft/vscode-python/issues/1190))
+1. Add support for Jinja template debugging. ([#1210](https://github.com/Microsoft/vscode-python/issues/1210))
+1. When debugging, use `Integrated Terminal` as the default console.
+ ([#526](https://github.com/Microsoft/vscode-python/issues/526))
+1. Disable the display of errors messages when rediscovering of tests fail in response to changes to files, e.g. don't show a message if there's a syntax error in the test code.
+ ([#704](https://github.com/Microsoft/vscode-python/issues/704))
+1. Bundle python depedencies (PTVSD package) in the extension for the experimental debugger.
+ ([#741](https://github.com/Microsoft/vscode-python/issues/741))
+1. Add support for expermental debugger when debugging Python Unit Tests.
+ ([#906](https://github.com/Microsoft/vscode-python/issues/906))
+1. Support `Debug Console` as a `console` option for the Experimental Debugger.
+ ([#950](https://github.com/Microsoft/vscode-python/issues/950))
+1. Enable syntax highlighting for `requirements.in` files as used by
+e.g. [pip-tools](https://github.com/jazzband/pip-tools)
+(thanks [Lorenzo Villani](https://github.com/lvillani))
+ ([#961](https://github.com/Microsoft/vscode-python/issues/961))
+1. Add support to read name of Pipfile from environment variable.
+ ([#999](https://github.com/Microsoft/vscode-python/issues/999))
+
+### Fixes
+
+1. Fixes issue that causes debugging of unit tests to hang indefinitely. ([#1009](https://github.com/Microsoft/vscode-python/issues/1009))
+1. Add ability to disable the check on memory usage of language server (Jedi) process.
+To turn off this check, add `"python.jediMemoryLimit": -1` to your user or workspace settings (`settings.json`) file.
+ ([#1036](https://github.com/Microsoft/vscode-python/issues/1036))
+1. Ignore test results when debugging unit tests.
+ ([#1043](https://github.com/Microsoft/vscode-python/issues/1043))
+1. Fixes auto formatting of conditional statements containing expressions with `<=` symbols.
+ ([#1096](https://github.com/Microsoft/vscode-python/issues/1096))
+1. Resolve debug configuration information in `launch.json` when debugging without opening a python file.
+ ([#1098](https://github.com/Microsoft/vscode-python/issues/1098))
+1. Disables auto completion when editing text at the end of a comment string.
+ ([#1123](https://github.com/Microsoft/vscode-python/issues/1123))
+1. Ensures file paths are properly encoded when passing them as arguments to linters.
+ ([#199](https://github.com/Microsoft/vscode-python/issues/199))
+1. Fix occasionally having unverified breakpoints
+ ([#87](https://github.com/Microsoft/vscode-python/issues/87))
+1. Ensure conda installer is not used for non-conda environments.
+ ([#969](https://github.com/Microsoft/vscode-python/issues/969))
+1. Fixes issue that display incorrect interpreter briefly before updating it to the right value.
+ ([#981](https://github.com/Microsoft/vscode-python/issues/981))
+
+### Code Health
+
+1. Exclude 'news' folder from getting packaged into the extension.
+ ([#1020](https://github.com/Microsoft/vscode-python/issues/1020))
+1. Remove Jupyter commands.
+(thanks [Yu Zhang](https://github.com/neilsustc))
+ ([#1034](https://github.com/Microsoft/vscode-python/issues/1034))
+1. Trigger incremental build compilation only when typescript files are modified.
+ ([#1040](https://github.com/Microsoft/vscode-python/issues/1040))
+1. Updated npm dependencies in devDependencies and fix TypeScript compilation issues.
+ ([#1042](https://github.com/Microsoft/vscode-python/issues/1042))
+1. Enable unit testing of stdout and stderr redirection for the experimental debugger.
+ ([#1048](https://github.com/Microsoft/vscode-python/issues/1048))
+1. Update npm package `vscode-extension-telemetry` to fix the warning 'os.tmpDir() deprecation'.
+(thanks [osya](https://github.com/osya))
+ ([#1066](https://github.com/Microsoft/vscode-python/issues/1066))
+1. Prevent the debugger stepping into JS code while developing the extension when debugging async TypeScript code.
+ ([#1090](https://github.com/Microsoft/vscode-python/issues/1090))
+1. Increase timeouts for the debugger unit tests.
+ ([#1094](https://github.com/Microsoft/vscode-python/issues/1094))
+1. Change the command used to install pip on AppVeyor to avoid installation errors.
+ ([#1107](https://github.com/Microsoft/vscode-python/issues/1107))
+1. Check whether a document is active when detecthing changes in the active document.
+ ([#1114](https://github.com/Microsoft/vscode-python/issues/1114))
+1. Remove SIGINT handler in debugger adapter, thereby preventing it from shutting down the debugger.
+ ([#1122](https://github.com/Microsoft/vscode-python/issues/1122))
+1. Improve compilation speed of the extension's TypeScript code.
+ ([#1146](https://github.com/Microsoft/vscode-python/issues/1146))
+1. Changes to how debug options are passed into the experimental version of PTVSD (debugger).
+ ([#1168](https://github.com/Microsoft/vscode-python/issues/1168))
+1. Ensure file paths are not sent in telemetry when running unit tests.
+ ([#1180](https://github.com/Microsoft/vscode-python/issues/1180))
+1. Change `DjangoDebugging` to `Django` in `debugOptions` of launch.json.
+ ([#1198](https://github.com/Microsoft/vscode-python/issues/1198))
+1. Changed property name used to capture the trigger source of Unit Tests. ([#1213](https://github.com/Microsoft/vscode-python/issues/1213))
+1. Enable unit testing of the experimental debugger on CI servers
+ ([#742](https://github.com/Microsoft/vscode-python/issues/742))
+1. Generate code coverage for debug adapter unit tests.
+ ([#778](https://github.com/Microsoft/vscode-python/issues/778))
+1. Execute prospector as a module (using -m).
+ ([#982](https://github.com/Microsoft/vscode-python/issues/982))
+1. Launch unit tests in debug mode as opposed to running and attaching the debugger to the already-running interpreter.
+ ([#983](https://github.com/Microsoft/vscode-python/issues/983))
+
+## 2018.2.1 (09 Mar 2018)
+
+### Fixes
+
+1. Check for `Pipfile` and not `pipfile` when looking for pipenv usage
+ (thanks to [Will Thompson for the fix](https://github.com/wjt))
+
## 2018.2.0 (08 Mar 2018)
[Release pushed by one week]
@@ -717,4 +1374,3 @@ the following people who contributed code:
## Version 0.0.3
* Added support for debugging using PDB
-
diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md
index bafa2de536e7..1a1a8bfc401e 100644
--- a/CODING_STANDARDS.md
+++ b/CODING_STANDARDS.md
@@ -1,5 +1,5 @@
## Coding guidelines for TypeScript
-* The following standards are inspired from [Coding guidelines for TypeScript](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines).
+* The following standards are inspired from [Coding guidelines for TypeScript](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines) (which you should follow when something is not specified in this document, although any pre-existing practices in a file being edited trump either style guide).
### Names
@@ -31,6 +31,11 @@ Use undefined. Do not use null.
Use single quotes for strings.
+### Imports
+
+* Use ES6 module imports.
+* Do not use bare `import *`; all imports should either explicitly pull in an object or import an entire module, otherwise you're implicitly polluting the global namespace and making it difficult to figure out from code examination where a name originates from.
+
### Style
* Use arrow functions over anonymous function expressions.
diff --git a/CONTRIBUTING - LANGUAGE SERVER.md b/CONTRIBUTING - LANGUAGE SERVER.md
new file mode 100644
index 000000000000..7c363ce23b81
--- /dev/null
+++ b/CONTRIBUTING - LANGUAGE SERVER.md
@@ -0,0 +1,63 @@
+# Contributing to Microsoft Python Language Server
+[]
+
+[](https://travis-ci.org/Microsoft/vscode-python) [](https://ci.appveyor.com/project/DonJayamanne/vscode-python-v3vd6) [](https://codecov.io/gh/Microsoft/vscode-python)
+
+
+## Contributing a pull request
+
+### Prerequisites
+
+1. .NET Core 2.1 SDK
+ - [Windows](https://www.microsoft.com/net/learn/get-started/windows)
+ - [Mac OS](https://www.microsoft.com/net/learn/get-started/macos)
+ - [Linux](https://www.microsoft.com/net/learn/get-started/linux/rhel)
+2. C# Extension to VS Code (all platforms)
+3. Python 2.7
+4. Python 3.6
+
+*Alternative:* [Visual Studio 2017](https://www.visualstudio.com/downloads/) (Windows only) with .NET Core and C# Workloads. Community Edition is free and is fully functional.
+
+### Setup
+
+```shell
+git clone https://github.com/microsoft/ptvs
+cd ptvs/Python/Product/VSCode/AnalysisVsc
+dotnet build
+```
+
+Visual Studio 2017:
+1. Open solution in Python/Product/VsCode
+2. Build AnalysisVsc project
+3. Binaries arrive in *Python/BuildOutput/VsCode/raw*
+4. Delete contents of the *languageServer* folder in the Python Extension folder
+5. Copy *.dll, *.pdb, *.json fron *Python/BuildOutput/VsCode/raw* to *languageServer*
+6. In VS Code set setting *python.downloadLanguageServer* to *false*
+7. In VS Code set setting *python.jediEnabled* to *false*
+
+### Debugging code in Python Extension to VS Code
+Folow regular TypeScript debugging steps
+
+### Debugging C# code in Python Analysis Engine
+1. Launch another instance of VS Code
+2. Open Python/Product/VsCode/AnalysisVsc folder
+3. Python Analysis Engine code is in *Python/Product/VsCode/Analysis*
+4. Run extension from VS Code
+5. In the instance with C# code select Dotnet Attach launch task.
+6. Attach to *dotnet* process running *Microsoft.Python.languageServer.dll*
+
+On Windows you can also attach from Visual Studio 2017.
+
+### Validate your changes
+
+1. Build C# code
+2. Copy binaries to *analysis* folder
+3. Use the `Launch Extension` launch option.
+
+### Unit Tests
+1. Run the Unit Tests via the `Launch Analysis Engine Tests`.
+2. On Windows you can also open complete PTVS solution in Visual Studio and run its tests (or at least the Analysis section).
+
+
+### Coding Standards
+See []
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ef238b941add..14bee772eea4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,14 +1,23 @@
# Contributing to the Python extension for Visual Studio Code
-[](https://travis-ci.org/Microsoft/vscode-python) [](https://ci.appveyor.com/project/DonJayamanne/vscode-python-v3vd6) [](https://codecov.io/gh/Microsoft/vscode-python)
+---
+
+| macOS/Windows CI | Linux CI | Rolling CI (macOS/Windows) | Code Coverage |
+|-|-|-|-|
+|[](https://vscode-python.visualstudio.com/VSCode-Python/_build/latest?definitionId=4) | [](https://travis-ci.org/Microsoft/vscode-python) | [](https://vscode-python.visualstudio.com/VSCode-Python/_build/latest?definitionId=9) | [](https://codecov.io/gh/Microsoft/vscode-python)|
+---
+
+# Contributing to Microsoft Python Analysis Engine
+[Contributing to Python Analysis Engine](https://github.com/Microsoft/vscode-python/blob/master/CONTRIBUTING%20-%20PYTHON_ANALYSIS.md)
+
## Contributing a pull request
### Prerequisites
-1. Node.js (>= 8.9.1, < 9.0.0), and [Yarn](https://yarnpkg.com/lang/en/docs/install/)
+1. Node.js (>= 8.9.1, < 9.0.0)
2. Python 2.7 or later (required only for testing the extension and running unit tests)
3. Windows, macOS, or Linux
4. Visual Studio Code
@@ -19,16 +28,16 @@
### Setup
```shell
-git clone https://github.com/microsoft/vscode-python
+git clone --recurse-submodules https://github.com/microsoft/vscode-python
cd vscode-python
-yarn install
+npm install
```
You may see warnings that ```The engine "vscode" appears to be invalid.```, you can ignore these.
### Incremental Build
-Run the `Compile` build Tasks from the [Command Palette](https://code.visualstudio.com/docs/editor/tasks) (short cut `CTRL+SHIFT+B` or `⇧⌘B`)
+Run the `Compile` and `Hygiene` build Tasks from the [Command Palette](https://code.visualstudio.com/docs/editor/tasks) (short cut `CTRL+SHIFT+B` or `⇧⌘B`)
### Errors and Warnings
@@ -88,73 +97,60 @@ person to do (long term this project aims to automate as much of the
development process as possible). The current issues being worked on
for a release are tracked in a
[milestone](https://github.com/Microsoft/vscode-python/milestones)
-(which is actively updated as plans change).
+(which is actively updated as plans change). All
+[P0](https://github.com/Microsoft/vscode-python/labels/P0) are expected to
+be fixed in a milestone, else the release will be blocked.
+[P1](https://github.com/Microsoft/vscode-python/labels/P1) issues are a
+top-priority in a milestone, but if they are not completed they will not
+block a milestone. All other issues are considered best-effort for that
+milestone.
The overall schedule for a release is to feature freeze for on the last
Monday of the month to coincide with Visual Studio Code's code freeze.
We then aim to release later that week so the latest version of the
-extension is already live by the time Visual Studio Code launches
-their new release. This is so we are ready to use any new features
+extension is already live by the time Visual Studio Code does their
+release the following week. This is so we are ready to use any new features
of Visual Studio Code the day they go live. We do bugfix-only releases
-between scheduled releases as necessary.
+between scheduled releases as necessary, but otherwise we aim to do one
+release a month.
All development is actively done in the `master` branch of the
-repository. It is what allows us to have an
-[insiders build](#insiders-build) which is expected to be stable at
+repository. It is what allows us to have a
+[development build](#development-build) which is expected to be stable at
all times. We do keep the most recent release as a branch in case the
need for a bugfix release arises. But once a new release is made we
delete the older release branch (all releases are appropriately
-tagged, so history is lost).
+tagged, so no history is lost).
### Issue triaging
-To help actively track what stage issues are at, various labels are
-used. Which labels are expected to be set vary from when an issue is
-open to when an issue is closed.
-
-#### Open issues
-
-When an
-[issue is first opened](https://github.com/Microsoft/vscode-python/issues),
-it is triaged to contain at least three types of labels:
+To help actively track what stage
+[issues](https://github.com/Microsoft/vscode-python/issues)
+are at, various labels are used. The following label types are expected to
+be set on all open issues (otherwise the issue is not considered triaged):
1. `needs`
1. `feature`
1. `type`
-These labels cover what is blocking the issue from closing, what
-feature(s) of the extension are related to the issue, and what type of
-issue it is, respectively.
+These labels cover what is blocking the issue from closing, what is affected by
+the issue, and what kind of issue it is.
#### Closed issues
-When an
-[issue is closed](https://github.com/Microsoft/vscode-python/issues?q=is%3Aissue+is%3Aclosed),
-it should have an appropriate `closed-` label.
+When an issue is closed by a pull request we add a
+[`validate fix`](https://github.com/Microsoft/vscode-python/issues?q=label%3A%22validate+fix%22+is%3Aclosed)
+label in order to request people help us test the fix to validate the issue was
+resolved successfully. Once the fix has been manually validated we remove the label.
### Pull request workflow
-1. Check that there is an issue corresponding to what the pull request
- is attempting to address
- * If an issue exists, make sure it has reached the stage of
- `awaiting 2-PR`
- * If no issue exists, open one and wait for it to reach the
- `awaiting 2-PR` stage before submitting the pull request
-1. Create the pull request, mentioning the appropriate issue(s) in the
- pull request message body
- * The pull request is expected to have appropriate unit tests
- * The pull request must pass its CI run before merging will be
- considered
- * Code coverage is expected to (at minimum) not worsen
- * A [news entry file](https://github.com/Microsoft/vscode-python/tree/master/news) (as appropriate)
-1. Make sure all status checks are green (e.g. CLA check, CI, etc.)
-1. Address any review comments
-1. [Maintainers only] Merge the pull request
-1. [Maintainers only] Update affected issues to be:
- 1. Closed (with an appropriate `closed-` label)
- 1. The issue(s) are attached to the current milestone
- 1. Register OSS usage
- 1. Email CELA about any 3rd-party usage changes
+Key details that all pull requests are expected to handle should be
+in the PR template. The only key detail not covered in that template is
+that any change in our dependencies must be properly reflected in our
+third-party notices file and registered with the OSPO internally at
+Microsoft (obviously external developers do not need to concern themselves
+with these legal/technical issues).
### Versioning
@@ -176,8 +172,7 @@ build of the extension onto a cloud storage provider.
If you are interested in helping us test our development builds or would like
to stay ahead of the curve, then please feel free to download and install the
extension from the following
-[location](https://pvsc.blob.core.windows.net/extension-builds/ms-python-insiders.vsix)
-(if the CI build is passing: [](https://travis-ci.org/Microsoft/vscode-python)).
+[location](https://pvsc.blob.core.windows.net/extension-builds/ms-python-insiders.vsix).
Once you have downloaded the
[ms-python-insiders.vsix](https://pvsc.blob.core.windows.net/extension-builds/ms-python-insiders.vsix)
file, please follow the instructions on
diff --git a/README.md b/README.md
index 46915398f950..ae7464ae31c1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Python extension for Visual Studio Code
-A [Visual Studio Code](https://code.visualstudio.com/) [extension](https://marketplace.visualstudio.com/VSCode) with rich support for the [Python language](https://www.python.org/) (_including Python 3.6_), including features such as linting, debugging, IntelliSense, code navigation, code formatting, refactoring, unit tests, snippets, and more!
+A [Visual Studio Code](https://code.visualstudio.com/) [extension](https://marketplace.visualstudio.com/VSCode) with rich support for the [Python language](https://www.python.org/) (2.7, >=3.4), including features such as linting, debugging, IntelliSense, code navigation, code formatting, refactoring, unit tests, snippets, and more!
## Quick start
@@ -37,11 +37,15 @@ To see all available Python commands, open the Command Palette and type ```Pytho
The extension is available in multiple languages thanks to external
contributors (if you would like to contribute a translation, see the
-[pull request which added simplified Chinese](https://github.com/Microsoft/vscode-python/pull/240)):
+[pull request which added Italian](https://github.com/Microsoft/vscode-python/pull/1152)):
* `en`
+* `es`
+* `fr`
+* `it`
* `ja`
* `ko-kr`
+* `pt-br`
* `ru`
* `zh-cn`
* `zh-tw`
@@ -54,6 +58,7 @@ contributors (if you would like to contribute a translation, see the
* Any and all feedback is appreciated and welcome!
- If someone has already [file an issue](https://github.com/Microsoft/vscode-python) that encompasses your feedback, please leave a 👍/👎 reaction on the issue
- Otherwise please file a new issue
+* If you're interested in the development of the extension, you can read about our [development process](https://github.com/Microsoft/vscode-python/blob/master/CONTRIBUTING.md#development-process)
## Feature details
@@ -67,9 +72,9 @@ contributors (if you would like to contribute a translation, see the
+ Ability to include custom module paths (e.g. include paths for libraries like Google App Engine, etc.; use the setting `python.autoComplete.extraPaths = []`)
* Code formatting
+ Auto formatting of code upon saving changes (default to 'Off')
- + Use either [yapf](https://pypi.io/project/yapf/) or [autopep8](https://pypi.io/project/autopep8/) for code formatting (defaults to autopep8)
+ + Use either [yapf](https://pypi.org/project/yapf/), [autopep8](https://pypi.org/project/autopep8/), or [Black](https://pypi.org/project/black/) for code formatting (defaults to autopep8)
* Linting
- + Support for multiple linters with custom settings (default is [Pylint](https://pypi.io/project/pylint/), but [Prospector](https://pypi.io/project/prospector/), [pycodestyle](https://pypi.io/project/pycodestyle/), [Flake8](https://pypi.io/project/flake8/), [pylama](https://github.com/klen/pylama), [pydocstyle](https://pypi.io/project/pydocstyle/), and [mypy](http://mypy-lang.org/) are also supported)
+ + Support for multiple linters with custom settings (default is [Pylint](https://pypi.org/project/pylint/), but [Prospector](https://pypi.org/project/prospector/), [Flake8](https://pypi.org/project/flake8/), [pylama](https://pypi.org/project/pylama/), [pydocstyle](https://pypi.org/project/pydocstyle/), and [mypy](https://pypi.org/project/mypy/) are also supported)
* Debugging
+ Watch window
+ Evaluate expressions
@@ -85,7 +90,7 @@ contributors (if you would like to contribute a translation, see the
+ Debugging in the integrated or external terminal window
+ Debugging as sudo
* Unit testing
- + Support for [unittest](https://docs.python.org/3/library/unittest.html#module-unittest), [pytest](https://pypi.io/project/pytest/), and [nose](https://pypi.io/project/nose/)
+ + Support for [unittest](https://docs.python.org/3/library/unittest.html#module-unittest), [pytest](https://pypi.org/project/pytest/), and [nose](https://pypi.org/project/nose/)
+ Ability to run all failed tests, individual tests
+ Debugging unit tests
* Snippets
diff --git a/ThirdPartyNotices-Distribution.txt b/ThirdPartyNotices-Distribution.txt
index 3b8e433c8a9b..762ca4aa3577 100644
--- a/ThirdPartyNotices-Distribution.txt
+++ b/ThirdPartyNotices-Distribution.txt
@@ -1,53 +1,67 @@
-
+
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
Microsoft Python extension for Visual Studio Code incorporates components from the projects listed below. Microsoft licenses these components to you under Microsoft's licensing terms for the Microsoft Python extension for Visual Studio Code. The original copyright notices and the licenses under which Microsoft received such components are set forth below for informational purposes. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise.
-
1. Arch (https://github.com/feross/arch)
2. diff-match-patch (https://github.com/ForbesLindesay-Unmaintained/diff-match-patch)
-3. Files from the Python Project (https://www.python.org/)
-4. fuzzy (https://github.com/mattyork/fuzzy)
-5. Get-port (https://github.com/sindresorhus/get-port)
-6. Go for Visual Studio Code (https://github.com/Microsoft/vscode-go)
-7. Google Diff Match and Patch (https://github.com/GerHobbelt/google-diff-match-patch)
-8. Iconv-lite (https://github.com/ashtuchkin/iconv-lite)
-9. Inversify (https://github.com/inversify/InversifyJS)
-10. isort (https://github.com/timothycrosley/isort)
-11. jedi (https://github.com/davidhalter/jedi)
-12. line-by-line (https://github.com/Osterjour/line-by-line)
-13. lodash (https://github.com/lodash/lodash)
+3. dotenv (https://github.com/motdotla/dotenv)
+4. Files from the Python Project (https://www.python.org/)
+5. fuzzy (https://github.com/mattyork/fuzzy)
+6. Get-port (https://github.com/sindresorhus/get-port)
+7. Glob (https://github.com/isaacs/node-glob)
+8. Go for Visual Studio Code (https://github.com/Microsoft/vscode-go)
+9. Google Diff Match and Patch (https://github.com/GerHobbelt/google-diff-match-patch)
+10. Iconv-lite (https://github.com/ashtuchkin/iconv-lite)
+11. Inversify (https://github.com/inversify/InversifyJS)
+12. isort (https://github.com/timothycrosley/isort)
+13. jedi (https://github.com/davidhalter/jedi)
+14. line-by-line (https://github.com/Osterjour/line-by-line)
+15. lodash (https://github.com/lodash/lodash)
Includes:Sizzle CSS Selector Engine
Includes:Webpack
-14. MD5 (https://github.com/pvorb/node-md5)
-15. minimatch (https://github.com/isaacs/minimatch)
-16. named-js-regexp (https://github.com/edvinv/named-js-regexp)
-17. node-fs-extra (https://github.com/jprichardson/node-fs-extra)
-18. node-semver (https://github.com/npm/node-semver)
-19. node-tmp (https://github.com/raszi/node-tmp)
-20. node-tree-kill (https://github.com/pkrumins/node-tree-kill)
-21. node-winreg (https://github.com/fresc81/node-winreg)
-22. node-xml2js (https://github.com/Leonidas-from-XIV/node-xml2js)
-23. omnisharp-vscode (https://github.com/OmniSharp/omnisharp-vscode)
-24. opn (https://github.com/sindresorhus/opn)
-25. pidusage (https://github.com/soyuka/pidusage)
-26. Python documentation (https://docs.python.org/)
-27. python-functools32 (https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py)
-28. pythonVSCode (https://github.com/DonJayamanne/pythonVSCode)
-29. Reflect-metadata (https://github.com/rbuckton/reflect-metadata)
-30. RxJS (https://github.com/ReactiveX/RxJS)
+16. MD5 (https://github.com/pvorb/node-md5)
+17. minimatch (https://github.com/isaacs/minimatch)
+18. named-js-regexp (https://github.com/edvinv/named-js-regexp)
+19. node-fs-extra (https://github.com/jprichardson/node-fs-extra)
+20. node-semver (https://github.com/npm/node-semver)
+21. node-stream-zip (https://github.com/antelle/node-stream-zip)
+22. node-tmp (https://github.com/raszi/node-tmp)
+23. node-tree-kill (https://github.com/pkrumins/node-tree-kill)
+24. node-winreg (https://github.com/fresc81/node-winreg)
+25. node-xml2js (https://github.com/Leonidas-from-XIV/node-xml2js)
+26. omnisharp-vscode (https://github.com/OmniSharp/omnisharp-vscode)
+27. opn (https://github.com/sindresorhus/opn)
+28. pidusage (https://github.com/soyuka/pidusage)
+29. PTVS (https://github.com/Microsoft/PTVS)
+30. PTVSD (https://github.com/Microsoft/PTVSD)
+31. PyDev.Debugger (https://github.com/fabioz/PyDev.Debugger)
+ Includes:Files copyright Yuli Fitterman
+ Includes:IPython
+ Includes:py2app
+ Includes:Python (various files)
+32. Python documentation (https://docs.python.org/)
+33. python-functools32 (https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py)
+34. pythonVSCode (https://github.com/DonJayamanne/pythonVSCode)
+35. Reflect-metadata (https://github.com/rbuckton/reflect-metadata)
+36. request (https://github.com/request/request)
+37. request-progress (https://github.com/IndigoUnited/node-request-progress)
+38. RxJS (https://github.com/ReactiveX/RxJS)
Includes:Contributor Covenant v1.1.0, v1.4
Includes:File from Angular.io
Includes:File from setImmediate
-31. Sphinx (http://sphinx-doc.org/)
-32. uint64be (https://github.com/mafintosh/uint64be)
-33. untildify (https://github.com/sindresorhus/untildify)
-34. vscode-debugadapter (https://github.com/Microsoft/vscode-debugadapter-node/tree/master/adapter)
-35. vscode-debugprotocol (https://github.com/Microsoft/vscode-debugadapter-node/tree/master/protocol)
-36. vscode-extension-telemetry (https://github.com/Microsoft/vscode-extension-telemetry)
-37. vscode-languageclient (https://github.com/Microsoft/vscode-languageserver-node)
-38. vscode-languageserver (https://github.com/Microsoft/vscode-languageserver-node/)
+39. Sphinx (http://sphinx-doc.org/)
+40. sudo-prompt (https://github.com/jorangreef/sudo-prompt)
+41. uint64be (https://github.com/mafintosh/uint64be)
+42. untangle (https://github.com/stchris/untangle)
+43. untildify (https://github.com/sindresorhus/untildify)
+44. vscode-debugadapter (https://github.com/Microsoft/vscode-debugadapter-node/tree/master/adapter)
+45. vscode-debugprotocol (https://github.com/Microsoft/vscode-debugadapter-node/tree/master/protocol)
+46. vscode-extension-telemetry (https://github.com/Microsoft/vscode-extension-telemetry)
+47. vscode-languageclient (https://github.com/Microsoft/vscode-languageserver-node)
+48. vscode-languageserver (https://github.com/Microsoft/vscode-languageserver-node/)
+49. Typeshed (https://github.com/python/typeshed/tree/95eff73ab2092f2c3158198d404a921447172418)
%% Arch NOTICES AND INFORMATION BEGIN HERE
@@ -94,6 +108,35 @@ limitations under the License.
=========================================
END OF diff-match-patch NOTICES AND INFORMATION
+%% dotenv NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Copyright (c) 2015, Scott Motte
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================
+END OF dotenv NOTICES AND INFORMATION
+
%% Files from the Python Project NOTICES AND INFORMATION BEGIN HERE
=========================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -333,6 +376,26 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
=========================================
END OF Get-port NOTICES AND INFORMATION
+%% Glob NOTICES AND INFORMATION BEGIN HERE
+=========================================
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+=========================================
+END OF Glob NOTICES AND INFORMATION
+
%%
Go for Visual Studio Code NOTICES AND INFORMATION BEGIN HERE
=========================================
@@ -745,6 +808,55 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
=========================================
END OF node-semver NOTICES AND INFORMATION
+%% node-stream-zip NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Copyright (c) 2015 Antelle https://github.com/antelle
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+== dependency license: adm-zip ==
+
+Copyright (c) 2012 Another-D-Mention Software and other contributors,
+http://www.another-d-mention.ro/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+=========================================
+END OF node-stream-zip NOTICES AND INFORMATION
+
%% node-tmp NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
@@ -774,7 +886,9 @@ END OF node-tmp NOTICES AND INFORMATION
%% node-tree-kill NOTICES AND INFORMATION BEGIN HERE
=========================================
-Copyright (c) 2014 Peteris Krumins
+MIT License
+
+Copyright (c) 2018 Peter Krumins
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -898,6 +1012,520 @@ SOFTWARE.
=========================================
END OF pidusage NOTICES AND INFORMATION
+%% PTVS NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+=========================================
+END OF PTVS NOTICES AND INFORMATION
+
+%% PTVSD NOTICES AND INFORMATION BEGIN HERE
+=========================================
+ ptvsd
+
+ Copyright (c) Microsoft Corporation
+ All rights reserved.
+
+ MIT License
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+=========================================
+END OF PTVSD NOTICES AND INFORMATION
+
+%% PyDev.Debugger NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+ distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates'
+ from a Contributor if it was added to the Program by such Contributor
+ itself or anyone acting on such Contributor's behalf. Contributions do not
+ include additions to the Program which: (i) are separate modules of
+ software distributed in conjunction with the Program under their own
+ license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly
+ perform, distribute and sublicense the Contribution of such Contributor,
+ if any, and such derivative works, in source code and object code form.
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of
+ the Contribution and the Program if, at the time the Contribution is
+ added by the Contributor, such addition of the Contribution causes such
+ combination to be covered by the Licensed Patents. The patent license
+ shall not apply to any other combinations which include the Contribution.
+ No hardware per se is licensed hereunder.
+ c) Recipient understands that although each Contributor grants the licenses
+ to its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor
+ disclaims any liability to Recipient for claims brought by any other
+ entity based on infringement of intellectual property rights or
+ otherwise. As a condition to exercising the rights and licenses granted
+ hereunder, each Recipient hereby assumes sole responsibility to secure
+ any other intellectual property rights needed, if any. For example, if a
+ third party patent license is required to allow Recipient to distribute
+ the Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+ b) its license agreement:
+ i) effectively disclaims on behalf of all Contributors all warranties
+ and conditions, express and implied, including warranties or
+ conditions of title and non-infringement, and implied warranties or
+ conditions of merchantability and fitness for a particular purpose;
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits;
+ iii) states that any provisions which differ from this Agreement are
+ offered by that Contributor alone and not by any other party; and
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+ b) a copy of this Agreement must be included with each copy of the Program.
+ Contributors may not remove or alter any copyright notices contained
+ within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution,
+if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore,
+if a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits and
+other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such Commercial
+Contributor in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any claims
+or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must:
+a) promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such claim at
+its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If
+that Commercial Contributor then makes performance claims, or offers
+warranties related to Product X, those performance claims and warranties are
+such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to the
+risks and costs of program errors, compliance with applicable laws, damage to
+or loss of data, programs or equipment, and unavailability or interruption of
+operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by the
+parties hereto, such provision shall be reformed to the minimum extent
+necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted
+under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to
+time. No one other than the Agreement Steward has the right to modify this
+Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+Eclipse Foundation may assign the responsibility to serve as the Agreement
+Steward to a suitable separate entity. Each new version of the Agreement will
+be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version of the
+Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly
+stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+licenses to the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in the
+Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
+=========================================
+Includes files copyright Yuli Fitterman
+
+Copyright (c) Yuli Fitterman
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=========================================
+Includes Ipython
+
+Copyright (c) 2008-2010, IPython Development Team
+Copyright (c) 2001-2007, Fernando Perez.
+Copyright (c) 2001, Janko Hauser
+Copyright (c) 2001, Nathaniel Gray
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of the IPython Development Team nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+=========================================
+Includes py2app
+
+This is the MIT license. This software may also be distributed under the same terms as Python (the PSF license).
+
+Copyright (c) 2004 Bob Ippolito.
+
+Some parts copyright (c) 2010-2014 Ronald Oussoren
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+=========================================
+Includes lib2to3 and other Python files
+
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+analyze, test, perform and/or display publicly, prepare derivative works,
+distribute, and otherwise use Python alone or in any derivative version,
+provided, however, that PSF's License Agreement and PSF's notice of copyright,
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+2011, 2012 Python Software Foundation; All Rights Reserved" are retained in Python
+alone or in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions. Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee. This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party. As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee. Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement. This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013. This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee. This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+ ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+=========================================
+END OF PyDev.Debugger NOTICES AND INFORMATION
+
%% Python documentation NOTICES AND INFORMATION BEGIN HERE
=========================================
Terms and conditions for accessing or otherwise using Python
@@ -1310,6 +1938,90 @@ and limitations under the License.
=========================================
END OF Reflect-metadata NOTICES AND INFORMATION
+%% request NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+=========================================
+END OF request NOTICES AND INFORMATION
+
+%% request-progress NOTICES AND INFORMATION BEGIN HERE
+=========================================
+Copyright (c) 2012 IndigoUnited
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+=========================================
+END OF request-progress NOTICES AND INFORMATION
+
%% RxJS NOTICES AND INFORMATION BEGIN HERE
=========================================
Copyright (c) 2015-2017 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
@@ -1415,6 +2127,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=========================================
END OF Sphinx NOTICES AND INFORMATION
+%% sudo-prompt NOTICES AND INFORMATION BEGIN HERE
+=========================================
+The MIT License (MIT)
+
+Copyright (c) 2015 Joran Dirk Greef
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+=========================================
+END OF sudo-prompt NOTICES AND INFORMATION
+
%% uint64be NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
@@ -1442,6 +2182,41 @@ THE SOFTWARE.
=========================================
END OF uint64be NOTICES AND INFORMATION
+%% untangle NOTICES AND INFORMATION BEGIN HERE
+=========================================
+# Author: Christian Stefanescu
+
+# Contributions from:
+
+Florian Idelberger
+Apalala
+
+// Copyright (c) 2011
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+=========================================
+END OF untangle NOTICES AND INFORMATION
+
%% untildify NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
@@ -1573,6 +2348,246 @@ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
=========================================
END OF vscode-languageserver NOTICES AND INFORMATION
+%% Typeshed NOTICES AND INFORMATION BEGIN HERE
+=========================================
+
+The "typeshed" project is licensed under the terms of the Apache license, as
+reproduced below.
+
+= = = = =
+
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+= = = = =
+
+Parts of typeshed are licensed under different licenses (like the MIT
+license), reproduced below.
+
+= = = = =
+
+The MIT License
+Copyright (c) 2015 Jukka Lehtosalo and contributors
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+= = = = =
+=========================================
+END OF Typeshed NOTICES AND INFORMATION
diff --git a/ThirdPartyNotices-Repository.txt b/ThirdPartyNotices-Repository.txt
index 8d0449fa5d4f..29bbf7b86c56 100644
--- a/ThirdPartyNotices-Repository.txt
+++ b/ThirdPartyNotices-Repository.txt
@@ -2,7 +2,7 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
-Microsoft Python extension for Visual Studio Code incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
+Microsoft Python extension for Visual Studio Code incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.
1.
Go for Visual Studio Code (https://github.com/Microsoft/vscode-go)
@@ -12,10 +12,11 @@ Go for Visual Studio Code (https://github.com/Microsoft/vscode-go)
5. jedi (https://github.com/davidhalter/jedi)
6. omnisharp-vscode (https://github.com/OmniSharp/omnisharp-vscode)
7. parso (https://github.com/davidhalter/parso)
-8. Python documentation (https://docs.python.org/)
-9. python-functools32 (https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py)
-10. pythonVSCode (https://github.com/DonJayamanne/pythonVSCode)
-11. Sphinx (http://sphinx-doc.org/)
+8. PTVS (https://github.com/Microsoft/PTVS)
+9. Python documentation (https://docs.python.org/)
+10. python-functools32 (https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py)
+11. pythonVSCode (https://github.com/DonJayamanne/pythonVSCode)
+12. Sphinx (http://sphinx-doc.org/)
%%
@@ -427,6 +428,24 @@ Agreement.
=========================================
END OF parso NOTICES, INFORMATION, AND LICENSE
+%% PTVS NOTICES, INFORMATION, AND LICENSE BEGIN HERE
+=========================================
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+=========================================
+END OF PTVS NOTICES, INFORMATION, AND LICENSE
+
%% Python documentation NOTICES, INFORMATION, AND LICENSE BEGIN HERE
=========================================
Terms and conditions for accessing or otherwise using Python
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index b4eca06c93b4..000000000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-environment:
- matrix:
- - PYTHON: "C:\\Python36"
- PYTHON_VERSION: "3.6.3"
- PYTHON_ARCH: "32"
- nodejs_version: "8.9.1"
- APPVEYOR: "true"
-
-init:
- - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
-
-install:
- - ps: Install-Product node $env:nodejs_version
- - npm i -g yarn
- - yarn
- - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- - pip install -U pip
- - pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/
- - python --version
- - python -m easy_install -U setuptools
- - "%PYTHON%/Scripts/pip.exe install --upgrade -r requirements.txt"
-
-test_script:
- - yarn run clean
- - yarn run vscode:prepublish
- - yarn run testDebugger --silent
- - yarn run testSingleWorkspace --silent
- - yarn run testMultiWorkspace --silent
-
-build: off
diff --git a/coverconfig.json b/coverconfig.json
index a84634e92ecc..201980b0fd63 100644
--- a/coverconfig.json
+++ b/coverconfig.json
@@ -11,7 +11,8 @@
"json",
"html",
"lcov",
- "lcovonly"
+ "lcovonly",
+ "cobertura"
],
"verbose": false
}
diff --git a/gulpfile.js b/gulpfile.js
index 05918ab7bc6d..708c3cb132ea 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -3,6 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+/* jshint node: true */
+/* jshint esversion: 6 */
+
'use strict';
const gulp = require('gulp');
@@ -13,6 +16,7 @@ const tslint = require('tslint');
const relative = require('relative');
const ts = require('gulp-typescript');
const cp = require('child_process');
+const spawn = require('cross-spawn');
const colors = require('colors/safe');
const gitmodified = require('gulp-gitmodified');
const path = require('path');
@@ -21,6 +25,14 @@ const jeditor = require("gulp-json-editor");
const del = require('del');
const sourcemaps = require('gulp-sourcemaps');
const fs = require('fs');
+const remapIstanbul = require('remap-istanbul');
+const istanbul = require('istanbul');
+const glob = require('glob');
+const os = require('os');
+const _ = require('lodash');
+const nativeDependencyChecker = require('node-has-native-dependencies');
+const flat = require('flat');
+const inlinesource = require('gulp-inline-source');
/**
* Hygiene works by creating cascading subsets of all our files and
@@ -36,6 +48,10 @@ const all = [
'src/client/**/*',
];
+const tsFilter = [
+ 'src/**/*.ts',
+];
+
const indentationFilter = [
'src/**/*.ts',
'!**/typings/**/*',
@@ -52,7 +68,7 @@ const tslintFilter = [
'!resources/**/*',
'!snippets/**/*',
'!syntaxes/**/*',
- '!**/typings/**/*',
+ '!**/typings/**/*'
];
const copyrightHeader = [
@@ -60,7 +76,8 @@ const copyrightHeader = [
'// Licensed under the MIT License.',
'',
'\'use strict\';'
-].join('\n');
+];
+const copyrightHeaders = [copyrightHeader.join('\n'), copyrightHeader.join('\r\n')];
gulp.task('hygiene', () => run({ mode: 'all', skipFormatCheck: true, skipIndentationCheck: true }));
@@ -68,7 +85,12 @@ gulp.task('compile', () => run({ mode: 'compile', skipFormatCheck: true, skipInd
gulp.task('watch', ['hygiene-modified', 'hygiene-watch']);
-gulp.task('hygiene-watch', () => gulp.watch(all, debounce(() => run({ mode: 'changes' }), 1000)));
+// Duplicate to allow duplicate task in tasks.json (one ith problem matching, and one without)
+gulp.task('watchProblems', ['hygiene-modified', 'hygiene-watch']);
+
+gulp.task('debugger-coverage', () => buildDebugAdapterCoverage());
+
+gulp.task('hygiene-watch', () => gulp.watch(tsFilter, debounce(() => run({ mode: 'changes', skipFormatCheck: true, skipIndentationCheck: true, skipCopyrightCheck: true }), 100)));
gulp.task('hygiene-all', () => run({ mode: 'all' }));
@@ -76,9 +98,17 @@ gulp.task('hygiene-modified', ['compile'], () => run({ mode: 'changes' }));
gulp.task('clean', ['output:clean', 'cover:clean'], () => { });
-gulp.task('output:clean', () => del('coverage'));
+gulp.task('output:clean', () => del(['coverage', 'debug_coverage*']));
+
+gulp.task('cover:clean', () => del(['coverage', 'debug_coverage*']));
-gulp.task('cover:clean', () => del('coverage'));
+gulp.task('clean:ptvsd', () => del(['coverage', 'pythonFiles/experimental/ptvsd*']));
+
+gulp.task('checkNativeDependencies', () => {
+ if (hasNativeDependencies()) {
+ throw new Error('Native dependencies deteced');
+ }
+});
gulp.task('cover:enable', () => {
return gulp.src("./coverconfig.json")
@@ -92,36 +122,120 @@ gulp.task('cover:enable', () => {
gulp.task('cover:disable', () => {
return gulp.src("./coverconfig.json")
.pipe(jeditor((json) => {
- json.enabled = true;
+ json.enabled = false;
return json;
}))
.pipe(gulp.dest("./out", { 'overwrite': true }));
});
+/**
+ * Inline CSS into the coverage report for better visualizations on
+ * the VSTS report page for code coverage.
+ */
+gulp.task('inlinesource', () => {
+ return gulp.src('./coverage/lcov-report/*.html')
+ .pipe(inlinesource({attribute: false}))
+ .pipe(gulp.dest('./coverage/lcov-report-inline'));
+});
+
+function hasNativeDependencies() {
+ let nativeDependencies = nativeDependencyChecker.check(path.join(__dirname, 'node_modules'));
+ if (!Array.isArray(nativeDependencies) || nativeDependencies.length === 0) {
+ return false;
+ }
+ const dependencies = JSON.parse(spawn.sync('npm', ['ls', '--json', '--prod']).stdout.toString());
+ const jsonProperties = Object.keys(flat.flatten(dependencies));
+ nativeDependencies = _.flatMap(nativeDependencies, item => path.dirname(item.substring(item.indexOf('node_modules') + 'node_modules'.length)).split(path.sep))
+ .filter(item => item.length > 0)
+ .filter(item => jsonProperties.findIndex(flattenedDependency => flattenedDependency.endsWith(`dependencies.${item}.version`)) >= 0);
+ if (nativeDependencies.length > 0) {
+ console.error('Native dependencies detected', nativeDependencies);
+ return true;
+ }
+ return false;
+}
+
+function buildDebugAdapterCoverage() {
+ const matches = glob.sync(path.join(__dirname, 'debug_coverage*/coverage.json'));
+ matches.forEach(coverageFile => {
+ const finalCoverageFile = path.join(path.dirname(coverageFile), 'coverage-final-upload.json');
+ const remappedCollector = remapIstanbul.remap(JSON.parse(fs.readFileSync(coverageFile, 'utf8')), {
+ warn: warning => {
+ // We expect some warnings as any JS file without a typescript mapping will cause this.
+ // By default, we'll skip printing these to the console as it clutters it up.
+ console.warn(warning);
+ }
+ });
+
+ const reporter = new istanbul.Reporter(undefined, path.dirname(coverageFile));
+ reporter.add('lcov');
+ reporter.write(remappedCollector, true, () => { });
+ });
+}
+
/**
* @typedef {Object} hygieneOptions - creates a new type named 'SpecialType'
* @property {'changes'|'staged'|'all'|'compile'} [mode=] - Mode.
* @property {boolean=} skipIndentationCheck - Skip indentation checks.
* @property {boolean=} skipFormatCheck - Skip format checks.
+* @property {boolean=} skipCopyrightCheck - Skip copyright checks.
* @property {boolean=} skipLinter - Skip linter.
*/
+const tsProjectMap = {};
+/**
+ *
+ * @param {hygieneOptions} options
+ */
+function getTsProject(options) {
+ const tsOptions = options.mode === 'compile' ? undefined : { strict: true, noImplicitAny: false, noImplicitThis: false };
+ const mode = tsOptions && tsOptions.mode ? tsOptions.mode : '';
+ return tsProjectMap[mode] ? tsProjectMap[mode] : tsProjectMap[mode] = ts.createProject('tsconfig.json', tsOptions);
+}
+
+let configuration;
+/**
+ *
+ * @param {hygieneOptions} options
+ */
+function getLinter(options) {
+ configuration = configuration ? configuration : tslint.Configuration.findConfiguration(null, '.');
+ const program = tslint.Linter.createProgram('./tsconfig.json');
+ const linter = new tslint.Linter({ formatter: 'json' }, program);
+ return { linter, configuration };
+}
+let compilationInProgress = false;
+let reRunCompilation = false;
/**
*
* @param {hygieneOptions} options
* @returns {NodeJS.ReadWriteStream}
*/
const hygiene = (options) => {
+ if (compilationInProgress) {
+ reRunCompilation = true;
+ return;
+ }
+ const fileListToProcess = options.mode === 'compile' ? undefined : getFileListToProcess(options);
+ if (Array.isArray(fileListToProcess) && fileListToProcess !== all
+ && fileListToProcess.filter(item => item.endsWith('.ts')).length === 0) {
+ return;
+ }
+
+ const started = new Date().getTime();
+ compilationInProgress = true;
options = options || {};
let errorCount = 0;
- const addedFiles = getAddedFilesSync();
+ const addedFiles = options.skipCopyrightCheck ? [] : getAddedFilesSync();
console.log(colors.blue('Hygiene started.'));
-
const copyrights = es.through(function (file) {
- if (addedFiles.indexOf(file.path) !== -1 && file.contents.toString('utf8').indexOf(copyrightHeader) !== 0) {
- // Use tslint format.
- console.error(`ERROR: (copyright) ${file.relative}[1,1]: Missing or bad copyright statement`);
- errorCount++;
+ if (addedFiles.indexOf(file.path) !== -1) {
+ const contents = file.contents.toString('utf8');
+ if (!copyrightHeaders.some(header => contents.indexOf(header) === 0)) {
+ // Use tslint format.
+ console.error(`ERROR: (copyright) ${file.relative}[1,1]: Missing or bad copyright statement`);
+ errorCount++;
+ }
}
this.emit('data', file);
@@ -200,15 +314,16 @@ const hygiene = (options) => {
.filter(reported => reported === true)
.length > 0;
}
- const configuration = tslint.Configuration.findConfiguration(null, '.');
- const program = tslint.Linter.createProgram('./tsconfig.json');
- const linter = new tslint.Linter({ formatter: 'json' }, program);
+
+ const { linter, configuration } = getLinter(options);
const tsl = es.through(function (file) {
const contents = file.contents.toString('utf8');
// Don't print anything to the console, we'll do that.
// Yes this is a hack, but tslinter doesn't provide an option to prevent this.
const oldWarn = console.warn;
console.warn = () => { };
+ linter.failures = [];
+ linter.fixes = [];
linter.lint(file.relative, contents, configuration.results);
console.warn = oldWarn;
const result = linter.getResult();
@@ -231,8 +346,7 @@ const hygiene = (options) => {
this.emit('data', file);
});
- const tsOptions = options.mode === 'compile' ? undefined : { strict: true, noImplicitAny: false, noImplicitThis: false };
- const tsProject = ts.createProject('tsconfig.json', tsOptions);
+ const tsProject = getTsProject(options);
const tsc = function () {
function customReporter() {
@@ -255,7 +369,7 @@ const hygiene = (options) => {
return tsProject(reporter);
}
- const files = options.mode === 'compile' ? tsProject.src() : getFilesToProcess(options);
+ const files = options.mode === 'compile' ? tsProject.src() : getFilesToProcess(fileListToProcess);
const dest = options.mode === 'compile' ? './out' : '.';
let result = files
.pipe(filter(f => f && f.stat && !f.stat.isDirectory()));
@@ -266,8 +380,11 @@ const hygiene = (options) => {
}
result = result
- .pipe(filter(tslintFilter))
- .pipe(copyrights);
+ .pipe(filter(tslintFilter));
+
+ if (!options.skipCopyrightCheck) {
+ result = result.pipe(copyrights);
+ }
if (!options.skipFormatCheck) {
// result = result
@@ -278,7 +395,7 @@ const hygiene = (options) => {
result = result
.pipe(tsl);
}
-
+ let totalTime = 0;
result = result
.pipe(tscFilesTracker)
.pipe(sourcemaps.init())
@@ -295,15 +412,22 @@ const hygiene = (options) => {
.pipe(gulp.dest(dest))
.pipe(es.through(null, function () {
if (errorCount > 0) {
- const errorMessage = `Hygiene failed with errors 👎 . Check 'gulpfile.js'.`;
+ const errorMessage = `Hygiene failed with errors 👎 . Check 'gulpfile.js' (completed in ${new Date().getTime() - started}ms).`;
console.error(colors.red(errorMessage));
exitHandler(options);
} else {
- console.log(colors.green('Hygiene passed with 0 errors 👍.'));
+ console.log(colors.green(`Hygiene passed with 0 errors 👍 (completed in ${new Date().getTime() - started}ms).`));
}
// Reset error counter.
errorCount = 0;
reportedLinterFailures = [];
+ compilationInProgress = false;
+ if (reRunCompilation) {
+ reRunCompilation = false;
+ setTimeout(() => {
+ hygiene(options);
+ }, 10);
+ }
this.emit('end');
}))
.on('error', exitHandler.bind(this, options));
@@ -318,6 +442,7 @@ const hygiene = (options) => {
* @property {string[]=} files - Optional list of files to be modified.
* @property {boolean=} skipIndentationCheck - Skip indentation checks.
* @property {boolean=} skipFormatCheck - Skip format checks.
+* @property {boolean=} skipCopyrightCheck - Skip copyright checks.
* @property {boolean=} skipLinter - Skip linter.
* @property {boolean=} watch - Watch mode.
*/
@@ -363,30 +488,44 @@ function getAddedFilesSync() {
return out
.split(/\r?\n/)
.filter(l => !!l)
- .filter(l => l.startsWith('A') || l.startsWith('??'))
+ .filter(l => _.intersection(['A', '?', 'U'], l.substring(0, 2).trim().split('')).length > 0)
+ .map(l => path.join(__dirname, l.substring(2).trim()));
+}
+function getModifiedFilesSync() {
+ const out = cp.execSync('git status -u -s', { encoding: 'utf8' });
+ return out
+ .split(/\r?\n/)
+ .filter(l => !!l)
+ .filter(l => _.intersection(['M', 'A', 'R', 'C', 'U', '?'], l.substring(0, 2).trim().split('')).length > 0)
.map(l => path.join(__dirname, l.substring(2).trim()));
}
/**
* @param {hygieneOptions} options
*/
-function getFilesToProcess(options) {
+function getFilesToProcess(fileList) {
+ const gulpSrcOptions = { base: '.' };
+ return gulp.src(fileList, gulpSrcOptions);
+}
+
+/**
+* @param {hygieneOptions} options
+*/
+function getFileListToProcess(options) {
const mode = options ? options.mode : 'all';
const gulpSrcOptions = { base: '.' };
// If we need only modified files, then filter the glob.
if (options && options.mode === 'changes') {
- return gulp.src(all, gulpSrcOptions)
- .pipe(gitmodified(['M', 'A', 'D', 'R', 'C', 'U', '??']));
+ return getModifiedFilesSync();
}
if (options && options.mode === 'staged') {
- return gulp.src(getStagedFilesSync(), gulpSrcOptions);
+ return getStagedFilesSync();
}
- return gulp.src(all, gulpSrcOptions);
+ return all;
}
-
exports.hygiene = hygiene;
// this allows us to run hygiene as a git pre-commit hook.
diff --git a/news/2 Fixes/404.md b/news/2 Fixes/404.md
deleted file mode 100644
index f3c6b68e7ccc..000000000000
--- a/news/2 Fixes/404.md
+++ /dev/null
@@ -1 +0,0 @@
-Determine pipenv usage based on finding a file named `Pipfile`, not `pipfile` (case-sensitive)
diff --git a/news/2 Fixes/87.md b/news/2 Fixes/87.md
deleted file mode 100644
index c024086fd1d3..000000000000
--- a/news/2 Fixes/87.md
+++ /dev/null
@@ -1 +0,0 @@
-Fix occasionally having unverified breakpoints
diff --git a/news/2 Fixes/896.md b/news/2 Fixes/896.md
deleted file mode 100644
index 2f9e652cca4b..000000000000
--- a/news/2 Fixes/896.md
+++ /dev/null
@@ -1 +0,0 @@
-Update npm package `vscode-extension-telemetry` to fix the warning 'os.tmpDir() deprecation'.
diff --git a/news/3 Code Health/742.md b/news/3 Code Health/742.md
deleted file mode 100644
index d35d1ffd391e..000000000000
--- a/news/3 Code Health/742.md
+++ /dev/null
@@ -1 +0,0 @@
-Enable unit testing of the experimental debugger on CI servers
diff --git a/news/3 Code Health/983.md b/news/3 Code Health/983.md
deleted file mode 100644
index bd0250359c96..000000000000
--- a/news/3 Code Health/983.md
+++ /dev/null
@@ -1 +0,0 @@
-Launch the unit tests in debug mode as opposed to running and attaching the debugger.
diff --git a/news/README.md b/news/README.md
index 8b8350f5ddec..d4e7d7de26a1 100644
--- a/news/README.md
+++ b/news/README.md
@@ -3,16 +3,18 @@
Our changelog is automatically generate from individual news entries.
This alleviates the burden of having to go back and try to figure out
what changed in a release. It also helps tie pull requests back to the
-issue(s) it addresses.
+issue(s) it addresses. Finally, it avoids merge conflicts if multiple
+pull requests try to edit the changelog.
## Entries
-Each news entries is represented by a Markdown file that contains the
+Each news entry is represented by a Markdown file that contains the
relevant details of what changed. The file name of the news entry is
-the issue that corresponds to the change along with an option nonce in
+the issue that corresponds to the change along with an optional nonce in
case a single issue corresponds to multiple changes. The directory
the news entry is saved in specifies what section of the changelog the
-change corresponds to.
+change corresponds to. External contributors should also make sure to
+thank themselves for taking the time and effort to contribute.
As an example, a change corresponding to a bug reported in issue #42
would be saved in the `1 Fixes` directory and named `42.md`
@@ -22,6 +24,7 @@ regarding issue #42) and could contain the following:
```markdown
[Answer](https://en.wikipedia.org/wiki/42_(number))
to the Ultimate Question of Life, the Universe, and Everything!
+(thanks [Don Jaymanne](https://github.com/donjayamanne/))
```
This would then be made into an entry in the changelog that was in the
diff --git a/news/__main__.py b/news/__main__.py
new file mode 100644
index 000000000000..e12476c4ecca
--- /dev/null
+++ b/news/__main__.py
@@ -0,0 +1,3 @@
+import runpy
+
+runpy.run_module('announce', run_name='__main__', alter_sys=True)
diff --git a/news/announce.py b/news/announce.py
index a17e5d086099..0666a53a2f0c 100644
--- a/news/announce.py
+++ b/news/announce.py
@@ -1,58 +1,70 @@
-"""Generate the changelog."""
+"""Generate the changelog.
+
+Usage: announce [--dry_run | --interim | --final] []
+
+"""
+import dataclasses
import enum
import operator
import os
import pathlib
import re
import subprocess
-import types
+import sys
-import click
+import docopt
FILENAME_RE = re.compile(r"(?P\d+)(?P-\S+)?\.md")
-ISSUE_URL = "https://github.com/Microsoft/vscode-python/issues/{issue}"
-ENTRY_TEMPLATE = "1. {entry} ([#{issue}]({issue_url}))"
-SECTION_DEPTH = "###"
-def NewsEntry(issue_number, description, path):
- """Construct a data object for a news entry."""
- # TODO: replace with a dataclass in Python 3.7.
- return types.SimpleNamespace(issue_number=issue_number,
- description=description, path=path)
+
+@dataclasses.dataclass
+class NewsEntry:
+ """Representation of a news entry."""
+
+ issue_number: int
+ description: str
+ path: pathlib.Path
def news_entries(directory):
"""Yield news entries in the directory."""
for path in directory.iterdir():
- if path.name == 'README.md':
+ if path.name == "README.md":
continue
match = FILENAME_RE.match(path.name)
if match is None:
- raise ValueError(f'{path} has a bad file name')
- issue = int(match.group('issue'))
+ raise ValueError(f"{path} has a bad file name")
+ issue = int(match.group("issue"))
entry = path.read_text("utf-8")
yield NewsEntry(issue, entry, path)
-def SectionTitle(index, title, path):
+@dataclasses.dataclass
+class SectionTitle:
"""Create a data object for a section of the changelog."""
- # TODO: replace with a dataclass in Python 3.7.
- return types.SimpleNamespace(index=index, title=title, path=path)
+
+ index: int
+ title: str
+ path: pathlib.Path
def sections(directory):
"""Yield the sections in their appropriate order."""
found = []
for path in directory.iterdir():
- if not path.is_dir():
+ if not path.is_dir() or path.name.startswith("."):
continue
- position, sep, title = path.name.partition(' ')
+ position, sep, title = path.name.partition(" ")
if not sep:
- raise ValueError('directory is missing position part')
+ print(
+ f"directory {path.name!r} is missing a ranking; skipping",
+ file=sys.stderr,
+ )
+ continue
found.append(SectionTitle(int(position), title, path))
- return sorted(found, key=operator.attrgetter('index'))
+ return sorted(found, key=operator.attrgetter("index"))
def gather(directory):
@@ -65,17 +77,27 @@ def gather(directory):
def entry_markdown(entry):
"""Generate the Markdown for the specified entry."""
- issue_url = ISSUE_URL.format(issue=entry.issue_number)
- return ENTRY_TEMPLATE.format(entry=entry.description,
- issue=entry.issue_number,
- issue_url=issue_url)
+ enumerated_item = "1. "
+ indent = " " * len(enumerated_item)
+ issue_url = (
+ f"https://github.com/Microsoft/vscode-python/issues/{entry.issue_number}"
+ )
+ issue_md = f"([#{entry.issue_number}]({issue_url}))"
+ entry_lines = entry.description.strip().splitlines()
+ formatted_lines = [f"{enumerated_item}{entry_lines[0]}"]
+ formatted_lines.extend(f"{indent}{line}" for line in entry_lines[1:])
+ formatted_lines.append(f"{indent}{issue_md}")
+ return "\n".join(formatted_lines)
+ return ENTRY_TEMPLATE.format(
+ entry=entry.description.strip(), issue=entry.issue_number, issue_url=issue_url
+ )
def changelog_markdown(data):
"""Generate the Markdown for the release."""
changelog = []
for section, entries in data:
- changelog.append(f"{SECTION_DEPTH} {section.title}")
+ changelog.append(f"### {section.title}")
changelog.append("")
changelog.extend(map(entry_markdown, entries))
changelog.append("")
@@ -84,9 +106,17 @@ def changelog_markdown(data):
def git_rm(path):
"""Run git-rm on the path."""
- status = subprocess.run(['git', 'rm', os.fspath(path.resolve())],
- shell=True)
- status.check_returncode()
+ status = subprocess.run(
+ ["git", "rm", os.fspath(path.resolve())],
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ try:
+ status.check_returncode()
+ except Exception:
+ print(status.stdout, file=sys.stderr)
+ raise
def cleanup(data):
@@ -104,23 +134,24 @@ class RunType(enum.Enum):
final = 2
-@click.command()
-@click.option('--dry-run', 'run_type', flag_value=RunType.dry_run,
- help='validate input')
-@click.option('--interim', 'run_type', flag_value=RunType.interim, default=True,
- help='generate Markdown')
-@click.option('--final', 'run_type', flag_value=RunType.final,
- help='generate Markdown & `git rm` news files')
-@click.argument('directory', default=pathlib.Path(__file__).parent,
- type=click.Path(exists=True, file_okay=False))
def main(run_type, directory):
+ directory = pathlib.Path(directory)
data = gather(directory)
markdown = changelog_markdown(data)
if run_type != RunType.dry_run:
+ # XXX This can lead to mojibake; hopefully Python 3.7 will resolve this.
print(markdown)
if run_type == RunType.final:
cleanup(data)
-if __name__ == '__main__':
- main()
+if __name__ == "__main__":
+ arguments = docopt.docopt(__doc__)
+ for possible_run_type in RunType:
+ if arguments[f"--{possible_run_type.name}"]:
+ run_type = possible_run_type
+ break
+ else:
+ run_type = RunType.interim
+ directory = arguments[""] or pathlib.Path(__file__).parent
+ main(run_type, directory)
diff --git a/news/requirements.txt b/news/requirements.txt
index d47e9da45e5a..316eef65b021 100644
--- a/news/requirements.txt
+++ b/news/requirements.txt
@@ -1,2 +1,2 @@
-click~=6.7.0
+docopt==0.6.2
pytest~=3.4.1
diff --git a/news/test_announce.py b/news/test_announce.py
index 6c9aa256bdc1..3270088b06b6 100644
--- a/news/test_announce.py
+++ b/news/test_announce.py
@@ -1,5 +1,6 @@
import pathlib
+import docopt
import pytest
import announce as ann
@@ -48,8 +49,7 @@ def test_sections_sorting(directory):
def test_sections_naming(directory):
(directory / 'Hello').mkdir()
- with pytest.raises(ValueError):
- list(ann.sections(directory))
+ assert not ann.sections(directory)
def test_gather(directory):
@@ -79,8 +79,6 @@ def test_gather(directory):
assert entries[1].description == 'Fix 2'
-
-
def test_entry_markdown():
markdown = ann.entry_markdown(ann.NewsEntry(42, 'Hello, world!', None))
assert '42' in markdown
@@ -126,3 +124,14 @@ def fake_git_rm(path):
section, entries = results.pop()
assert len(entries) == 1
assert rm_path == entries[0].path
+
+
+def test_cli():
+ for option in ("--"+opt for opt in ["dry_run", "interim", "final"]):
+ args = docopt.docopt(ann.__doc__, [option])
+ assert args[option]
+ args = docopt.docopt(ann.__doc__, ["./news"])
+ assert args[""] == "./news"
+ args = docopt.docopt(ann.__doc__, ["--dry_run", "./news"])
+ assert args["--dry_run"]
+ assert args[""] == "./news"
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000000..8f255d8aabab
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,9819 @@
+{
+ "name": "python",
+ "version": "2018.7.1",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@gulp-sourcemaps/identity-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz",
+ "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=",
+ "dev": true,
+ "requires": {
+ "acorn": "5.5.3",
+ "css": "2.2.3",
+ "normalize-path": "2.1.1",
+ "source-map": "0.5.7",
+ "through2": "2.0.3"
+ }
+ },
+ "@gulp-sourcemaps/map-sources": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz",
+ "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=",
+ "dev": true,
+ "requires": {
+ "normalize-path": "2.1.1",
+ "through2": "2.0.3"
+ }
+ },
+ "@sindresorhus/is": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
+ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
+ "dev": true
+ },
+ "@sinonjs/formatio": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz",
+ "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==",
+ "dev": true,
+ "requires": {
+ "samsam": "1.3.0"
+ }
+ },
+ "@types/caseless": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz",
+ "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==",
+ "dev": true
+ },
+ "@types/chai": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz",
+ "integrity": "sha512-f5dXGzOJycyzSMdaXVhiBhauL4dYydXwVpavfQ1mVCaGjR56a9QfklXObUxlIY9bGTmCPHEEZ04I16BZ/8w5ww==",
+ "dev": true
+ },
+ "@types/chai-arrays": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/chai-arrays/-/chai-arrays-1.0.2.tgz",
+ "integrity": "sha512-/kgYvj5Pwiv/bOlJ6c5GlRF/W6lUGSLrpQGl/7Gg6w7tvBYcf0iF91+wwyuwDYGO2zM0wNpcoPixZVif8I/r6g==",
+ "dev": true,
+ "requires": {
+ "@types/chai": "4.1.3"
+ }
+ },
+ "@types/chai-as-promised": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.0.tgz",
+ "integrity": "sha512-MFiW54UOSt+f2bRw8J7LgQeIvE/9b4oGvwU7XW30S9QGAiHGnU/fmiOprsyMkdmH2rl8xSPc0/yrQw8juXU6bQ==",
+ "dev": true,
+ "requires": {
+ "@types/chai": "4.1.3"
+ }
+ },
+ "@types/commander": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
+ "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
+ "dev": true,
+ "requires": {
+ "commander": "2.15.1"
+ }
+ },
+ "@types/decompress": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@types/decompress/-/decompress-4.2.2.tgz",
+ "integrity": "sha512-2jlSsNAVhrWJtgOV3V85MJ09yRoeUTUWQeeusNYAcJVkUmoVRVElvmkWN0TK+Lgdlyd9pIRyja/DTBcyqD8xyA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/del": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/del/-/del-3.0.1.tgz",
+ "integrity": "sha512-y6qRq6raBuu965clKgx6FHuiPu3oHdtmzMPXi8Uahsjdq1L6DL5fS/aY5/s71YwM7k6K1QIWvem5vNwlnNGIkQ==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "5.0.35"
+ }
+ },
+ "@types/dotenv": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-4.0.3.tgz",
+ "integrity": "sha512-mmhpINC/HcLGQK5ikFJlLXINVvcxhlrV+ZOUJSN7/ottYl+8X4oSXzS9lBtDkmWAl96EGyGyLrNvk9zqdSH8Fw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/download": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/@types/download/-/download-6.2.2.tgz",
+ "integrity": "sha512-gwRnrp1yFweJhPGBR01nfesxYcml8SayxHEwA6x+1T+Lqez5iMdCRJgt/I9HqpjMi5Mmtb/7MswY6FN4bMypNg==",
+ "dev": true,
+ "requires": {
+ "@types/decompress": "4.2.2",
+ "@types/got": "8.3.1",
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/event-stream": {
+ "version": "3.3.34",
+ "resolved": "https://registry.npmjs.org/@types/event-stream/-/event-stream-3.3.34.tgz",
+ "integrity": "sha512-LLiivgWKii4JeMzFy3trrxqkRrVSdue8WmbXyHuSJLwNrhIQU5MTrc65jhxEPwMyh5HR1xevSdD+k2nnSRKw9g==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/events": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
+ "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==",
+ "dev": true
+ },
+ "@types/form-data": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
+ "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/fs-extra": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz",
+ "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/get-port": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz",
+ "integrity": "sha512-TiNg8R1kjDde5Pub9F9vCwZA/BNW9HeXP5b9j7Qucqncy/McfPZ6xze/EyBdXS5FhMIGN6Fx3vg75l5KHy3V1Q==",
+ "dev": true
+ },
+ "@types/glob": {
+ "version": "5.0.35",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz",
+ "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==",
+ "dev": true,
+ "requires": {
+ "@types/events": "1.2.0",
+ "@types/minimatch": "3.0.3",
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/got": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@types/got/-/got-8.3.1.tgz",
+ "integrity": "sha512-CGEPw67/Ub6gNMusk062tueurxN+HyjDCvYl4QVBKiSO+fqluXmRX/wSqST/4RtKth4mz8lDZiaZIpXr/uPROg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/iconv-lite": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@types/iconv-lite/-/iconv-lite-0.0.1.tgz",
+ "integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/istanbul": {
+ "version": "0.4.30",
+ "resolved": "https://registry.npmjs.org/@types/istanbul/-/istanbul-0.4.30.tgz",
+ "integrity": "sha512-+hQU4fh2G96ze78uI5/V6+SRDZD1UnVrFn23i2eDetwfbBq3s0/zYP92xj/3qyvVMM3WnvS88N56zjz+HmL04A==",
+ "dev": true
+ },
+ "@types/lodash": {
+ "version": "4.14.109",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.109.tgz",
+ "integrity": "sha512-hop8SdPUEzbcJm6aTsmuwjIYQo1tqLseKCM+s2bBqTU2gErwI4fE+aqUVOlscPSQbKHKgtMMPoC+h4AIGOJYvw==",
+ "dev": true
+ },
+ "@types/md5": {
+ "version": "2.1.32",
+ "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.1.32.tgz",
+ "integrity": "sha1-k+I0N/zRenucqY0CqmAC6DWEL+g=",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+ "dev": true
+ },
+ "@types/mocha": {
+ "version": "2.2.48",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz",
+ "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "9.4.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-9.4.7.tgz",
+ "integrity": "sha512-4Ba90mWNx8ddbafuyGGwjkZMigi+AWfYLSDCpovwsE63ia8w93r3oJ8PIAQc3y8U+XHcnMOHPIzNe3o438Ywcw==",
+ "dev": true
+ },
+ "@types/request": {
+ "version": "2.47.0",
+ "resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.0.tgz",
+ "integrity": "sha512-/KXM5oev+nNCLIgBjkwbk8VqxmzI56woD4VUxn95O+YeQ8hJzcSmIZ1IN3WexiqBb6srzDo2bdMbsXxgXNkz5Q==",
+ "dev": true,
+ "requires": {
+ "@types/caseless": "0.12.1",
+ "@types/form-data": "2.2.1",
+ "@types/node": "9.4.7",
+ "@types/tough-cookie": "2.3.3"
+ }
+ },
+ "@types/semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==",
+ "dev": true
+ },
+ "@types/shortid": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz",
+ "integrity": "sha1-gJPuBBam4r8qpjOBCRFLP7/6Dps=",
+ "dev": true
+ },
+ "@types/sinon": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-4.3.3.tgz",
+ "integrity": "sha512-Tt7w/ylBS/OEAlSCwzB0Db1KbxnkycP/1UkQpbvKFYoUuRn4uYsC3xh5TRPrOjTy0i8TIkSz1JdNL4GPVdf3KQ==",
+ "dev": true
+ },
+ "@types/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=",
+ "dev": true
+ },
+ "@types/tough-cookie": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz",
+ "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ==",
+ "dev": true
+ },
+ "@types/untildify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/untildify/-/untildify-3.0.0.tgz",
+ "integrity": "sha512-FTktI3Y1h+gP9GTjTvXBP5v8xpH4RU6uS9POoBcGy4XkS2Np6LNtnP1eiNNth4S7P+qw2c/rugkwBasSHFzJEg==",
+ "dev": true
+ },
+ "@types/uuid": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.3.tgz",
+ "integrity": "sha512-5fRLCYhLtDb3hMWqQyH10qtF+Ud2JnNCXTCZ+9ktNdCcgslcuXkDTkFcJNk++MT29yDntDnlF1+jD+uVGumsbw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "@types/winreg": {
+ "version": "1.2.30",
+ "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz",
+ "integrity": "sha1-kdZxDlNtNFucmwF8V0z2qNpkxRg=",
+ "dev": true
+ },
+ "@types/xml2js": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.2.tgz",
+ "integrity": "sha512-8aKUBSj3oGcnuiBmDLm3BIk09RYg01mz9HlQ2u4aS17oJ25DxjQrEUVGFSBVNOfM45pQW4OjcBPplq6r/exJdA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "9.4.7"
+ }
+ },
+ "JSONStream": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz",
+ "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "1.2.0",
+ "through": "2.3.8"
+ }
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
+ "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.1.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2",
+ "longest": "1.0.1",
+ "repeat-string": "1.6.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
+ "ansi-colors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
+ "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-cyan": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
+ "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-gray": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
+ "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-red": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
+ "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "ansi-wrap": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
+ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "dev": true,
+ "requires": {
+ "micromatch": "2.3.11",
+ "normalize-path": "2.1.1"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ }
+ }
+ },
+ "append-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz",
+ "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=",
+ "dev": true,
+ "requires": {
+ "buffer-equal": "1.0.0"
+ }
+ },
+ "applicationinsights": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz",
+ "integrity": "sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=",
+ "requires": {
+ "diagnostic-channel": "0.2.0",
+ "diagnostic-channel-publishers": "0.2.1",
+ "zone.js": "0.7.6"
+ }
+ },
+ "arch": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz",
+ "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk="
+ },
+ "archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "argv": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz",
+ "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=",
+ "dev": true
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "array-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
+ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-slice": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
+ "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "atob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
+ "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
+ "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
+ },
+ "azure-storage": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.8.3.tgz",
+ "integrity": "sha512-gcbdUY0tLivJvjUZD9BAxWrRDcige4OLFHhN3kY0p9oZYAFNNNqwgO7rBXvV+zdoX9HajeMOEog9/S/wxabeGg==",
+ "dev": true,
+ "requires": {
+ "browserify-mime": "1.2.9",
+ "extend": "1.2.1",
+ "json-edm-parser": "0.1.2",
+ "md5.js": "1.3.4",
+ "readable-stream": "2.0.6",
+ "request": "2.87.0",
+ "underscore": "1.8.3",
+ "uuid": "3.2.1",
+ "validator": "9.4.1",
+ "xml2js": "0.2.8",
+ "xmlbuilder": "0.4.3"
+ },
+ "dependencies": {
+ "extend": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz",
+ "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=",
+ "dev": true
+ },
+ "request": {
+ "version": "2.87.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
+ "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "0.7.0",
+ "aws4": "1.7.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.6",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.3.2",
+ "har-validator": "5.0.3",
+ "http-signature": "1.2.0",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.18",
+ "oauth-sign": "0.8.2",
+ "performance-now": "2.1.0",
+ "qs": "6.5.2",
+ "safe-buffer": "5.1.2",
+ "tough-cookie": "2.3.4",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.2.1"
+ },
+ "dependencies": {
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
+ "dev": true
+ }
+ }
+ },
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
+ "dev": true
+ },
+ "xml2js": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz",
+ "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=",
+ "dev": true,
+ "requires": {
+ "sax": "0.5.8"
+ }
+ },
+ "xmlbuilder": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.3.tgz",
+ "integrity": "sha1-xGFLp04K0ZbmCcknLNnh3bKKilg=",
+ "dev": true
+ }
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "1.0.1",
+ "class-utils": "0.3.6",
+ "component-emitter": "1.2.1",
+ "define-property": "1.0.0",
+ "isobject": "3.0.1",
+ "mixin-deep": "1.3.1",
+ "pascalcase": "0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "1.0.2"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "1.0.0",
+ "is-data-descriptor": "1.0.0",
+ "kind-of": "6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
+ "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "beeper": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
+ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+ "dev": true
+ },
+ "bl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+ "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.3.6",
+ "safe-buffer": "5.1.2"
+ },
+ "dependencies": {
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+ "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
+ "dev": true
+ },
+ "boom": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
+ "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
+ "requires": {
+ "hoek": "4.2.1"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0",
+ "array-unique": "0.3.2",
+ "extend-shallow": "2.0.1",
+ "fill-range": "4.0.0",
+ "isobject": "3.0.1",
+ "repeat-element": "1.1.2",
+ "snapdragon": "0.8.2",
+ "snapdragon-node": "2.1.1",
+ "split-string": "3.1.0",
+ "to-regex": "3.0.2"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ }
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "browserify-mime": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz",
+ "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=",
+ "dev": true
+ },
+ "buffer": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz",
+ "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=",
+ "dev": true,
+ "requires": {
+ "base64-js": "0.0.8",
+ "ieee754": "1.1.11",
+ "isarray": "1.0.0"
+ }
+ },
+ "buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc-unsafe": "1.1.0",
+ "buffer-fill": "1.0.0"
+ }
+ },
+ "buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+ "dev": true
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "dev": true
+ },
+ "buffer-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
+ "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=",
+ "dev": true
+ },
+ "buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz",
+ "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "1.0.0",
+ "component-emitter": "1.2.1",
+ "get-value": "2.0.6",
+ "has-value": "1.0.0",
+ "isobject": "3.0.1",
+ "set-value": "2.0.0",
+ "to-object-path": "0.3.0",
+ "union-value": "1.0.0",
+ "unset-value": "1.0.0"
+ }
+ },
+ "cacheable-request": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+ "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
+ "dev": true,
+ "requires": {
+ "clone-response": "1.0.2",
+ "get-stream": "3.0.0",
+ "http-cache-semantics": "3.8.1",
+ "keyv": "3.0.0",
+ "lowercase-keys": "1.0.0",
+ "normalize-url": "2.0.1",
+ "responselike": "1.0.2"
+ },
+ "dependencies": {
+ "lowercase-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
+ "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=",
+ "dev": true
+ }
+ }
+ },
+ "callsite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ }
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "caw": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
+ "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
+ "dev": true,
+ "requires": {
+ "get-proxy": "2.1.0",
+ "isurl": "1.0.0",
+ "tunnel-agent": "0.6.0",
+ "url-to-options": "1.0.1"
+ }
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "align-text": "0.1.4",
+ "lazy-cache": "1.0.4"
+ }
+ },
+ "chai": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz",
+ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=",
+ "dev": true,
+ "requires": {
+ "assertion-error": "1.1.0",
+ "check-error": "1.0.2",
+ "deep-eql": "3.0.1",
+ "get-func-name": "2.0.0",
+ "pathval": "1.1.0",
+ "type-detect": "4.0.8"
+ }
+ },
+ "chai-arrays": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chai-arrays/-/chai-arrays-2.0.0.tgz",
+ "integrity": "sha512-jWAvZu1BV8tL3pj0iosBECzzHEg+XB1zSnMjJGX83bGi/1GlGdDO7J/A0sbBBS6KJT0FVqZIzZW9C6WLiMkHpQ==",
+ "dev": true
+ },
+ "chai-as-promised": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
+ "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
+ "dev": true,
+ "requires": {
+ "check-error": "1.0.2"
+ }
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.2",
+ "async-each": "1.0.1",
+ "fsevents": "1.2.4",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true,
+ "requires": {
+ "is-glob": "2.0.1"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ }
+ }
+ },
+ "ci-info": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz",
+ "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==",
+ "dev": true
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+ "dev": true
+ },
+ "clap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz",
+ "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3"
+ }
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "3.1.0",
+ "define-property": "0.2.5",
+ "isobject": "3.0.1",
+ "static-extend": "0.1.2"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ }
+ }
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "center-align": "0.1.3",
+ "right-align": "0.1.3",
+ "wordwrap": "0.0.2"
+ },
+ "dependencies": {
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "clone-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
+ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
+ "dev": true
+ },
+ "clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "1.0.0"
+ }
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ },
+ "cloneable-readable": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz",
+ "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "process-nextick-args": "2.0.0",
+ "readable-stream": "2.3.6"
+ },
+ "dependencies": {
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "coa": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz",
+ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=",
+ "dev": true,
+ "requires": {
+ "q": "1.5.1"
+ }
+ },
+ "codecov": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.0.2.tgz",
+ "integrity": "sha512-9ljtIROIjPIUmMRqO+XuDITDoV8xRrZmA0jcEq6p2hg2+wY9wGmLfreAZGIL72IzUfdEDZaU8+Vjidg1fBQ8GQ==",
+ "dev": true,
+ "requires": {
+ "argv": "0.0.2",
+ "request": "2.85.0",
+ "urlgrey": "0.4.4"
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "1.0.0",
+ "object-visit": "1.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz",
+ "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+ "dev": true
+ },
+ "commandpost": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.3.0.tgz",
+ "integrity": "sha512-T62tyrmYTkaRDbV2z1k2yXTyxk0cFptXYwo1cUbnfHtp7ThLgQ9/90jG1Ym5WLZgFhvOTaHA5VSARWJ9URpLDw==",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "config-chain": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz",
+ "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=",
+ "dev": true,
+ "requires": {
+ "ini": "1.3.5",
+ "proto-list": "1.2.4"
+ }
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
+ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
+ "dev": true
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "1.0.4",
+ "path-key": "2.0.1",
+ "semver": "5.5.0",
+ "shebang-command": "1.2.0",
+ "which": "1.3.1"
+ }
+ },
+ "crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
+ },
+ "cryptiles": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
+ "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
+ "requires": {
+ "boom": "5.2.0"
+ },
+ "dependencies": {
+ "boom": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
+ "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
+ "requires": {
+ "hoek": "4.2.1"
+ }
+ }
+ }
+ },
+ "css": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz",
+ "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "source-map": "0.1.43",
+ "source-map-resolve": "0.5.2",
+ "urix": "0.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "dev": true,
+ "requires": {
+ "amdefine": "1.0.1"
+ }
+ }
+ }
+ },
+ "css-tree": {
+ "version": "1.0.0-alpha25",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha25.tgz",
+ "integrity": "sha512-XC6xLW/JqIGirnZuUWHXCHRaAjje2b3OIB0Vj5RIJo6mIi/AdJo30quQl5LxUl0gkXDIrTrFGbMlcZjyFplz1A==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "1.1.4",
+ "source-map": "0.5.7"
+ }
+ },
+ "csso": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-3.4.0.tgz",
+ "integrity": "sha1-V7J+9VPMy/WqlkxkF0hkHprxE/M=",
+ "dev": true,
+ "requires": {
+ "css-tree": "1.0.0-alpha25"
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "1.0.2"
+ }
+ },
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.43"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "1.0.0"
+ }
+ },
+ "dateformat": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
+ "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
+ "dev": true
+ },
+ "debounce": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.1.0.tgz",
+ "integrity": "sha512-ZQVKfRVlwRfD150ndzEK8M90ABT+Y/JQKs4Y7U4MXdpuoUkkrr4DwKbVux3YjylA5bUMUj0Nc3pMxPJX6N2QQQ==",
+ "dev": true
+ },
+ "debounce-hashed": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/debounce-hashed/-/debounce-hashed-0.1.2.tgz",
+ "integrity": "sha1-oN/jB8Gn2zD2kRyM+8DvhB831K8=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "debug-fabulous": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz",
+ "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==",
+ "dev": true,
+ "requires": {
+ "debug": "3.1.0",
+ "memoizee": "0.4.12",
+ "object-assign": "4.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "decache": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/decache/-/decache-4.4.0.tgz",
+ "integrity": "sha1-b232uF1+fEQQqTL/wmSJt46azRM=",
+ "dev": true,
+ "requires": {
+ "callsite": "1.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "decompress": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
+ "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
+ "dev": true,
+ "requires": {
+ "decompress-tar": "4.1.1",
+ "decompress-tarbz2": "4.1.1",
+ "decompress-targz": "4.1.1",
+ "decompress-unzip": "4.0.1",
+ "graceful-fs": "4.1.11",
+ "make-dir": "1.3.0",
+ "pify": "2.3.0",
+ "strip-dirs": "2.1.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "1.0.0"
+ }
+ },
+ "decompress-tar": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
+ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
+ "dev": true,
+ "requires": {
+ "file-type": "5.2.0",
+ "is-stream": "1.1.0",
+ "tar-stream": "1.6.1"
+ },
+ "dependencies": {
+ "file-type": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
+ "dev": true
+ }
+ }
+ },
+ "decompress-tarbz2": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+ "dev": true,
+ "requires": {
+ "decompress-tar": "4.1.1",
+ "file-type": "6.2.0",
+ "is-stream": "1.1.0",
+ "seek-bzip": "1.0.5",
+ "unbzip2-stream": "1.2.5"
+ },
+ "dependencies": {
+ "file-type": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
+ "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
+ "dev": true
+ }
+ }
+ },
+ "decompress-targz": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
+ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
+ "dev": true,
+ "requires": {
+ "decompress-tar": "4.1.1",
+ "file-type": "5.2.0",
+ "is-stream": "1.1.0"
+ },
+ "dependencies": {
+ "file-type": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
+ "dev": true
+ }
+ }
+ },
+ "decompress-unzip": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
+ "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
+ "dev": true,
+ "requires": {
+ "file-type": "3.9.0",
+ "get-stream": "2.3.1",
+ "pify": "2.3.0",
+ "yauzl": "2.9.1"
+ },
+ "dependencies": {
+ "file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
+ "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.1",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "deep-assign": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz",
+ "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=",
+ "dev": true,
+ "requires": {
+ "is-obj": "1.0.1"
+ }
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "deepmerge": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.1.tgz",
+ "integrity": "sha512-urQxA1smbLZ2cBbXbaYObM1dJ82aJ2H57A1C/Kklfh/ZN1bgH4G/n5KWhdNfOK11W98gqZfyYj7W4frJJRwA2w==",
+ "dev": true
+ },
+ "defaults": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+ "dev": true,
+ "requires": {
+ "foreach": "2.0.5",
+ "object-keys": "1.0.11"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "1.0.2",
+ "isobject": "3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "1.0.0",
+ "is-data-descriptor": "1.0.0",
+ "kind-of": "6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+ "dev": true,
+ "requires": {
+ "globby": "6.1.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.1",
+ "p-map": "1.2.0",
+ "pify": "3.0.0",
+ "rimraf": "2.6.2"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "deprecated": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz",
+ "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=",
+ "dev": true
+ },
+ "detect-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz",
+ "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=",
+ "dev": true
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "dev": true
+ },
+ "diagnostic-channel": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz",
+ "integrity": "sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=",
+ "requires": {
+ "semver": "5.5.0"
+ }
+ },
+ "diagnostic-channel-publishers": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz",
+ "integrity": "sha1-ji1geottef6IC1SLxYzGvrKIxPM="
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diff-match-patch": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz",
+ "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg="
+ },
+ "doctrine": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
+ "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
+ "dev": true,
+ "requires": {
+ "esutils": "1.1.6",
+ "isarray": "0.0.1"
+ },
+ "dependencies": {
+ "esutils": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
+ "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ }
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.1.3",
+ "entities": "1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
+ "dev": true
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0.1.0",
+ "domelementtype": "1.3.0"
+ }
+ },
+ "dotenv": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz",
+ "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow=="
+ },
+ "download": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/download/-/download-7.0.0.tgz",
+ "integrity": "sha512-0Fe/CAjKycx12IG9We9gYlLP03BEcWTpttg7P5mwfOiQTg584kpuHqP7F61RkUJM+mfEdEU9TJonm0PJp5rQLw==",
+ "dev": true,
+ "requires": {
+ "caw": "2.0.1",
+ "content-disposition": "0.5.2",
+ "decompress": "4.2.0",
+ "ext-name": "5.0.0",
+ "file-type": "7.7.1",
+ "filenamify": "2.0.0",
+ "get-stream": "3.0.0",
+ "got": "8.3.1",
+ "make-dir": "1.3.0",
+ "p-event": "1.3.0",
+ "pify": "3.0.0"
+ }
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "duplexer2": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ }
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
+ "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "1.4.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.0.6",
+ "stream-shift": "1.0.0"
+ },
+ "dependencies": {
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0"
+ }
+ }
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "editorconfig": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz",
+ "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==",
+ "dev": true,
+ "requires": {
+ "bluebird": "3.5.1",
+ "commander": "2.15.1",
+ "lru-cache": "3.2.0",
+ "semver": "5.5.0",
+ "sigmund": "1.0.1"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz",
+ "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2"
+ }
+ }
+ }
+ },
+ "end-of-stream": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz",
+ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=",
+ "dev": true,
+ "requires": {
+ "once": "1.3.3"
+ },
+ "dependencies": {
+ "once": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
+ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ }
+ }
+ },
+ "entities": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.43",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.43.tgz",
+ "integrity": "sha512-cZd1vezWuTM5qMlasKWqQFioFKwO352nVBzhOTMUf/pKQl5Gcq5EdJzqtSNXKnFQSCJDiQZjCYlYbnzFB657OA==",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.3",
+ "es6-symbol": "3.1.1",
+ "next-tick": "1.0.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.43",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.43"
+ }
+ },
+ "es6-weak-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
+ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.43",
+ "es6-iterator": "2.0.3",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+ "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+ "dev": true,
+ "requires": {
+ "esprima": "2.7.3",
+ "estraverse": "1.9.3",
+ "esutils": "2.0.2",
+ "optionator": "0.8.2",
+ "source-map": "0.2.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+ "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "amdefine": "1.0.1"
+ }
+ }
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
+ "estraverse": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+ "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.43"
+ }
+ },
+ "event-stream": {
+ "version": "3.3.4",
+ "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+ "dev": true,
+ "requires": {
+ "duplexer": "0.1.1",
+ "from": "0.1.7",
+ "map-stream": "0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.3.3",
+ "stream-combiner": "0.0.4",
+ "through": "2.3.8"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "posix-character-classes": "0.1.1",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ }
+ }
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "dev": true,
+ "requires": {
+ "fill-range": "2.2.4"
+ },
+ "dependencies": {
+ "fill-range": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
+ "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
+ "dev": true,
+ "requires": {
+ "is-number": "2.1.0",
+ "isobject": "2.1.0",
+ "randomatic": "3.0.0",
+ "repeat-element": "1.1.2",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ }
+ },
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "expand-tilde": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+ "dev": true,
+ "requires": {
+ "homedir-polyfill": "1.0.1"
+ }
+ },
+ "ext-list": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
+ "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.33.0"
+ }
+ },
+ "ext-name": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
+ "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
+ "dev": true,
+ "requires": {
+ "ext-list": "2.2.2",
+ "sort-keys-length": "1.0.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "1.0.0",
+ "is-extendable": "1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "0.3.2",
+ "define-property": "1.0.0",
+ "expand-brackets": "2.1.4",
+ "extend-shallow": "2.0.1",
+ "fragment-cache": "0.2.1",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "1.0.2"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "1.0.0",
+ "is-data-descriptor": "1.0.0",
+ "kind-of": "6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fancy-log": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz",
+ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=",
+ "dev": true,
+ "requires": {
+ "ansi-gray": "0.1.1",
+ "color-support": "1.1.3",
+ "time-stamp": "1.1.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fd-slicer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+ "dev": true,
+ "requires": {
+ "pend": "1.2.0"
+ }
+ },
+ "file-type": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.7.1.tgz",
+ "integrity": "sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==",
+ "dev": true
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+ "dev": true
+ },
+ "filename-reserved-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
+ "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
+ "dev": true
+ },
+ "filenamify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz",
+ "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=",
+ "dev": true,
+ "requires": {
+ "filename-reserved-regex": "2.0.0",
+ "strip-outer": "1.0.1",
+ "trim-repeated": "1.0.0"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1",
+ "is-number": "3.0.0",
+ "repeat-string": "1.6.1",
+ "to-regex-range": "2.1.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ }
+ }
+ },
+ "find-index": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz",
+ "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "findup-sync": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
+ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
+ "dev": true,
+ "requires": {
+ "detect-file": "1.0.0",
+ "is-glob": "3.1.0",
+ "micromatch": "3.1.10",
+ "resolve-dir": "1.0.1"
+ }
+ },
+ "fined": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
+ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "is-plain-object": "2.0.4",
+ "object.defaults": "1.1.0",
+ "object.pick": "1.3.0",
+ "parse-filepath": "1.0.2"
+ }
+ },
+ "first-chunk-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz",
+ "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=",
+ "dev": true
+ },
+ "flagged-respawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
+ "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=",
+ "dev": true
+ },
+ "flat": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-4.0.0.tgz",
+ "integrity": "sha512-ji/WMv2jdsE+LaznpkIF9Haax0sdpTBozrz/Dtg4qSRMfbs8oVg4ypJunIRYPiMLvH/ed6OflXbnbTIKJhtgeg==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
+ "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.0.6"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
+ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.6",
+ "mime-types": "2.1.18"
+ }
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "0.2.2"
+ }
+ },
+ "from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.0.6"
+ }
+ },
+ "fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+ "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "jsonfile": "4.0.0",
+ "universalify": "0.1.1"
+ }
+ },
+ "fs-mkdirp-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
+ "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "through2": "2.0.3"
+ }
+ },
+ "fs-walk": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz",
+ "integrity": "sha1-9/yRw64e6tB8mYvF0N1B8tvr0zU=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
+ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "2.10.0",
+ "node-pre-gyp": "0.10.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.3.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "2.2.4"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "1.2.0",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.21",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": "2.1.2"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.11"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.2.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1",
+ "yallist": "3.0.2"
+ }
+ },
+ "minizlib": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "2.2.4"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "2.6.9",
+ "iconv-lite": "0.4.21",
+ "sax": "1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.10.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.3",
+ "mkdirp": "0.5.1",
+ "needle": "2.2.0",
+ "nopt": "4.0.1",
+ "npm-packlist": "1.1.10",
+ "npmlog": "4.1.2",
+ "rc": "1.2.7",
+ "rimraf": "2.6.2",
+ "semver": "5.5.0",
+ "tar": "4.4.1"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.1",
+ "osenv": "0.1.5"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.1.10",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "3.0.1",
+ "npm-bundled": "1.0.3"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "0.5.1",
+ "ini": "1.3.5",
+ "minimist": "1.2.0",
+ "strip-json-comments": "2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.5.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "1.0.1",
+ "fs-minipass": "1.2.5",
+ "minipass": "2.2.4",
+ "minizlib": "1.1.0",
+ "mkdirp": "0.5.1",
+ "safe-buffer": "5.1.1",
+ "yallist": "3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "fuzzy": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz",
+ "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg="
+ },
+ "gaze": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz",
+ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=",
+ "dev": true,
+ "requires": {
+ "globule": "0.1.0"
+ }
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+ "dev": true
+ },
+ "get-port": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
+ "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw="
+ },
+ "get-proxy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
+ "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
+ "dev": true,
+ "requires": {
+ "npm-conf": "1.1.3"
+ }
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true,
+ "requires": {
+ "glob-parent": "2.0.0",
+ "is-glob": "2.0.1"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true,
+ "requires": {
+ "is-glob": "2.0.1"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ }
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "3.1.0",
+ "path-dirname": "1.0.2"
+ }
+ },
+ "glob-stream": {
+ "version": "3.1.18",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz",
+ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=",
+ "dev": true,
+ "requires": {
+ "glob": "4.5.3",
+ "glob2base": "0.0.12",
+ "minimatch": "2.0.10",
+ "ordered-read-streams": "0.1.0",
+ "through2": "0.6.5",
+ "unique-stream": "1.0.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz",
+ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "2.0.10",
+ "once": "1.4.0"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
+ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.11"
+ }
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "glob-watcher": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz",
+ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=",
+ "dev": true,
+ "requires": {
+ "gaze": "0.5.2"
+ }
+ },
+ "glob2base": {
+ "version": "0.0.12",
+ "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz",
+ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=",
+ "dev": true,
+ "requires": {
+ "find-index": "0.1.1"
+ }
+ },
+ "global-modules": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+ "dev": true,
+ "requires": {
+ "global-prefix": "1.0.2",
+ "is-windows": "1.0.2",
+ "resolve-dir": "1.0.1"
+ }
+ },
+ "global-prefix": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "homedir-polyfill": "1.0.1",
+ "ini": "1.3.5",
+ "is-windows": "1.0.2",
+ "which": "1.3.1"
+ }
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "globule": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz",
+ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=",
+ "dev": true,
+ "requires": {
+ "glob": "3.1.21",
+ "lodash": "1.0.2",
+ "minimatch": "0.2.14"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "3.1.21",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
+ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "1.2.3",
+ "inherits": "1.0.2",
+ "minimatch": "0.2.14"
+ }
+ },
+ "graceful-fs": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz",
+ "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz",
+ "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz",
+ "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "2.7.3",
+ "sigmund": "1.0.1"
+ }
+ }
+ }
+ },
+ "glogg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz",
+ "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.1"
+ }
+ },
+ "got": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz",
+ "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "0.7.0",
+ "cacheable-request": "2.1.4",
+ "decompress-response": "3.3.0",
+ "duplexer3": "0.1.4",
+ "get-stream": "3.0.0",
+ "into-stream": "3.1.0",
+ "is-retry-allowed": "1.1.0",
+ "isurl": "1.0.0",
+ "lowercase-keys": "1.0.1",
+ "mimic-response": "1.0.0",
+ "p-cancelable": "0.4.1",
+ "p-timeout": "2.0.1",
+ "pify": "3.0.0",
+ "safe-buffer": "5.1.2",
+ "timed-out": "4.0.1",
+ "url-parse-lax": "3.0.0",
+ "url-to-options": "1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+ },
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "gulp": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz",
+ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=",
+ "dev": true,
+ "requires": {
+ "archy": "1.0.0",
+ "chalk": "1.1.3",
+ "deprecated": "0.0.1",
+ "gulp-util": "3.0.8",
+ "interpret": "1.1.0",
+ "liftoff": "2.5.0",
+ "minimist": "1.2.0",
+ "orchestrator": "0.3.8",
+ "pretty-hrtime": "1.0.3",
+ "semver": "4.3.6",
+ "tildify": "1.2.0",
+ "v8flags": "2.1.1",
+ "vinyl-fs": "0.3.14"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
+ "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-chmod": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz",
+ "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=",
+ "dev": true,
+ "requires": {
+ "deep-assign": "1.0.0",
+ "stat-mode": "0.2.2",
+ "through2": "2.0.3"
+ }
+ },
+ "gulp-debounced-watch": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/gulp-debounced-watch/-/gulp-debounced-watch-1.0.4.tgz",
+ "integrity": "sha1-WkfU4kzkY2XOguysMqKjA+QysSo=",
+ "dev": true,
+ "requires": {
+ "debounce-hashed": "0.1.2",
+ "gulp-watch": "4.3.11",
+ "object-assign": "3.0.0"
+ },
+ "dependencies": {
+ "gulp-watch": {
+ "version": "4.3.11",
+ "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-4.3.11.tgz",
+ "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.2",
+ "chokidar": "1.7.0",
+ "glob-parent": "3.1.0",
+ "gulp-util": "3.0.8",
+ "object-assign": "4.1.1",
+ "path-is-absolute": "1.0.1",
+ "readable-stream": "2.3.6",
+ "slash": "1.0.0",
+ "vinyl": "1.2.0",
+ "vinyl-file": "2.0.0"
+ },
+ "dependencies": {
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ }
+ }
+ },
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ },
+ "gulp-filter": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz",
+ "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=",
+ "dev": true,
+ "requires": {
+ "multimatch": "2.1.0",
+ "plugin-error": "0.1.2",
+ "streamfilter": "1.0.7"
+ }
+ },
+ "gulp-gitmodified": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/gulp-gitmodified/-/gulp-gitmodified-1.1.1.tgz",
+ "integrity": "sha1-hfNnWRXB1RtmgH8o3g67WR5+nfQ=",
+ "dev": true,
+ "requires": {
+ "gulp-util": "2.2.20",
+ "lodash.find": "3.2.1",
+ "through2": "2.0.3",
+ "vinyl": "0.4.6",
+ "which": "1.0.9"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
+ "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
+ "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
+ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "1.1.0",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "0.1.0",
+ "strip-ansi": "0.3.0",
+ "supports-color": "0.2.0"
+ }
+ },
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ }
+ },
+ "gulp-util": {
+ "version": "2.2.20",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz",
+ "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=",
+ "dev": true,
+ "requires": {
+ "chalk": "0.5.1",
+ "dateformat": "1.0.12",
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.template": "2.4.1",
+ "minimist": "0.2.0",
+ "multipipe": "0.1.2",
+ "through2": "0.5.1",
+ "vinyl": "0.2.3"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz",
+ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "3.0.0"
+ }
+ },
+ "vinyl": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz",
+ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=",
+ "dev": true,
+ "requires": {
+ "clone-stats": "0.0.1"
+ }
+ }
+ }
+ },
+ "has-ansi": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
+ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "0.2.1"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz",
+ "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=",
+ "dev": true
+ },
+ "lodash.escape": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz",
+ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=",
+ "dev": true,
+ "requires": {
+ "lodash._escapehtmlchar": "2.4.1",
+ "lodash._reunescapedhtml": "2.4.1",
+ "lodash.keys": "2.4.1"
+ }
+ },
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ },
+ "lodash.template": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz",
+ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=",
+ "dev": true,
+ "requires": {
+ "lodash._escapestringchar": "2.4.1",
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.defaults": "2.4.1",
+ "lodash.escape": "2.4.1",
+ "lodash.keys": "2.4.1",
+ "lodash.templatesettings": "2.4.1",
+ "lodash.values": "2.4.1"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz",
+ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.escape": "2.4.1"
+ }
+ },
+ "minimist": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz",
+ "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "strip-ansi": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
+ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "0.2.1"
+ }
+ },
+ "supports-color": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
+ "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "0.2.0",
+ "clone-stats": "0.0.1"
+ }
+ },
+ "which": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz",
+ "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
+ "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-gunzip": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz",
+ "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=",
+ "dev": true,
+ "requires": {
+ "through2": "0.6.5",
+ "vinyl": "0.4.6"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "0.2.0",
+ "clone-stats": "0.0.1"
+ }
+ }
+ }
+ },
+ "gulp-inline-source": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/gulp-inline-source/-/gulp-inline-source-3.2.0.tgz",
+ "integrity": "sha512-Ky5SKDgM517QZ6Jw9rKhYz+ynX9T4sr72iUW2fbOhqzN74D37DzWZDZnbKLSwdlTbbqt7JFq/JmUmT12qroW+A==",
+ "dev": true,
+ "requires": {
+ "inline-source": "5.2.7",
+ "plugin-error": "1.0.1",
+ "through2": "2.0.3"
+ },
+ "dependencies": {
+ "plugin-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz",
+ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "1.1.0",
+ "arr-diff": "4.0.0",
+ "arr-union": "3.1.0",
+ "extend-shallow": "3.0.2"
+ }
+ }
+ }
+ },
+ "gulp-json-editor": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.4.1.tgz",
+ "integrity": "sha512-20nYwO5Bec5X6DfXmBmHEtDAyluTkMguhuvCzqwrHDv/NzwOn3qS4ofAMw9L2gnWAmzxKzHAkFO19LNDWyTwlg==",
+ "dev": true,
+ "requires": {
+ "deepmerge": "2.1.1",
+ "detect-indent": "5.0.0",
+ "js-beautify": "1.7.5",
+ "plugin-error": "1.0.1",
+ "through2": "2.0.3"
+ },
+ "dependencies": {
+ "plugin-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz",
+ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "1.1.0",
+ "arr-diff": "4.0.0",
+ "arr-union": "3.1.0",
+ "extend-shallow": "3.0.2"
+ }
+ }
+ }
+ },
+ "gulp-remote-src-vscode": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.0.tgz",
+ "integrity": "sha512-/9vtSk9eI9DEWCqzGieglPqmx0WUQ9pwPHyHFpKmfxqdgqGJC2l0vFMdYs54hLdDsMDEZFLDL2J4ikjc4hQ5HQ==",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "node.extend": "1.1.6",
+ "request": "2.85.0",
+ "through2": "2.0.3",
+ "vinyl": "2.1.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+ "dev": true,
+ "requires": {
+ "clone": "2.1.1",
+ "clone-buffer": "1.0.0",
+ "clone-stats": "1.0.0",
+ "cloneable-readable": "1.1.2",
+ "remove-trailing-separator": "1.1.0",
+ "replace-ext": "1.0.0"
+ }
+ }
+ }
+ },
+ "gulp-sourcemaps": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz",
+ "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=",
+ "dev": true,
+ "requires": {
+ "@gulp-sourcemaps/identity-map": "1.0.1",
+ "@gulp-sourcemaps/map-sources": "1.0.0",
+ "acorn": "5.5.3",
+ "convert-source-map": "1.5.1",
+ "css": "2.2.3",
+ "debug-fabulous": "1.1.0",
+ "detect-newline": "2.1.0",
+ "graceful-fs": "4.1.11",
+ "source-map": "0.6.1",
+ "strip-bom-string": "1.0.0",
+ "through2": "2.0.3"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "gulp-symdest": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz",
+ "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "mkdirp": "0.5.1",
+ "queue": "3.1.0",
+ "vinyl-fs": "2.4.4"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "glob-stream": {
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz",
+ "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=",
+ "dev": true,
+ "requires": {
+ "extend": "3.0.1",
+ "glob": "5.0.15",
+ "glob-parent": "3.1.0",
+ "micromatch": "2.3.11",
+ "ordered-read-streams": "0.3.0",
+ "through2": "0.6.5",
+ "to-absolute-glob": "0.1.1",
+ "unique-stream": "2.2.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "gulp-sourcemaps": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz",
+ "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "1.5.1",
+ "graceful-fs": "4.1.11",
+ "strip-bom": "2.0.0",
+ "through2": "2.0.3",
+ "vinyl": "1.2.0"
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-valid-glob": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz",
+ "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz",
+ "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=",
+ "dev": true,
+ "requires": {
+ "is-stream": "1.1.0",
+ "readable-stream": "2.0.6"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "strip-bom-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz",
+ "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "1.0.0",
+ "strip-bom": "2.0.0"
+ }
+ },
+ "to-absolute-glob": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz",
+ "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1"
+ }
+ },
+ "unique-stream": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz",
+ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify": "1.0.1",
+ "through2-filter": "2.0.0"
+ }
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ },
+ "vinyl-fs": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz",
+ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=",
+ "dev": true,
+ "requires": {
+ "duplexify": "3.6.0",
+ "glob-stream": "5.3.5",
+ "graceful-fs": "4.1.11",
+ "gulp-sourcemaps": "1.6.0",
+ "is-valid-glob": "0.3.0",
+ "lazystream": "1.0.0",
+ "lodash.isequal": "4.5.0",
+ "merge-stream": "1.0.1",
+ "mkdirp": "0.5.1",
+ "object-assign": "4.1.1",
+ "readable-stream": "2.0.6",
+ "strip-bom": "2.0.0",
+ "strip-bom-stream": "1.0.0",
+ "through2": "2.0.3",
+ "through2-filter": "2.0.0",
+ "vali-date": "1.0.0",
+ "vinyl": "1.2.0"
+ }
+ }
+ }
+ },
+ "gulp-typescript": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-4.0.2.tgz",
+ "integrity": "sha512-Hhbn5Aa2l3T+tnn0KqsG6RRJmcYEsr3byTL2nBpNBeAK8pqug9Od4AwddU4JEI+hRw7mzZyjRbB8DDWR6paGVA==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "1.1.0",
+ "plugin-error": "0.1.2",
+ "source-map": "0.6.1",
+ "through2": "2.0.3",
+ "vinyl": "2.1.0",
+ "vinyl-fs": "3.0.3"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "glob-stream": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
+ "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
+ "dev": true,
+ "requires": {
+ "extend": "3.0.1",
+ "glob": "7.1.2",
+ "glob-parent": "3.1.0",
+ "is-negated-glob": "1.0.0",
+ "ordered-read-streams": "1.0.1",
+ "pumpify": "1.5.1",
+ "readable-stream": "2.3.6",
+ "remove-trailing-separator": "1.1.0",
+ "to-absolute-glob": "2.0.2",
+ "unique-stream": "2.2.1"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
+ "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.3.6"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "unique-stream": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz",
+ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify": "1.0.1",
+ "through2-filter": "2.0.0"
+ }
+ },
+ "vinyl": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+ "dev": true,
+ "requires": {
+ "clone": "2.1.1",
+ "clone-buffer": "1.0.0",
+ "clone-stats": "1.0.0",
+ "cloneable-readable": "1.1.2",
+ "remove-trailing-separator": "1.1.0",
+ "replace-ext": "1.0.0"
+ }
+ },
+ "vinyl-fs": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
+ "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==",
+ "dev": true,
+ "requires": {
+ "fs-mkdirp-stream": "1.0.0",
+ "glob-stream": "6.1.0",
+ "graceful-fs": "4.1.11",
+ "is-valid-glob": "1.0.0",
+ "lazystream": "1.0.0",
+ "lead": "1.0.0",
+ "object.assign": "4.1.0",
+ "pumpify": "1.5.1",
+ "readable-stream": "2.3.6",
+ "remove-bom-buffer": "3.0.0",
+ "remove-bom-stream": "1.2.0",
+ "resolve-options": "1.1.0",
+ "through2": "2.0.3",
+ "to-through": "2.0.0",
+ "value-or-function": "3.0.0",
+ "vinyl": "2.1.0",
+ "vinyl-sourcemap": "1.1.0"
+ }
+ }
+ }
+ },
+ "gulp-untar": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz",
+ "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "streamifier": "0.1.1",
+ "tar": "2.2.1",
+ "through2": "2.0.3",
+ "vinyl": "1.2.0"
+ },
+ "dependencies": {
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ },
+ "gulp-util": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
+ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-uniq": "1.0.3",
+ "beeper": "1.1.1",
+ "chalk": "1.1.3",
+ "dateformat": "2.2.0",
+ "fancy-log": "1.3.2",
+ "gulplog": "1.0.0",
+ "has-gulplog": "0.1.0",
+ "lodash._reescape": "3.0.0",
+ "lodash._reevaluate": "3.0.0",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.template": "3.6.2",
+ "minimist": "1.2.0",
+ "multipipe": "0.1.2",
+ "object-assign": "3.0.0",
+ "replace-ext": "0.0.1",
+ "through2": "2.0.3",
+ "vinyl": "0.5.3"
+ },
+ "dependencies": {
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-vinyl-zip": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz",
+ "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "queue": "4.4.2",
+ "through2": "2.0.3",
+ "vinyl": "2.1.0",
+ "vinyl-fs": "2.4.4",
+ "yauzl": "2.9.1",
+ "yazl": "2.4.3"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0"
+ }
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
+ "clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "glob-stream": {
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz",
+ "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=",
+ "dev": true,
+ "requires": {
+ "extend": "3.0.1",
+ "glob": "5.0.15",
+ "glob-parent": "3.1.0",
+ "micromatch": "2.3.11",
+ "ordered-read-streams": "0.3.0",
+ "through2": "0.6.5",
+ "to-absolute-glob": "0.1.1",
+ "unique-stream": "2.2.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "gulp-sourcemaps": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz",
+ "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "1.5.1",
+ "graceful-fs": "4.1.11",
+ "strip-bom": "2.0.0",
+ "through2": "2.0.3",
+ "vinyl": "1.2.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-valid-glob": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz",
+ "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz",
+ "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=",
+ "dev": true,
+ "requires": {
+ "is-stream": "1.1.0",
+ "readable-stream": "2.0.6"
+ }
+ },
+ "queue": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz",
+ "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "strip-bom-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz",
+ "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "1.0.0",
+ "strip-bom": "2.0.0"
+ }
+ },
+ "to-absolute-glob": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz",
+ "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1"
+ }
+ },
+ "unique-stream": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz",
+ "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify": "1.0.1",
+ "through2-filter": "2.0.0"
+ }
+ },
+ "vinyl": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+ "dev": true,
+ "requires": {
+ "clone": "2.1.1",
+ "clone-buffer": "1.0.0",
+ "clone-stats": "1.0.0",
+ "cloneable-readable": "1.1.2",
+ "remove-trailing-separator": "1.1.0",
+ "replace-ext": "1.0.0"
+ }
+ },
+ "vinyl-fs": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz",
+ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=",
+ "dev": true,
+ "requires": {
+ "duplexify": "3.6.0",
+ "glob-stream": "5.3.5",
+ "graceful-fs": "4.1.11",
+ "gulp-sourcemaps": "1.6.0",
+ "is-valid-glob": "0.3.0",
+ "lazystream": "1.0.0",
+ "lodash.isequal": "4.5.0",
+ "merge-stream": "1.0.1",
+ "mkdirp": "0.5.1",
+ "object-assign": "4.1.1",
+ "readable-stream": "2.0.6",
+ "strip-bom": "2.0.0",
+ "strip-bom-stream": "1.0.0",
+ "through2": "2.0.3",
+ "through2-filter": "2.0.0",
+ "vali-date": "1.0.0",
+ "vinyl": "1.2.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "gulp-watch": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.0.tgz",
+ "integrity": "sha512-q+HLppxXd11z9ndqql4Z0sd5xOAesJjycl0PRaq6ImK7b1BqBRL37YvxEE8ngUdIfpfHa0O9OCoovoggcFpCaQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.2",
+ "chokidar": "2.0.3",
+ "glob-parent": "3.1.0",
+ "gulp-util": "3.0.8",
+ "object-assign": "4.1.1",
+ "path-is-absolute": "1.0.1",
+ "readable-stream": "2.3.6",
+ "slash": "1.0.0",
+ "vinyl": "2.1.0",
+ "vinyl-file": "2.0.0"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz",
+ "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "2.0.0",
+ "async-each": "1.0.1",
+ "braces": "2.3.2",
+ "fsevents": "1.2.4",
+ "glob-parent": "3.1.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "4.0.0",
+ "normalize-path": "2.1.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0",
+ "upath": "1.1.0"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "3.1.10",
+ "normalize-path": "2.1.1"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "2.1.1"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "vinyl": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+ "dev": true,
+ "requires": {
+ "clone": "2.1.1",
+ "clone-buffer": "1.0.0",
+ "clone-stats": "1.0.0",
+ "cloneable-readable": "1.1.2",
+ "remove-trailing-separator": "1.1.0",
+ "replace-ext": "1.0.0"
+ }
+ }
+ }
+ },
+ "gulplog": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
+ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
+ "dev": true,
+ "requires": {
+ "glogg": "1.0.1"
+ }
+ },
+ "handlebars": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
+ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "optimist": "0.6.1",
+ "source-map": "0.4.4",
+ "uglify-js": "2.8.29"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true,
+ "requires": {
+ "amdefine": "1.0.1"
+ }
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
+ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
+ "requires": {
+ "ajv": "5.5.2",
+ "har-schema": "2.0.0"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "has-gulplog": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
+ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.1"
+ }
+ },
+ "has-symbol-support-x": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
+ "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-to-string-tag-x": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
+ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
+ "dev": true,
+ "requires": {
+ "has-symbol-support-x": "1.4.2"
+ }
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "2.0.6",
+ "has-values": "1.0.0",
+ "isobject": "3.0.1"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "3.0.0",
+ "kind-of": "4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "hawk": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
+ "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
+ "requires": {
+ "boom": "4.3.1",
+ "cryptiles": "3.1.2",
+ "hoek": "4.2.1",
+ "sntp": "2.1.0"
+ }
+ },
+ "he": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+ "dev": true
+ },
+ "hoek": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
+ "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
+ },
+ "homedir-polyfill": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
+ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
+ "dev": true,
+ "requires": {
+ "parse-passwd": "1.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
+ "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0",
+ "domhandler": "2.4.2",
+ "domutils": "1.7.0",
+ "entities": "1.1.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.0.6"
+ }
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "jsprim": "1.4.1",
+ "sshpk": "1.14.1"
+ }
+ },
+ "husky": {
+ "version": "0.14.3",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
+ "integrity": "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==",
+ "dev": true,
+ "requires": {
+ "is-ci": "1.1.0",
+ "normalize-path": "1.0.0",
+ "strip-indent": "2.0.0"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
+ "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+ "dev": true
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.21",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz",
+ "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==",
+ "requires": {
+ "safer-buffer": "2.1.2"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz",
+ "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "2.0.1"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "inline-source": {
+ "version": "5.2.7",
+ "resolved": "https://registry.npmjs.org/inline-source/-/inline-source-5.2.7.tgz",
+ "integrity": "sha512-RvMOGMXxAqqve4ld128B7TYyNR2aP1LB38dcSpWFmqXrhKPuey1+yFU6kFUgyH8IWX+gRZdWtHN4eQ9d0IpFZg==",
+ "dev": true,
+ "requires": {
+ "csso": "3.4.0",
+ "htmlparser2": "3.9.2",
+ "is-plain-obj": "1.1.0",
+ "object-assign": "4.1.1",
+ "svgo": "0.7.2",
+ "uglify-js": "3.3.28"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.3.28",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz",
+ "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==",
+ "dev": true,
+ "requires": {
+ "commander": "2.15.1",
+ "source-map": "0.6.1"
+ }
+ }
+ }
+ },
+ "interpret": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
+ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=",
+ "dev": true
+ },
+ "into-stream": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+ "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
+ "dev": true,
+ "requires": {
+ "from2": "2.3.0",
+ "p-is-promise": "1.1.0"
+ }
+ },
+ "inversify": {
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/inversify/-/inversify-4.11.1.tgz",
+ "integrity": "sha512-9bs/36crPdTSOCcoomHMb96s+B8W0+2c9dHFP/Srv9ZQaPnUvsMgzmMHfgVECqfHVUIW+M5S7SYOjoig8khWuQ=="
+ },
+ "is": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz",
+ "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=",
+ "dev": true
+ },
+ "is-absolute": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+ "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+ "dev": true,
+ "requires": {
+ "is-relative": "1.0.0",
+ "is-windows": "1.0.2"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "1.11.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1"
+ }
+ },
+ "is-ci": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz",
+ "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==",
+ "dev": true,
+ "requires": {
+ "ci-info": "1.1.3"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+ "dev": true
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "dev": true,
+ "requires": {
+ "is-primitive": "2.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "2.1.1"
+ }
+ },
+ "is-natural-number": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
+ "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=",
+ "dev": true
+ },
+ "is-negated-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
+ "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
+ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
+ "dev": true
+ },
+ "is-odd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz",
+ "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "4.0.0"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+ "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+ "dev": true
+ }
+ }
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "1.0.1"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "3.0.1"
+ }
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "dev": true
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-relative": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+ "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+ "dev": true,
+ "requires": {
+ "is-unc-path": "1.0.0"
+ }
+ },
+ "is-retry-allowed": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
+ "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=",
+ "dev": true
+ },
+ "is-running": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz",
+ "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "is-unc-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+ "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+ "dev": true,
+ "requires": {
+ "unc-path-regex": "0.1.2"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-valid-glob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
+ "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "istanbul": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+ "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1.0.9",
+ "async": "1.5.2",
+ "escodegen": "1.8.1",
+ "esprima": "2.7.3",
+ "glob": "5.0.15",
+ "handlebars": "4.0.11",
+ "js-yaml": "3.11.0",
+ "mkdirp": "0.5.1",
+ "nopt": "3.0.6",
+ "once": "1.4.0",
+ "resolve": "1.1.7",
+ "supports-color": "3.2.3",
+ "which": "1.3.1",
+ "wordwrap": "1.0.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+ "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
+ "dev": true
+ },
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true,
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ }
+ }
+ },
+ "isurl": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
+ "dev": true,
+ "requires": {
+ "has-to-string-tag-x": "1.4.1",
+ "is-object": "1.0.1"
+ }
+ },
+ "js-beautify": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.5.tgz",
+ "integrity": "sha512-9OhfAqGOrD7hoQBLJMTA+BKuKmoEtTJXzZ7WDF/9gvjtey1koVLuZqIY6c51aPDjbNdNtIXAkiWKVhziawE9Og==",
+ "dev": true,
+ "requires": {
+ "config-chain": "1.1.11",
+ "editorconfig": "0.13.3",
+ "mkdirp": "0.5.1",
+ "nopt": "3.0.6"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
+ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.10",
+ "esprima": "4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+ "dev": true
+ }
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "optional": true
+ },
+ "json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "dev": true
+ },
+ "json-edm-parser": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz",
+ "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=",
+ "dev": true,
+ "requires": {
+ "jsonparse": "1.2.0"
+ }
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dev": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "4.1.11"
+ }
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true
+ },
+ "jsonparse": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz",
+ "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "just-extend": {
+ "version": "1.1.27",
+ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz",
+ "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==",
+ "dev": true
+ },
+ "keyv": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
+ "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+ "dev": true,
+ "optional": true
+ },
+ "lazystream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
+ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6"
+ }
+ },
+ "lead": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz",
+ "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=",
+ "dev": true,
+ "requires": {
+ "flush-write-stream": "1.0.3"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "liftoff": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
+ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=",
+ "dev": true,
+ "requires": {
+ "extend": "3.0.1",
+ "findup-sync": "2.0.0",
+ "fined": "1.1.0",
+ "flagged-respawn": "1.0.0",
+ "is-plain-object": "2.0.4",
+ "object.map": "1.0.1",
+ "rechoir": "0.6.2",
+ "resolve": "1.7.1"
+ }
+ },
+ "line-by-line": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/line-by-line/-/line-by-line-0.1.6.tgz",
+ "integrity": "sha512-MmwVPfOyp0lWnEZ3fBA8Ah4pMFvxO6WgWovqZNu7Y4J0TNnGcsV4S1LzECHbdgqk1hoHc2mFP1Axc37YUqwafg=="
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
+ },
+ "lodash._basecallback": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecallback/-/lodash._basecallback-3.3.1.tgz",
+ "integrity": "sha1-t7K7Q9whYEJKIczybFfkQ3cqjic=",
+ "dev": true,
+ "requires": {
+ "lodash._baseisequal": "3.0.7",
+ "lodash._bindcallback": "3.0.1",
+ "lodash.isarray": "3.0.4",
+ "lodash.pairs": "3.0.1"
+ }
+ },
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._baseeach": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash._baseeach/-/lodash._baseeach-3.0.4.tgz",
+ "integrity": "sha1-z4cGVyyhROjZ11InyZDamC+TKvM=",
+ "dev": true,
+ "requires": {
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash._basefind": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basefind/-/lodash._basefind-3.0.0.tgz",
+ "integrity": "sha1-srugXMZF+XLeLPkl+iv2Og9gyK4=",
+ "dev": true
+ },
+ "lodash._basefindindex": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/lodash._basefindindex/-/lodash._basefindindex-3.6.0.tgz",
+ "integrity": "sha1-8IM2ChsCJBjtgbyJm+sxLiHnSk8=",
+ "dev": true
+ },
+ "lodash._baseisequal": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz",
+ "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=",
+ "dev": true,
+ "requires": {
+ "lodash.isarray": "3.0.4",
+ "lodash.istypedarray": "3.0.6",
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash._basetostring": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
+ "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
+ "dev": true
+ },
+ "lodash._basevalues": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
+ "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
+ "dev": true
+ },
+ "lodash._bindcallback": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz",
+ "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=",
+ "dev": true
+ },
+ "lodash._escapehtmlchar": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz",
+ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=",
+ "dev": true,
+ "requires": {
+ "lodash._htmlescapes": "2.4.1"
+ }
+ },
+ "lodash._escapestringchar": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz",
+ "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash._htmlescapes": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz",
+ "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash._isnative": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz",
+ "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=",
+ "dev": true
+ },
+ "lodash._objecttypes": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz",
+ "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=",
+ "dev": true
+ },
+ "lodash._reescape": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
+ "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
+ "dev": true
+ },
+ "lodash._reevaluate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
+ "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
+ "dev": true
+ },
+ "lodash._reunescapedhtml": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz",
+ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=",
+ "dev": true,
+ "requires": {
+ "lodash._htmlescapes": "2.4.1",
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ },
+ "lodash._shimkeys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz",
+ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1"
+ }
+ },
+ "lodash.defaults": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz",
+ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1",
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "lodash.escape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
+ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ }
+ },
+ "lodash.find": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-3.2.1.tgz",
+ "integrity": "sha1-BG4xnzrOkSrGySRsf2g8XsB7Nq0=",
+ "dev": true,
+ "requires": {
+ "lodash._basecallback": "3.3.1",
+ "lodash._baseeach": "3.0.4",
+ "lodash._basefind": "3.0.0",
+ "lodash._basefindindex": "3.6.0",
+ "lodash.isarray": "3.0.4",
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
+ "dev": true
+ },
+ "lodash.isobject": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz",
+ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1"
+ }
+ },
+ "lodash.istypedarray": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz",
+ "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=",
+ "dev": true
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ }
+ },
+ "lodash.pairs": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz",
+ "integrity": "sha1-u+CNV4bu6qCaFckevw3LfSvjJqk=",
+ "dev": true,
+ "requires": {
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
+ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
+ "dev": true
+ },
+ "lodash.template": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
+ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash._basetostring": "3.0.1",
+ "lodash._basevalues": "3.0.0",
+ "lodash._isiterateecall": "3.0.9",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0",
+ "lodash.keys": "3.1.2",
+ "lodash.restparam": "3.6.1",
+ "lodash.templatesettings": "3.1.1"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
+ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0"
+ }
+ },
+ "lodash.values": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz",
+ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=",
+ "dev": true,
+ "requires": {
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "lolex": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.0.tgz",
+ "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==",
+ "dev": true
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+ "dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
+ "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
+ "dev": true
+ },
+ "lru-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
+ "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.43"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "3.0.0"
+ }
+ },
+ "make-iterator": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
+ "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "1.0.1"
+ }
+ },
+ "math-random": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
+ "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
+ "dev": true
+ },
+ "md5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz",
+ "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=",
+ "requires": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "1.1.6"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "dev": true,
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.3"
+ }
+ },
+ "mdn-data": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
+ "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==",
+ "dev": true
+ },
+ "memoizee": {
+ "version": "0.4.12",
+ "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz",
+ "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.43",
+ "es6-weak-map": "2.0.2",
+ "event-emitter": "0.3.5",
+ "is-promise": "2.1.0",
+ "lru-queue": "0.1.0",
+ "next-tick": "1.0.0",
+ "timers-ext": "0.1.5"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.4.0",
+ "object-assign": "4.1.1",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ }
+ },
+ "merge-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
+ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "4.0.0",
+ "array-unique": "0.3.2",
+ "braces": "2.3.2",
+ "define-property": "2.0.2",
+ "extend-shallow": "3.0.2",
+ "extglob": "2.0.4",
+ "fragment-cache": "0.2.1",
+ "kind-of": "6.0.2",
+ "nanomatch": "1.2.9",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ }
+ },
+ "mime-db": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
+ "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
+ },
+ "mime-types": {
+ "version": "2.1.18",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
+ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+ "requires": {
+ "mime-db": "1.33.0"
+ }
+ },
+ "mimic-response": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz",
+ "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "1.1.11"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "mixin-deep": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2",
+ "is-extendable": "1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ }
+ }
+ },
+ "mocha": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
+ "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.1",
+ "commander": "2.15.1",
+ "debug": "3.1.0",
+ "diff": "3.5.0",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.2",
+ "growl": "1.10.5",
+ "he": "1.1.1",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "supports-color": "5.4.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "mocha-junit-reporter": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz",
+ "integrity": "sha1-LlFJ7UD8XS48px5C21qx/snG2Fw=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "md5": "2.2.1",
+ "mkdirp": "0.5.1",
+ "strip-ansi": "4.0.0",
+ "xml": "1.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "multimatch": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
+ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-union": "1.0.2",
+ "arrify": "1.0.1",
+ "minimatch": "3.0.4"
+ }
+ },
+ "multipipe": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
+ "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
+ "dev": true,
+ "requires": {
+ "duplexer2": "0.0.2"
+ }
+ },
+ "named-js-regexp": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/named-js-regexp/-/named-js-regexp-1.3.3.tgz",
+ "integrity": "sha512-zIUAXzGQOp16VR0Ct89SDstU62hzAPBluNUrUrsdD7MNSRbm/vyqGhEnp+4hnsMjmX3C2wh1cbIEP0joKMFLxw=="
+ },
+ "nan": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
+ "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz",
+ "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "4.0.0",
+ "array-unique": "0.3.2",
+ "define-property": "2.0.2",
+ "extend-shallow": "3.0.2",
+ "fragment-cache": "0.2.1",
+ "is-odd": "2.0.0",
+ "is-windows": "1.0.2",
+ "kind-of": "6.0.2",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.2",
+ "snapdragon": "0.8.2",
+ "to-regex": "3.0.2"
+ }
+ },
+ "natives": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz",
+ "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==",
+ "dev": true
+ },
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
+ "dev": true
+ },
+ "nice-try": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz",
+ "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==",
+ "dev": true
+ },
+ "nise": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz",
+ "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/formatio": "2.0.0",
+ "just-extend": "1.1.27",
+ "lolex": "2.7.0",
+ "path-to-regexp": "1.7.0",
+ "text-encoding": "0.6.4"
+ }
+ },
+ "node-has-native-dependencies": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/node-has-native-dependencies/-/node-has-native-dependencies-1.0.2.tgz",
+ "integrity": "sha1-MVLsl1O2ZB5NMi0YXdSTBkmto9o=",
+ "dev": true,
+ "requires": {
+ "fs-walk": "0.0.1"
+ }
+ },
+ "node-stream-zip": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.6.0.tgz",
+ "integrity": "sha512-py/b/mLnyp/VvHCAl/Pqn6y+oLJrWpLYpLxJmGEAs1vxYDoAxgdbOzYgjpjEju/jrHzxUPurF+kT6KTfb+a4tA=="
+ },
+ "node.extend": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz",
+ "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=",
+ "dev": true,
+ "requires": {
+ "is": "3.2.1"
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1.1.1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "2.6.0",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.5.0",
+ "validate-npm-package-license": "3.0.3"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "1.1.0"
+ }
+ },
+ "normalize-url": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
+ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
+ "dev": true,
+ "requires": {
+ "prepend-http": "2.0.0",
+ "query-string": "5.1.1",
+ "sort-keys": "2.0.0"
+ },
+ "dependencies": {
+ "sort-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "1.1.0"
+ }
+ }
+ }
+ },
+ "now-and-later": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz",
+ "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0"
+ }
+ },
+ "npm-conf": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
+ "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
+ "dev": true,
+ "requires": {
+ "config-chain": "1.1.11",
+ "pify": "3.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "0.1.1",
+ "define-property": "0.2.5",
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "object-keys": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "3.0.1"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "function-bind": "1.1.1",
+ "has-symbols": "1.0.0",
+ "object-keys": "1.0.11"
+ }
+ },
+ "object.defaults": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
+ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=",
+ "dev": true,
+ "requires": {
+ "array-each": "1.0.1",
+ "array-slice": "1.1.0",
+ "for-own": "1.0.0",
+ "isobject": "3.0.1"
+ }
+ },
+ "object.map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
+ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=",
+ "dev": true,
+ "requires": {
+ "for-own": "1.0.0",
+ "make-iterator": "1.0.1"
+ }
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "dev": true,
+ "requires": {
+ "for-own": "0.1.5",
+ "is-extendable": "0.1.1"
+ },
+ "dependencies": {
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ }
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "3.0.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "opn": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
+ "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
+ "requires": {
+ "is-wsl": "1.1.0"
+ }
+ },
+ "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.10",
+ "wordwrap": "0.0.3"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ }
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ }
+ },
+ "orchestrator": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz",
+ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "0.1.5",
+ "sequencify": "0.0.7",
+ "stream-consume": "0.1.1"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz",
+ "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "p-cancelable": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
+ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==",
+ "dev": true
+ },
+ "p-event": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz",
+ "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=",
+ "dev": true,
+ "requires": {
+ "p-timeout": "1.2.1"
+ },
+ "dependencies": {
+ "p-timeout": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
+ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
+ "dev": true,
+ "requires": {
+ "p-finally": "1.0.0"
+ }
+ }
+ }
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=",
+ "dev": true
+ },
+ "p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "dev": true
+ },
+ "p-timeout": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
+ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
+ "dev": true,
+ "requires": {
+ "p-finally": "1.0.0"
+ }
+ },
+ "parse-filepath": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
+ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=",
+ "dev": true,
+ "requires": {
+ "is-absolute": "1.0.0",
+ "map-cache": "0.2.2",
+ "path-root": "0.1.1"
+ }
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true,
+ "requires": {
+ "glob-base": "0.3.0",
+ "is-dotfile": "1.0.3",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1"
+ },
+ "dependencies": {
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ }
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "1.3.1"
+ }
+ },
+ "parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "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="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+ "dev": true
+ },
+ "path-root": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
+ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=",
+ "dev": true,
+ "requires": {
+ "path-root-regex": "0.1.2"
+ }
+ },
+ "path-root-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
+ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "dev": true,
+ "requires": {
+ "isarray": "0.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ }
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "pathval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+ "dev": true
+ },
+ "pause-stream": {
+ "version": "0.0.11",
+ "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+ "dev": true,
+ "requires": {
+ "through": "2.3.8"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "pidusage": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-1.2.0.tgz",
+ "integrity": "sha512-OGo+iSOk44HRJ8q15AyG570UYxcm5u+R99DI8Khu8P3tKGkVu5EZX4ywHglWSTMNNXQ274oeGpYrvFEhDIFGPg=="
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
+ "requires": {
+ "ansi-cyan": "0.1.1",
+ "ansi-red": "0.1.1",
+ "arr-diff": "1.1.0",
+ "arr-union": "2.1.0",
+ "extend-shallow": "1.1.4"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0",
+ "array-slice": "0.2.3"
+ }
+ },
+ "arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true
+ },
+ "array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "requires": {
+ "kind-of": "1.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "postinstall-build": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.1.tgz",
+ "integrity": "sha1-uRepB5smF42aJK9aXNjLSpkdEbk=",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "pretty-hrtime": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
+ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "1.4.1",
+ "once": "1.4.0"
+ },
+ "dependencies": {
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0"
+ }
+ }
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "requires": {
+ "duplexify": "3.6.0",
+ "inherits": "2.0.3",
+ "pump": "2.0.1"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "query-string": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
+ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
+ "dev": true,
+ "requires": {
+ "decode-uri-component": "0.2.0",
+ "object-assign": "4.1.1",
+ "strict-uri-encode": "1.1.0"
+ }
+ },
+ "querystringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz",
+ "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
+ "dev": true
+ },
+ "queue": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz",
+ "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "randomatic": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz",
+ "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==",
+ "dev": true,
+ "requires": {
+ "is-number": "4.0.0",
+ "kind-of": "6.0.2",
+ "math-random": "1.0.1"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+ "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "1.1.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "minimatch": "3.0.4",
+ "readable-stream": "2.0.6",
+ "set-immediate-shim": "1.0.1"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "requires": {
+ "resolve": "1.7.1"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
+ "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A=="
+ },
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "dev": true,
+ "requires": {
+ "is-equal-shallow": "0.1.3"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "3.0.2",
+ "safe-regex": "1.1.0"
+ }
+ },
+ "relative": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/relative/-/relative-3.0.2.tgz",
+ "integrity": "sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8=",
+ "dev": true,
+ "requires": {
+ "isobject": "2.1.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "remap-istanbul": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.10.1.tgz",
+ "integrity": "sha512-gsNQXs5kJLhErICSyYhzVZ++C8LBW8dgwr874Y2QvzAUS75zBlD/juZgXs39nbYJ09fZDlX2AVLVJAY2jbFJoQ==",
+ "dev": true,
+ "requires": {
+ "amdefine": "1.0.1",
+ "istanbul": "0.4.5",
+ "minimatch": "3.0.4",
+ "plugin-error": "0.1.2",
+ "source-map": "0.6.1",
+ "through2": "2.0.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
+ "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "remove-bom-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
+ "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6",
+ "is-utf8": "0.2.1"
+ }
+ },
+ "remove-bom-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz",
+ "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=",
+ "dev": true,
+ "requires": {
+ "remove-bom-buffer": "3.0.0",
+ "safe-buffer": "5.1.2",
+ "through2": "2.0.3"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "1.0.2"
+ }
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "request": {
+ "version": "2.85.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz",
+ "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==",
+ "requires": {
+ "aws-sign2": "0.7.0",
+ "aws4": "1.7.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.6",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.3.2",
+ "har-validator": "5.0.3",
+ "hawk": "6.0.2",
+ "http-signature": "1.2.0",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.18",
+ "oauth-sign": "0.8.2",
+ "performance-now": "2.1.0",
+ "qs": "6.5.2",
+ "safe-buffer": "5.1.2",
+ "stringstream": "0.0.6",
+ "tough-cookie": "2.3.4",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.2.1"
+ }
+ },
+ "request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
+ "requires": {
+ "throttleit": "1.0.0"
+ }
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
+ "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
+ "dev": true,
+ "requires": {
+ "path-parse": "1.0.5"
+ }
+ },
+ "resolve-dir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "global-modules": "1.0.0"
+ }
+ },
+ "resolve-options": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz",
+ "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=",
+ "dev": true,
+ "requires": {
+ "value-or-function": "3.0.0"
+ }
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "dev": true,
+ "requires": {
+ "lowercase-keys": "1.0.1"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "retyped-diff-match-patch-tsd-ambient": {
+ "version": "1.0.0-1",
+ "resolved": "https://registry.npmjs.org/retyped-diff-match-patch-tsd-ambient/-/retyped-diff-match-patch-tsd-ambient-1.0.0-1.tgz",
+ "integrity": "sha1-Jkgr9JFcftn4MAu1y+xI/U/1vGI=",
+ "dev": true
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "align-text": "0.1.4"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "rxjs": {
+ "version": "5.5.9",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.9.tgz",
+ "integrity": "sha512-DHG9AHmCmgaFWgjBcXp6NxFDmh3MvIA62GqTWmLnTzr/3oZ6h5hLD8NA+9j+GF0jEwklNIpI4KuuyLG8UWMEvQ==",
+ "requires": {
+ "symbol-observable": "1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "0.1.15"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "samsam": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz",
+ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==",
+ "dev": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "seek-bzip": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
+ "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
+ "dev": true,
+ "requires": {
+ "commander": "2.8.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
+ "dev": true,
+ "requires": {
+ "graceful-readlink": "1.0.1"
+ }
+ }
+ }
+ },
+ "semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
+ },
+ "sequencify": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz",
+ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=",
+ "dev": true
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1",
+ "is-extendable": "0.1.1",
+ "is-plain-object": "2.0.4",
+ "split-string": "3.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shortid": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.8.tgz",
+ "integrity": "sha1-AzsRfWoul1gE9vCWnb59PQs1UTE=",
+ "dev": true
+ },
+ "sigmund": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "sinon": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz",
+ "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/formatio": "2.0.0",
+ "diff": "3.5.0",
+ "lodash.get": "4.4.2",
+ "lolex": "2.7.0",
+ "nise": "1.3.3",
+ "supports-color": "5.4.0",
+ "type-detect": "4.0.8"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "0.11.2",
+ "debug": "2.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "map-cache": "0.2.2",
+ "source-map": "0.5.7",
+ "source-map-resolve": "0.5.2",
+ "use": "3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "1.0.0",
+ "isobject": "3.0.1",
+ "snapdragon-util": "3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "1.0.2"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "1.0.0",
+ "is-data-descriptor": "1.0.0",
+ "kind-of": "6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "sntp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
+ "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
+ "requires": {
+ "hoek": "4.2.1"
+ }
+ },
+ "sort-keys": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
+ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "1.1.0"
+ }
+ },
+ "sort-keys-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
+ "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
+ "dev": true,
+ "requires": {
+ "sort-keys": "1.1.2"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "2.1.1",
+ "decode-uri-component": "0.2.0",
+ "resolve-url": "0.2.1",
+ "source-map-url": "0.4.0",
+ "urix": "0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz",
+ "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "1.0.0",
+ "source-map": "0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "sparkles": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
+ "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "3.0.0",
+ "spdx-license-ids": "3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+ "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "2.1.0",
+ "spdx-license-ids": "3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
+ "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
+ "dev": true
+ },
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "dev": true,
+ "requires": {
+ "through": "2.3.8"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "3.0.2"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
+ "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "stat-mode": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz",
+ "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=",
+ "dev": true
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "0.2.5",
+ "object-copy": "0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ }
+ }
+ },
+ "stream-combiner": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+ "dev": true,
+ "requires": {
+ "duplexer": "0.1.1"
+ }
+ },
+ "stream-consume": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz",
+ "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==",
+ "dev": true
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "streamfilter": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz",
+ "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6"
+ }
+ },
+ "streamifier": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz",
+ "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
+ "dev": true
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ },
+ "stringstream": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
+ "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA=="
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-bom": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz",
+ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "1.0.0",
+ "is-utf8": "0.2.1"
+ }
+ },
+ "strip-bom-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz",
+ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "2.0.0",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "first-chunk-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz",
+ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ }
+ }
+ },
+ "strip-bom-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
+ "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=",
+ "dev": true
+ },
+ "strip-dirs": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
+ "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
+ "dev": true,
+ "requires": {
+ "is-natural-number": "4.0.1"
+ }
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ },
+ "strip-outer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
+ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "sudo-prompt": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.0.tgz",
+ "integrity": "sha512-n5Nv2lIZaWfVBg10EWC8yaJCB6xV7sEsuaISAVFIS9F4fTRjy/O35A82lkweKuSqQItDlKOGQpTHK9/udQhRRw=="
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "svgo": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz",
+ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=",
+ "dev": true,
+ "requires": {
+ "coa": "1.0.4",
+ "colors": "1.1.2",
+ "csso": "2.3.2",
+ "js-yaml": "3.7.0",
+ "mkdirp": "0.5.1",
+ "sax": "1.2.4",
+ "whet.extend": "0.9.9"
+ },
+ "dependencies": {
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "csso": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz",
+ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=",
+ "dev": true,
+ "requires": {
+ "clap": "1.2.3",
+ "source-map": "0.5.7"
+ }
+ },
+ "js-yaml": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
+ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.10",
+ "esprima": "2.7.3"
+ }
+ }
+ }
+ },
+ "symbol-observable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ="
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+ "dev": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "tar-stream": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz",
+ "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==",
+ "dev": true,
+ "requires": {
+ "bl": "1.2.2",
+ "buffer-alloc": "1.2.0",
+ "end-of-stream": "1.4.1",
+ "fs-constants": "1.0.0",
+ "readable-stream": "2.3.6",
+ "to-buffer": "1.1.1",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "text-encoding": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=",
+ "dev": true
+ },
+ "throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw="
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.3.6",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "through2-filter": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz",
+ "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=",
+ "dev": true,
+ "requires": {
+ "through2": "2.0.3",
+ "xtend": "4.0.1"
+ }
+ },
+ "tildify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz",
+ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=",
+ "dev": true,
+ "requires": {
+ "os-homedir": "1.0.2"
+ }
+ },
+ "time-stamp": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
+ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
+ "dev": true
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+ "dev": true
+ },
+ "timers-ext": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz",
+ "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.43",
+ "next-tick": "1.0.0"
+ }
+ },
+ "tmp": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
+ "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=",
+ "requires": {
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "to-absolute-glob": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
+ "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
+ "dev": true,
+ "requires": {
+ "is-absolute": "1.0.0",
+ "is-negated-glob": "1.0.0"
+ }
+ },
+ "to-buffer": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "2.0.2",
+ "extend-shallow": "3.0.2",
+ "regex-not": "1.0.2",
+ "safe-regex": "1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "3.0.0",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "to-through": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz",
+ "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=",
+ "dev": true,
+ "requires": {
+ "through2": "2.0.3"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
+ "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "tree-kill": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz",
+ "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg=="
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "trim-repeated": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
+ "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "tslib": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.1.tgz",
+ "integrity": "sha512-avfPS28HmGLLc2o4elcc2EIq2FcH++Yo5YxpBZi9Yw93BCTGFthI4HPE4Rpep6vSYQaK8e69PelM44tPj+RaQg==",
+ "dev": true
+ },
+ "tslint": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz",
+ "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "builtin-modules": "1.1.1",
+ "chalk": "2.4.1",
+ "commander": "2.15.1",
+ "diff": "3.5.0",
+ "glob": "7.1.2",
+ "js-yaml": "3.11.0",
+ "minimatch": "3.0.4",
+ "resolve": "1.7.1",
+ "semver": "5.5.0",
+ "tslib": "1.9.1",
+ "tsutils": "2.27.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.1",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "5.4.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "tslint-eslint-rules": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.3.1.tgz",
+ "integrity": "sha512-qq2H/AU/FlFbQJKXuxhtIk+ni/nQu9jHHhsFKa6hnA0/n3zl1/RWRc3TVFlL8HfWFMzkST350VeTrFpy1u4OUg==",
+ "dev": true,
+ "requires": {
+ "doctrine": "0.7.2",
+ "tslib": "1.9.0",
+ "tsutils": "2.8.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
+ "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.8.0.tgz",
+ "integrity": "sha1-AWAXNymzvxOGKN0UoVN+AIUdgUo=",
+ "dev": true,
+ "requires": {
+ "tslib": "1.9.0"
+ }
+ }
+ }
+ },
+ "tslint-microsoft-contrib": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.3.tgz",
+ "integrity": "sha512-5AnfTGlfpUzpRHLmoojPBKFTTmbjnwgdaTHMdllausa4GBPya5u36i9ddrTX4PhetGZvd4JUYIpAmgHqVnsctg==",
+ "dev": true,
+ "requires": {
+ "tsutils": "2.27.1"
+ }
+ },
+ "tsutils": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz",
+ "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==",
+ "dev": true,
+ "requires": {
+ "tslib": "1.9.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "optional": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "typemoq": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/typemoq/-/typemoq-2.1.0.tgz",
+ "integrity": "sha512-DtRNLb7x8yCTv/KHlwes+NI+aGb4Vl1iPC63Hhtcvk1DpxSAZzKWQv0RQFY0jX2Uqj0SDBNl8Na4e6MV6TNDgw==",
+ "dev": true,
+ "requires": {
+ "circular-json": "0.3.3",
+ "lodash": "4.17.5",
+ "postinstall-build": "5.0.1"
+ }
+ },
+ "typescript": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz",
+ "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==",
+ "dev": true
+ },
+ "typescript-char": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/typescript-char/-/typescript-char-0.0.0.tgz",
+ "integrity": "sha1-VY/tpzfHZaYQtzfu+7F3Xum8jas="
+ },
+ "typescript-formatter": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.0.tgz",
+ "integrity": "sha512-A16UqkHtkQOF340cf21LJXchcftyBTPqNOAmP1J8Plu2m3Q8o+2fAYwgFjLXMKP6ooSPjDoOS6z8j9q+1nEnXg==",
+ "dev": true,
+ "requires": {
+ "commandpost": "1.3.0",
+ "editorconfig": "0.15.0"
+ },
+ "dependencies": {
+ "editorconfig": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz",
+ "integrity": "sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg==",
+ "dev": true,
+ "requires": {
+ "@types/commander": "2.12.2",
+ "@types/semver": "5.5.0",
+ "commander": "2.15.1",
+ "lru-cache": "4.1.3",
+ "semver": "5.5.0",
+ "sigmund": "1.0.1"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
+ "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ }
+ }
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "source-map": "0.5.7",
+ "uglify-to-browserify": "1.0.2",
+ "yargs": "3.10.0"
+ }
+ },
+ "uglify-to-browserify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "dev": true,
+ "optional": true
+ },
+ "uint64be": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uint64be/-/uint64be-1.0.1.tgz",
+ "integrity": "sha1-H3FUIC8qG4rzU4cd2mUb80zpPpU="
+ },
+ "unbzip2-stream": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
+ "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
+ "dev": true,
+ "requires": {
+ "buffer": "3.6.0",
+ "through": "2.3.8"
+ }
+ },
+ "unc-path-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
+ "dev": true
+ },
+ "underscore": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
+ "dev": true
+ },
+ "unicode": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/unicode/-/unicode-10.0.0.tgz",
+ "integrity": "sha1-5dUcHbk7bHGguHngsMSvfm/faI4="
+ },
+ "union-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "dev": true,
+ "requires": {
+ "arr-union": "3.1.0",
+ "get-value": "2.0.6",
+ "is-extendable": "0.1.1",
+ "set-value": "0.4.3"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1"
+ }
+ },
+ "set-value": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1",
+ "is-extendable": "0.1.1",
+ "is-plain-object": "2.0.4",
+ "to-object-path": "0.3.0"
+ }
+ }
+ }
+ },
+ "unique-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz",
+ "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=",
+ "dev": true
+ },
+ "universalify": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
+ "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "0.3.1",
+ "isobject": "3.0.1"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "2.0.6",
+ "has-values": "0.1.4",
+ "isobject": "2.1.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "untildify": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz",
+ "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E="
+ },
+ "upath": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
+ "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==",
+ "dev": true
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url-parse": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz",
+ "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==",
+ "dev": true,
+ "requires": {
+ "querystringify": "2.0.0",
+ "requires-port": "1.0.0"
+ }
+ },
+ "url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "2.0.0"
+ }
+ },
+ "url-to-options": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
+ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
+ "dev": true
+ },
+ "urlgrey": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz",
+ "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=",
+ "dev": true
+ },
+ "use": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
+ "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==",
+ "dev": true,
+ "requires": {
+ "kind-of": "6.0.2"
+ }
+ },
+ "user-home": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
+ "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
+ },
+ "v8flags": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz",
+ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=",
+ "dev": true,
+ "requires": {
+ "user-home": "1.1.1"
+ }
+ },
+ "vali-date": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
+ "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
+ "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "3.0.0",
+ "spdx-expression-parse": "3.0.0"
+ }
+ },
+ "validator": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz",
+ "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==",
+ "dev": true
+ },
+ "value-or-function": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz",
+ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "1.3.0"
+ }
+ },
+ "vinyl": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
+ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ },
+ "vinyl-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz",
+ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0",
+ "strip-bom-stream": "2.0.0",
+ "vinyl": "1.2.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "vinyl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
+ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.4",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ }
+ }
+ },
+ "vinyl-fs": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz",
+ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=",
+ "dev": true,
+ "requires": {
+ "defaults": "1.0.3",
+ "glob-stream": "3.1.18",
+ "glob-watcher": "0.0.6",
+ "graceful-fs": "3.0.11",
+ "mkdirp": "0.5.1",
+ "strip-bom": "1.0.0",
+ "through2": "0.6.5",
+ "vinyl": "0.4.6"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz",
+ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=",
+ "dev": true,
+ "requires": {
+ "natives": "1.1.4"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "0.2.0",
+ "clone-stats": "0.0.1"
+ }
+ }
+ }
+ },
+ "vinyl-source-stream": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz",
+ "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=",
+ "dev": true,
+ "requires": {
+ "through2": "2.0.3",
+ "vinyl": "0.4.6"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "0.2.0",
+ "clone-stats": "0.0.1"
+ }
+ }
+ }
+ },
+ "vinyl-sourcemap": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz",
+ "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=",
+ "dev": true,
+ "requires": {
+ "append-buffer": "1.0.2",
+ "convert-source-map": "1.5.1",
+ "graceful-fs": "4.1.11",
+ "normalize-path": "2.1.1",
+ "now-and-later": "2.0.0",
+ "remove-bom-buffer": "3.0.0",
+ "vinyl": "2.1.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
+ "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz",
+ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=",
+ "dev": true,
+ "requires": {
+ "clone": "2.1.1",
+ "clone-buffer": "1.0.0",
+ "clone-stats": "1.0.0",
+ "cloneable-readable": "1.1.2",
+ "remove-trailing-separator": "1.1.0",
+ "replace-ext": "1.0.0"
+ }
+ }
+ }
+ },
+ "vscode": {
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.18.tgz",
+ "integrity": "sha512-SyDw4qFwZ+WthZX7RWp71PNiWLF7VhpM65j2oryY/6jtSORd8qH6J8vclwWZJ6Jvu0EH7JamO2RWNfBfsMR9Zw==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2",
+ "gulp-chmod": "2.0.0",
+ "gulp-filter": "5.1.0",
+ "gulp-gunzip": "1.0.0",
+ "gulp-remote-src-vscode": "0.5.0",
+ "gulp-symdest": "1.1.0",
+ "gulp-untar": "0.0.7",
+ "gulp-vinyl-zip": "2.1.0",
+ "mocha": "4.1.0",
+ "request": "2.85.0",
+ "semver": "5.5.0",
+ "source-map-support": "0.5.6",
+ "url-parse": "1.4.0",
+ "vinyl-source-stream": "1.1.2"
+ },
+ "dependencies": {
+ "browser-stdout": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "diff": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
+ "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
+ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "mocha": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz",
+ "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.0",
+ "commander": "2.11.0",
+ "debug": "3.1.0",
+ "diff": "3.3.1",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.2",
+ "growl": "1.10.3",
+ "he": "1.1.1",
+ "mkdirp": "0.5.1",
+ "supports-color": "4.4.0"
+ }
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "vscode-debugadapter": {
+ "version": "1.28.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.28.0.tgz",
+ "integrity": "sha512-GCR1326LFtfYjl7SDN1wmU2pBJ98HgUCnbWoU3s3bz0GhUWYN1xSYGg7MfuwxY6WwZk2cuqzANhy/oaKADMXaw==",
+ "requires": {
+ "vscode-debugprotocol": "1.28.0",
+ "vscode-uri": "1.0.1"
+ }
+ },
+ "vscode-debugadapter-testsupport": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.29.0.tgz",
+ "integrity": "sha512-4P0h3gfe7MNw9FXx0k/TpKBJMA4s880Gu+puxuOHOY3txYpIGC1I2jQdPlWt0XPWK2Qcz7q/biQ221cfavqifw==",
+ "dev": true,
+ "requires": {
+ "vscode-debugprotocol": "1.29.0"
+ },
+ "dependencies": {
+ "vscode-debugprotocol": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.29.0.tgz",
+ "integrity": "sha512-jrbSayWof7jyXo7VRhIcTcsjWeiPloi6vzbrucVarKvuSrZUV7Bc+ggQRSG1lzNiMmBG5AHIe/Npf6G2q4SBiw==",
+ "dev": true
+ }
+ }
+ },
+ "vscode-debugprotocol": {
+ "version": "1.28.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.28.0.tgz",
+ "integrity": "sha512-QM4J8A13jBY9I7OPWXN0ZO1cqydnD4co2j/O81jIj6em8VkmJT4VyJQkq4HmwJe3af+u9+7IYCIEDrowgvKxTA=="
+ },
+ "vscode-extension-telemetry": {
+ "version": "0.0.15",
+ "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz",
+ "integrity": "sha512-Yf6dL9r2x2GISI1xh22XsAaydSTQG/4aBitu8sGBwGr42n2TyOsIXGtXSDgqQBNZgYD6+P1EHqrrzetn9ekWTQ==",
+ "requires": {
+ "applicationinsights": "1.0.1"
+ }
+ },
+ "vscode-jsonrpc": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz",
+ "integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA=="
+ },
+ "vscode-languageclient": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-4.3.0.tgz",
+ "integrity": "sha512-vDpsmYfYpfuyDKZ46pCJEFBOCNHepRBSmlBGA0fczEbYghYm059BiFo3SmT4MK1r8NvYrFEem4k5TYNW3wommg==",
+ "requires": {
+ "vscode-languageserver-protocol": "3.9.0"
+ }
+ },
+ "vscode-languageserver": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-4.3.0.tgz",
+ "integrity": "sha512-4dTpnyTB6Q0HmMhxaG60rrpQthbTBlMtFX5cwJpPxcPzLZIFDWB3msR6TxGCzWpdYF11REIJihWByobpGkljdQ==",
+ "requires": {
+ "vscode-languageserver-protocol": "3.9.0",
+ "vscode-uri": "1.0.5"
+ },
+ "dependencies": {
+ "vscode-uri": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.5.tgz",
+ "integrity": "sha1-O4majvccN/MFTXm9vdoxx7828g0="
+ }
+ }
+ },
+ "vscode-languageserver-protocol": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.9.0.tgz",
+ "integrity": "sha512-i1sG5iU88Mocc7egTeh6dAow/yRWpPK5PLJaxsWsKiA+dspq1Yzr/R1bNLPc+6P/ab010lXhzdUHQY0CuIUyDw==",
+ "requires": {
+ "vscode-jsonrpc": "3.6.2",
+ "vscode-languageserver-types": "3.9.0"
+ }
+ },
+ "vscode-languageserver-types": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.9.0.tgz",
+ "integrity": "sha512-Qzh3VsU3t0zhKtYl1revyax+4gGHl2ejNzYXeiZYQMF3i0vX4dtPohxGDFoZYfGFQI738aXYbSUQmhLeBckDlQ=="
+ },
+ "vscode-uri": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz",
+ "integrity": "sha1-Eahr7+rDxKo+wIYjZRo8gabQu8g="
+ },
+ "whet.extend": {
+ "version": "0.9.9",
+ "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
+ "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "dev": true,
+ "optional": true
+ },
+ "winreg": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz",
+ "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs="
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "xml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+ "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=",
+ "dev": true
+ },
+ "xml2js": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
+ "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
+ "requires": {
+ "sax": "1.2.4",
+ "xmlbuilder": "9.0.7"
+ }
+ },
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase": "1.2.1",
+ "cliui": "2.1.0",
+ "decamelize": "1.2.0",
+ "window-size": "0.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "yauzl": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz",
+ "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "0.2.13",
+ "fd-slicer": "1.0.1"
+ }
+ },
+ "yazl": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz",
+ "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "0.2.13"
+ }
+ },
+ "zone.js": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz",
+ "integrity": "sha1-+7w50+AmHQmG8boGMG6zrrDSIAk="
+ }
+ }
+}
diff --git a/package.json b/package.json
index a22c95dac590..c502de7d7d68 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "python",
"displayName": "Python",
"description": "Linting, Debugging (multi-threaded, remote), Intellisense, code formatting, refactoring, unit tests, snippets, and more.",
- "version": "2018.3.0-alpha",
+ "version": "2018.7.1",
"publisher": "ms-python",
"author": {
"name": "Microsoft Corporation"
@@ -16,17 +16,18 @@
"bugs": {
"url": "https://github.com/Microsoft/vscode-python/issues"
},
+ "qna": "https://stackoverflow.com/questions/tagged/visual-studio-code+python",
"badges": [
+ {
+ "url": "https://vscode-python.visualstudio.com/VSCode-Python/_apis/build/status/VSCode-Python-Rolling-CI?branchName=master",
+ "href": "https://vscode-python.visualstudio.com/VSCode-Python/VSCode-Python%20Team/_build/index?context=allDefinitions&path=&definitionId=9",
+ "description": "Continuous integration (VSTS)"
+ },
{
"url": "https://travis-ci.org/Microsoft/vscode-python.svg?branch=master",
"href": "https://travis-ci.org/Microsoft/vscode-python",
"description": "Continuous integration (Travis)"
},
- {
- "url": "https://ci.appveyor.com/api/projects/status/s0pt8d79gqw222j7?svg=true",
- "href": "https://ci.appveyor.com/project/DonJayamanne/vscode-python-v3vd6/branch/master",
- "description": "Continuous integration (AppVeyor)"
- },
{
"url": "https://codecov.io/gh/Microsoft/vscode-python/branch/master/graph/badge.svg",
"href": "https://codecov.io/gh/Microsoft/vscode-python",
@@ -39,7 +40,7 @@
"theme": "dark"
},
"engines": {
- "vscode": "^1.18.0"
+ "vscode": "^1.25.0"
},
"recommendations": [
"donjayamanne.jupyter"
@@ -51,7 +52,7 @@
"multi-root ready"
],
"categories": [
- "Languages",
+ "Programming Languages",
"Debuggers",
"Linters",
"Snippets",
@@ -60,6 +61,8 @@
],
"activationEvents": [
"onLanguage:python",
+ "onDebugResolve:python",
+ "onDebugResolve:pythonExperimental",
"onCommand:python.execInTerminal",
"onCommand:python.sortImports",
"onCommand:python.runtests",
@@ -81,7 +84,8 @@
"onCommand:python.goToPythonObject",
"onCommand:python.setLinter",
"onCommand:python.enableLinting",
- "onCommand:python.createTerminal"
+ "onCommand:python.createTerminal",
+ "onCommand:python.discoverTests"
],
"main": "./out/client/extension",
"contributes": {
@@ -91,6 +95,13 @@
"path": "./snippets/python.json"
}
],
+ "keybindings": [
+ {
+ "command": "python.execSelectionInTerminal",
+ "key": "shift+enter",
+ "when": "editorFocus && editorLangId == python && !findInputFocussed && !replaceInputFocussed"
+ }
+ ],
"commands": [
{
"command": "python.sortImports",
@@ -177,6 +188,11 @@
"title": "%python.command.python.runFailedTests.title%",
"category": "Python"
},
+ {
+ "command": "python.discoverTests",
+ "title": "%python.command.python.discoverTests.title%",
+ "category": "Python"
+ },
{
"command": "python.execSelectionInTerminal",
"title": "%python.command.python.execSelectionInTerminal.title%",
@@ -231,7 +247,7 @@
{
"command": "python.execSelectionInTerminal",
"group": "Python",
- "when": "editorHasSelection && editorLangId == python"
+ "when": "editorFocus && editorLangId == python"
},
{
"command": "python.execSelectionInDjangoShell",
@@ -360,7 +376,7 @@
],
"debugOptions": [
"RedirectOutput",
- "DjangoDebugging"
+ "Django"
]
}
},
@@ -376,7 +392,7 @@
"module": "flask",
"cwd": "^\"\\${workspaceFolder}\"",
"env": {
- "FLASK_APP": "^\"\\${workspaceFolder}/app.py\""
+ "FLASK_APP": "app.py"
},
"args": [
"run",
@@ -496,7 +512,7 @@
"externalTerminal"
],
"description": "Where to launch the debug target: internal console, integrated terminal, or external terminal.",
- "default": "none"
+ "default": "integratedTerminal"
},
"cwd": {
"type": "string",
@@ -512,7 +528,7 @@
"RedirectOutput",
"DebugStdLib",
"BreakOnSystemExitZero",
- "DjangoDebugging",
+ "Django",
"Sudo",
"IgnoreDjangoTemplateWarnings",
"Pyramid"
@@ -660,7 +676,7 @@
],
"debugOptions": [
"RedirectOutput",
- "DjangoDebugging"
+ "Django"
]
},
{
@@ -669,7 +685,7 @@
"request": "launch",
"module": "flask",
"env": {
- "FLASK_APP": "${workspaceFolder}/app.py"
+ "FLASK_APP": "app.py"
},
"args": [
"run",
@@ -737,7 +753,8 @@
"enableBreakpointsFor": {
"languageIds": [
"python",
- "html"
+ "html",
+ "jinja"
]
},
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
@@ -771,21 +788,121 @@
"description": "%python.snippet.launch.django.description%",
"body": {
"name": "Django",
- "type": "python",
+ "type": "pythonExperimental",
"request": "launch",
- "pythonPath": "^\"\\${config:python.pythonPath}\"",
"program": "^\"\\${workspaceFolder}/manage.py\"",
- "cwd": "^\"\\${workspaceFolder}\"",
- "console": "integratedTerminal",
- "internalConsoleOptions": "neverOpen",
"args": [
"runserver",
"--noreload",
"--nothreading"
],
- "env": {},
- "envFile": "^\"\\${workspaceFolder}/.env\"",
- "debugOptions": []
+ "django": true
+ }
+ },
+ {
+ "label": "Python Experimental: Flask",
+ "description": "%python.snippet.launch.flask.description%",
+ "body": {
+ "name": "Flask",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "module": "flask",
+ "env": {
+ "FLASK_APP": "app.py"
+ },
+ "args": [
+ "run",
+ "--no-debugger",
+ "--no-reload"
+ ],
+ "jinja": true
+ }
+ },
+ {
+ "label": "Python Experimental: Gevent",
+ "description": "%python.snippet.launch.gevent.description%",
+ "body": {
+ "name": "Gevent",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "program": "^\"\\${file}\"",
+ "gevent": true
+ }
+ },
+ {
+ "label": "Python Experimental: PySpark",
+ "description": "%python.snippet.launch.pyspark.description%",
+ "body": {
+ "name": "PySpark",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "osx": {
+ "pythonPath": "^\"\\${env:SPARK_HOME}/bin/spark-submit\""
+ },
+ "windows": {
+ "pythonPath": "^\"\\${env:SPARK_HOME}/bin/spark-submit.cmd\""
+ },
+ "linux": {
+ "pythonPath": "^\"\\${env:SPARK_HOME}/bin/spark-submit\""
+ },
+ "program": "^\"\\${file}\""
+ }
+ },
+ {
+ "label": "Python Experimental: Watson",
+ "description": "%python.snippet.launch.watson.description%",
+ "body": {
+ "name": "Watson",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "program": "^\"\\${workspaceFolder}/console.py\"",
+ "args": [
+ "dev",
+ "runserver",
+ "--noreload=True"
+ ],
+ "jinja": true
+ }
+ },
+ {
+ "label": "Python Experimental: Scrapy",
+ "description": "%python.snippet.launch.scrapy.description%",
+ "body": {
+ "name": "Scrapy",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "module": "scrapy",
+ "args": [
+ "crawl",
+ "specs",
+ "-o",
+ "bikes.json"
+ ]
+ }
+ },
+ {
+ "label": "Python Experimental: Pyramid",
+ "description": "%python.snippet.launch.pyramid.description%",
+ "body": {
+ "name": "Pyramid",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "args": [
+ "^\"\\${workspaceFolder}/development.ini\""
+ ],
+ "pyramid": true,
+ "jinja": true
+ }
+ },
+ {
+ "label": "Python Experimental: Attach",
+ "description": "%python.snippet.launch.attach.description%",
+ "body": {
+ "name": "Attach (Remote Debug)",
+ "type": "pythonExperimental",
+ "request": "attach",
+ "port": 5678,
+ "host": "localhost"
}
}
],
@@ -822,6 +939,7 @@
},
"console": {
"enum": [
+ "none",
"integratedTerminal",
"externalTerminal"
],
@@ -833,17 +951,6 @@
"description": "Absolute path to the working directory of the program being debugged. Default is the root directory of the file (leave empty).",
"default": "${workspaceFolder}"
},
- "debugOptions": {
- "type": "array",
- "description": "Advanced options, view read me for further details.",
- "items": {
- "type": "string",
- "enum": [
- "Sudo"
- ]
- },
- "default": []
- },
"env": {
"type": "object",
"description": "Environment variables defined as a key value pair. Property ends up being the Environment Variable and the value of the property ends up being the value of the Env Variable.",
@@ -868,6 +975,116 @@
"type": "boolean",
"description": "Enable logging of debugger events to a log file.",
"default": false
+ },
+ "redirectOutput": {
+ "type": "boolean",
+ "description": "Redirect output.",
+ "default": true
+ },
+ "debugStdLib": {
+ "type": "boolean",
+ "description": "Debug standard library code.",
+ "default": false
+ },
+ "gevent": {
+ "type": "boolean",
+ "description": "Enable debugging of gevent monkey-patched code.",
+ "default": false
+ },
+ "django": {
+ "type": "boolean",
+ "description": "Django debugging.",
+ "default": false
+ },
+ "jinja": {
+ "enum": [
+ true,
+ false,
+ null
+ ],
+ "description": "Jinja template debugging (e.g. Flask).",
+ "default": null
+ },
+ "sudo": {
+ "type": "boolean",
+ "description": "Running debug program under elevated permissions (on Unix).",
+ "default": false
+ },
+ "pyramid": {
+ "type": "boolean",
+ "description": "Whether debugging Pyramid applications",
+ "default": false
+ }
+ }
+ },
+ "attach": {
+ "required": [
+ "port"
+ ],
+ "properties": {
+ "port": {
+ "type": "number",
+ "description": "Debug port to attach",
+ "default": 0
+ },
+ "host": {
+ "type": "string",
+ "description": "IP Address of the of remote server (default is localhost or use 127.0.0.1).",
+ "default": "localhost"
+ },
+ "pathMappings": {
+ "type": "array",
+ "label": "Path mappings.",
+ "items": {
+ "type": "object",
+ "label": "Path mapping",
+ "required": [
+ "localRoot",
+ "remoteRoot"
+ ],
+ "properties": {
+ "localRoot": {
+ "type": "string",
+ "label": "Local source root.",
+ "default": "${workspaceFolder}"
+ },
+ "remoteRoot": {
+ "type": "string",
+ "label": "Remote source root.",
+ "default": ""
+ }
+ }
+ },
+ "default": []
+ },
+ "logToFile": {
+ "type": "boolean",
+ "description": "Enable logging of debugger events to a log file.",
+ "default": false
+ },
+ "redirectOutput": {
+ "type": "boolean",
+ "description": "Redirect output.",
+ "default": true
+ },
+ "debugStdLib": {
+ "type": "boolean",
+ "description": "Debug standard library code.",
+ "default": false
+ },
+ "django": {
+ "type": "boolean",
+ "description": "Django debugging.",
+ "default": false
+ },
+ "jinja": {
+ "enum": [
+ true,
+ false,
+ null
+ ],
+ "description": "Jinja template debugging (e.g. Flask).",
+ "default": null
}
}
}
@@ -880,6 +1097,13 @@
"program": "${file}",
"console": "integratedTerminal"
},
+ {
+ "name": "Python Experimental: Attach",
+ "type": "pythonExperimental",
+ "request": "attach",
+ "port": 5678,
+ "host": "localhost"
+ },
{
"name": "Python Experimental: Django",
"type": "pythonExperimental",
@@ -890,7 +1114,23 @@
"runserver",
"--noreload",
"--nothreading"
- ]
+ ],
+ "django": true
+ },
+ {
+ "name": "Python Experimental: Flask",
+ "type": "pythonExperimental",
+ "request": "launch",
+ "module": "flask",
+ "env": {
+ "FLASK_APP": "app.py"
+ },
+ "args": [
+ "run",
+ "--no-debugger",
+ "--no-reload"
+ ],
+ "jinja": true
},
{
"name": "Python Experimental: Current File (External Terminal)",
@@ -906,56 +1146,55 @@
"type": "object",
"title": "Python Configuration",
"properties": {
- "python.pythonPath": {
- "type": "string",
- "default": "python",
- "description": "Path to Python, you can use a custom version of Python by modifying this setting to include the full path.",
+ "python.autoComplete.addBrackets": {
+ "type": "boolean",
+ "default": false,
+ "description": "Automatically add brackets for functions.",
"scope": "resource"
},
- "python.venvPath": {
- "type": "string",
- "default": "",
- "description": "Path to folder with a list of Virtual Environments (e.g. ~/.pyenv, ~/Envs, ~/.virtualenvs).",
+ "python.autoComplete.extraPaths": {
+ "type": "array",
+ "default": [],
+ "description": "List of paths to libraries and the like that need to be imported by auto complete engine. E.g. when using Google App SDK, the paths are not in system path, hence need to be added into this list.",
"scope": "resource"
},
- "python.venvFolders": {
+ "python.autoComplete.preloadModules": {
"type": "array",
- "default": [
- "envs",
- ".pyenv",
- ".direnv"
- ],
- "description": "Folders to look into for virtual environments.",
- "scope": "resource",
"items": {
"type": "string"
- }
+ },
+ "default": [],
+ "description": "Comma delimited list of modules preloaded to speed up Auto Complete (e.g. add Numpy, Pandas, etc, items slow to load when autocompleting).",
+ "scope": "resource"
},
- "python.envFile": {
- "type": "string",
- "description": "Absolute path to a file containing environment variable definitions.",
- "default": "${workspaceFolder}/.env",
+ "python.autoComplete.showAdvancedMembers": {
+ "type": "boolean",
+ "default": true,
+ "description": "Controls appearance of methods with double underscores in the completion list.",
"scope": "resource"
},
- "python.jediPath": {
- "type": "string",
- "default": "",
- "description": "Path to directory containing the Jedi library (this path will contain the 'Jedi' sub directory).",
+ "python.autoComplete.typeshedPaths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "description": "Specifies paths to local typeshed repository clone(s) for the Python language server.",
"scope": "resource"
},
- "python.jediMemoryLimit": {
- "type": "number",
- "default": "0",
- "description": "Memory limit for the Jedi completion engine in megabytes. Zero (default) means 1024 MB",
+ "python.disableInstallationCheck": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to check if Python is installed (also warn when using the macOS-installed Python).",
"scope": "resource"
},
- "python.sortImports.path": {
+ "python.envFile": {
"type": "string",
- "description": "Path to isort script, default using inner version",
- "default": "",
+ "description": "Absolute path to a file containing environment variable definitions.",
+ "default": "${workspaceFolder}/.env",
"scope": "resource"
},
- "python.sortImports.args": {
+ "python.formatting.autopep8Args": {
"type": "array",
"description": "Arguments passed in. Each argument is a separate item in the array.",
"default": [],
@@ -964,102 +1203,148 @@
},
"scope": "resource"
},
- "python.disablePromptForFeatures": {
- "type": "array",
- "default": [],
- "description": "Do not display a prompt to install these features",
- "items": {
- "type": "string",
- "default": "pylint",
- "description": "Feature",
- "enum": [
- "flake8",
- "mypy",
- "pep8",
- "pylama",
- "prospector",
- "pydocstyle",
- "pylint"
- ]
+ "python.formatting.autopep8Path": {
+ "type": "string",
+ "default": "autopep8",
+ "description": "Path to autopep8, you can use a custom version of autopep8 by modifying this setting to include the full path.",
+ "scope": "resource"
+ },
+ "python.formatting.provider": {
+ "type": "string",
+ "default": "autopep8",
+ "description": "Provider for formatting. Possible options include 'autopep8', 'black', and 'yapf'.",
+ "enum": [
+ "autopep8",
+ "black",
+ "yapf",
+ "none"
+ ],
+ "scope": "resource"
+ },
+ "python.formatting.blackArgs": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
+ "items": {
+ "type": "string"
},
"scope": "resource"
},
- "python.disableInstallationCheck": {
- "type": "boolean",
- "default": false,
- "description": "Whether to check if Python is installed.",
+ "python.formatting.blackPath": {
+ "type": "string",
+ "default": "black",
+ "description": "Path to Black, you can use a custom version of Black by modifying this setting to include the full path.",
+ "scope": "resource"
+ },
+ "python.formatting.yapfArgs": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "scope": "resource"
+ },
+ "python.formatting.yapfPath": {
+ "type": "string",
+ "default": "yapf",
+ "description": "Path to yapf, you can use a custom version of yapf by modifying this setting to include the full path.",
"scope": "resource"
},
"python.globalModuleInstallation": {
"type": "boolean",
"default": false,
- "description": "Whether to install Python modules globally.",
+ "description": "Whether to install Python modules globally when not using an environment.",
"scope": "resource"
},
- "python.linting.enabled": {
+ "python.jediEnabled": {
"type": "boolean",
"default": true,
- "description": "Whether to lint Python files.",
+ "description": "Enables Jedi as IntelliSense engine instead of Microsoft Python Analysis Engine.",
"scope": "resource"
},
- "python.linting.prospectorEnabled": {
- "type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using prospector.",
+ "python.jediMemoryLimit": {
+ "type": "number",
+ "default": 0,
+ "description": "Memory limit for the Jedi completion engine in megabytes. Zero (default) means 1024 MB. -1 means unlimited (disable memory limit check)",
"scope": "resource"
},
- "python.linting.pylintEnabled": {
- "type": "boolean",
- "default": true,
- "description": "Whether to lint Python files using pylint.",
+ "python.jediPath": {
+ "type": "string",
+ "default": "",
+ "description": "Path to directory containing the Jedi library (this path will contain the 'Jedi' sub directory).",
"scope": "resource"
},
- "python.linting.pep8Enabled": {
+ "python.analysis.openFilesOnly": {
"type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using pep8",
+ "default": true,
+ "description": "Only show errors and warnings for open files rather than for the entire workspace.",
"scope": "resource"
},
- "python.linting.flake8Enabled": {
- "type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using flake8",
+ "python.analysis.typeshedPaths": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "description": "Paths to look for typeshed modules.",
"scope": "resource"
},
- "python.linting.pydocstyleEnabled": {
- "type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using pydocstyle",
+ "python.analysis.errors": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "description": "List of diagnostics messages to be shown as errors.",
"scope": "resource"
},
- "python.linting.mypyEnabled": {
- "type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using mypy.",
+ "python.analysis.warnings": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "description": "List of diagnostics messages to be shown as warnings.",
"scope": "resource"
},
- "python.linting.lintOnSave": {
- "type": "boolean",
- "default": true,
- "description": "Whether to lint Python files when saved.",
+ "python.analysis.information": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "description": "List of diagnostics messages to be shown as information.",
"scope": "resource"
},
- "python.linting.maxNumberOfProblems": {
- "type": "number",
- "default": 100,
- "description": "Controls the maximum number of problems produced by the server.",
+ "python.analysis.disabled": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "description": "List of suppressed diagnostic messages.",
"scope": "resource"
},
- "python.linting.pylintUseMinimalCheckers": {
+ "python.linting.enabled": {
"type": "boolean",
"default": true,
- "description": "Whether to run Pylint with minimal set of rules.",
+ "description": "Whether to lint Python files.",
"scope": "resource"
},
- "python.linting.pylintCategorySeverity.convention": {
+ "python.linting.flake8Args": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "scope": "resource"
+ },
+ "python.linting.flake8CategorySeverity.E": {
"type": "string",
- "default": "Information",
- "description": "Severity of Pylint message type 'Convention/C'.",
+ "default": "Error",
+ "description": "Severity of Flake8 message type 'E'.",
"enum": [
"Hint",
"Error",
@@ -1068,10 +1353,10 @@
],
"scope": "resource"
},
- "python.linting.pylintCategorySeverity.refactor": {
+ "python.linting.flake8CategorySeverity.F": {
"type": "string",
- "default": "Hint",
- "description": "Severity of Pylint message type 'Refactor/R'.",
+ "default": "Error",
+ "description": "Severity of Flake8 message type 'F'.",
"enum": [
"Hint",
"Error",
@@ -1080,10 +1365,10 @@
],
"scope": "resource"
},
- "python.linting.pylintCategorySeverity.warning": {
+ "python.linting.flake8CategorySeverity.W": {
"type": "string",
"default": "Warning",
- "description": "Severity of Pylint message type 'Warning/W'.",
+ "description": "Severity of Flake8 message type 'W'.",
"enum": [
"Hint",
"Error",
@@ -1092,58 +1377,58 @@
],
"scope": "resource"
},
- "python.linting.pylintCategorySeverity.error": {
- "type": "string",
- "default": "Error",
- "description": "Severity of Pylint message type 'Error/E'.",
- "enum": [
- "Hint",
- "Error",
- "Information",
- "Warning"
- ],
+ "python.linting.flake8Enabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using flake8",
"scope": "resource"
},
- "python.linting.pylintCategorySeverity.fatal": {
+ "python.linting.flake8Path": {
"type": "string",
- "default": "Error",
- "description": "Severity of Pylint message type 'Fatal/F'.",
- "enum": [
- "Hint",
- "Error",
- "Information",
- "Warning"
- ],
+ "default": "flake8",
+ "description": "Path to flake8, you can use a custom version of flake8 by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.linting.pep8CategorySeverity.W": {
- "type": "string",
- "default": "Warning",
- "description": "Severity of Pep8 message type 'W'.",
- "enum": [
- "Hint",
- "Error",
- "Information",
- "Warning"
+ "python.linting.ignorePatterns": {
+ "type": "array",
+ "description": "Patterns used to exclude files or folders from being linted.",
+ "default": [
+ ".vscode/*.py",
+ "**/site-packages/**/*.py"
],
+ "items": {
+ "type": "string"
+ },
"scope": "resource"
},
- "python.linting.pep8CategorySeverity.E": {
- "type": "string",
- "default": "Error",
- "description": "Severity of Pep8 message type 'E'.",
- "enum": [
- "Hint",
- "Error",
- "Information",
- "Warning"
+ "python.linting.lintOnSave": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to lint Python files when saved.",
+ "scope": "resource"
+ },
+ "python.linting.maxNumberOfProblems": {
+ "type": "number",
+ "default": 100,
+ "description": "Controls the maximum number of problems produced by the server.",
+ "scope": "resource"
+ },
+ "python.linting.mypyArgs": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [
+ "--ignore-missing-imports",
+ "--follow-imports=silent"
],
+ "items": {
+ "type": "string"
+ },
"scope": "resource"
},
- "python.linting.flake8CategorySeverity.F": {
+ "python.linting.mypyCategorySeverity.error": {
"type": "string",
"default": "Error",
- "description": "Severity of Flake8 message type 'F'.",
+ "description": "Severity of Mypy message type 'Error'.",
"enum": [
"Hint",
"Error",
@@ -1152,10 +1437,10 @@
],
"scope": "resource"
},
- "python.linting.flake8CategorySeverity.E": {
+ "python.linting.mypyCategorySeverity.note": {
"type": "string",
- "default": "Error",
- "description": "Severity of Flake8 message type 'E'.",
+ "default": "Information",
+ "description": "Severity of Mypy message type 'Note'.",
"enum": [
"Hint",
"Error",
@@ -1164,22 +1449,31 @@
],
"scope": "resource"
},
- "python.linting.flake8CategorySeverity.W": {
+ "python.linting.mypyEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using mypy.",
+ "scope": "resource"
+ },
+ "python.linting.mypyPath": {
"type": "string",
- "default": "Warning",
- "description": "Severity of Flake8 message type 'W'.",
- "enum": [
- "Hint",
- "Error",
- "Information",
- "Warning"
- ],
+ "default": "mypy",
+ "description": "Path to mypy, you can use a custom version of mypy by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.linting.mypyCategorySeverity.error": {
+ "python.linting.pep8Args": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "scope": "resource"
+ },
+ "python.linting.pep8CategorySeverity.E": {
"type": "string",
"default": "Error",
- "description": "Severity of Mypy message type 'Error'.",
+ "description": "Severity of Pep8 message type 'E'.",
"enum": [
"Hint",
"Error",
@@ -1188,10 +1482,10 @@
],
"scope": "resource"
},
- "python.linting.mypyCategorySeverity.note": {
+ "python.linting.pep8CategorySeverity.W": {
"type": "string",
- "default": "Information",
- "description": "Severity of Mypy message type 'Note'.",
+ "default": "Warning",
+ "description": "Severity of Pep8 message type 'W'.",
"enum": [
"Hint",
"Error",
@@ -1200,16 +1494,10 @@
],
"scope": "resource"
},
- "python.linting.prospectorPath": {
- "type": "string",
- "default": "prospector",
- "description": "Path to Prospector, you can use a custom version of prospector by modifying this setting to include the full path.",
- "scope": "resource"
- },
- "python.linting.pylintPath": {
- "type": "string",
- "default": "pylint",
- "description": "Path to Pylint, you can use a custom version of pylint by modifying this setting to include the full path.",
+ "python.linting.pep8Enabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using pep8",
"scope": "resource"
},
"python.linting.pep8Path": {
@@ -1218,24 +1506,6 @@
"description": "Path to pep8, you can use a custom version of pep8 by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.linting.flake8Path": {
- "type": "string",
- "default": "flake8",
- "description": "Path to flake8, you can use a custom version of flake8 by modifying this setting to include the full path.",
- "scope": "resource"
- },
- "python.linting.pydocstylePath": {
- "type": "string",
- "default": "pydocstyle",
- "description": "Path to pydocstyle, you can use a custom version of pydocstyle by modifying this setting to include the full path.",
- "scope": "resource"
- },
- "python.linting.mypyPath": {
- "type": "string",
- "default": "mypy",
- "description": "Path to mypy, you can use a custom version of mypy by modifying this setting to include the full path.",
- "scope": "resource"
- },
"python.linting.prospectorArgs": {
"type": "array",
"description": "Arguments passed in. Each argument is a separate item in the array.",
@@ -1245,31 +1515,16 @@
},
"scope": "resource"
},
- "python.linting.pylintArgs": {
- "type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [],
- "items": {
- "type": "string"
- },
- "scope": "resource"
- },
- "python.linting.pep8Args": {
- "type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [],
- "items": {
- "type": "string"
- },
+ "python.linting.prospectorEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using prospector.",
"scope": "resource"
},
- "python.linting.flake8Args": {
- "type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [],
- "items": {
- "type": "string"
- },
+ "python.linting.prospectorPath": {
+ "type": "string",
+ "default": "prospector",
+ "description": "Path to Prospector, you can use a custom version of prospector by modifying this setting to include the full path.",
"scope": "resource"
},
"python.linting.pydocstyleArgs": {
@@ -1281,42 +1536,19 @@
},
"scope": "resource"
},
- "python.linting.mypyArgs": {
- "type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [
- "--ignore-missing-imports",
- "--follow-imports=silent"
- ],
- "items": {
- "type": "string"
- },
- "scope": "resource"
- },
- "python.formatting.provider": {
- "type": "string",
- "default": "autopep8",
- "description": "Provider for formatting. Possible options include 'autopep8' and 'yapf'.",
- "enum": [
- "autopep8",
- "yapf",
- "none"
- ],
- "scope": "resource"
- },
- "python.formatting.autopep8Path": {
- "type": "string",
- "default": "autopep8",
- "description": "Path to autopep8, you can use a custom version of autopep8 by modifying this setting to include the full path.",
+ "python.linting.pydocstyleEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using pydocstyle",
"scope": "resource"
},
- "python.formatting.yapfPath": {
+ "python.linting.pydocstylePath": {
"type": "string",
- "default": "yapf",
- "description": "Path to yapf, you can use a custom version of yapf by modifying this setting to include the full path.",
+ "default": "pydocstyle",
+ "description": "Path to pydocstyle, you can use a custom version of pydocstyle by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.formatting.autopep8Args": {
+ "python.linting.pylamaArgs": {
"type": "array",
"description": "Arguments passed in. Each argument is a separate item in the array.",
"default": [],
@@ -1325,7 +1557,19 @@
},
"scope": "resource"
},
- "python.formatting.yapfArgs": {
+ "python.linting.pylamaEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to lint Python files using pylama.",
+ "scope": "resource"
+ },
+ "python.linting.pylamaPath": {
+ "type": "string",
+ "default": "pylama",
+ "description": "Path to pylama, you can use a custom version of pylama by modifying this setting to include the full path.",
+ "scope": "resource"
+ },
+ "python.linting.pylintArgs": {
"type": "array",
"description": "Arguments passed in. Each argument is a separate item in the array.",
"default": [],
@@ -1334,84 +1578,121 @@
},
"scope": "resource"
},
- "python.autoComplete.preloadModules": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "default": [],
- "description": "Comma delimited list of modules preloaded to speed up Auto Complete (e.g. add Numpy, Pandas, etc, items slow to load when autocompleting).",
+ "python.linting.pylintCategorySeverity.convention": {
+ "type": "string",
+ "default": "Information",
+ "description": "Severity of Pylint message type 'Convention/C'.",
+ "enum": [
+ "Hint",
+ "Error",
+ "Information",
+ "Warning"
+ ],
"scope": "resource"
},
- "python.autoComplete.extraPaths": {
- "type": "array",
- "default": [],
- "description": "List of paths to libraries and the like that need to be imported by auto complete engine. E.g. when using Google App SDK, the paths are not in system path, hence need to be added into this list.",
+ "python.linting.pylintCategorySeverity.error": {
+ "type": "string",
+ "default": "Error",
+ "description": "Severity of Pylint message type 'Error/E'.",
+ "enum": [
+ "Hint",
+ "Error",
+ "Information",
+ "Warning"
+ ],
"scope": "resource"
},
- "python.autoComplete.addBrackets": {
- "type": "boolean",
- "default": false,
- "description": "Automatically add brackets for functions.",
+ "python.linting.pylintCategorySeverity.fatal": {
+ "type": "string",
+ "default": "Error",
+ "description": "Severity of Pylint message type 'Fatal/F'.",
+ "enum": [
+ "Hint",
+ "Error",
+ "Information",
+ "Warning"
+ ],
"scope": "resource"
},
- "python.workspaceSymbols.tagFilePath": {
+ "python.linting.pylintCategorySeverity.refactor": {
"type": "string",
- "default": "${workspaceFolder}/.vscode/tags",
- "description": "Fully qualified path to tag file (exuberant ctag file), used to provide workspace symbols.",
+ "default": "Hint",
+ "description": "Severity of Pylint message type 'Refactor/R'.",
+ "enum": [
+ "Hint",
+ "Error",
+ "Information",
+ "Warning"
+ ],
"scope": "resource"
},
- "python.workspaceSymbols.enabled": {
- "type": "boolean",
- "default": true,
- "description": "Set to 'false' to disable Workspace Symbol provider using ctags.",
+ "python.linting.pylintCategorySeverity.warning": {
+ "type": "string",
+ "default": "Warning",
+ "description": "Severity of Pylint message type 'Warning/W'.",
+ "enum": [
+ "Hint",
+ "Error",
+ "Information",
+ "Warning"
+ ],
"scope": "resource"
},
- "python.workspaceSymbols.rebuildOnStart": {
+ "python.linting.pylintEnabled": {
"type": "boolean",
"default": true,
- "description": "Whether to re-build the tags file on start (defaults to true).",
+ "description": "Whether to lint Python files using pylint.",
"scope": "resource"
},
- "python.workspaceSymbols.rebuildOnFileSave": {
+ "python.linting.pylintPath": {
+ "type": "string",
+ "default": "pylint",
+ "description": "Path to Pylint, you can use a custom version of pylint by modifying this setting to include the full path.",
+ "scope": "resource"
+ },
+ "python.linting.pylintUseMinimalCheckers": {
"type": "boolean",
"default": true,
- "description": "Whether to re-build the tags file on when changes made to python files are saved.",
+ "description": "Whether to run Pylint with minimal set of rules.",
"scope": "resource"
},
- "python.workspaceSymbols.ctagsPath": {
+ "python.pythonPath": {
"type": "string",
- "default": "ctags",
- "description": "Fully qualilified path to the ctags executable (else leave as ctags, assuming it is in current path).",
+ "default": "python",
+ "description": "Path to Python, you can use a custom version of Python by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.workspaceSymbols.exclusionPatterns": {
+ "python.sortImports.args": {
"type": "array",
- "default": [
- "**/site-packages/**"
- ],
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
"items": {
"type": "string"
},
- "description": "Pattern used to exclude files and folders from ctags See http://ctags.sourceforge.net/ctags.html.",
"scope": "resource"
},
- "python.unitTest.promptToConfigure": {
+ "python.sortImports.path": {
+ "type": "string",
+ "description": "Path to isort script, default using inner version",
+ "default": "",
+ "scope": "resource"
+ },
+ "python.terminal.activateEnvironment": {
"type": "boolean",
"default": true,
- "description": "Where to prompt to configure a test framework if potential tests directories are discovered.",
+ "description": "Activate Python Environment in Terminal created using the Extension.",
"scope": "resource"
},
- "python.unitTest.debugPort": {
- "type": "number",
- "default": 3000,
- "description": "Port number used for debugging of unittests.",
+ "python.terminal.executeInFileDir": {
+ "type": "boolean",
+ "default": false,
+ "description": "When executing a file in the terminal, whether to use execute in the file's directory, instead of the current open folder.",
"scope": "resource"
},
- "python.unitTest.debugHost": {
- "type": "number",
- "default": "localhost",
- "description": "IP Address of the of the local unit test server (default is localhost or use 127.0.0.1).",
+ "python.terminal.launchArgs": {
+ "type": "array",
+ "default": [],
+ "description": "Python launch arguments to use when executing a file in the terminal.",
"scope": "resource"
},
"python.unitTest.cwd": {
@@ -1420,6 +1701,21 @@
"description": "Optional working directory for unit tests.",
"scope": "resource"
},
+ "python.unitTest.debugPort": {
+ "type": "number",
+ "default": 3000,
+ "description": "Port number used for debugging of unittests.",
+ "scope": "resource"
+ },
+ "python.unitTest.nosetestArgs": {
+ "type": "array",
+ "description": "Arguments passed in. Each argument is a separate item in the array.",
+ "default": [],
+ "items": {
+ "type": "string"
+ },
+ "scope": "resource"
+ },
"python.unitTest.nosetestsEnabled": {
"type": "boolean",
"default": false,
@@ -1432,25 +1728,10 @@
"description": "Path to nosetests, you can use a custom version of nosetests by modifying this setting to include the full path.",
"scope": "resource"
},
- "python.unitTest.pyTestEnabled": {
+ "python.unitTest.promptToConfigure": {
"type": "boolean",
- "default": false,
- "description": "Whether to enable or disable unit testing using pytest.",
- "scope": "resource"
- },
- "python.unitTest.pyTestPath": {
- "type": "string",
- "default": "pytest",
- "description": "Path to pytest (pytest), you can use a custom version of pytest by modifying this setting to include the full path.",
- "scope": "resource"
- },
- "python.unitTest.nosetestArgs": {
- "type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [],
- "items": {
- "type": "string"
- },
+ "default": true,
+ "description": "Where to prompt to configure a test framework if potential tests directories are discovered.",
"scope": "resource"
},
"python.unitTest.pyTestArgs": {
@@ -1462,10 +1743,16 @@
},
"scope": "resource"
},
- "python.unitTest.unittestEnabled": {
+ "python.unitTest.pyTestEnabled": {
"type": "boolean",
"default": false,
- "description": "Whether to enable or disable unit testing using unittest.",
+ "description": "Whether to enable or disable unit testing using pytest.",
+ "scope": "resource"
+ },
+ "python.unitTest.pyTestPath": {
+ "type": "string",
+ "default": "pytest",
+ "description": "Path to pytest (pytest), you can use a custom version of pytest by modifying this setting to include the full path.",
"scope": "resource"
},
"python.unitTest.unittestArgs": {
@@ -1483,55 +1770,82 @@
},
"scope": "resource"
},
- "python.linting.ignorePatterns": {
+ "python.unitTest.unittestEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Whether to enable or disable unit testing using unittest.",
+ "scope": "resource"
+ },
+ "python.unitTest.useExperimentalDebugger": {
+ "type": "boolean",
+ "default": false,
+ "description": "Use the experimental debugger when debugging unit tests.",
+ "scope": "resource"
+ },
+ "python.unitTest.autoTestDiscoverOnSaveEnabled": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to enable or disable auto run test discovery when saving a unit test file.",
+ "scope": "resource"
+ },
+ "python.venvFolders": {
"type": "array",
- "description": "Patterns used to exclude files or folders from being linted.",
"default": [
- ".vscode/*.py",
- "**/site-packages/**/*.py"
+ "envs",
+ ".pyenv",
+ ".direnv"
],
+ "description": "Folders in your home directory to look into for virtual environments.",
+ "scope": "resource",
"items": {
"type": "string"
- },
- "scope": "resource"
+ }
},
- "python.linting.pylamaEnabled": {
- "type": "boolean",
- "default": false,
- "description": "Whether to lint Python files using pylama.",
+ "python.venvPath": {
+ "type": "string",
+ "default": "",
+ "description": "Path to folder with a list of Virtual Environments (e.g. ~/.pyenv, ~/Envs, ~/.virtualenvs).",
"scope": "resource"
},
- "python.linting.pylamaPath": {
+ "python.workspaceSymbols.ctagsPath": {
"type": "string",
- "default": "pylama",
- "description": "Path to pylama, you can use a custom version of pylama by modifying this setting to include the full path.",
+ "default": "ctags",
+ "description": "Fully qualilified path to the ctags executable (else leave as ctags, assuming it is in current path).",
"scope": "resource"
},
- "python.linting.pylamaArgs": {
+ "python.workspaceSymbols.enabled": {
+ "type": "boolean",
+ "default": true,
+ "description": "Set to 'false' to disable Workspace Symbol provider using ctags.",
+ "scope": "resource"
+ },
+ "python.workspaceSymbols.exclusionPatterns": {
"type": "array",
- "description": "Arguments passed in. Each argument is a separate item in the array.",
- "default": [],
+ "default": [
+ "**/site-packages/**"
+ ],
"items": {
"type": "string"
},
+ "description": "Pattern used to exclude files and folders from ctags See http://ctags.sourceforge.net/ctags.html.",
"scope": "resource"
},
- "python.terminal.executeInFileDir": {
+ "python.workspaceSymbols.rebuildOnFileSave": {
"type": "boolean",
- "default": false,
- "description": "When executing a file in the terminal, whether to use execute in the file's directory, instead of the current open folder.",
+ "default": true,
+ "description": "Whether to re-build the tags file on when changes made to python files are saved.",
"scope": "resource"
},
- "python.terminal.activateEnvironment": {
+ "python.workspaceSymbols.rebuildOnStart": {
"type": "boolean",
"default": true,
- "description": "Activate Python Environment in Terminal created using the Extension.",
+ "description": "Whether to re-build the tags file on start (defaults to true).",
"scope": "resource"
},
- "python.terminal.launchArgs": {
- "type": "array",
- "default": [],
- "description": "Python launch arguments to use when executing a file in the terminal.",
+ "python.workspaceSymbols.tagFilePath": {
+ "type": "string",
+ "default": "${workspaceFolder}/.vscode/tags",
+ "description": "Fully qualified path to tag file (exuberant ctag file), used to provide workspace symbols.",
"scope": "resource"
}
}
@@ -1544,11 +1858,17 @@
"requirements.txt"
],
"filenames": [
- "requirements.txt"
+ "requirements.txt",
+ "constraints.txt",
+ "requirements.in"
],
"filenamePatterns": [
"*-requirements.txt",
- "requirements-*.txt"
+ "requirements-*.txt",
+ "constraints-*.txt",
+ "*-constraints.txt",
+ "*-requirements.in",
+ "requirements-*.in"
],
"configuration": "./languages/pip-requirements.json"
},
@@ -1557,6 +1877,28 @@
"filenames": [
".condarc"
]
+ },
+ {
+ "id": "toml",
+ "filenames": [
+ "Pipfile"
+ ]
+ },
+ {
+ "id": "json",
+ "filenames": [
+ "Pipfile.lock"
+ ]
+ },
+ {
+ "id": "jinja",
+ "extensions": [
+ ".jinja2",
+ ".j2"
+ ],
+ "aliases": [
+ "Jinja"
+ ]
}
],
"grammars": [
@@ -1596,112 +1938,137 @@
]
},
"scripts": {
- "vscode:prepublish": "tsc -p ./",
+ "vscode:prepublish": "gulp checkNativeDependencies && tsc -p ./",
"compile": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "node ./out/test/standardTest.js && node ./out/test/multiRootTest.js",
+ "test:unittests": "node ./out/test/unittests.js",
"testDebugger": "node ./out/test/debuggerTest.js",
"testSingleWorkspace": "node ./out/test/standardTest.js",
"testMultiWorkspace": "node ./out/test/multiRootTest.js",
+ "testAnalysisEngine": "node ./out/test/analysisEngineTest.js",
+ "testPerformance": "node ./out/test/performanceTest.js",
"precommit": "node gulpfile.js",
"lint-staged": "node gulpfile.js",
"lint": "tslint src/**/*.ts -t verbose",
"clean": "gulp clean",
- "cover:enable": "gulp cover:enable"
+ "clean:ptvsd": "gulp clean:ptvsd",
+ "cover:enable": "gulp cover:enable",
+ "debugger-coverage": "gulp debugger-coverage",
+ "cover:inlinesource": "gulp inlinesource"
},
"dependencies": {
- "arch": "^2.1.0",
- "diff-match-patch": "^1.0.0",
- "fs-extra": "^4.0.2",
- "fuzzy": "^0.1.3",
- "get-port": "^3.2.0",
- "iconv-lite": "^0.4.19",
- "inversify": "^4.5.2",
- "line-by-line": "^0.1.5",
- "lodash": "^4.17.4",
- "md5": "^2.2.1",
- "minimatch": "^3.0.3",
- "named-js-regexp": "^1.3.1",
- "opn": "^5.1.0",
- "pidusage": "^1.2.0",
- "reflect-metadata": "^0.1.12",
- "rxjs": "^5.5.2",
- "semver": "^5.4.1",
- "sudo-prompt": "^8.0.0",
+ "arch": "2.1.0",
+ "diff-match-patch": "1.0.0",
+ "dotenv": "5.0.1",
+ "fs-extra": "4.0.3",
+ "fuzzy": "0.1.3",
+ "get-port": "3.2.0",
+ "glob": "7.1.2",
+ "iconv-lite": "0.4.21",
+ "inversify": "4.11.1",
+ "line-by-line": "0.1.6",
+ "lodash": "4.17.5",
+ "md5": "2.2.1",
+ "minimatch": "3.0.4",
+ "named-js-regexp": "1.3.3",
+ "node-stream-zip": "1.6.0",
+ "opn": "5.3.0",
+ "pidusage": "1.2.0",
+ "reflect-metadata": "0.1.12",
+ "request": "2.85.0",
+ "request-progress": "3.0.0",
+ "rxjs": "5.5.9",
+ "semver": "5.5.0",
+ "sudo-prompt": "8.2.0",
"tmp": "0.0.29",
- "tree-kill": "^1.1.0",
- "typescript-char": "^0.0.0",
- "uint64be": "^1.0.1",
- "unicode": "^10.0.0",
- "untildify": "^3.0.2",
- "vscode-debugadapter": "^1.0.1",
- "vscode-debugprotocol": "^1.0.1",
- "vscode-extension-telemetry": "^0.0.14",
- "vscode-languageclient": "^3.1.0",
- "vscode-languageserver": "^3.1.0",
- "winreg": "^1.2.4",
- "xml2js": "^0.4.17"
+ "tree-kill": "1.2.0",
+ "typescript-char": "0.0.0",
+ "uint64be": "1.0.1",
+ "unicode": "10.0.0",
+ "untildify": "3.0.2",
+ "vscode-debugadapter": "1.28.0",
+ "vscode-debugprotocol": "1.28.0",
+ "vscode-extension-telemetry": "0.0.15",
+ "vscode-languageclient": "4.3.0",
+ "vscode-languageserver": "4.3.0",
+ "vscode-languageserver-protocol": "3.9.0",
+ "winreg": "1.2.4",
+ "xml2js": "0.4.19"
},
"devDependencies": {
- "@types/chai": "4.0.6",
+ "@types/chai": "^4.1.2",
+ "@types/chai-arrays": "^1.0.2",
"@types/chai-as-promised": "^7.1.0",
"@types/del": "^3.0.0",
+ "@types/dotenv": "^4.0.3",
+ "@types/download": "^6.2.2",
"@types/event-stream": "^3.3.33",
- "@types/fs-extra": "^4.0.2",
+ "@types/fs-extra": "^5.0.1",
"@types/get-port": "^3.2.0",
- "@types/glob": "^5.0.34",
- "@types/iconv-lite": "0.0.1",
+ "@types/glob": "^5.0.35",
+ "@types/iconv-lite": "^0.0.1",
"@types/istanbul": "^0.4.29",
- "@types/lodash": "^4.14.74",
+ "@types/lodash": "^4.14.104",
"@types/md5": "^2.1.32",
- "@types/mocha": "^2.2.43",
- "@types/node": "^6.0.40",
- "@types/semver": "^5.4.0",
- "@types/shortid": "0.0.29",
- "@types/sinon": "^2.3.2",
+ "@types/mocha": "^2.2.48",
+ "@types/node": "9.4.7",
+ "@types/request": "^2.47.0",
+ "@types/semver": "^5.5.0",
+ "@types/shortid": "^0.0.29",
+ "@types/sinon": "^4.3.0",
+ "@types/tmp": "0.0.33",
"@types/untildify": "^3.0.0",
- "@types/uuid": "^3.3.27",
+ "@types/uuid": "^3.4.3",
"@types/winreg": "^1.2.30",
- "@types/xml2js": "^0.4.0",
+ "@types/xml2js": "^0.4.2",
"JSONStream": "^1.3.2",
- "azure-storage": "^2.7.0",
+ "azure-storage": "^2.8.1",
"chai": "^4.1.2",
+ "chai-arrays": "^2.0.0",
"chai-as-promised": "^7.1.1",
"codecov": "^3.0.0",
- "colors": "^1.1.2",
+ "colors": "^1.2.1",
+ "cross-spawn": "^6.0.5",
"debounce": "^1.1.0",
- "decache": "^4.3.0",
+ "decache": "^4.4.0",
"del": "^3.0.0",
+ "download": "^7.0.0",
"event-stream": "^3.3.4",
+ "flat": "^4.0.0",
"gulp": "^3.9.1",
"gulp-debounced-watch": "^1.0.4",
- "gulp-filter": "^5.0.1",
+ "gulp-filter": "^5.1.0",
"gulp-gitmodified": "^1.1.1",
- "gulp-json-editor": "^2.2.1",
+ "gulp-inline-source": "^3.2.0",
+ "gulp-json-editor": "^2.2.2",
"gulp-sourcemaps": "^2.6.4",
- "gulp-typescript": "^3.2.2",
- "gulp-watch": "^4.3.11",
+ "gulp-typescript": "^4.0.1",
+ "gulp-watch": "^5.0.0",
"husky": "^0.14.3",
"is-running": "^2.1.0",
"istanbul": "^0.4.5",
- "mocha": "^2.3.3",
+ "mocha": "^5.0.4",
+ "mocha-junit-reporter": "^1.17.0",
+ "node-has-native-dependencies": "^1.0.2",
"relative": "^3.0.2",
- "remap-istanbul": "^0.9.5",
+ "remap-istanbul": "^0.10.1",
"retyped-diff-match-patch-tsd-ambient": "^1.0.0-0",
"shortid": "^2.2.8",
- "sinon": "^2.3.6",
- "tslint": "^5.7.0",
- "tslint-eslint-rules": "^4.1.1",
- "tslint-microsoft-contrib": "^5.0.1",
+ "sinon": "^4.4.5",
+ "tslint": "^5.9.1",
+ "tslint-eslint-rules": "^5.1.0",
+ "tslint-microsoft-contrib": "^5.0.3",
"typemoq": "^2.1.0",
- "typescript": "^2.6.2",
- "typescript-formatter": "^6.0.0",
+ "typescript": "^2.9.1",
+ "typescript-formatter": "^7.1.0",
+ "uuid": "^3.2.1",
"vscode": "^1.1.5",
- "vscode-debugadapter-testsupport": "^1.25.0"
+ "vscode-debugadapter-testsupport": "^1.27.0"
},
"__metadata": {
"id": "f1f59ae4-9318-4f3c-a9b5-81b2eaa5f8a5",
"publisherDisplayName": "Microsoft",
"publisherId": "998b010b-e2af-44a5-a6cd-0b5fd3b9b6f8"
}
-}
\ No newline at end of file
+}
diff --git a/package.nls.es.json b/package.nls.es.json
new file mode 100644
index 000000000000..3d2df644941f
--- /dev/null
+++ b/package.nls.es.json
@@ -0,0 +1,52 @@
+{
+ "python.command.python.sortImports.title": "Ordenar importaciones",
+ "python.command.python.startREPL.title": "Nuevo REPL",
+ "python.command.python.createTerminal.title": "Nueva terminal",
+ "python.command.python.buildWorkspaceSymbols.title": "Compilar símbolos del area de trabajo",
+ "python.command.python.runtests.title": "Ejecutar todas las pruebas unitarias",
+ "python.command.python.debugtests.title": "Depurar todas la pruebas unitarias",
+ "python.command.python.execInTerminal.title": "Ejecutar archivo Python en la terminal",
+ "python.command.python.setInterpreter.title": "Seleccionar intérprete",
+ "python.command.python.updateSparkLibrary.title": "Actualizar las librerías PySpark del area de trabajo",
+ "python.command.python.refactorExtractVariable.title": "Extraer variable",
+ "python.command.python.refactorExtractMethod.title": "Extraer método",
+ "python.command.python.viewTestOutput.title": "Mostrar resultados de la prueba unitaria",
+ "python.command.python.selectAndRunTestMethod.title": "Método de ejecución de pruebas unitarias ...",
+ "python.command.python.selectAndDebugTestMethod.title": "Método de depuración de pruebas unitarias ...",
+ "python.command.python.selectAndRunTestFile.title": "Ejecutar archivo de prueba unitaria ...",
+ "python.command.python.runCurrentTestFile.title": "Ejecutar archivo de prueba unitaria actual",
+ "python.command.python.runFailedTests.title": "Ejecutar pruebas unitarias fallidas",
+ "python.command.python.discoverTests.title": "Encontrar pruebas unitarias",
+ "python.command.python.execSelectionInTerminal.title": "Ejecutar linea/selección en la terminal",
+ "python.command.python.execSelectionInDjangoShell.title": "Ejecutar linea/selección en el interprete de Django",
+ "python.command.python.goToPythonObject.title": "Ir al objeto de Python",
+ "python.command.python.setLinter.title": "Selecionar Linter",
+ "python.command.python.enableLinting.title": "Habilitar Linting",
+ "python.command.python.runLinting.title": "Ejecutar Linting",
+ "python.snippet.launch.standard.label": "Python: Archivo actual",
+ "python.snippet.launch.standard.description": "Depurar una aplicación Python con salida estandar",
+ "python.snippet.launch.pyspark.label": "Python: PySpark",
+ "python.snippet.launch.pyspark.description": "Depurar una aplicación de PySpark",
+ "python.snippet.launch.module.label": "Python: Módulo",
+ "python.snippet.launch.module.description": "Depurar un módulo de Python",
+ "python.snippet.launch.terminal.label": "Python: Terminal (integrada)",
+ "python.snippet.launch.terminal.description": "Depurar una aplicación Python usando la terminal integrada",
+ "python.snippet.launch.externalTerminal.label": "Python: Terminal (externa)",
+ "python.snippet.launch.externalTerminal.description": "Depurar una aplicación Python usando una terminal externa",
+ "python.snippet.launch.django.label": "Python: Django",
+ "python.snippet.launch.django.description": "Depurar una aplicación de Django",
+ "python.snippet.launch.flask.label": "Python: Flask (Versión 0.11.x o posterior)",
+ "python.snippet.launch.flask.description": "Depurar una aplicación de Flask",
+ "python.snippet.launch.flaskOld.label": "Python: Flask (Versión 0.10.x o anterior)",
+ "python.snippet.launch.flaskOld.description": "Depurar una aplicación de Flask de estilo antiguo",
+ "python.snippet.launch.gevent.label": "Python: Gevent",
+ "python.snippet.launch.gevent.description": "Depurar una aplicación de Gevent",
+ "python.snippet.launch.pyramid.label": "Python: Pyramid",
+ "python.snippet.launch.pyramid.description": "Depurar una aplicación de Pyramid",
+ "python.snippet.launch.watson.label": "Python: Watson",
+ "python.snippet.launch.watson.description": "Depurar una aplicación de Watson",
+ "python.snippet.launch.attach.label": "Python: Adjuntar",
+ "python.snippet.launch.attach.description": "Depuración remota usando depurador adjunto",
+ "python.snippet.launch.scrapy.label": "Python: Scrapy",
+ "python.snippet.launch.scrapy.description": "Scrapy usando la terminal integrada"
+}
diff --git a/package.nls.fr.json b/package.nls.fr.json
new file mode 100644
index 000000000000..c764405ca1da
--- /dev/null
+++ b/package.nls.fr.json
@@ -0,0 +1,49 @@
+{
+ "python.command.python.sortImports.title": "Trier les imports",
+ "python.command.python.startREPL.title": "Démarrer la console interactive",
+ "python.command.python.createTerminal.title": "Créer un terminal",
+ "python.command.python.buildWorkspaceSymbols.title": "Construire les symboles de l'espace de travail",
+ "python.command.python.runtests.title": "Exécuter tous les tests unitaires",
+ "python.command.python.debugtests.title": "Déboguer tous les tests unitaires",
+ "python.command.python.execInTerminal.title": "Exécuter le script Python dans un terminal",
+ "python.command.python.setInterpreter.title": "Sélectionner l'interpreteur",
+ "python.command.python.updateSparkLibrary.title": "Mettre à jour les librairies de l'espace de travail PySpark",
+ "python.command.python.refactorExtractVariable.title": "Extraire la variable",
+ "python.command.python.refactorExtractMethod.title": "Extraire la méthode",
+ "python.command.python.viewTestOutput.title": "Afficher la sortie des tests unitaires",
+ "python.command.python.selectAndRunTestMethod.title": "Exécuter la méthode de test unitaire ...",
+ "python.command.python.selectAndDebugTestMethod.title": "Déboguer la méthode de test unitaire ...",
+ "python.command.python.selectAndRunTestFile.title": "Exécuter le fichier de test unitaire ...",
+ "python.command.python.runCurrentTestFile.title": "Exécuter le fichier de test unitaire courant",
+ "python.command.python.runFailedTests.title": "Exécuter les derniers test unitaires échoués",
+ "python.command.python.execSelectionInTerminal.title": "Exécuter la ligne/sélection dans un terminal Python",
+ "python.command.python.execSelectionInDjangoShell.title": "Exécuter la ligne/sélection dans un shell Django",
+ "python.command.python.goToPythonObject.title": "Se rendre à l'objet Python",
+ "python.command.python.setLinter.title": "Sélectionner le linter",
+ "python.command.python.enableLinting.title": "Activer le linting",
+ "python.command.python.runLinting.title": "Exécuter le linting",
+ "python.snippet.launch.standard.label": "Python : Fichier actuel",
+ "python.snippet.launch.standard.description": "Déboguer un programme Python avec la sortie standard",
+ "python.snippet.launch.pyspark.label": "Python : PySpark",
+ "python.snippet.launch.pyspark.description": "Déboguer PySpark",
+ "python.snippet.launch.module.label": "Python: Module",
+ "python.snippet.launch.module.description": "Déboguer un module Python",
+ "python.snippet.launch.terminal.label": "Python : Terminal (intégré)",
+ "python.snippet.launch.terminal.description": "Déboguer un programme Python avec la console intégrée",
+ "python.snippet.launch.externalTerminal.label": "Python : Terminal (externe)",
+ "python.snippet.launch.externalTerminal.description": "Déboguer un programme Python avec une console externe",
+ "python.snippet.launch.django.label": "Python : Django",
+ "python.snippet.launch.django.description": "Déboguer une application Django",
+ "python.snippet.launch.flask.label": "Python : Flask (0.11.x ou supérieur)",
+ "python.snippet.launch.flask.description": "Déboguer une application Flask",
+ "python.snippet.launch.flaskOld.label": "Python : Flask (0.10.x ou antérieur)",
+ "python.snippet.launch.flaskOld.description": "Déboguer une application Flask (0.10.x ou antérieur)",
+ "python.snippet.launch.pyramid.label": "Python : application Pyramid",
+ "python.snippet.launch.pyramid.description": "Déboguer une application Pyramid",
+ "python.snippet.launch.watson.label": "Python: Application Watson",
+ "python.snippet.launch.watson.description": "Déboguer une Application Watson",
+ "python.snippet.launch.attach.label": "Python: Attacher",
+ "python.snippet.launch.attach.description": "Attacher le débogueur pour un débogage distant",
+ "python.snippet.launch.scrapy.label": "Python : Scrapy",
+ "python.snippet.launch.scrapy.description": "Scrapy avec un terminal intégré"
+}
diff --git a/package.nls.it.json b/package.nls.it.json
new file mode 100644
index 000000000000..6fabf1d664c8
--- /dev/null
+++ b/package.nls.it.json
@@ -0,0 +1,49 @@
+{
+ "python.command.python.sortImports.title": "Ordina gli import",
+ "python.command.python.startREPL.title": "Apri nuova REPL",
+ "python.command.python.createTerminal.title": "Apri nuovo terminale",
+ "python.command.python.buildWorkspaceSymbols.title": "Compila simboli dello spazio di lavoro",
+ "python.command.python.runtests.title": "Esegui tutti i test",
+ "python.command.python.debugtests.title": "Esegui debug di tutti i test",
+ "python.command.python.execInTerminal.title": "Esegui file Python nel terminale",
+ "python.command.python.setInterpreter.title": "Seleziona interprete",
+ "python.command.python.updateSparkLibrary.title": "Aggiorna librerie PySpark dello spazio di lavoro",
+ "python.command.python.refactorExtractVariable.title": "Estrai variable",
+ "python.command.python.refactorExtractMethod.title": "Estrai metodo",
+ "python.command.python.viewTestOutput.title": "Mostra output dei test",
+ "python.command.python.selectAndRunTestMethod.title": "Esegui metodo di test ...",
+ "python.command.python.selectAndDebugTestMethod.title": "Esegui debug del metodo di test ...",
+ "python.command.python.selectAndRunTestFile.title": "Esegui file di test ...",
+ "python.command.python.runCurrentTestFile.title": "Esegui file di test attuale",
+ "python.command.python.runFailedTests.title": "Esegui test falliti",
+ "python.command.python.execSelectionInTerminal.title": "Esegui selezione/linea nel terminale di Python",
+ "python.command.python.execSelectionInDjangoShell.title": "Esegui selezione/linea nella shell Django",
+ "python.command.python.goToPythonObject.title": "Vai a oggetto Python",
+ "python.command.python.setLinter.title": "Selezione Linter",
+ "python.command.python.enableLinting.title": "Attiva Linting",
+ "python.command.python.runLinting.title": "Esegui Linting",
+ "python.snippet.launch.standard.label": "Python: File corrente",
+ "python.snippet.launch.standard.description": "Esegui debug di un programma Python su output predefinito",
+ "python.snippet.launch.pyspark.label": "Python: PySpark",
+ "python.snippet.launch.pyspark.description": "Esegui debug PySpark",
+ "python.snippet.launch.module.label": "Python: Modulo",
+ "python.snippet.launch.module.description": "Esegui debug modulo Python",
+ "python.snippet.launch.terminal.label": "Python: Terminale (integrato)",
+ "python.snippet.launch.terminal.description": "Esegui debug di un programma Python nel terminale integrato",
+ "python.snippet.launch.externalTerminal.label": "Python: Terminale (esterno)",
+ "python.snippet.launch.externalTerminal.description": "Esegui debug di un programma Python nel terminale esterno",
+ "python.snippet.launch.django.label": "Python: Django",
+ "python.snippet.launch.django.description": "Esegui debug applicazione Django",
+ "python.snippet.launch.flask.label": "Python: Flask (0.11.x o successiva)",
+ "python.snippet.launch.flask.description": "Esegui debug applicazione Flask",
+ "python.snippet.launch.flaskOld.label": "Python: Flask (0.10.x o precedente)",
+ "python.snippet.launch.flaskOld.description": "Esegui debug applicazione Flask in vecchio stile",
+ "python.snippet.launch.pyramid.label": "Python: Applicazione Pyramid",
+ "python.snippet.launch.pyramid.description": "Esegui debug applicazione Pyramid",
+ "python.snippet.launch.watson.label": "Python: Applicazione Watson",
+ "python.snippet.launch.watson.description": "Esegui debug applicazione Watson",
+ "python.snippet.launch.attach.label": "Python: Allega",
+ "python.snippet.launch.attach.description": "Allega debugger per debug remoto",
+ "python.snippet.launch.scrapy.label": "Python: Scrapy",
+ "python.snippet.launch.scrapy.description": "Scrapy con terminale integrato"
+}
diff --git a/package.nls.json b/package.nls.json
index f1fd181184ab..333a94791381 100644
--- a/package.nls.json
+++ b/package.nls.json
@@ -16,6 +16,7 @@
"python.command.python.selectAndRunTestFile.title": "Run Unit Test File ...",
"python.command.python.runCurrentTestFile.title": "Run Current Unit Test File",
"python.command.python.runFailedTests.title": "Run Failed Unit Tests",
+ "python.command.python.discoverTests.title": "Discover Unit Tests",
"python.command.python.execSelectionInTerminal.title": "Run Selection/Line in Python Terminal",
"python.command.python.execSelectionInDjangoShell.title": "Run Selection/Line in Django Shell",
"python.command.python.goToPythonObject.title": "Go to Python Object",
@@ -23,7 +24,7 @@
"python.command.python.enableLinting.title": "Enable Linting",
"python.command.python.runLinting.title": "Run Linting",
"python.snippet.launch.standard.label": "Python: Current File",
- "python.snippet.launch.standard.description": "Debug a Python program with standard output",
+ "python.snippet.launch.standard.description": "Debug a Python Program with Standard Output",
"python.snippet.launch.pyspark.label": "Python: PySpark",
"python.snippet.launch.pyspark.description": "Debug PySpark",
"python.snippet.launch.module.label": "Python: Module",
@@ -38,12 +39,14 @@
"python.snippet.launch.flask.description": "Debug a Flask Application",
"python.snippet.launch.flaskOld.label": "Python: Flask (0.10.x or earlier)",
"python.snippet.launch.flaskOld.description": "Debug an older styled Flask Application",
+ "python.snippet.launch.gevent.label": "Python: Gevent",
+ "python.snippet.launch.gevent.description": "Debug a Gevent Application",
"python.snippet.launch.pyramid.label": "Python: Pyramid Application",
"python.snippet.launch.pyramid.description": "Debug a Pyramid Application",
"python.snippet.launch.watson.label": "Python: Watson Application",
"python.snippet.launch.watson.description": "Debug a Watson Application",
"python.snippet.launch.attach.label": "Python: Attach",
- "python.snippet.launch.attach.description": "Attach the debugger for remote debugging",
+ "python.snippet.launch.attach.description": "Attach the Debugger for Remote Debugging",
"python.snippet.launch.scrapy.label": "Python: Scrapy",
"python.snippet.launch.scrapy.description": "Scrapy with Integrated Terminal/Console"
}
diff --git a/package.nls.pt-br.json b/package.nls.pt-br.json
new file mode 100644
index 000000000000..5b6e4dc2b539
--- /dev/null
+++ b/package.nls.pt-br.json
@@ -0,0 +1,52 @@
+{
+ "python.command.python.sortImports.title": "Ordenar Importações",
+ "python.command.python.startREPL.title": "Iniciar REPL",
+ "python.command.python.createTerminal.title": "Criar Terminal",
+ "python.command.python.buildWorkspaceSymbols.title": "Construir Símbolos da Área de Trabalho",
+ "python.command.python.runtests.title": "Executar Todos os Testes Unitários",
+ "python.command.python.debugtests.title": "Depurar Todos os Testes Unitários",
+ "python.command.python.execInTerminal.title": "Executar Arquivo no Terminal",
+ "python.command.python.setInterpreter.title": "Selecionar Interpretador",
+ "python.command.python.updateSparkLibrary.title": "Atualizar Área de Trabalho da Biblioteca PySpark",
+ "python.command.python.refactorExtractVariable.title": "Extrair Variável",
+ "python.command.python.refactorExtractMethod.title": "Extrair Método",
+ "python.command.python.viewTestOutput.title": "Exibir Resultados dos Testes Unitários",
+ "python.command.python.selectAndRunTestMethod.title": "Executar Testes Unitários do Método ...",
+ "python.command.python.selectAndDebugTestMethod.title": "Depurar Testes Unitários do Método ...",
+ "python.command.python.selectAndRunTestFile.title": "Executar Arquivo de Testes Unitários ...",
+ "python.command.python.runCurrentTestFile.title": "Executar o Arquivo de Testes Unitários Atual",
+ "python.command.python.runFailedTests.title": "Executar Testes Unitários com Falhas",
+ "python.command.python.discoverTests.title": "Descobrir Testes Unitários",
+ "python.command.python.execSelectionInTerminal.title": "Executar Seleção/Linha no Terminal",
+ "python.command.python.execSelectionInDjangoShell.title": "Executar Seleção/Linha no Django Shell",
+ "python.command.python.goToPythonObject.title": "Ir para Objeto Python",
+ "python.command.python.setLinter.title": "Selecionar Linter",
+ "python.command.python.enableLinting.title": "Habilitar Linting",
+ "python.command.python.runLinting.title": "Executar Linting",
+ "python.snippet.launch.standard.label": "Python: Arquivo Atual",
+ "python.snippet.launch.standard.description": "Depurar um Programa Python com a saída padrão",
+ "python.snippet.launch.pyspark.label": "Python: PySpark",
+ "python.snippet.launch.pyspark.description": "Depurar PySpark",
+ "python.snippet.launch.module.label": "Python: Módulo",
+ "python.snippet.launch.module.description": "Depurar um Módulo Python",
+ "python.snippet.launch.terminal.label": "Python: Terminal (integrado)",
+ "python.snippet.launch.terminal.description": "Depurar um Programa Python com Terminal/Console Integrado",
+ "python.snippet.launch.externalTerminal.label": "Python: Terminal (externo)",
+ "python.snippet.launch.externalTerminal.description": "Depurar um Programa Python com Terminal/Console Externo",
+ "python.snippet.launch.django.label": "Python: Django",
+ "python.snippet.launch.django.description": "Depurar uma Aplicação Django",
+ "python.snippet.launch.flask.label": "Python: Flask (0.11.x ou superior)",
+ "python.snippet.launch.flask.description": "Depurar uma Aplicação Flask",
+ "python.snippet.launch.flaskOld.label": "Python: Flask (0.10.x ou inferior)",
+ "python.snippet.launch.flaskOld.description": "Depurar uma Aplicação Flask no Estilo Antigo",
+ "python.snippet.launch.gevent.label": "Python: Gevent",
+ "python.snippet.launch.gevent.description": "Depurar uma Aplicação Gevent",
+ "python.snippet.launch.pyramid.label": "Python: Aplicação Pyramid",
+ "python.snippet.launch.pyramid.description": "Depurar uma Aplicação Pyramid",
+ "python.snippet.launch.watson.label": "Python: Aplicação Watson",
+ "python.snippet.launch.watson.description": "Depurar uma Aplicação Watson",
+ "python.snippet.launch.attach.label": "Python: Anexar",
+ "python.snippet.launch.attach.description": "Anexar depurador para depuração remota",
+ "python.snippet.launch.scrapy.label": "Python: Scrapy",
+ "python.snippet.launch.scrapy.description": "Scrapy com Terminal/Console Integrado"
+}
diff --git a/package.nls.zh-cn.json b/package.nls.zh-cn.json
index b884240efa16..4580d1fa4b10 100644
--- a/package.nls.zh-cn.json
+++ b/package.nls.zh-cn.json
@@ -1,6 +1,7 @@
{
"python.command.python.sortImports.title": "排序 import 语句",
"python.command.python.startREPL.title": "启动 REPL",
+ "python.command.python.createTerminal.title": "创建终端",
"python.command.python.buildWorkspaceSymbols.title": "构建工作区符号",
"python.command.python.runtests.title": "运行所有单元测试",
"python.command.python.debugtests.title": "调试所有单元测试",
@@ -15,9 +16,14 @@
"python.command.python.selectAndRunTestFile.title": "运行单元测试文件...",
"python.command.python.runCurrentTestFile.title": "运行当前单元测试文件",
"python.command.python.runFailedTests.title": "运行失败的单元测试",
+ "python.command.python.discoverTests.title": "检测单元测试",
"python.command.python.execSelectionInTerminal.title": "在 Python 终端中运行选定内容/行",
"python.command.python.execSelectionInDjangoShell.title": "在 Django Shell 中运行选定内容/行",
"python.command.python.goToPythonObject.title": "转到 Python 对象",
+ "python.command.python.setLinter.title": "选择 Linter 插件",
+ "python.command.python.enableLinting.title": "启用 Linting",
+ "python.command.python.runLinting.title": "运行 Linting",
+ "python.snippet.launch.standard.label": "Python: 当前文件",
"python.snippet.launch.standard.label": "Python: Current File",
"python.snippet.launch.standard.description": "使用标准输出调试 Python 应用",
"python.snippet.launch.pyspark.label": "Python: PySpark",
@@ -34,6 +40,8 @@
"python.snippet.launch.flask.description": "调试 Flask 应用",
"python.snippet.launch.flaskOld.label": "Python: Flask (0.10.x 或之前)",
"python.snippet.launch.flaskOld.description": "调试旧式 Flask 应用",
+ "python.snippet.launch.gevent.label": "Python: Gevent 应用",
+ "python.snippet.launch.gevent.description": "调试 Gevent 应用",
"python.snippet.launch.pyramid.label": "Python: Pyramid 应用",
"python.snippet.launch.pyramid.description": "调试 Pyramid 应用",
"python.snippet.launch.watson.label": "Python: Watson 应用",
diff --git a/packageExtension.cmd b/packageExtension.cmd
new file mode 100644
index 000000000000..dc3026c20f3e
--- /dev/null
+++ b/packageExtension.cmd
@@ -0,0 +1 @@
+%1\vsce package --out %2
\ No newline at end of file
diff --git a/pythonFiles/PythonTools/ptvsd/__init__.py b/pythonFiles/PythonTools/ptvsd/__init__.py
index 25765e165f14..c1b6fb6cf61e 100644
--- a/pythonFiles/PythonTools/ptvsd/__init__.py
+++ b/pythonFiles/PythonTools/ptvsd/__init__.py
@@ -1,22 +1,22 @@
# Python Tools for Visual Studio
# Copyright(c) Microsoft Corporation
# All rights reserved.
-#
+#
# Licensed under the Apache License, Version 2.0 (the License); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
+#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
__author__ = "Microsoft Corporation "
__version__ = "3.0.0.0"
-__all__ = ['enable_attach', 'wait_for_attach', 'break_into_debugger', 'settrace', 'is_attached', 'AttachAlreadyEnabledError']
+__all__ = ['enable_attach', 'enable_attach_ui', 'wait_for_attach', 'break_into_debugger', 'set_attach_ui_options', 'set_trace', 'is_attached', 'AttachAlreadyEnabledError']
-from ptvsd.attach_server import enable_attach, wait_for_attach, break_into_debugger, settrace, is_attached, AttachAlreadyEnabledError
\ No newline at end of file
+from ptvsd.attach_server import enable_attach, enable_attach_ui, wait_for_attach, break_into_debugger, set_attach_ui_options, set_trace, is_attached, AttachAlreadyEnabledError
diff --git a/pythonFiles/PythonTools/ptvsd/__main__.py b/pythonFiles/PythonTools/ptvsd/__main__.py
index 8fc5004aa43a..2837de743528 100644
--- a/pythonFiles/PythonTools/ptvsd/__main__.py
+++ b/pythonFiles/PythonTools/ptvsd/__main__.py
@@ -54,4 +54,4 @@
DONT_DEBUG.append(os.path.normcase(__file__))
sys.argv = script_argv
-exec_file(script_argv[0], {'__name__': '__main__'})
\ No newline at end of file
+exec_file(script_argv[0], {'__name__': '__main__'})
diff --git a/pythonFiles/PythonTools/ptvsd/attach_server.py b/pythonFiles/PythonTools/ptvsd/attach_server.py
index 743c89be787f..48dbda79b434 100644
--- a/pythonFiles/PythonTools/ptvsd/attach_server.py
+++ b/pythonFiles/PythonTools/ptvsd/attach_server.py
@@ -1,16 +1,16 @@
# Python Tools for Visual Studio
# Copyright(c) Microsoft Corporation
# All rights reserved.
-#
+#
# Licensed under the Apache License, Version 2.0 (the License); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
+#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
@@ -37,6 +37,14 @@
except ImportError:
ssl = None
+import json
+import errno
+from socket import error as socket_error
+try:
+ from urllib.request import urlopen, Request, URLError
+except ImportError:
+ from urllib2 import urlopen, Request, URLError
+
import ptvsd.visualstudio_py_debugger as vspd
import ptvsd.visualstudio_py_repl as vspr
from ptvsd.visualstudio_py_util import to_bytes, read_bytes, read_int, read_string, write_bytes, write_int, write_string
@@ -66,12 +74,12 @@
# (int64), and then the Python language version that the server is running represented by three int64s -
# major, minor, micro; From there on the socket is assumed to be using the normal PTVS debugging protocol.
# If attaching was not successful (which can happen if some other debugger is already attached), the server
-# responds with 'RJCT' and closes the connection.
+# responds with 'RJCT' and closes the connection.
#
# 'REPL'
# Attach REPL to the process. If successful, the server responds with 'ACPT', and from there on the socket
# is assumed to be using the normal PTVS REPL protocol. If not successful (which can happen if there is
-# no debugger attached), the server responds with 'RJCT' and closes the connection.
+# no debugger attached), the server responds with 'RJCT' and closes the connection.
PTVS_VER = '2.2'
DEFAULT_PORT = 5678
@@ -82,16 +90,19 @@
INFO = to_bytes('INFO')
ATCH = to_bytes('ATCH')
REPL = to_bytes('REPL')
+DEBUGGER_UI_PORT = 9615
_attach_enabled = False
_attached = threading.Event()
+_attach_port = None
+_ui_attach_enabled = False
+_ui_attach_options = {}
vspd.DONT_DEBUG.append(os.path.normcase(__file__))
class AttachAlreadyEnabledError(Exception):
"""`ptvsd.enable_attach` has already been called in this process."""
-
def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None, keyfile = None, redirect_output = True):
"""Enables Python Tools for Visual Studio to attach to this process remotely
to debug Python code.
@@ -105,7 +116,7 @@ def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None,
hostname by ``'@'``, e.g.: ``'secret@myhost.cloudapp.net:5678'``. If
secret is ``None``, there's no validation, and any client can connect
freely.
- address : (str, int), optional
+ address : (str, int), optional
Specifies the interface and port on which the debugging server should
listen for TCP connections. It is in the same format as used for
regular sockets of the `socket.AF_INET` family, i.e. a tuple of
@@ -116,7 +127,7 @@ def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None,
Used to enable SSL. If not specified, or if set to ``None``, the
connection between this program and the debugger will be unsecure,
and can be intercepted on the wire. If specified, the meaning of this
- parameter is the same as for `ssl.wrap_socket`.
+ parameter is the same as for `ssl.wrap_socket`.
keyfile : str, optional
Used together with `certfile` when SSL is enabled. Its meaning is the
same as for ``ssl.wrap_socket``.
@@ -131,7 +142,7 @@ def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None,
is attached, call `ptvsd.wait_for_attach`. The debugger can be detached
and re-attached multiple times after `enable_attach` is called.
- This function can only be called once during the lifetime of the process.
+ This function can only be called once during the lifetime of the process.
On a second call, `AttachAlreadyEnabledError` is raised. In circumstances
where the caller does not control how many times the function will be
called (e.g. when a script with a single call is run more than once by
@@ -166,6 +177,8 @@ def enable_attach(secret, address = ('0.0.0.0', DEFAULT_PORT), certfile = None,
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(address)
server.listen(1)
+ global _attach_port
+ _attach_port = server.getsockname()[1]
def server_thread_func():
while True:
client = None
@@ -298,8 +311,61 @@ def replace_trace_func():
vspd.intercept_threads(for_attach = True)
-# Alias for convenience of users of pydevd
-settrace = enable_attach
+# `set_trace` should pause debug execution and attach the debugger UI to the debugger engine
+def set_trace():
+ # Enable on-demand UI attach to the debugger.
+ enable_attach_ui()
+ # Trigger the debugger ui to attach, if one exists
+ debugger_ui_attach()
+ wait_for_attach(30)
+ if vspd.DETACHED:
+ sys.stderr.write('Debugger timed out (30 seconds) waiting for attach!\n')
+ else:
+ break_into_debugger()
+
+
+# Options could have: `debugOptions`, `localRoot` & `remoteRoot` & `id`.
+def enable_attach_ui():
+ global _attach_enabled, _ui_attach_options, _ui_attach_enabled
+ if not _attach_enabled:
+ enable_attach(None, ('0.0.0.0', 0))
+ if not _ui_attach_enabled:
+ _ui_attach_enabled = debugger_ui_enable_attach()
+
+
+def set_attach_ui_options(options):
+ global _ui_attach_options
+ _ui_attach_options = options
+
+
+def debugger_ui_attach():
+ if not vspd.DETACHED:
+ return
+ global _attach_port
+ attach_info = {"domain": "debug", "type": "python", "command": "attach", "port": _attach_port}
+ debugger_ui_request(attach_info)
+
+
+def debugger_ui_enable_attach():
+ global _attach_port, _ui_attach_options
+ attach_info = {"domain": "debug", "type": "python", "command": "enable-attach",
+ "port": _attach_port, "options": _ui_attach_options}
+ return debugger_ui_request(attach_info)
+
+
+def debugger_ui_request(info):
+ req = Request('http://127.0.0.1:' + str(DEBUGGER_UI_PORT),
+ data=json.dumps(info).encode('utf8'),
+ headers={'Content-Type': 'application/json', 'Accept': 'application/json'})
+ try:
+ response = urlopen(req)
+ except URLError:
+ # It's okay if there's no debugger ui server waiting for that info
+ return False
+ json_response = json.loads(response.read())
+ if not json_response['success']:
+ raise RuntimeError('Failed attach attempt')
+ return True
def wait_for_attach(timeout = None):
diff --git a/pythonFiles/PythonTools/ptvsd/visualstudio_py_debugger.py b/pythonFiles/PythonTools/ptvsd/visualstudio_py_debugger.py
index b589a8208baa..12aa0b09f2ed 100644
--- a/pythonFiles/PythonTools/ptvsd/visualstudio_py_debugger.py
+++ b/pythonFiles/PythonTools/ptvsd/visualstudio_py_debugger.py
@@ -1,16 +1,16 @@
# Python Tools for Visual Studio
# Copyright(c) Microsoft Corporation
# All rights reserved.
-#
+#
# Licensed under the Apache License, Version 2.0 (the License); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
+#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
# With number of modifications by Don Jayamanne
@@ -76,8 +76,10 @@
except ImportError:
import ptvsd.visualstudio_py_repl as _vspr
+
try:
import stackless
+ stackless.tasklet # work-around lazy on-demand importers
except ImportError:
stackless = None
@@ -233,8 +235,8 @@ def find_by_id(breakpoint_id):
send_lock = thread.allocate_lock()
class _SendLockContextManager(object):
- """context manager for send lock. Handles both acquiring/releasing the
- send lock as well as detaching the debugger if the remote process
+ """context manager for send lock. Handles both acquiring/releasing the
+ send lock as well as detaching the debugger if the remote process
is disconnected"""
def __enter__(self):
@@ -248,7 +250,7 @@ def __enter__(self):
def __exit__(self, exc_type, exc_value, tb):
send_lock.release()
-
+
# start sending debug events again
cur_thread = get_thread_from_id(thread.get_ident())
if cur_thread is not None:
@@ -258,8 +260,8 @@ def __exit__(self, exc_type, exc_value, tb):
detach_threads()
detach_process()
# swallow the exception, we're no longer debugging
- return True
-
+ return True
+
_SendLockCtx = _SendLockContextManager()
SEND_BREAK_COMPLETE = False
@@ -334,7 +336,7 @@ def is_repr_round_tripping(x):
try:
# getfilesystemencoding is used here because it effectively corresponds to the notion of "locale encoding":
# current ANSI codepage on Windows, LC_CTYPE on Linux, UTF-8 on OS X - which is exactly what we want.
- TYPES_WITH_RAW_REPR[bytearray] = lambda b: b.decode(sys.getfilesystemencoding(), 'ignore')
+ TYPES_WITH_RAW_REPR[bytearray] = lambda b: b.decode(sys.getfilesystemencoding(), 'ignore')
except:
pass
@@ -350,7 +352,7 @@ def is_repr_round_tripping(x):
class StackOverflowException(Exception): pass
else:
StackOverflowException = RuntimeError
-
+
ASBR = to_bytes('ASBR')
SETL = to_bytes('SETL')
THRF = to_bytes('THRF')
@@ -420,7 +422,7 @@ def lookup_local(frame, name):
while bits and obj is not None and type(obj) is types.ModuleType:
obj = getattr(obj, bits.pop(0), None)
return obj
-
+
if sys.version_info[0] >= 3:
_EXCEPTIONS_MODULE = 'builtins'
else:
@@ -489,7 +491,7 @@ def should_break(self, thread, ex_type, ex_value, trace):
break_type = BREAK_TYPE_NONE
return break_type
-
+
def is_handled(self, thread, ex_type, ex_value, trace):
if trace is None:
# get out if we didn't get a traceback
@@ -500,9 +502,9 @@ def is_handled(self, thread, ex_type, ex_value, trace):
# don't break if this is not the top of the traceback,
# unless the previous frame was not debuggable
return True
-
+
cur_frame = trace.tb_frame
-
+
while should_send_frame(cur_frame) and cur_frame.f_code is not None and cur_frame.f_code.co_filename is not None:
filename = path.normcase(cur_frame.f_code.co_filename)
if is_file_in_zip(filename):
@@ -511,11 +513,11 @@ def is_handled(self, thread, ex_type, ex_value, trace):
if not is_same_py_file(filename, __file__):
handlers = self.handler_cache.get(filename)
-
+
if handlers is None:
# req handlers for this file from the debug engine
self.handler_lock.acquire()
-
+
with _SendLockCtx:
write_bytes(conn, REQH)
write_string(conn, filename)
@@ -547,7 +549,7 @@ def is_handled(self, thread, ex_type, ex_value, trace):
cur_frame = cur_frame.f_back
return False
-
+
def add_exception(self, name, mode=BREAK_MODE_UNHANDLED):
if name.startswith(_EXCEPTIONS_MODULE + '.'):
name = name[len(_EXCEPTIONS_MODULE) + 1:]
@@ -556,7 +558,7 @@ def add_exception(self, name, mode=BREAK_MODE_UNHANDLED):
BREAK_ON = ExceptionBreakInfo()
def probe_stack(depth = 10):
- """helper to make sure we have enough stack space to proceed w/o corrupting
+ """helper to make sure we have enough stack space to proceed w/o corrupting
debugger state."""
if depth == 0:
return
@@ -599,7 +601,7 @@ def breakpoint_path_match(vs_path, local_path):
local_path_norm = path.normcase(local_path)
if local_path_to_vs_path.get(local_path_norm) == vs_path_norm:
return True
-
+
# Walk the local filesystem from local_path up, matching agains win_path component by component,
# and stop when we no longer see an __init__.py. This should give a reasonably close approximation
# of matching the package name.
@@ -615,7 +617,7 @@ def breakpoint_path_match(vs_path, local_path):
# needed to, and matched all names on our way, so this is a match.
if not path.exists(path.join(local_path, '__init__.py')):
break
-
+
local_path_to_vs_path[local_path_norm] = vs_path_norm
return True
@@ -623,26 +625,26 @@ def update_all_thread_stacks(blocking_thread = None, check_is_blocked = True):
THREADS_LOCK.acquire()
all_threads = list(THREADS.values())
THREADS_LOCK.release()
-
+
for cur_thread in all_threads:
if cur_thread is blocking_thread:
continue
-
+
cur_thread._block_starting_lock.acquire()
if not check_is_blocked or not cur_thread._is_blocked:
# release the lock, we're going to run user code to evaluate the frames
- cur_thread._block_starting_lock.release()
-
+ cur_thread._block_starting_lock.release()
+
frames = cur_thread.get_frame_list()
-
+
# re-acquire the lock and make sure we're still not blocked. If so send
# the frame list.
cur_thread._block_starting_lock.acquire()
if not check_is_blocked or not cur_thread._is_blocked:
cur_thread.send_frame_list(frames)
-
+
cur_thread._block_starting_lock.release()
-
+
DJANGO_BREAKPOINTS = {}
DJANGO_TEMPLATES = {}
@@ -652,7 +654,7 @@ def __init__(self, filename):
self.filename = filename
self.breakpoints = {}
self.rangeIsPlainText = {}
-
+
def add_breakpoint(self, lineno, brkpt_id):
self.breakpoints[lineno] = brkpt_id
@@ -673,20 +675,20 @@ def is_range_plain_text(self, start, end):
with open(self.filename, 'rb') as contents:
contents.seek(start, 0) # 0 = start of file, optional in this case
data = contents.read(end - start)
- isPlainText = True
+ isPlainText = True
if data.startswith('{{') and data.endswith('}}'):
isPlainText = False
if data.startswith('{%') and data.endswith('%}'):
isPlainText = False
self.rangeIsPlainText[key] = isPlainText
- return isPlainText
+ return isPlainText
except:
return False
else:
return self.rangeIsPlainText.get(key)
def line_number_to_offset(self, lineNumber):
- line_locs = self.line_locations
+ line_locs = self.line_locations
if line_locs is not None:
low_line = line_locs[lineNumber - 1]
hi_line = line_locs[lineNumber]
@@ -722,7 +724,7 @@ def line_locations(self):
return self._line_locations
def get_line_range(self, start, end):
- line_locs = self.line_locations
+ line_locs = self.line_locations
if line_locs is not None:
low_line = bisect.bisect_right(line_locs, start)
hi_line = bisect.bisect_right(line_locs, end)
@@ -735,10 +737,10 @@ def should_break(self, start, end):
low_line, hi_line = self.get_line_range(start, end)
if low_line is not None and hi_line is not None:
# low_line/hi_line is 0 based, self.breakpoints is 1 based
- for i in xrange(low_line+1, hi_line+2):
+ for i in xrange(low_line+1, hi_line+2):
bkpt_id = self.breakpoints.get(i)
if bkpt_id is not None:
- return True, bkpt_id
+ return True, bkpt_id
return False, 0
@@ -756,7 +758,7 @@ def get_django_frame_source(frame):
IS_DJANGO19 = version[0] == 1 and version[1] == 9
IS_DJANGO19_OR_HIGHER = ((version[0] == 1 and version[1] >= 9) or version[0] > 1)
except:
- pass
+ pass
if frame.f_code.co_name == 'render':
self_obj = frame.f_locals.get('self', None)
if self_obj is None:
@@ -794,12 +796,12 @@ def __getattr__(self, name):
class Thread(object):
def __init__(self, id = None):
if id is not None:
- self.id = id
+ self.id = id
else:
self.id = thread.get_ident()
- self._events = {'call' : self.handle_call,
- 'line' : self.handle_line,
- 'return' : self.handle_return,
+ self._events = {'call' : self.handle_call,
+ 'line' : self.handle_line,
+ 'return' : self.handle_return,
'exception' : self.handle_exception,
'c_call' : self.handle_c_call,
'c_return' : self.handle_c_return,
@@ -865,7 +867,7 @@ def new_f(old_f, args, kwargs):
tsk.tempval = new_f
stackless.tasklet.setup(tsk, f, args, kwargs)
return tsk
-
+
def settrace(tsk, tb):
if hasattr(tsk.frame, "f_trace"):
tsk.frame.f_trace = tb
@@ -876,14 +878,14 @@ def settrace(tsk, tb):
stackless.tasklet.__call__ = __call__
if sys.platform == 'cli':
self.frames = []
-
+
if sys.platform == 'cli':
# workaround an IronPython bug where we're sometimes missing the back frames
# http://ironpython.codeplex.com/workitem/31437
def push_frame(self, frame):
self.cur_frame = frame
self.frames.append(frame)
-
+
def pop_frame(self):
self.frames.pop()
self.cur_frame = self.frames[-1]
@@ -908,11 +910,11 @@ def _stackless_schedule_cb(self, prev, next):
if not current:
return
current_tf = current.trace_function
-
+
try:
current.trace_function = None
self.stepping = STEPPING_NONE
-
+
# If the current frame has no trace function, we may need to get it
# from the previous frame, depending on how we ended up in the
# callback.
@@ -939,7 +941,7 @@ def trace_func(self, frame, event, arg):
if sys is None:
return None
elif self.is_sending:
- # https://pytools.codeplex.com/workitem/1864
+ # https://pytools.codeplex.com/workitem/1864
# we're currently doing I/O w/ the socket, we don't want to deliver
# any breakpoints or async breaks because we'll deadlock. Continue
# to return the trace function so all of our frames remain
@@ -953,7 +955,7 @@ def trace_func(self, frame, event, arg):
try:
# if should_debug_code(frame.f_code) is not true during attach
- # the current frame is None and a pop_frame will cause an exception and
+ # the current frame is None and a pop_frame will cause an exception and
# break the debugger
if self.cur_frame is None:
# happens during attach, we need frame for blocking
@@ -972,7 +974,7 @@ def trace_func(self, frame, event, arg):
except (StackOverflowException, KeyboardInterrupt):
# stack overflow, disable tracing
return self.trace_func
-
+
def handle_call(self, frame, arg):
self.push_frame(frame)
@@ -980,10 +982,10 @@ def handle_call(self, frame, arg):
source_obj = get_django_frame_source(frame)
if source_obj is not None:
origin, (start, end), lineNumber = source_obj
-
+
active_bps = DJANGO_BREAKPOINTS.get(origin.lower())
should_break = False
- if active_bps is not None and origin != '':
+ if active_bps is not None and origin != '':
should_break, bkpt_id = active_bps.should_break(start, end)
isPlainText = active_bps.is_range_plain_text(start, end)
if isPlainText:
@@ -1023,8 +1025,8 @@ def handle_call(self, frame, arg):
elif stepping <= STEPPING_OUT:
self.stepping -= 1
- if (sys.platform == 'cli' and
- frame.f_code.co_name == '' and
+ if (sys.platform == 'cli' and
+ frame.f_code.co_name == '' and
not IPY_SEEN_MODULES.TryGetValue(frame.f_code)[0]):
IPY_SEEN_MODULES.Add(frame.f_code, None)
# work around IronPython bug - http://ironpython.codeplex.com/workitem/30127
@@ -1038,7 +1040,7 @@ def handle_call(self, frame, arg):
self.prev_trace_func = old_trace_func(frame, 'call', arg)
return self.trace_func
-
+
def should_block_on_frame(self, frame):
if not should_debug_code(frame.f_code):
return False
@@ -1091,7 +1093,7 @@ def handle_line(self, frame, arg):
# the module to which it was bound, so only exact matches are considered hits.
if bp.is_bound:
continue
- # Otherwise, use relaxed path check that tries to handle differences between
+ # Otherwise, use relaxed path check that tries to handle differences between
# local and remote filesystems for remote scenarios:
if not breakpoint_path_match(filename, frame.f_code.co_filename):
continue
@@ -1159,7 +1161,7 @@ def handle_line(self, frame, arg):
self.prev_trace_func = old_trace_func(frame, 'line', arg)
return self.trace_func
-
+
def handle_return(self, frame, arg):
self.pop_frame()
@@ -1196,7 +1198,7 @@ def handle_return(self, frame, arg):
# restore previous frames trace function if there is one
if self.trace_func_stack:
self.prev_trace_func = self.trace_func_stack.pop()
-
+
def handle_exception(self, frame, arg):
if self.stepping == STEPPING_ATTACH_BREAK:
self.block_maybe_attach()
@@ -1214,15 +1216,15 @@ def handle_exception(self, frame, arg):
self.prev_trace_func = old_trace_func(frame, 'exception', arg)
return self.trace_func
-
+
def handle_c_call(self, frame, arg):
# break points?
pass
-
+
def handle_c_return(self, frame, arg):
# step out of ?
pass
-
+
def handle_c_exception(self, frame, arg):
pass
@@ -1236,7 +1238,7 @@ def block_maybe_attach(self):
will_block_now = False
attach_sent_break = True
attach_lock.release()
-
+
probe_stack()
stepping = self.stepping
self.stepping = STEPPING_NONE
@@ -1252,7 +1254,7 @@ def block_cond():
return report_process_loaded(self.id)
update_all_thread_stacks(self)
self.block(block_cond)
-
+
def async_break(self):
def async_break_send():
with _SendLockCtx:
@@ -1266,7 +1268,7 @@ def async_break_send():
write_int(conn, self.id)
if sent_break_complete:
- # if we have threads which have not broken yet capture their frame list and
+ # if we have threads which have not broken yet capture their frame list and
# send it now. If they block we'll send an updated (and possibly more accurate - if
# there are any thread locals) list of frames.
update_all_thread_stacks(self)
@@ -1278,10 +1280,10 @@ def block(self, block_lambda, keep_stopped_on_line = False):
"""blocks the current thread until the debugger resumes it"""
assert not self._is_blocked
#assert self.id == thread.get_ident(), 'wrong thread identity' + str(self.id) + ' ' + str(thread.get_ident()) # we should only ever block ourselves
-
+
# send thread frames before we block
self.enum_thread_frames_locally()
-
+
if not keep_stopped_on_line:
self.stopped_on_line = self.cur_frame.f_lineno
@@ -1301,7 +1303,7 @@ def block(self, block_lambda, keep_stopped_on_line = False):
self.unblock_work()
self.unblock_work = None
self._is_working = False
-
+
self._block_starting_lock.acquire()
assert self._is_blocked
self._is_blocked = False
@@ -1309,10 +1311,11 @@ def block(self, block_lambda, keep_stopped_on_line = False):
def unblock(self):
"""unblocks the current thread allowing it to continue to run"""
- assert self._is_blocked
+ assert self._is_blocked
assert self.id != thread.get_ident() # only someone else should unblock us
-
- self._block_lock.release()
+
+ if self._block_lock.locked():
+ self._block_lock.release()
def schedule_work(self, work):
self.unblock_work = work
@@ -1320,26 +1323,26 @@ def schedule_work(self, work):
def run_on_thread(self, text, cur_frame, execution_id, frame_kind, repr_kind = PYTHON_EVALUATION_RESULT_REPR_KIND_NORMAL):
self._block_starting_lock.acquire()
-
+
if not self._is_blocked:
report_execution_error('', execution_id)
elif not self._is_working:
self.schedule_work(lambda : self.run_locally(text, cur_frame, execution_id, frame_kind, repr_kind))
else:
report_execution_error('', execution_id)
-
+
self._block_starting_lock.release()
def run_on_thread_no_report(self, text, cur_frame, frame_kind):
self._block_starting_lock.acquire()
-
+
if not self._is_blocked:
pass
elif not self._is_working:
self.schedule_work(lambda : self.run_locally_no_report(text, cur_frame, frame_kind))
else:
pass
-
+
self._block_starting_lock.release()
def enum_child_on_thread(self, text, cur_frame, execution_id, frame_kind):
@@ -1463,7 +1466,7 @@ def enum_child_locally(self, expr, cur_frame, execution_id, frame_kind):
break
key_repr = safe_repr(key)
-
+
# Some objects are enumerable but not indexable, or repr(key) is not a valid Python expression. For those, we
# cannot use obj[key] to get the item by its key, and have to retrieve it by index from enumerate() instead.
try:
@@ -1494,7 +1497,7 @@ def enum_child_locally(self, expr, cur_frame, execution_id, frame_kind):
def get_frame_list(self):
frames = []
cur_frame = self.cur_frame
-
+
while should_send_frame(cur_frame):
# calculate the ending line number
lineno = cur_frame.f_code.co_firstlineno
@@ -1541,7 +1544,7 @@ def get_frame_list(self):
f_globals = cur_frame.f_globals
if f_globals: # ensure globals to work with (IPy may have None for cur_frame.f_globals for frames within stdlib)
self.collect_variables(vars, f_globals, cur_frame.f_code.co_names, treated, skip_unknown = True)
-
+
frame_info = None
if source_obj is not None:
@@ -1557,8 +1560,8 @@ def get_frame_list(self):
frame_kind = FRAME_KIND_DJANGO
frame_info = (
low_line + 1,
- hi_line + 1,
- low_line + 1,
+ hi_line + 1,
+ low_line + 1,
cur_frame.f_code.co_name,
str(origin),
0,
@@ -1571,8 +1574,8 @@ def get_frame_list(self):
if frame_info is None:
frame_info = (
cur_frame.f_code.co_firstlineno,
- lineno,
- cur_frame.f_lineno,
+ lineno,
+ cur_frame.f_lineno,
cur_frame.f_code.co_name,
get_code_filename(cur_frame.f_code),
cur_frame.f_code.co_argcount,
@@ -1583,9 +1586,9 @@ def get_frame_list(self):
)
frames.append(frame_info)
-
+
cur_frame = cur_frame.f_back
-
+
return frames
def collect_variables(self, vars, objects, names, treated, skip_unknown = False):
@@ -1613,24 +1616,24 @@ def send_frame_list(self, frames, thread_name = None):
write_bytes(conn, THRF)
write_int(conn, self.id)
write_string(conn, thread_name)
-
+
# send the frame count
write_int(conn, len(frames))
for firstlineno, lineno, curlineno, name, filename, argcount, variables, frameKind, sourceFile, sourceLine in frames:
- # send each frame
+ # send each frame
write_int(conn, firstlineno)
write_int(conn, lineno)
write_int(conn, curlineno)
-
+
write_string(conn, name)
write_string(conn, filename)
write_int(conn, argcount)
-
+
write_int(conn, frameKind)
if frameKind == FRAME_KIND_DJANGO:
write_string(conn, sourceFile)
write_int(conn, sourceLine)
-
+
write_int(conn, len(variables))
for name, type_obj, safe_repr_obj, hex_repr_obj, type_name, obj_len in variables:
write_string(conn, name)
@@ -1737,7 +1740,7 @@ def loop(self):
pass
except:
traceback.print_exc()
-
+
def command_step_into(self):
tid = read_int(self.conn)
thread = get_thread_from_id(tid)
@@ -1753,7 +1756,7 @@ def command_step_out(self):
assert thread._is_blocked
thread.stepping = STEPPING_OUT
self.command_resume_all()
-
+
def command_step_over(self):
# set step over
tid = read_int(self.conn)
@@ -1793,7 +1796,7 @@ def command_set_breakpoint_condition(self):
breakpoint_id = read_int(self.conn)
kind = read_int(self.conn)
condition = read_string(self.conn)
-
+
bp = BreakpointInfo.find_by_id(breakpoint_id)
if bp is not None:
bp.condition_kind = kind
@@ -1812,7 +1815,7 @@ def command_set_breakpoint_pass_count(self):
def command_set_breakpoint_hit_count(self):
breakpoint_id = read_int(self.conn)
count = read_int(self.conn)
-
+
bp = BreakpointInfo.find_by_id(breakpoint_id)
if bp is not None:
bp.hit_count = count
@@ -1820,7 +1823,7 @@ def command_set_breakpoint_hit_count(self):
def command_get_breakpoint_hit_count(self):
req_id = read_int(self.conn)
breakpoint_id = read_int(self.conn)
-
+
bp = BreakpointInfo.find_by_id(breakpoint_id)
count = 0
if bp is not None:
@@ -1907,7 +1910,7 @@ def command_resume_all(self):
if thread._is_blocked:
thread.unblock()
thread._block_starting_lock.release()
-
+
def command_resume_thread(self):
tid = read_int(self.conn)
THREADS_LOCK.acquire()
@@ -1927,7 +1930,7 @@ def command_auto_resume(self):
THREADS_LOCK.release()
stepping = thread.stepping
- if ((stepping == STEPPING_OVER or stepping == STEPPING_INTO) and thread.cur_frame.f_lineno != thread.stopped_on_line):
+ if ((stepping == STEPPING_OVER or stepping == STEPPING_INTO) and thread.cur_frame.f_lineno != thread.stopped_on_line):
report_step_finished(tid)
else:
self.command_resume_all()
@@ -2020,11 +2023,11 @@ def command_enum_children(self):
fid = read_int(self.conn) # frame id
eid = read_int(self.conn) # execution id
frame_kind = read_int(self.conn) # frame kind
-
+
thread, cur_frame = self.get_thread_and_frame(tid, fid, frame_kind)
if thread is not None and cur_frame is not None:
thread.enum_child_on_thread(text, cur_frame, eid, frame_kind)
-
+
def get_thread_and_frame(self, tid, fid, frame_kind):
thread = get_thread_from_id(tid)
cur_frame = None
@@ -2049,11 +2052,11 @@ def command_detach(self):
with _SendLockCtx:
write_bytes(conn, DETC)
- detach_process()
+ detach_process()
for callback in DETACH_CALLBACKS:
callback()
-
+
raise DebuggerExitException()
def command_last_ack(self):
@@ -2099,12 +2102,12 @@ def report_exception(frame, exc_info, tid, break_type):
exc_name = get_exception_name(exc_type)
exc_value = exc_info[1]
tb_value = exc_info[2]
-
+
if type(exc_value) is tuple:
- # exception object hasn't been created yet, create it now
+ # exception object hasn't been created yet, create it now
# so we can get the correct msg.
exc_value = exc_type(*exc_value)
-
+
data = {
'typename': get_exception_name(exc_type),
'message': str(exc_value),
@@ -2172,7 +2175,7 @@ def report_breakpoint_failed(id):
write_bytes(conn, BRKF)
write_int(conn, id)
-def report_breakpoint_hit(id, tid):
+def report_breakpoint_hit(id, tid):
with _SendLockCtx:
write_bytes(conn, BRKH)
write_int(conn, id)
@@ -2191,7 +2194,8 @@ def report_execution_error(exc_text, execution_id):
def report_execution_exception(execution_id, exc_info):
try:
- exc_text = str(exc_info[1])
+ exc_type, exc_value, traceback = exc_info
+ exc_text = '{}: {}'.format(get_exception_name(exc_type), exc_value)
except:
exc_text = 'An exception was thrown'
@@ -2217,7 +2221,7 @@ def report_execution_result(execution_id, result, repr_kind = PYTHON_EVALUATION_
hex_repr = safe_hex_repr(result)
else:
flags = PYTHON_EVALUATION_RESULT_RAW
- hex_repr = None
+ hex_repr = None
for cls, raw_repr in TYPES_WITH_RAW_REPR.items():
if isinstance(result, cls):
try:
@@ -2311,7 +2315,7 @@ def attach_process(port_num, debug_id, debug_options, currentPid, report = False
## Begin modification by Don Jayamanne
# Pass current Process id to pass back to debugger
write_int(conn, currentPid) # success
- ## End Modification by Don Jayamanne
+ ## End Modification by Don Jayamanne
break
except:
import time
@@ -2359,9 +2363,16 @@ def _excepthook(exc_type, exc_value, exc_tb):
global debugger_thread_id
debugger_thread_id = _start_new_thread(DebuggerLoop(conn).loop, ())
- for mod_name, mod_value in sys.modules.items():
+ for mod_value in list(sys.modules.values()):
try:
- filename = getattr(mod_value, '__file__', None)
+ lazyModule = False
+ try:
+ lazyModule = mod_value.__class__.__name__ == 'LazyImporter'
+ except:
+ lazyModule = False
+ filename = None
+ if not lazyModule:
+ filename = getattr(mod_value, '__file__', None)
if filename is not None:
try:
fullpath = path.abspath(filename)
@@ -2370,7 +2381,7 @@ def _excepthook(exc_type, exc_value, exc_tb):
else:
MODULES.append((filename, Module(fullpath)))
except:
- traceback.print_exc()
+ traceback.print_exc()
if report:
THREADS_LOCK.acquire()
@@ -2409,7 +2420,7 @@ def detach_process():
global DETACHED
DETACHED = True
if not _INTERCEPTING_FOR_ATTACH:
- if isinstance(sys.stdout, _DebuggerOutput):
+ if isinstance(sys.stdout, _DebuggerOutput):
sys.stdout = sys.stdout.old_out
if isinstance(sys.stderr, _DebuggerOutput):
sys.stderr = sys.stderr.old_out
@@ -2436,7 +2447,7 @@ def detach_threads():
THREADS_LOCK.acquire()
THREADS.clear()
THREADS_LOCK.release()
-
+
BREAKPOINTS.clear()
def new_thread(tid = None, set_break = False, frame = None):
@@ -2444,7 +2455,7 @@ def new_thread(tid = None, set_break = False, frame = None):
if tid == debugger_thread_id:
return None
- cur_thread = Thread(tid)
+ cur_thread = Thread(tid)
THREADS_LOCK.acquire()
THREADS[cur_thread.id] = cur_thread
THREADS_LOCK.release()
@@ -2498,11 +2509,11 @@ def __init__(self, old_out, is_stdout):
def flush(self):
if self.old_out:
self.old_out.flush()
-
+
def writelines(self, lines):
for line in lines:
self.write(line)
-
+
@property
def encoding(self):
return 'utf8'
@@ -2516,13 +2527,13 @@ def write(self, value):
write_string(conn, value)
if self.old_out:
self.old_out.write(value)
-
+
def isatty(self):
return True
def next(self):
pass
-
+
@property
def name(self):
if self.is_stdout:
@@ -2547,7 +2558,7 @@ def write(self, data):
write_string(conn, str_data)
self.buffer.write(data)
- def flush(self):
+ def flush(self):
self.buffer.flush()
def truncate(self, pos = None):
@@ -2561,9 +2572,9 @@ def seek(self, pos, whence = 0):
def is_same_py_file(file1, file2):
"""compares 2 filenames accounting for .pyc files"""
- if file1.endswith('.pyc') or file1.endswith('.pyo'):
+ if file1.endswith('.pyc') or file1.endswith('.pyo'):
file1 = file1[:-1]
- if file2.endswith('.pyc') or file2.endswith('.pyo'):
+ if file2.endswith('.pyc') or file2.endswith('.pyo'):
file2 = file2[:-1]
return file1 == file2
@@ -2583,7 +2594,7 @@ def print_exception(exc_type, exc_value, exc_tb):
print('Traceback (most recent call last):')
for out in traceback.format_list(tb):
sys.stderr.write(out)
-
+
# print the exception
for out in traceback.format_exception_only(exc_type, exc_value):
sys.stdout.write(out)
@@ -2595,9 +2606,14 @@ def parse_debug_options(s):
# Accept current Process id to pass back to debugger
def debug(file, port_num, debug_id, debug_options, currentPid, run_as = 'script'):
# remove us from modules so there's no trace of us
- sys.modules['$visualstudio_py_debugger'] = sys.modules['visualstudio_py_debugger']
- __name__ = '$visualstudio_py_debugger'
- del sys.modules['visualstudio_py_debugger']
+ if sys.modules.has_key('visualstudio_py_debugger'):
+ sys.modules['$visualstudio_py_debugger'] = sys.modules['visualstudio_py_debugger']
+ __name__ = '$visualstudio_py_debugger'
+ del sys.modules['visualstudio_py_debugger']
+ elif sys.modules.has_key('ptvsd.visualstudio_py_debugger'):
+ sys.modules['$ptvsd.visualstudio_py_debugger'] = sys.modules['ptvsd.visualstudio_py_debugger']
+ __name__ = '$ptvsd.visualstudio_py_debugger'
+ del sys.modules['ptvsd.visualstudio_py_debugger']
wait_on_normal_exit = 'WaitOnNormalExit' in debug_options
@@ -2621,6 +2637,8 @@ def debug(file, port_num, debug_id, debug_options, currentPid, run_as = 'script'
elif run_as == 'code':
exec_code(file, '', globals_obj)
else:
+ # fix sys.path to be the script file dir
+ sys.path[0] = ''
exec_file(file, globals_obj)
finally:
sys.settrace(None)
@@ -2691,7 +2709,7 @@ def _get_source_django_18_or_lower(frame):
else:
if IGNORE_DJANGO_TEMPLATE_WARNINGS:
return None
-
+
if IS_DJANGO18:
# The debug setting was changed since Django 1.8
print("WARNING: Template path is not available. Set the 'debug' option in the OPTIONS of a DjangoTemplates "
@@ -2749,4 +2767,4 @@ def _get_template_line(frame):
return _offset_to_line_number(_read_file(file_name), source[1][0])
except:
return None
-## End modification by Don Jayamanne
\ No newline at end of file
+## End modification by Don Jayamanne
diff --git a/pythonFiles/PythonTools/ptvsd/visualstudio_py_repl.py b/pythonFiles/PythonTools/ptvsd/visualstudio_py_repl.py
index 3618533910e1..35a4d810132e 100644
--- a/pythonFiles/PythonTools/ptvsd/visualstudio_py_repl.py
+++ b/pythonFiles/PythonTools/ptvsd/visualstudio_py_repl.py
@@ -39,7 +39,6 @@
import select
import time
import struct
-import imp
import traceback
import random
import os
@@ -553,6 +552,7 @@ class BasicReplBackend(ReplBackend):
"""Basic back end which executes all Python code in-proc"""
def __init__(self, mod_name='__main__'):
import threading
+ import imp
ReplBackend.__init__(self)
if mod_name is not None:
if sys.platform == 'cli':
diff --git a/pythonFiles/PythonTools/ptvsd/visualstudio_py_util.py b/pythonFiles/PythonTools/ptvsd/visualstudio_py_util.py
index c00519eebb09..88d173b2a1c3 100644
--- a/pythonFiles/PythonTools/ptvsd/visualstudio_py_util.py
+++ b/pythonFiles/PythonTools/ptvsd/visualstudio_py_util.py
@@ -22,7 +22,6 @@
# hasn't been loaded already, it will assume that the thread on which it is being loaded is the
# main thread. This will cause issues when the thread goes away after attach completes.
-import imp
import os
import sys
import struct
@@ -68,6 +67,7 @@ def exec_code(code, file, global_variables):
``sys.path[0]`` will be changed to the value of `file` without the filename.
Both values are restored when this function exits.
'''
+ import imp
original_main = sys.modules.get('__main__')
global_variables = dict(global_variables)
@@ -510,14 +510,14 @@ def re_test(source, pattern):
d1 = {}
d1_key = 'a' * self.maxstring_inner * 2
d1[d1_key] = d1_key
- re_test(d1, "{'a+\.\.\.a+': 'a+\.\.\.a+'}")
+ re_test(d1, r"{'a+\.\.\.a+': 'a+\.\.\.a+'}")
d2 = {d1_key : d1}
- re_test(d2, "{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}")
+ re_test(d2, r"{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}")
d3 = {d1_key : d2}
if len(self.maxcollection) == 2:
- re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}")
+ re_test(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}")
else:
- re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}")
+ re_test(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}")
# Ensure empty dicts work
test({}, '{}')
diff --git a/pythonFiles/PythonTools/visualstudio_ipython_repl.py b/pythonFiles/PythonTools/visualstudio_ipython_repl.py
index 14f42362a8f8..0e2b8ca056ff 100644
--- a/pythonFiles/PythonTools/visualstudio_ipython_repl.py
+++ b/pythonFiles/PythonTools/visualstudio_ipython_repl.py
@@ -21,8 +21,8 @@
import re
import sys
-from visualstudio_py_repl import BasicReplBackend, ReplBackend, UnsupportedReplException, _command_line_to_args_list
-from visualstudio_py_util import to_bytes
+from ptvsd.visualstudio_py_repl import BasicReplBackend, ReplBackend, UnsupportedReplException, _command_line_to_args_list
+from ptvsd.visualstudio_py_util import to_bytes
try:
import thread
except:
@@ -401,7 +401,7 @@ def init_debugger(self):
def __visualstudio_debugger_init():
import sys
sys.path.append(''' + repr(path.dirname(__file__)) + ''')
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visualstudio_py_debugger
new_thread = visualstudio_py_debugger.new_thread()
sys.settrace(new_thread.trace_func)
visualstudio_py_debugger.intercept_threads(True)
@@ -413,7 +413,7 @@ def __visualstudio_debugger_init():
def attach_process(self, port, debugger_id):
self.run_command('''
def __visualstudio_debugger_attach():
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visual_studio_py_debugger
def do_detach():
visualstudio_py_debugger.DETACH_CALLBACKS.remove(do_detach)
@@ -427,4 +427,4 @@ def do_detach():
class IPythonBackendWithoutPyLab(IPythonBackend):
def get_extra_arguments(self):
- return []
\ No newline at end of file
+ return []
diff --git a/pythonFiles/PythonTools/visualstudio_py_debugger.py b/pythonFiles/PythonTools/visualstudio_py_debugger.py
index c0a603c077e5..b2db85fcae17 100644
--- a/pythonFiles/PythonTools/visualstudio_py_debugger.py
+++ b/pythonFiles/PythonTools/visualstudio_py_debugger.py
@@ -47,12 +47,12 @@
try:
# In the local attach scenario, visualstudio_py_util is injected into globals()
# by PyDebugAttach before loading this module, and cannot be imported.
- _vspu = visualstudio_py_util
+ _vspu = ptvsd.visualstudio_py_util
except:
try:
- import visualstudio_py_util as _vspu
- except ImportError:
import ptvsd.visualstudio_py_util as _vspu
+ except ImportError:
+ import visualstudio_py_util as _vspu
to_bytes = _vspu.to_bytes
exec_file = _vspu.exec_file
@@ -69,15 +69,17 @@
try:
# In the local attach scenario, visualstudio_py_repl is injected into globals()
# by PyDebugAttach before loading this module, and cannot be imported.
- _vspr = visualstudio_py_repl
+ _vspr = ptvsd.visualstudio_py_repl
except:
try:
- import visualstudio_py_repl as _vspr
- except ImportError:
import ptvsd.visualstudio_py_repl as _vspr
+ except ImportError:
+ import visualstudio_py_repl as _vspr
+
try:
import stackless
+ stackless.tasklet # work-around lazy on-demand importers
except ImportError:
stackless = None
@@ -1312,7 +1314,8 @@ def unblock(self):
assert self._is_blocked
assert self.id != thread.get_ident() # only someone else should unblock us
- self._block_lock.release()
+ if self._block_lock.locked():
+ self._block_lock.release()
def schedule_work(self, work):
self.unblock_work = work
@@ -2360,9 +2363,16 @@ def _excepthook(exc_type, exc_value, exc_tb):
global debugger_thread_id
debugger_thread_id = _start_new_thread(DebuggerLoop(conn).loop, ())
- for mod_name, mod_value in sys.modules.items():
+ for mod_value in list(sys.modules.values()):
try:
- filename = getattr(mod_value, '__file__', None)
+ lazyModule = False
+ try:
+ lazyModule = mod_value.__class__.__name__ == 'LazyImporter'
+ except:
+ lazyModule = False
+ filename = None
+ if not lazyModule:
+ filename = getattr(mod_value, '__file__', None)
if filename is not None:
try:
fullpath = path.abspath(filename)
@@ -2371,7 +2381,7 @@ def _excepthook(exc_type, exc_value, exc_tb):
else:
MODULES.append((filename, Module(fullpath)))
except:
- traceback.print_exc()
+ traceback.print_exc()
if report:
THREADS_LOCK.acquire()
@@ -2596,9 +2606,14 @@ def parse_debug_options(s):
# Accept current Process id to pass back to debugger
def debug(file, port_num, debug_id, debug_options, currentPid, run_as = 'script'):
# remove us from modules so there's no trace of us
- sys.modules['$visualstudio_py_debugger'] = sys.modules['visualstudio_py_debugger']
- __name__ = '$visualstudio_py_debugger'
- del sys.modules['visualstudio_py_debugger']
+ if sys.modules.has_key('visualstudio_py_debugger'):
+ sys.modules['$visualstudio_py_debugger'] = sys.modules['visualstudio_py_debugger']
+ __name__ = '$visualstudio_py_debugger'
+ del sys.modules['visualstudio_py_debugger']
+ elif sys.modules.has_key('ptvsd.visualstudio_py_debugger'):
+ sys.modules['$ptvsd.visualstudio_py_debugger'] = sys.modules['ptvsd.visualstudio_py_debugger']
+ __name__ = '$ptvsd.visualstudio_py_debugger'
+ del sys.modules['ptvsd.visualstudio_py_debugger']
wait_on_normal_exit = 'WaitOnNormalExit' in debug_options
@@ -2622,6 +2637,8 @@ def debug(file, port_num, debug_id, debug_options, currentPid, run_as = 'script'
elif run_as == 'code':
exec_code(file, '', globals_obj)
else:
+ # fix sys.path to be the script file dir
+ sys.path[0] = ''
exec_file(file, globals_obj)
finally:
sys.settrace(None)
@@ -2750,4 +2767,4 @@ def _get_template_line(frame):
return _offset_to_line_number(_read_file(file_name), source[1][0])
except:
return None
-## End modification by Don Jayamanne
\ No newline at end of file
+## End modification by Don Jayamanne
diff --git a/pythonFiles/PythonTools/visualstudio_py_launcher.py b/pythonFiles/PythonTools/visualstudio_py_launcher.py
index 12b2140c4f72..38f7a0bd53ac 100644
--- a/pythonFiles/PythonTools/visualstudio_py_launcher.py
+++ b/pythonFiles/PythonTools/visualstudio_py_launcher.py
@@ -1,16 +1,16 @@
# Python Tools for Visual Studio
# Copyright(c) Microsoft Corporation
# All rights reserved.
-#
+#
# Licensed under the Apache License, Version 2.0 (the License); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
+#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
@@ -23,70 +23,72 @@
__author__ = "Microsoft Corporation "
__version__ = "3.0.0.0"
-import os
-import os.path
-import sys
-import traceback
-try:
- import visualstudio_py_debugger as vspd
-except:
- traceback.print_exc()
- print('''
-Internal error detected. Please copy the above traceback and report at
-http://go.microsoft.com/fwlink/?LinkId=293415
-
-Press Enter to close. . .''')
+def launch():
+ import os
+ import os.path
+ import sys
+ import traceback
try:
- raw_input()
- except NameError:
- input()
- sys.exit(1)
+ import ptvsd.visualstudio_py_debugger as vspd
+ except:
+ traceback.print_exc()
+ print('''
+ Internal error detected. Please copy the above traceback and report at
+ http://go.microsoft.com/fwlink/?LinkId=293415
+
+ Press Enter to close. . .''')
+ try:
+ raw_input()
+ except NameError:
+ input()
+ sys.exit(1)
+
+ # Arguments are:
+ # 1. Working directory.
+ # 2. VS debugger port to connect to.
+ # 3. GUID for the debug session.
+ # 4. Debug options (as integer - see enum PythonDebugOptions).
+ # 5. '-m' or '-c' to override the default run-as mode. [optional]
+ # 6. Startup script name.
+ # 7. Script arguments.
-# Arguments are:
-# 1. Working directory.
-# 2. VS debugger port to connect to.
-# 3. GUID for the debug session.
-# 4. Debug options (as integer - see enum PythonDebugOptions).
-# 5. '-m' or '-c' to override the default run-as mode. [optional]
-# 6. Startup script name.
-# 7. Script arguments.
+ # change to directory we expected to start from
+ os.chdir(sys.argv[1])
-# change to directory we expected to start from
-os.chdir(sys.argv[1])
+ port_num = int(sys.argv[2])
+ debug_id = sys.argv[3]
+ debug_options = vspd.parse_debug_options(sys.argv[4])
+ del sys.argv[0:5]
-port_num = int(sys.argv[2])
-debug_id = sys.argv[3]
-debug_options = vspd.parse_debug_options(sys.argv[4])
-del sys.argv[0:5]
+ # set run_as mode appropriately
+ run_as = 'script'
+ if sys.argv and sys.argv[0] == '-m':
+ run_as = 'module'
+ del sys.argv[0]
+ if sys.argv and sys.argv[0] == '-c':
+ run_as = 'code'
+ del sys.argv[0]
-# set run_as mode appropriately
-run_as = 'script'
-if sys.argv and sys.argv[0] == '-m':
- run_as = 'module'
- del sys.argv[0]
-if sys.argv and sys.argv[0] == '-c':
- run_as = 'code'
- del sys.argv[0]
+ # preserve filename before we del sys
+ filename = sys.argv[0]
-# preserve filename before we del sys
-filename = sys.argv[0]
+ # exclude ourselves from being debugged
+ vspd.DONT_DEBUG.append(os.path.normcase(__file__))
-# fix sys.path to be the script file dir
-sys.path[0] = ''
+ ## Begin modification by Don Jayamanne
+ # Get current Process id to pass back to debugger
+ currentPid = os.getpid()
+ ## End Modification by Don Jayamanne
-# exclude ourselves from being debugged
-vspd.DONT_DEBUG.append(os.path.normcase(__file__))
+ # remove all state we imported
+ del sys, os
-## Begin modification by Don Jayamanne
-# Get current Process id to pass back to debugger
-currentPid = os.getpid()
-## End Modification by Don Jayamanne
+ # and start debugging
+ ## Begin modification by Don Jayamanne
+ # Pass current Process id to pass back to debugger
+ vspd.debug(filename, port_num, debug_id, debug_options, currentPid, run_as)
+ ## End Modification by Don Jayamanne
-# remove all state we imported
-del sys, os
-# and start debugging
-## Begin modification by Don Jayamanne
-# Pass current Process id to pass back to debugger
-vspd.debug(filename, port_num, debug_id, debug_options, currentPid, run_as)
-## End Modification by Don Jayamanne
+if __name__ == "__main__":
+ launch()
diff --git a/pythonFiles/PythonTools/visualstudio_py_launcher_nodebug.py b/pythonFiles/PythonTools/visualstudio_py_launcher_nodebug.py
index 7285d6d8558b..0ada07cba53a 100644
--- a/pythonFiles/PythonTools/visualstudio_py_launcher_nodebug.py
+++ b/pythonFiles/PythonTools/visualstudio_py_launcher_nodebug.py
@@ -9,7 +9,7 @@
import time
import socket
try:
- import visualstudio_py_util as _vspu
+ import ptvsd.visualstudio_py_util as _vspu
except:
traceback.print_exc()
print("""Internal error detected. Please copy the above traceback and report at
diff --git a/pythonFiles/PythonTools/visualstudio_py_repl.py b/pythonFiles/PythonTools/visualstudio_py_repl.py
index 74870fd696b3..dac8a2efc3f4 100644
--- a/pythonFiles/PythonTools/visualstudio_py_repl.py
+++ b/pythonFiles/PythonTools/visualstudio_py_repl.py
@@ -39,7 +39,6 @@
import select
import time
import struct
-import imp
import traceback
import random
import os
@@ -50,12 +49,12 @@
try:
# In the local attach scenario, visualstudio_py_util is injected into globals()
# by PyDebugAttach before loading this module, and cannot be imported.
- _vspu = visualstudio_py_util
+ _vspu = ptvsd.visualstudio_py_util
except:
try:
- import visualstudio_py_util as _vspu
- except ImportError:
import ptvsd.visualstudio_py_util as _vspu
+ except ImportError:
+ import visualstudio_py_util as _vspu
to_bytes = _vspu.to_bytes
read_bytes = _vspu.read_bytes
read_int = _vspu.read_int
@@ -351,7 +350,7 @@ def _cmd_excx(self):
self.execute_file_ex(filetype, filename, args)
def _cmd_debug_attach(self):
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visualstudio_py_debugger
port = read_int(self.conn)
id = read_string(self.conn)
debug_options = visualstudio_py_debugger.parse_debug_options(read_string(self.conn))
@@ -385,7 +384,7 @@ def on_debugger_detach(self):
def init_debugger(self):
from os import path
sys.path.append(path.dirname(__file__))
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visualstudio_py_debugger
visualstudio_py_debugger.DONT_DEBUG.append(path.normcase(__file__))
new_thread = visualstudio_py_debugger.new_thread()
sys.settrace(new_thread.trace_func)
@@ -553,6 +552,7 @@ class BasicReplBackend(ReplBackend):
"""Basic back end which executes all Python code in-proc"""
def __init__(self, mod_name='__main__'):
import threading
+ import imp
ReplBackend.__init__(self)
if mod_name is not None:
if sys.platform == 'cli':
@@ -1005,13 +1005,13 @@ def flush(self):
sys.stdout.flush()
def do_detach(self):
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visualstudio_py_debugger
visualstudio_py_debugger.DETACH_CALLBACKS.remove(self.do_detach)
self.on_debugger_detach()
def attach_process(self, port, debugger_id, debug_options):
def execute_attach_process_work_item():
- import visualstudio_py_debugger
+ import ptvsd.visualstudio_py_debugger as visualstudio_py_debugger
visualstudio_py_debugger.DETACH_CALLBACKS.append(self.do_detach)
visualstudio_py_debugger.attach_process(port, debugger_id, debug_options, report=True, block=True)
@@ -1388,4 +1388,4 @@ def _run_repl():
_debug_write(traceback.format_exc())
_debug_write('exiting')
input()
- raise
\ No newline at end of file
+ raise
diff --git a/pythonFiles/PythonTools/visualstudio_py_testlauncher.py b/pythonFiles/PythonTools/visualstudio_py_testlauncher.py
index 9464afddc6f1..270d87be3399 100644
--- a/pythonFiles/PythonTools/visualstudio_py_testlauncher.py
+++ b/pythonFiles/PythonTools/visualstudio_py_testlauncher.py
@@ -1,16 +1,16 @@
# Python Tools for Visual Studio
# Copyright(c) Microsoft Corporation
# All rights reserved.
-#
+#
# Licensed under the Apache License, Version 2.0 (the License); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
+#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
@@ -43,11 +43,11 @@ def __init__(self, old_out, is_stdout):
def flush(self):
if self.old_out:
self.old_out.flush()
-
+
def writelines(self, lines):
for line in lines:
self.write(line)
-
+
@property
def encoding(self):
return 'utf8'
@@ -58,13 +58,13 @@ def write(self, value):
self.old_out.write(value)
# flush immediately, else things go wonky and out of order
self.flush()
-
+
def isatty(self):
return True
def next(self):
pass
-
+
@property
def name(self):
if self.is_stdout:
@@ -84,7 +84,7 @@ def write(self, data):
_channel.send_event('stdout' if self.is_stdout else 'stderr', content=data)
self.buffer.write(data)
- def flush(self):
+ def flush(self):
self.buffer.flush()
def truncate(self, pos = None):
@@ -102,12 +102,20 @@ def __init__(self, socket, callback):
self.seq = 0
self.callback = callback
self.lock = thread.allocate_lock()
+ self._closed = False
# start the testing reader thread loop
self.test_thread_id = thread.start_new_thread(self.readSocket, ())
+ def close(self):
+ self._closed = True
+
def readSocket(self):
- data = self.socket.recv(1024)
- self.callback()
+ try:
+ data = self.socket.recv(1024)
+ self.callback()
+ except OSError:
+ if not self._closed:
+ raise
def receive(self):
pass
@@ -129,7 +137,7 @@ def startTest(self, test):
super(VsTestResult, self).startTest(test)
if _channel is not None:
_channel.send_event(
- name='start',
+ name='start',
test = test.id()
)
@@ -169,7 +177,7 @@ def sendResult(self, test, outcome, trace = None):
tb = ''.join(formatted)
message = str(trace[1])
_channel.send_event(
- name='result',
+ name='result',
outcome=outcome,
traceback = tb,
message = message,
@@ -188,7 +196,7 @@ def stopTests():
class ExitCommand(Exception):
pass
-def signal_handler(signal, frame):
+def signal_handler(signal, frame):
raise ExitCommand()
def main():
@@ -215,7 +223,7 @@ def main():
if opts.debug:
from ptvsd.visualstudio_py_debugger import DONT_DEBUG, DEBUG_ENTRYPOINTS, get_code
-
+
sys.path[0] = os.getcwd()
if opts.result_port:
try:
@@ -235,7 +243,7 @@ def main():
pass
elif opts.mixed_mode:
- # For mixed-mode attach, there's no ptvsd and hence no wait_for_attach(),
+ # For mixed-mode attach, there's no ptvsd and hence no wait_for_attach(),
# so we have to use Win32 API in a loop to do the same thing.
from time import sleep
from ctypes import windll, c_char
@@ -270,48 +278,51 @@ def main():
opts.up = 'test*.py'
tests = unittest.defaultTestLoader.discover(opts.us, opts.up)
else:
- # loadTestsFromNames doesn't work well (with duplicate file names or class names)
+ # loadTestsFromNames doesn't work well (with duplicate file names or class names)
# Easier approach is find the test suite and use that for running
loader = unittest.TestLoader()
# opts.us will be passed in
suites = loader.discover(opts.us, pattern=os.path.basename(opts.testFile))
suite = None
- tests = None
+ tests = None
if opts.tests is None:
# Run everything in the test file
tests = suites
else:
# Run a specific test class or test method
- for suite in suites._tests:
- for cls in suite._tests:
+ for test_suite in suites._tests:
+ for cls in test_suite._tests:
try:
for m in cls._tests:
testId = m.id()
if testId.startswith(opts.tests[0]):
suite = cls
+ break
if testId == opts.tests[0]:
tests = m
break
except Exception as err:
- errorMessage = traceback.format_exception()
+ errorMessage = traceback.format_exception()
pass
if tests is None:
tests = suite
if tests is None and suite is None:
_channel.send_event(
- name='error',
+ name='error',
outcome='',
traceback = '',
message = 'Failed to identify the test',
test = ''
)
if opts.uvInt is None:
- opts.uvInt = 0
+ opts.uvInt = 0
if opts.uf is not None:
runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult, failfast=True)
else:
runner = unittest.TextTestRunner(verbosity=opts.uvInt, resultclass=VsTestResult)
result = runner.run(tests)
+ if _channel is not None:
+ _channel.close()
sys.exit(not result.wasSuccessful())
finally:
if cov is not None:
diff --git a/pythonFiles/PythonTools/visualstudio_py_util.py b/pythonFiles/PythonTools/visualstudio_py_util.py
index b3ed951e8718..58b798821750 100644
--- a/pythonFiles/PythonTools/visualstudio_py_util.py
+++ b/pythonFiles/PythonTools/visualstudio_py_util.py
@@ -22,7 +22,6 @@
# hasn't been loaded already, it will assume that the thread on which it is being loaded is the
# main thread. This will cause issues when the thread goes away after attach completes.
-import imp
import os
import sys
import struct
@@ -68,6 +67,7 @@ def exec_code(code, file, global_variables):
``sys.path[0]`` will be changed to the value of `file` without the filename.
Both values are restored when this function exits.
'''
+ import imp
original_main = sys.modules.get('__main__')
global_variables = dict(global_variables)
@@ -510,14 +510,14 @@ def re_test(source, pattern):
d1 = {}
d1_key = 'a' * self.maxstring_inner * 2
d1[d1_key] = d1_key
- re_test(d1, "{'a+\.\.\.a+': 'a+\.\.\.a+'}")
+ re_test(d1, r"{'a+\.\.\.a+': 'a+\.\.\.a+'}")
d2 = {d1_key : d1}
- re_test(d2, "{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}")
+ re_test(d2, r"{'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}")
d3 = {d1_key : d2}
if len(self.maxcollection) == 2:
- re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}")
+ re_test(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {\.\.\.}}}")
else:
- re_test(d3, "{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}")
+ re_test(d3, r"{'a+\.\.\.a+': {'a+\.\.\.a+': {'a+\.\.\.a+': 'a+\.\.\.a+'}}}")
# Ensure empty dicts work
test({}, '{}')
diff --git a/pythonFiles/completion.py b/pythonFiles/completion.py
index e530be32b367..5ab933715689 100644
--- a/pythonFiles/completion.py
+++ b/pythonFiles/completion.py
@@ -33,6 +33,7 @@ class JediCompletion(object):
def __init__(self):
self.default_sys_path = sys.path
+ self.environment = jedi.api.environment.Environment(sys.prefix, sys.executable)
self._input = io.open(sys.stdin.fileno(), encoding='utf-8')
if (os.path.sep == '/') and (platform.uname()[2].find('Microsoft') > -1):
# WSL; does not support UNC paths
@@ -150,7 +151,7 @@ def _get_call_signatures_with_args(self, script):
except Exception:
sig["docstring"] = ''
sig["raw_docstring"] = ''
-
+
sig["name"] = signature.name
sig["paramindex"] = signature.index
sig["bracketstart"].append(signature.index)
@@ -199,7 +200,7 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
}
_completion['description'] = ''
_completion['raw_docstring'] = ''
-
+
# we pass 'text' here only for fuzzy matcher
if value:
_completion['snippet'] = '%s=${1:%s}$0' % (name, value)
@@ -223,7 +224,7 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
'type': self._get_definition_type(completion),
'raw_type': completion.type,
'rightLabel': self._additional_info(completion)
- }
+ }
except Exception:
continue
@@ -231,7 +232,7 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
if c['text'] == _completion['text']:
c['type'] = _completion['type']
c['raw_type'] = _completion['raw_type']
-
+
if any([c['text'].split('=')[0] == _completion['text']
for c in _completions]):
# ignore function arguments we already have
@@ -361,7 +362,7 @@ def _get_definitionsx(self, definitions, identifier=None, ignoreNoModulePath=Fal
definition = self._top_definition(definition)
definitionRange = {
'start_line': 0,
- 'start_column': 0,
+ 'start_column': 0,
'end_line': 0,
'end_column': 0
}
@@ -377,7 +378,7 @@ def _get_definitionsx(self, definitions, identifier=None, ignoreNoModulePath=Fal
container = parent.name if parent.type != 'module' else ''
except Exception:
container = ''
-
+
try:
docstring = definition.docstring()
rawdocstring = definition.docstring(raw=True)
@@ -424,7 +425,7 @@ def _serialize_definitions(self, definitions, identifier=None):
container = parent.name if parent.type != 'module' else ''
except Exception:
container = ''
-
+
try:
docstring = definition.docstring()
rawdocstring = definition.docstring(raw=True)
@@ -474,7 +475,7 @@ def _serialize_tooltip(self, definitions, identifier=None):
'type': self._get_definition_type(definition),
'text': definition.name,
'description': description,
- 'docstring': description,
+ 'docstring': description,
'signature': signature
}
_definitions.append(_definition)
@@ -551,7 +552,7 @@ def _process_request(self, request):
self._normalize_request_path(request)
path = self._get_top_level_module(request.get('path', ''))
- if path not in sys.path:
+ if len(path) > 0 and path not in sys.path:
sys.path.insert(0, path)
lookup = request.get('lookup', 'completions')
@@ -563,26 +564,13 @@ def _process_request(self, request):
all_scopes=True),
request['id'])
- script = jedi.api.Script(
+ script = jedi.Script(
source=request.get('source', None), line=request['line'] + 1,
- column=request['column'], path=request.get('path', ''))
-
+ column=request['column'], path=request.get('path', ''),
+ sys_path=sys.path, environment=self.environment)
+
if lookup == 'definitions':
- defs = []
- try:
- defs = self._get_definitionsx(script.goto_assignments(follow_imports=False), request['id'])
- except:
- pass
- try:
- if len(defs) == 0:
- defs = self._get_definitionsx(script.goto_definitions(), request['id'])
- except:
- pass
- try:
- if len(defs) == 0:
- defs = self._get_definitionsx(script.goto_assignments(), request['id'])
- except:
- pass
+ defs = self._get_definitionsx(script.goto_assignments(follow_imports=True), request['id'])
return json.dumps({'id': request['id'], 'results': defs})
if lookup == 'tooltip':
if jediPreview:
@@ -624,7 +612,7 @@ def watch(self):
try:
rq = self._input.readline()
if len(rq) == 0:
- # Reached EOF - indication our parent process is gone.
+ # Reached EOF - indication our parent process is gone.
sys.stderr.write('Received EOF from the standard input,exiting' + '\n')
sys.stderr.flush()
return
diff --git a/pythonFiles/completionServer.py b/pythonFiles/completionServer.py
index 9c380e493f73..d4defc59fe82 100644
--- a/pythonFiles/completionServer.py
+++ b/pythonFiles/completionServer.py
@@ -28,7 +28,7 @@
# http://pydoc.net/Python/magni/1.4.0/magni.tests.ipynb_examples/
# http://www.xavierdupre.fr/app/pyquickhelper/helpsphinx/_modules/pyquickhelper/ipythonhelper/notebook_runner.html
-import visualstudio_py_util as _vspu
+import ptvsd.visualstudio_py_util as _vspu
to_bytes = _vspu.to_bytes
read_bytes = _vspu.read_bytes
diff --git a/pythonFiles/experimental/ptvsd_launcher.py b/pythonFiles/experimental/ptvsd_launcher.py
deleted file mode 100644
index 98c4c5525bcf..000000000000
--- a/pythonFiles/experimental/ptvsd_launcher.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Python Tools for Visual Studio
-# Copyright(c) Microsoft Corporation
-# All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the License); you may not use
-# this file except in compliance with the License. You may obtain a copy of the
-# License at http://www.apache.org/licenses/LICENSE-2.0
-#
-# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
-# OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
-# IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
-# MERCHANTABLITY OR NON-INFRINGEMENT.
-#
-# See the Apache Version 2.0 License for specific language governing
-# permissions and limitations under the License.
-
-"""
-Starts Debugging, expected to start with normal program
-to start as first argument and directory to run from as
-the second argument.
-"""
-
-__author__ = "Microsoft Corporation "
-__version__ = "3.2.0.0"
-
-import os
-import os.path
-import sys
-import traceback
-
-# Arguments are:
-# 1. Working directory.
-# 2. VS debugger port to connect to.
-# 3. GUID for the debug session.
-# 4. Debug options (as list of names - see enum PythonDebugOptions).
-# 5. '-g' to use the installed ptvsd package, rather than bundled one.
-# 6. '-m' or '-c' to override the default run-as mode. [optional]
-# 7. Startup script name.
-# 8. Script arguments.
-
-# change to directory we expected to start from
-os.chdir(sys.argv[1])
-
-port_num = int(sys.argv[2])
-debug_id = sys.argv[3]
-debug_options = set([opt.strip() for opt in sys.argv[4].split(',')])
-
-del sys.argv[0:5]
-
-# Use bundled ptvsd or not?
-bundled_ptvsd = True
-if sys.argv and sys.argv[0] == '-g':
- bundled_ptvsd = False
- del sys.argv[0]
-
-# set run_as mode appropriately
-run_as = 'script'
-if sys.argv and sys.argv[0] == '-m':
- run_as = 'module'
- del sys.argv[0]
-if sys.argv and sys.argv[0] == '-c':
- run_as = 'code'
- del sys.argv[0]
-
-# preserve filename before we del sys
-filename = sys.argv[0]
-
-# fix sys.path to be the script file dir
-sys.path[0] = ''
-
-# Load the debugger package
-try:
- if bundled_ptvsd:
- ptvs_lib_path = os.path.dirname(__file__)
- sys.path.insert(0, ptvs_lib_path)
- import ptvsd
- import ptvsd.debugger as vspd
- vspd.DONT_DEBUG.append(os.path.normcase(__file__))
-except:
- traceback.print_exc()
- print('''
-Internal error detected. Please copy the above traceback and report at
-https://go.microsoft.com/fwlink/?LinkId=293415
-
-Press Enter to close. . .''')
- try:
- raw_input()
- except NameError:
- input()
- sys.exit(1)
-finally:
- if bundled_ptvsd:
- sys.path.remove(ptvs_lib_path)
-
-# and start debugging
-vspd.debug(filename, port_num, debug_id, debug_options, run_as)
diff --git a/pythonFiles/experimental/testlauncher.py b/pythonFiles/experimental/testlauncher.py
new file mode 100644
index 000000000000..e8c860ce133d
--- /dev/null
+++ b/pythonFiles/experimental/testlauncher.py
@@ -0,0 +1,64 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+import os
+import sys
+
+
+def parse_argv():
+ """Parses arguments for use with the test launcher.
+ Arguments are:
+ 1. Working directory.
+ 2. Test runner, `pytest` or `nose`
+ 3. Rest of the arguments are passed into the test runner.
+ """
+
+ return (sys.argv[1], sys.argv[2], sys.argv[3:])
+
+
+def exclude_current_file_from_debugger():
+ # Load the debugger package
+ try:
+ import ptvsd
+ import ptvsd.debugger as vspd
+ vspd.DONT_DEBUG.append(os.path.normcase(__file__))
+ except:
+ traceback.print_exc()
+ print('''
+Internal error detected. Please copy the above traceback and report at
+https://github.com/Microsoft/vscode-python/issues/new
+
+Press Enter to close. . .''')
+ try:
+ raw_input()
+ except NameError:
+ input()
+ sys.exit(1)
+
+
+def run(cwd, testRunner, args):
+ """Runs the test
+ cwd -- the current directory to be set
+ testRuner -- test runner to be used `pytest` or `nose`
+ args -- arguments passed into the test runner
+ """
+
+ sys.path[0] = os.getcwd()
+ os.chdir(cwd)
+
+ try:
+ if testRunner == 'pytest':
+ import pytest
+ pytest.main(args)
+ else:
+ import nose
+ nose.run(argv=args)
+ sys.exit(0)
+ finally:
+ pass
+
+
+if __name__ == '__main__':
+ exclude_current_file_from_debugger()
+ cwd, testRunner, args = parse_argv()
+ run(cwd, testRunner, args)
diff --git a/pythonFiles/interpreterInfo.py b/pythonFiles/interpreterInfo.py
new file mode 100644
index 000000000000..4822594bd046
--- /dev/null
+++ b/pythonFiles/interpreterInfo.py
@@ -0,0 +1,13 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+import json
+import sys
+
+obj = {}
+obj["versionInfo"] = sys.version_info[:4]
+obj["sysPrefix"] = sys.prefix
+obj["version"] = sys.version
+obj["is64Bit"] = sys.maxsize > 2**32
+
+print(json.dumps(obj))
diff --git a/pythonFiles/isort/__init__.py b/pythonFiles/isort/__init__.py
index 3063d1ed92d8..4f1adaa05bf0 100644
--- a/pythonFiles/isort/__init__.py
+++ b/pythonFiles/isort/__init__.py
@@ -22,7 +22,7 @@
from __future__ import absolute_import, division, print_function, unicode_literals
-from . import settings
-from .isort import SortImports
+from . import settings # noqa: F401
+from .isort import SortImports # noqa: F401
-__version__ = "4.2.15"
+__version__ = "4.3.4"
diff --git a/pythonFiles/isort/__main__.py b/pythonFiles/isort/__main__.py
index 94b1d057bb0c..186c98e85ea7 100644
--- a/pythonFiles/isort/__main__.py
+++ b/pythonFiles/isort/__main__.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import
+
from isort.main import main
main()
diff --git a/pythonFiles/isort/isort.py b/pythonFiles/isort/isort.py
index cecd5af991a1..3ba3e7d19d9e 100644
--- a/pythonFiles/isort/isort.py
+++ b/pythonFiles/isort/isort.py
@@ -32,7 +32,8 @@
import os
import re
import sys
-from collections import namedtuple
+import sysconfig
+from collections import OrderedDict, namedtuple
from datetime import datetime
from difflib import unified_diff
from fnmatch import fnmatch
@@ -40,7 +41,7 @@
from . import settings
from .natural import nsorted
-from .pie_slice import OrderedDict, OrderedSet, input, itemsview
+from .pie_slice import OrderedSet, input, itemsview
KNOWN_SECTION_MAPPING = {
'STDLIB': 'STANDARD_LIBRARY',
@@ -87,6 +88,8 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch
indent = "\t"
self.config['indent'] = indent
+ self.config['comment_prefix'] = self.config['comment_prefix'].strip("'").strip('"')
+
self.place_imports = {}
self.import_placements = {}
self.remove_imports = [self._format_simplified(removal) for removal in self.config['remove_imports']]
@@ -108,13 +111,24 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch
elif not file_contents:
self.file_path = file_path
self.file_encoding = coding_check(file_path)
- with io.open(file_path, encoding=self.file_encoding) as file_to_import_sort:
+ with io.open(file_path, encoding=self.file_encoding, newline='') as file_to_import_sort:
file_contents = file_to_import_sort.read()
if file_contents is None or ("isort:" + "skip_file") in file_contents:
+ self.skipped = True
+ self.output = None
return
- self.in_lines = file_contents.split("\n")
+ if self.config['line_ending']:
+ self.line_separator = self.config['line_ending']
+ else:
+ if '\r\n' in file_contents:
+ self.line_separator = '\r\n'
+ elif '\r' in file_contents:
+ self.line_separator = '\r'
+ else:
+ self.line_separator = '\n'
+ self.in_lines = file_contents.split(self.line_separator)
self.original_length = len(self.in_lines)
if (self.original_length > 1 or self.in_lines[:1] not in ([], [""])) or self.config['force_adds']:
for add_import in self.add_imports:
@@ -147,22 +161,20 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch
self._parse()
if self.import_index != -1:
self._add_formatted_imports()
-
self.length_change = len(self.out_lines) - self.original_length
while self.out_lines and self.out_lines[-1].strip() == "":
self.out_lines.pop(-1)
self.out_lines.append("")
-
- self.output = "\n".join(self.out_lines)
+ self.output = self.line_separator.join(self.out_lines)
if self.config['atomic']:
try:
- compile(self._strip_top_comments(self.out_lines), self.file_path, 'exec', 0, 1)
+ compile(self._strip_top_comments(self.out_lines, self.line_separator), self.file_path, 'exec', 0, 1)
except SyntaxError:
self.output = file_contents
self.incorrectly_sorted = True
try:
- compile(self._strip_top_comments(self.in_lines), self.file_path, 'exec', 0, 1)
- print("ERROR: {0} isort would have introduced syntax errors, please report to the project!". \
+ compile(self._strip_top_comments(self.in_lines, self.line_separator), self.file_path, 'exec', 0, 1)
+ print("ERROR: {0} isort would have introduced syntax errors, please report to the project!".
format(self.file_path))
except SyntaxError:
print("ERROR: {0} File contains syntax errors.".format(self.file_path))
@@ -172,8 +184,8 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch
check_output = self.output
check_against = file_contents
if self.config['ignore_whitespace']:
- check_output = check_output.replace("\n", "").replace(" ", "")
- check_against = check_against.replace("\n", "").replace(" ", "")
+ check_output = check_output.replace(self.line_separator, "").replace(" ", "")
+ check_against = check_against.replace(self.line_separator, "").replace(" ", "")
if check_output == check_against:
if self.config['verbose']:
@@ -187,18 +199,20 @@ def __init__(self, file_path=None, file_contents=None, write_to_stdout=False, ch
elif write_to_stdout:
sys.stdout.write(self.output)
elif file_name and not check:
+ if self.output == file_contents:
+ return
+
if ask_to_apply:
- if self.output == file_contents:
- return
self._show_diff(file_contents)
answer = None
while answer not in ('yes', 'y', 'no', 'n', 'quit', 'q'):
- answer = input("Apply suggested changes to '{0}' [y/n/q]?".format(self.file_path)).lower()
+ answer = input("Apply suggested changes to '{0}' [y/n/q]? ".format(self.file_path)).lower()
if answer in ('no', 'n'):
return
if answer in ('quit', 'q'):
sys.exit(1)
- with io.open(self.file_path, encoding=self.file_encoding, mode='w') as output_file:
+ with io.open(self.file_path, encoding=self.file_encoding, mode='w', newline='') as output_file:
+ print("Fixing {0}".format(self.file_path))
output_file.write(self.output)
def _show_diff(self, file_contents):
@@ -214,12 +228,12 @@ def _show_diff(self, file_contents):
sys.stdout.write(line)
@staticmethod
- def _strip_top_comments(lines):
+ def _strip_top_comments(lines, line_separator):
"""Strips # comments that exist at the top of the given lines"""
lines = copy.copy(lines)
while lines and lines[0].startswith("#"):
lines = lines[1:]
- return "\n".join(lines)
+ return line_separator.join(lines)
def place_module(self, module_name):
"""Tries to determine if a module is a python std import, third party import, or project code:
@@ -261,13 +275,12 @@ def place_module(self, module_name):
virtual_env_src = '{0}/src/'.format(virtual_env)
# handle case-insensitive paths on windows
- stdlib_lib_prefix = os.path.normcase(get_stdlib_path())
+ stdlib_lib_prefix = os.path.normcase(sysconfig.get_paths()['stdlib'])
for prefix in paths:
- module_path = "/".join((prefix, module_name.replace(".", "/")))
package_path = "/".join((prefix, module_name.split(".")[0]))
- is_module = (exists_case_sensitive(module_path + ".py") or
- exists_case_sensitive(module_path + ".so"))
+ is_module = (exists_case_sensitive(package_path + ".py") or
+ exists_case_sensitive(package_path + ".so"))
is_package = exists_case_sensitive(package_path) and os.path.isdir(package_path)
if is_module or is_package:
if ('site-packages' in prefix or 'dist-packages' in prefix or
@@ -323,7 +336,8 @@ def _add_comments(self, comments, original_string=""):
"""
Returns a string with comments added
"""
- return comments and "{0} # {1}".format(self._strip_comments(original_string)[0],
+ return comments and "{0}{1} {2}".format(self._strip_comments(original_string)[0],
+ self.config['comment_prefix'],
"; ".join(comments)) or original_string
def _wrap(self, line):
@@ -332,10 +346,16 @@ def _wrap(self, line):
"""
wrap_mode = self.config['multi_line_output']
if len(line) > self.config['line_length'] and wrap_mode != settings.WrapModes.NOQA:
- for splitter in ("import", ".", "as"):
+ line_without_comment = line
+ comment = None
+ if '#' in line:
+ line_without_comment, comment = line.split('#', 1)
+ for splitter in ("import ", ".", "as "):
exp = r"\b" + re.escape(splitter) + r"\b"
- if re.search(exp, line) and not line.strip().startswith(splitter):
- line_parts = re.split(exp, line)
+ if re.search(exp, line_without_comment) and not line_without_comment.strip().startswith(splitter):
+ line_parts = re.split(exp, line_without_comment)
+ if comment:
+ line_parts[-1] = '{0}#{1}'.format(line_parts[-1], comment)
next_line = []
while (len(line) + 2) > (self.config['wrap_length'] or self.config['line_length']) and line_parts:
next_line.append(line_parts.pop())
@@ -345,22 +365,22 @@ def _wrap(self, line):
cont_line = self._wrap(self.config['indent'] + splitter.join(next_line).lstrip())
if self.config['use_parentheses']:
- output = "{0}{1} (\n{2}{3}{4})".format(
- line, splitter, cont_line,
+ output = "{0}{1}({2}{3}{4}{5})".format(
+ line, splitter, self.line_separator, cont_line,
"," if self.config['include_trailing_comma'] else "",
- "\n" if wrap_mode in (
+ self.line_separator if wrap_mode in (
settings.WrapModes.VERTICAL_HANGING_INDENT,
settings.WrapModes.VERTICAL_GRID_GROUPED,
) else "")
- lines = output.split('\n')
- if ' #' in lines[-1] and lines[-1].endswith(')'):
- line, comment = lines[-1].split(' #', 1)
- lines[-1] = line + ') #' + comment[:-1]
- return '\n'.join(lines)
- return "{0}{1} \\\n{2}".format(line, splitter, cont_line)
+ lines = output.split(self.line_separator)
+ if self.config['comment_prefix'] in lines[-1] and lines[-1].endswith(')'):
+ line, comment = lines[-1].split(self.config['comment_prefix'], 1)
+ lines[-1] = line + ')' + self.config['comment_prefix'] + comment[:-1]
+ return self.line_separator.join(lines)
+ return "{0}{1}\\{2}{3}".format(line, splitter, self.line_separator, cont_line)
elif len(line) > self.config['line_length'] and wrap_mode == settings.WrapModes.NOQA:
if "# NOQA" not in line:
- return "{0} # NOQA".format(line)
+ return "{0}{1} NOQA".format(line, self.config['comment_prefix'])
return line
@@ -370,7 +390,10 @@ def _add_straight_imports(self, straight_modules, section, section_output):
continue
if module in self.as_map:
- import_definition = "import {0} as {1}".format(module, self.as_map[module])
+ import_definition = ''
+ if self.config['keep_direct_and_as_imports']:
+ import_definition = "import {0}\n".format(module)
+ import_definition += "import {0} as {1}".format(module, self.as_map[module])
else:
import_definition = "import {0}".format(module)
@@ -385,44 +408,50 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case):
continue
import_start = "from {0} import ".format(module)
- from_imports = self.imports[section]['from'][module]
- from_imports = nsorted(from_imports, key=lambda key: self._module_key(key, self.config, True, ignore_case))
+ from_imports = list(self.imports[section]['from'][module])
+ if not self.config['no_inline_sort'] or self.config['force_single_line']:
+ from_imports = nsorted(from_imports, key=lambda key: self._module_key(key, self.config, True, ignore_case))
if self.remove_imports:
from_imports = [line for line in from_imports if not "{0}.{1}".format(module, line) in
self.remove_imports]
- for from_import in copy.copy(from_imports):
- submodule = module + "." + from_import
- import_as = self.as_map.get(submodule, False)
- if import_as:
- import_definition = "{0} as {1}".format(from_import, import_as)
- if self.config['combine_as_imports'] and not ("*" in from_imports and
- self.config['combine_star']):
- from_imports[from_imports.index(from_import)] = import_definition
- else:
- import_statement = import_start + import_definition
- force_grid_wrap = self.config['force_grid_wrap']
- comments = self.comments['straight'].get(submodule)
- import_statement = self._add_comments(comments, self._wrap(import_statement))
- from_imports.remove(from_import)
- section_output.append(import_statement)
-
+ sub_modules = ['{0}.{1}'.format(module, from_import) for from_import in from_imports]
+ as_imports = dict((from_import, "{0} as {1}".format(from_import, self.as_map[sub_module])) for
+ from_import, sub_module in zip(from_imports, sub_modules) if sub_module in self.as_map)
+ if self.config['combine_as_imports'] and not ("*" in from_imports and self.config['combine_star']):
+ for from_import in copy.copy(from_imports):
+ if from_import in as_imports:
+ from_imports[from_imports.index(from_import)] = as_imports.pop(from_import)
- if from_imports:
+ while from_imports:
comments = self.comments['from'].pop(module, ())
if "*" in from_imports and self.config['combine_star']:
import_statement = self._wrap(self._add_comments(comments, "{0}*".format(import_start)))
+ from_imports = None
elif self.config['force_single_line']:
import_statements = []
- for from_import in from_imports:
+ while from_imports:
+ from_import = from_imports.pop(0)
+ if from_import in as_imports:
+ from_comments = self.comments['straight'].get('{}.{}'.format(module, from_import))
+ import_statements.append(self._add_comments(from_comments,
+ self._wrap(import_start + as_imports[from_import])))
+ continue
single_import_line = self._add_comments(comments, import_start + from_import)
comment = self.comments['nested'].get(module, {}).pop(from_import, None)
if comment:
- single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
+ single_import_line += "{0} {1}".format(comments and ";" or self.config['comment_prefix'],
+ comment)
import_statements.append(self._wrap(single_import_line))
comments = None
- import_statement = "\n".join(import_statements)
+ import_statement = self.line_separator.join(import_statements)
else:
+ while from_imports and from_imports[0] in as_imports:
+ from_import = from_imports.pop(0)
+ from_comments = self.comments['straight'].get('{}.{}'.format(module, from_import))
+ section_output.append(self._add_comments(from_comments,
+ self._wrap(import_start + as_imports[from_import])))
+
star_import = False
if "*" in from_imports:
section_output.append(self._add_comments(comments, "{0}*".format(import_start)))
@@ -431,10 +460,13 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case):
comments = None
for from_import in copy.copy(from_imports):
+ if from_import in as_imports:
+ continue
comment = self.comments['nested'].get(module, {}).pop(from_import, None)
if comment:
single_import_line = self._add_comments(comments, import_start + from_import)
- single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
+ single_import_line += "{0} {1}".format(comments and ";" or self.config['comment_prefix'],
+ comment)
above_comments = self.comments['above']['from'].pop(module, None)
if above_comments:
section_output.extend(above_comments)
@@ -442,29 +474,32 @@ def _add_from_imports(self, from_modules, section, section_output, ignore_case):
from_imports.remove(from_import)
comments = None
+ from_import_section = []
+ while from_imports and from_imports[0] not in as_imports:
+ from_import_section.append(from_imports.pop(0))
if star_import:
- import_statement = import_start + (", ").join(from_imports)
+ import_statement = import_start + (", ").join(from_import_section)
else:
- import_statement = self._add_comments(comments, import_start + (", ").join(from_imports))
- if not from_imports:
+ import_statement = self._add_comments(comments, import_start + (", ").join(from_import_section))
+ if not from_import_section:
import_statement = ""
do_multiline_reformat = False
force_grid_wrap = self.config['force_grid_wrap']
- if force_grid_wrap and len(from_imports) >= force_grid_wrap:
+ if force_grid_wrap and len(from_import_section) >= force_grid_wrap:
do_multiline_reformat = True
- if len(import_statement) > self.config['line_length'] and len(from_imports) > 1:
+ if len(import_statement) > self.config['line_length'] and len(from_import_section) > 1:
do_multiline_reformat = True
# If line too long AND have imports AND we are NOT using GRID or VERTICAL wrap modes
- if (len(import_statement) > self.config['line_length'] and len(from_imports) > 0 and
+ if (len(import_statement) > self.config['line_length'] and len(from_import_section) > 0 and
self.config['multi_line_output'] not in (1, 0)):
do_multiline_reformat = True
if do_multiline_reformat:
- import_statement = self._multi_line_reformat(import_start, from_imports, comments)
+ import_statement = self._multi_line_reformat(import_start, from_import_section, comments)
if not do_multiline_reformat and len(import_statement) > self.config['line_length']:
import_statement = self._wrap(import_statement)
@@ -483,10 +518,10 @@ def _multi_line_reformat(self, import_start, from_imports, comments):
import_statement = formatter(import_start, copy.copy(from_imports),
dynamic_indent, indent, line_length, comments)
if self.config['balanced_wrapping']:
- lines = import_statement.split("\n")
+ lines = import_statement.split(self.line_separator)
line_count = len(lines)
if len(lines) > 1:
- minimum_length = min([len(line) for line in lines[:-1]])
+ minimum_length = min(len(line) for line in lines[:-1])
else:
minimum_length = 0
new_import_statement = import_statement
@@ -496,8 +531,8 @@ def _multi_line_reformat(self, import_start, from_imports, comments):
line_length -= 1
new_import_statement = formatter(import_start, copy.copy(from_imports),
dynamic_indent, indent, line_length, comments)
- lines = new_import_statement.split("\n")
- if import_statement.count('\n') == 0:
+ lines = new_import_statement.split(self.line_separator)
+ if import_statement.count(self.line_separator) == 0:
return self._wrap(import_statement)
return import_statement
@@ -518,6 +553,7 @@ def _add_formatted_imports(self):
sections = ('no_sections', )
output = []
+ prev_section_has_imports = False
for section in sections:
straight_modules = self.imports[section]['straight']
straight_modules = nsorted(straight_modules, key=lambda key: self._module_key(key, self.config))
@@ -550,7 +586,6 @@ def by_module(line):
line = line.lower()
return '{0}{1}'.format(section, line)
section_output = nsorted(section_output, key=by_module)
-
if section_output:
section_name = section
if section_name in self.place_imports:
@@ -560,12 +595,17 @@ def by_module(line):
section_title = self.config.get('import_heading_' + str(section_name).lower(), '')
if section_title:
section_comment = "# {0}".format(section_title)
- if not section_comment in self.out_lines[0:1] and not section_comment in self.in_lines[0:1]:
+ if section_comment not in self.out_lines[0:1] and section_comment not in self.in_lines[0:1]:
section_output.insert(0, section_comment)
+ if prev_section_has_imports and section_name in self.config['no_lines_before']:
+ while output and output[-1].strip() == '':
+ output.pop()
output += section_output + ([''] * self.config['lines_between_sections'])
-
- while [character.strip() for character in output[-1:]] == [""]:
+ prev_section_has_imports = bool(section_output)
+ while output and output[-1].strip() == '':
output.pop()
+ while output and output[0].strip() == '':
+ output.pop(0)
output_at = 0
if self.import_index < self.original_length:
@@ -582,16 +622,23 @@ def by_module(line):
next_construct = ""
self._in_quote = False
tail = self.out_lines[imports_tail:]
+
for index, line in enumerate(tail):
+ in_quote = self._in_quote
if not self._skip_line(line) and line.strip():
if line.strip().startswith("#") and len(tail) > (index + 1) and tail[index + 1].strip():
continue
next_construct = line
break
+ elif not in_quote:
+ parts = line.split()
+ if len(parts) >= 3 and parts[1] == '=' and "'" not in parts[0] and '"' not in parts[0]:
+ next_construct = line
+ break
if self.config['lines_after_imports'] != -1:
self.out_lines[imports_tail:0] = ["" for line in range(self.config['lines_after_imports'])]
- elif next_construct.startswith("def") or next_construct.startswith("class") or \
+ elif next_construct.startswith("def ") or next_construct.startswith("class ") or \
next_construct.startswith("@") or next_construct.startswith("async def"):
self.out_lines[imports_tail:0] = ["", ""]
else:
@@ -612,7 +659,7 @@ def _output_grid(self, statement, imports, white_space, indent, line_length, com
while imports:
next_import = imports.pop(0)
next_statement = self._add_comments(comments, statement + ", " + next_import)
- if len(next_statement.split("\n")[-1]) + 1 > line_length:
+ if len(next_statement.split(self.line_separator)[-1]) + 1 > line_length:
lines = ['{0}{1}'.format(white_space, next_import.split(" ")[0])]
for part in next_import.split(" ")[1:]:
new_line = '{0} {1}'.format(lines[-1], part)
@@ -620,20 +667,20 @@ def _output_grid(self, statement, imports, white_space, indent, line_length, com
lines.append('{0}{1}'.format(white_space, part))
else:
lines[-1] = new_line
- next_import = '\n'.join(lines)
+ next_import = self.line_separator.join(lines)
statement = (self._add_comments(comments, "{0},".format(statement)) +
- "\n{0}".format(next_import))
+ "{0}{1}".format(self.line_separator, next_import))
comments = None
else:
statement += ", " + next_import
return statement + ("," if self.config['include_trailing_comma'] else "") + ")"
def _output_vertical(self, statement, imports, white_space, indent, line_length, comments):
- first_import = self._add_comments(comments, imports.pop(0) + ",") + "\n" + white_space
+ first_import = self._add_comments(comments, imports.pop(0) + ",") + self.line_separator + white_space
return "{0}({1}{2}{3})".format(
statement,
first_import,
- (",\n" + white_space).join(imports),
+ ("," + self.line_separator + white_space).join(imports),
"," if self.config['include_trailing_comma'] else "",
)
@@ -642,56 +689,69 @@ def _output_hanging_indent(self, statement, imports, white_space, indent, line_l
while imports:
next_import = imports.pop(0)
next_statement = self._add_comments(comments, statement + ", " + next_import)
- if len(next_statement.split("\n")[-1]) + 3 > line_length:
+ if len(next_statement.split(self.line_separator)[-1]) + 3 > line_length:
next_statement = (self._add_comments(comments, "{0}, \\".format(statement)) +
- "\n{0}{1}".format(indent, next_import))
+ "{0}{1}{2}".format(self.line_separator, indent, next_import))
comments = None
statement = next_statement
return statement
def _output_vertical_hanging_indent(self, statement, imports, white_space, indent, line_length, comments):
- return "{0}({1}\n{2}{3}{4}\n)".format(
+ return "{0}({1}{2}{3}{4}{5}{2})".format(
statement,
self._add_comments(comments),
+ self.line_separator,
indent,
- (",\n" + indent).join(imports),
+ ("," + self.line_separator + indent).join(imports),
"," if self.config['include_trailing_comma'] else "",
)
- def _output_vertical_grid_common(self, statement, imports, white_space, indent, line_length, comments):
- statement += self._add_comments(comments, "(") + "\n" + indent + imports.pop(0)
+ def _output_vertical_grid_common(self, statement, imports, white_space, indent, line_length, comments,
+ need_trailing_char):
+ statement += self._add_comments(comments, "(") + self.line_separator + indent + imports.pop(0)
while imports:
next_import = imports.pop(0)
next_statement = "{0}, {1}".format(statement, next_import)
- if len(next_statement.split("\n")[-1]) + 1 > line_length:
- next_statement = "{0},\n{1}{2}".format(statement, indent, next_import)
+ current_line_length = len(next_statement.split(self.line_separator)[-1])
+ if imports or need_trailing_char:
+ # If we have more imports we need to account for a comma after this import
+ # We might also need to account for a closing ) we're going to add.
+ current_line_length += 1
+ if current_line_length > line_length:
+ next_statement = "{0},{1}{2}{3}".format(statement, self.line_separator, indent, next_import)
statement = next_statement
if self.config['include_trailing_comma']:
statement += ','
return statement
def _output_vertical_grid(self, statement, imports, white_space, indent, line_length, comments):
- return self._output_vertical_grid_common(statement, imports, white_space, indent, line_length, comments) + ")"
+ return self._output_vertical_grid_common(statement, imports, white_space, indent, line_length, comments,
+ True) + ")"
def _output_vertical_grid_grouped(self, statement, imports, white_space, indent, line_length, comments):
- return self._output_vertical_grid_common(statement, imports, white_space, indent, line_length, comments) + "\n)"
+ return self._output_vertical_grid_common(statement, imports, white_space, indent, line_length, comments,
+ True) + self.line_separator + ")"
+
+ def _output_vertical_grid_grouped_no_comma(self, statement, imports, white_space, indent, line_length, comments):
+ return self._output_vertical_grid_common(statement, imports, white_space, indent, line_length, comments,
+ False) + self.line_separator + ")"
def _output_noqa(self, statement, imports, white_space, indent, line_length, comments):
retval = '{0}{1}'.format(statement, ', '.join(imports))
comment_str = ' '.join(comments)
if comments:
- if len(retval) + 4 + len(comment_str) <= line_length:
- return '{0} # {1}'.format(retval, comment_str)
+ if len(retval) + len(self.config['comment_prefix']) + 1 + len(comment_str) <= line_length:
+ return '{0}{1} {2}'.format(retval, self.config['comment_prefix'], comment_str)
else:
if len(retval) <= line_length:
return retval
if comments:
if "NOQA" in comments:
- return '{0} # {1}'.format(retval, comment_str)
+ return '{0}{1} {2}'.format(retval, self.config['comment_prefix'], comment_str)
else:
- return '{0} # NOQA {1}'.format(retval, comment_str)
+ return '{0}{1} NOQA {2}'.format(retval, self.config['comment_prefix'], comment_str)
else:
- return '{0} # NOQA'.format(retval)
+ return '{0}{1} NOQA'.format(retval, self.config['comment_prefix'])
@staticmethod
def _strip_comments(line, comments=None):
@@ -723,7 +783,7 @@ def _format_simplified(import_line):
def _format_natural(import_line):
import_line = import_line.strip()
if not import_line.startswith("from ") and not import_line.startswith("import "):
- if not "." in import_line:
+ if "." not in import_line:
return "import {0}".format(import_line)
parts = import_line.split(".")
end = parts.pop(-1)
@@ -783,7 +843,10 @@ def _parse(self):
self._in_quote = False
self._in_top_comment = False
while not self._at_end():
- line = self._get_line()
+ raw_line = line = self._get_line()
+ line = line.replace("from.import ", "from . import ")
+ line = line.replace("\t", " ").replace('import*', 'import *')
+ line = line.replace(" .import ", " . import ")
statement_index = self.index
skip_line = self._skip_line(line)
@@ -804,7 +867,7 @@ def _parse(self):
import_type = self._import_type(line)
if not import_type or skip_line:
- self.out_lines.append(line)
+ self.out_lines.append(raw_line)
continue
for line in (line.strip() for line in line.split(";")):
@@ -813,14 +876,12 @@ def _parse(self):
self.out_lines.append(line)
continue
- line = line.replace("\t", " ").replace('import*', 'import *')
if self.import_index == -1:
self.import_index = self.index - 1
nested_comments = {}
import_string, comments, new_comments = self._strip_comments(line)
stripped_line = [part for part in self._strip_syntax(import_string).strip().split(" ") if part]
-
if import_type == "from" and len(stripped_line) == 2 and stripped_line[1] != "*" and new_comments:
nested_comments[stripped_line[-1]] = comments[0]
@@ -828,17 +889,32 @@ def _parse(self):
while not line.strip().endswith(")") and not self._at_end():
line, comments, new_comments = self._strip_comments(self._get_line(), comments)
stripped_line = self._strip_syntax(line).strip()
- if import_type == "from" and stripped_line and not " " in stripped_line and new_comments:
+ if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
nested_comments[stripped_line] = comments[-1]
- import_string += "\n" + line
+ import_string += self.line_separator + line
else:
while line.strip().endswith("\\"):
line, comments, new_comments = self._strip_comments(self._get_line(), comments)
+
+ # Still need to check for parentheses after an escaped line
+ if "(" in line.split("#")[0] and not self._at_end():
+ stripped_line = self._strip_syntax(line).strip()
+ if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
+ nested_comments[stripped_line] = comments[-1]
+ import_string += self.line_separator + line
+
+ while not line.strip().endswith(")") and not self._at_end():
+ line, comments, new_comments = self._strip_comments(self._get_line(), comments)
+ stripped_line = self._strip_syntax(line).strip()
+ if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
+ nested_comments[stripped_line] = comments[-1]
+ import_string += self.line_separator + line
+
stripped_line = self._strip_syntax(line).strip()
- if import_type == "from" and stripped_line and not " " in stripped_line and new_comments:
+ if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
nested_comments[stripped_line] = comments[-1]
if import_string.strip().endswith(" import") or line.strip().startswith("import "):
- import_string += "\n" + line
+ import_string += self.line_separator + line
else:
import_string = import_string.rstrip().rstrip("\\") + " " + line.lstrip()
@@ -866,6 +942,8 @@ def _parse(self):
if import_type == "from":
import_from = imports.pop(0)
placed_module = self.place_module(import_from)
+ if self.config['verbose']:
+ print("from-type place_module for %s returned %s" % (import_from, placed_module))
if placed_module == '':
print(
"WARNING: could not place module {0} of line {1} --"
@@ -882,8 +960,8 @@ def _parse(self):
if len(self.out_lines) > max(self.import_index, self._first_comment_index_end + 1, 1) - 1:
last = self.out_lines and self.out_lines[-1].rstrip() or ""
- while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and not
- 'isort:imports-' in last):
+ while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and
+ 'isort:imports-' not in last):
self.comments['above']['from'].setdefault(import_from, []).insert(0, self.out_lines.pop(-1))
if len(self.out_lines) > max(self.import_index - 1, self._first_comment_index_end + 1, 1) - 1:
last = self.out_lines[-1].rstrip()
@@ -906,7 +984,7 @@ def _parse(self):
last = self.out_lines and self.out_lines[-1].rstrip() or ""
while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and
- not 'isort:imports-' in last):
+ 'isort:imports-' not in last):
self.comments['above']['straight'].setdefault(module, []).insert(0,
self.out_lines.pop(-1))
if len(self.out_lines) > 0:
@@ -916,6 +994,8 @@ def _parse(self):
if self.index - 1 == self.import_index:
self.import_index -= len(self.comments['above']['straight'].get(module, []))
placed_module = self.place_module(module)
+ if self.config['verbose']:
+ print("else-type place_module for %s returned %s" % (module, placed_module))
if placed_module == '':
print(
"WARNING: could not place module {0} of line {1} --"
@@ -942,18 +1022,6 @@ def coding_check(fname, default='utf-8'):
return coding
-def get_stdlib_path():
- """Returns the path to the standard lib for the current path installation.
-
- This function can be dropped and "sysconfig.get_paths()" used directly once Python 2.6 support is dropped.
- """
- if sys.version_info >= (2, 7):
- import sysconfig
- return sysconfig.get_paths()['stdlib']
- else:
- return os.path.join(sys.prefix, 'lib')
-
-
def exists_case_sensitive(path):
"""
Returns if the given path exists and also matches the case on Windows.
@@ -963,7 +1031,7 @@ def exists_case_sensitive(path):
can only import using the case of the real file.
"""
result = os.path.exists(path)
- if sys.platform.startswith('win') and result:
+ if (sys.platform.startswith('win') or sys.platform == 'darwin') and result:
directory, basename = os.path.split(path)
result = basename in os.listdir(directory)
return result
diff --git a/pythonFiles/isort/main.py b/pythonFiles/isort/main.py
old mode 100755
new mode 100644
index eae7afa53409..efb3793d0a1b
--- a/pythonFiles/isort/main.py
+++ b/pythonFiles/isort/main.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#!/usr/bin/env python
''' Tool for sorting imports alphabetically, and automatically separated into sections.
Copyright (C) 2013 Timothy Edmund Crosley
@@ -23,7 +23,10 @@
import argparse
import glob
import os
+import re
import sys
+from concurrent.futures import ProcessPoolExecutor
+import functools
import setuptools
@@ -32,7 +35,6 @@
from .pie_slice import itemsview
-
INTRO = r"""
/#######################################################################\
@@ -56,6 +58,36 @@
\########################################################################/
""".format(__version__)
+shebang_re = re.compile(br'^#!.*\bpython[23w]?\b')
+
+
+def is_python_file(path):
+ if path.endswith('.py'):
+ return True
+
+ try:
+ with open(path, 'rb') as fp:
+ line = fp.readline(100)
+ except IOError:
+ return False
+ else:
+ return bool(shebang_re.match(line))
+
+
+class SortAttempt(object):
+ def __init__(self, incorrectly_sorted, skipped):
+ self.incorrectly_sorted = incorrectly_sorted
+ self.skipped = skipped
+
+
+def sort_imports(file_name, **arguments):
+ try:
+ result = SortImports(file_name, **arguments)
+ return SortAttempt(result.incorrectly_sorted, result.skipped)
+ except IOError as e:
+ print("WARNING: Unable to parse file {0} due to {1}".format(file_name, e))
+ return None
+
def iter_source_code(paths, config, skipped):
"""Iterate over all Python source files defined in paths."""
@@ -71,11 +103,12 @@ def iter_source_code(paths, config, skipped):
skipped.append(dirname)
dirnames.remove(dirname)
for filename in filenames:
- if filename.endswith('.py'):
+ filepath = os.path.join(dirpath, filename)
+ if is_python_file(filepath):
if should_skip(filename, config, dirpath):
skipped.append(filename)
else:
- yield os.path.join(dirpath, filename)
+ yield filepath
else:
yield path
@@ -138,105 +171,119 @@ def run(self):
def create_parser():
parser = argparse.ArgumentParser(description='Sort Python import definitions alphabetically '
'within logical sections.')
- parser.add_argument('files', nargs='*', help='One or more Python source files that need their imports sorted.')
- parser.add_argument('-y', '--apply', dest='apply', action='store_true',
- help='Tells isort to apply changes recursively without asking')
- parser.add_argument('-l', '--lines', help='[Deprecated] The max length of an import line (used for wrapping '
- 'long imports).',
- dest='line_length', type=int)
- parser.add_argument('-w', '--line-width', help='The max length of an import line (used for wrapping long imports).',
- dest='line_length', type=int)
- parser.add_argument('-s', '--skip', help='Files that sort imports should skip over. If you want to skip multiple '
- 'files you should specify twice: --skip file1 --skip file2.', dest='skip', action='append')
- parser.add_argument('-ns', '--dont-skip', help='Files that sort imports should never skip over.',
- dest='not_skip', action='append')
- parser.add_argument('-sg', '--skip-glob', help='Files that sort imports should skip over.', dest='skip_glob',
- action='append')
- parser.add_argument('-t', '--top', help='Force specific imports to the top of their appropriate section.',
- dest='force_to_top', action='append')
- parser.add_argument('-f', '--future', dest='known_future_library', action='append',
- help='Force sortImports to recognize a module as part of the future compatibility libraries.')
- parser.add_argument('-b', '--builtin', dest='known_standard_library', action='append',
- help='Force sortImports to recognize a module as part of the python standard library.')
- parser.add_argument('-o', '--thirdparty', dest='known_third_party', action='append',
- help='Force sortImports to recognize a module as being part of a third party library.')
- parser.add_argument('-p', '--project', dest='known_first_party', action='append',
- help='Force sortImports to recognize a module as being part of the current python project.')
- parser.add_argument('--virtual-env', dest='virtual_env',
- help='Virtual environment to use for determining whether a package is third-party')
- parser.add_argument('-m', '--multi-line', dest='multi_line_output', type=int, choices=[0, 1, 2, 3, 4, 5],
- help='Multi line output (0-grid, 1-vertical, 2-hanging, 3-vert-hanging, 4-vert-grid, '
- '5-vert-grid-grouped).')
- parser.add_argument('-i', '--indent', help='String to place for indents defaults to " " (4 spaces).',
- dest='indent', type=str)
+ inline_args_group = parser.add_mutually_exclusive_group()
parser.add_argument('-a', '--add-import', dest='add_imports', action='append',
help='Adds the specified import line to all files, '
'automatically determining correct placement.')
+ parser.add_argument('-ac', '--atomic', dest='atomic', action='store_true',
+ help="Ensures the output doesn't save if the resulting file contains syntax errors.")
parser.add_argument('-af', '--force-adds', dest='force_adds', action='store_true',
help='Forces import adds even if the original file is empty.')
- parser.add_argument('-r', '--remove-import', dest='remove_imports', action='append',
- help='Removes the specified import from all files.')
- parser.add_argument('-ls', '--length-sort', help='Sort imports by their string length.',
- dest='length_sort', action='store_true')
- parser.add_argument('-d', '--stdout', help='Force resulting output to stdout, instead of in-place.',
- dest='write_to_stdout', action='store_true')
+ parser.add_argument('-b', '--builtin', dest='known_standard_library', action='append',
+ help='Force sortImports to recognize a module as part of the python standard library.')
parser.add_argument('-c', '--check-only', action='store_true', dest="check",
help='Checks the file for unsorted / unformatted imports and prints them to the '
'command line without modifying the file.')
- parser.add_argument('-ws', '--ignore-whitespace', action='store_true', dest="ignore_whitespace",
- help='Tells isort to ignore whitespace differences when --check-only is being used.')
- parser.add_argument('-sl', '--force-single-line-imports', dest='force_single_line', action='store_true',
- help='Forces all from imports to appear on their own line')
- parser.add_argument('-ds', '--no-sections', help='Put all imports into the same section bucket', dest='no_sections',
- action='store_true')
- parser.add_argument('-sd', '--section-default', dest='default_section',
- help='Sets the default section for imports (by default FIRSTPARTY) options: ' +
- str(DEFAULT_SECTIONS))
+ parser.add_argument('-ca', '--combine-as', dest='combine_as_imports', action='store_true',
+ help="Combines as imports on the same line.")
+ parser.add_argument('-cs', '--combine-star', dest='combine_star', action='store_true',
+ help="Ensures that if a star import is present, nothing else is imported from that namespace.")
+ parser.add_argument('-d', '--stdout', help='Force resulting output to stdout, instead of in-place.',
+ dest='write_to_stdout', action='store_true')
parser.add_argument('-df', '--diff', dest='show_diff', action='store_true',
help="Prints a diff of all the changes isort would make to a file, instead of "
"changing it in place")
- parser.add_argument('-e', '--balanced', dest='balanced_wrapping', action='store_true',
- help='Balances wrapping to produce the most consistent line length possible')
- parser.add_argument('-rc', '--recursive', dest='recursive', action='store_true',
- help='Recursively look for Python files of which to sort imports')
- parser.add_argument('-ot', '--order-by-type', dest='order_by_type',
- action='store_true', help='Order imports by type in addition to alphabetically')
+ parser.add_argument('-ds', '--no-sections', help='Put all imports into the same section bucket', dest='no_sections',
+ action='store_true')
parser.add_argument('-dt', '--dont-order-by-type', dest='dont_order_by_type',
action='store_true', help='Only order imports alphabetically, do not attempt type ordering')
- parser.add_argument('-ac', '--atomic', dest='atomic', action='store_true',
- help="Ensures the output doesn't save if the resulting file contains syntax errors.")
- parser.add_argument('-cs', '--combine-star', dest='combine_star', action='store_true',
- help="Ensures that if a star import is present, nothing else is imported from that namespace.")
- parser.add_argument('-ca', '--combine-as', dest='combine_as_imports', action='store_true',
- help="Combines as imports on the same line.")
- parser.add_argument('-tc', '--trailing-comma', dest='include_trailing_comma', action='store_true',
- help='Includes a trailing comma on multi line imports that include parentheses.')
- parser.add_argument('-v', '--version', action='store_true', dest='show_version')
- parser.add_argument('-vb', '--verbose', action='store_true', dest="verbose",
- help='Shows verbose output, such as when files are skipped or when a check is successful.')
- parser.add_argument('-q', '--quiet', action='store_true', dest="quiet",
- help='Shows extra quiet output, only errors are outputted.')
- parser.add_argument('-sp', '--settings-path', dest="settings_path",
- help='Explicitly set the settings path instead of auto determining based on file location.')
+ parser.add_argument('-e', '--balanced', dest='balanced_wrapping', action='store_true',
+ help='Balances wrapping to produce the most consistent line length possible')
+ parser.add_argument('-f', '--future', dest='known_future_library', action='append',
+ help='Force sortImports to recognize a module as part of the future compatibility libraries.')
+ parser.add_argument('-fas', '--force-alphabetical-sort', action='store_true', dest="force_alphabetical_sort",
+ help='Force all imports to be sorted as a single section')
+ parser.add_argument('-fass', '--force-alphabetical-sort-within-sections', action='store_true',
+ dest="force_alphabetical_sort", help='Force all imports to be sorted alphabetically within a '
+ 'section')
parser.add_argument('-ff', '--from-first', dest='from_first',
help="Switches the typical ordering preference, showing from imports first then straight ones.")
- parser.add_argument('-wl', '--wrap-length', dest='wrap_length',
- help="Specifies how long lines that are wrapped should be, if not set line_length is used.")
parser.add_argument('-fgw', '--force-grid-wrap', nargs='?', const=2, type=int, dest="force_grid_wrap",
help='Force number of from imports (defaults to 2) to be grid wrapped regardless of line '
'length')
- parser.add_argument('-fass', '--force-alphabetical-sort-within-sections', action='store_true',
- dest="force_alphabetical_sort", help='Force all imports to be sorted alphabetically within a '
- 'section')
- parser.add_argument('-fas', '--force-alphabetical-sort', action='store_true', dest="force_alphabetical_sort",
- help='Force all imports to be sorted as a single section')
parser.add_argument('-fss', '--force-sort-within-sections', action='store_true', dest="force_sort_within_sections",
help='Force imports to be sorted by module, independent of import_type')
+ parser.add_argument('-i', '--indent', help='String to place for indents defaults to " " (4 spaces).',
+ dest='indent', type=str)
+ parser.add_argument('-j', '--jobs', help='Number of files to process in parallel.',
+ dest='jobs', type=int)
+ parser.add_argument('-k', '--keep-direct-and-as', dest='keep_direct_and_as_imports', action='store_true',
+ help="Turns off default behavior that removes direct imports when as imports exist.")
+ parser.add_argument('-l', '--lines', help='[Deprecated] The max length of an import line (used for wrapping '
+ 'long imports).',
+ dest='line_length', type=int)
+ parser.add_argument('-lai', '--lines-after-imports', dest='lines_after_imports', type=int)
parser.add_argument('-lbt', '--lines-between-types', dest='lines_between_types', type=int)
+ parser.add_argument('-le', '--line-ending', dest='line_ending',
+ help="Forces line endings to the specified value. If not set, values will be guessed per-file.")
+ parser.add_argument('-ls', '--length-sort', help='Sort imports by their string length.',
+ dest='length_sort', action='store_true')
+ parser.add_argument('-m', '--multi-line', dest='multi_line_output', type=int, choices=[0, 1, 2, 3, 4, 5],
+ help='Multi line output (0-grid, 1-vertical, 2-hanging, 3-vert-hanging, 4-vert-grid, '
+ '5-vert-grid-grouped, 6-vert-grid-grouped-no-comma).')
+ inline_args_group.add_argument('-nis', '--no-inline-sort', dest='no_inline_sort', action='store_true',
+ help='Leaves `from` imports with multiple imports \'as-is\' (e.g. `from foo import a, c ,b`).')
+ parser.add_argument('-nlb', '--no-lines-before', help='Sections which should not be split with previous by empty lines',
+ dest='no_lines_before', action='append')
+ parser.add_argument('-ns', '--dont-skip', help='Files that sort imports should never skip over.',
+ dest='not_skip', action='append')
+ parser.add_argument('-o', '--thirdparty', dest='known_third_party', action='append',
+ help='Force sortImports to recognize a module as being part of a third party library.')
+ parser.add_argument('-ot', '--order-by-type', dest='order_by_type',
+ action='store_true', help='Order imports by type in addition to alphabetically')
+ parser.add_argument('-p', '--project', dest='known_first_party', action='append',
+ help='Force sortImports to recognize a module as being part of the current python project.')
+ parser.add_argument('-q', '--quiet', action='store_true', dest="quiet",
+ help='Shows extra quiet output, only errors are outputted.')
+ parser.add_argument('-r', '--remove-import', dest='remove_imports', action='append',
+ help='Removes the specified import from all files.')
+ parser.add_argument('-rc', '--recursive', dest='recursive', action='store_true',
+ help='Recursively look for Python files of which to sort imports')
+ parser.add_argument('-s', '--skip', help='Files that sort imports should skip over. If you want to skip multiple '
+ 'files you should specify twice: --skip file1 --skip file2.', dest='skip', action='append')
+ parser.add_argument('-sd', '--section-default', dest='default_section',
+ help='Sets the default section for imports (by default FIRSTPARTY) options: ' +
+ str(DEFAULT_SECTIONS))
+ parser.add_argument('-sg', '--skip-glob', help='Files that sort imports should skip over.', dest='skip_glob',
+ action='append')
+ inline_args_group.add_argument('-sl', '--force-single-line-imports', dest='force_single_line', action='store_true',
+ help='Forces all from imports to appear on their own line')
+ parser.add_argument('-sp', '--settings-path', dest="settings_path",
+ help='Explicitly set the settings path instead of auto determining based on file location.')
+ parser.add_argument('-t', '--top', help='Force specific imports to the top of their appropriate section.',
+ dest='force_to_top', action='append')
+ parser.add_argument('-tc', '--trailing-comma', dest='include_trailing_comma', action='store_true',
+ help='Includes a trailing comma on multi line imports that include parentheses.')
parser.add_argument('-up', '--use-parentheses', dest='use_parentheses', action='store_true',
- help='Use parenthesis for line continuation on lenght limit instead of slashes.')
+ help='Use parenthesis for line continuation on length limit instead of slashes.')
+ parser.add_argument('-v', '--version', action='store_true', dest='show_version')
+ parser.add_argument('-vb', '--verbose', action='store_true', dest="verbose",
+ help='Shows verbose output, such as when files are skipped or when a check is successful.')
+ parser.add_argument('--virtual-env', dest='virtual_env',
+ help='Virtual environment to use for determining whether a package is third-party')
+ parser.add_argument('-vn', '--version-number', action='version', version=__version__,
+ help='Returns just the current version number without the logo')
+ parser.add_argument('-w', '--line-width', help='The max length of an import line (used for wrapping long imports).',
+ dest='line_length', type=int)
+ parser.add_argument('-wl', '--wrap-length', dest='wrap_length',
+ help="Specifies how long lines that are wrapped should be, if not set line_length is used.")
+ parser.add_argument('-ws', '--ignore-whitespace', action='store_true', dest="ignore_whitespace",
+ help='Tells isort to ignore whitespace differences when --check-only is being used.')
+ parser.add_argument('-y', '--apply', dest='apply', action='store_true',
+ help='Tells isort to apply changes recursively without asking')
+ parser.add_argument('files', nargs='*', help='One or more Python source files that need their imports sorted.')
- arguments = dict((key, value) for (key, value) in itemsview(vars(parser.parse_args())) if value)
+ arguments = {key: value for key, value in itemsview(vars(parser.parse_args())) if value}
if 'dont_order_by_type' in arguments:
arguments['order_by_type'] = False
return arguments
@@ -251,6 +298,14 @@ def main():
if 'settings_path' in arguments:
sp = arguments['settings_path']
arguments['settings_path'] = os.path.abspath(sp) if os.path.isdir(sp) else os.path.dirname(os.path.abspath(sp))
+ if not os.path.isdir(arguments['settings_path']):
+ print("WARNING: settings_path dir does not exist: {0}".format(arguments['settings_path']))
+
+ if 'virtual_env' in arguments:
+ venv = arguments['virtual_env']
+ arguments['virtual_env'] = os.path.abspath(venv)
+ if not os.path.isdir(arguments['virtual_env']):
+ print("WARNING: virtual_env dir does not exist: {0}".format(arguments['virtual_env']))
file_names = arguments.pop('files', [])
if file_names == ['-']:
@@ -270,16 +325,29 @@ def main():
num_skipped = 0
if config['verbose'] or config.get('show_logo', False):
print(INTRO)
- for file_name in file_names:
- try:
- sort_attempt = SortImports(file_name, **arguments)
+ jobs = arguments.get('jobs')
+ if jobs:
+ executor = ProcessPoolExecutor(max_workers=jobs)
+
+ for sort_attempt in executor.map(functools.partial(sort_imports, **arguments), file_names):
+ if not sort_attempt:
+ continue
incorrectly_sorted = sort_attempt.incorrectly_sorted
if arguments.get('check', False) and incorrectly_sorted:
wrong_sorted_files = True
if sort_attempt.skipped:
num_skipped += 1
- except IOError as e:
- print("WARNING: Unable to parse file {0} due to {1}".format(file_name, e))
+ else:
+ for file_name in file_names:
+ try:
+ sort_attempt = SortImports(file_name, **arguments)
+ incorrectly_sorted = sort_attempt.incorrectly_sorted
+ if arguments.get('check', False) and incorrectly_sorted:
+ wrong_sorted_files = True
+ if sort_attempt.skipped:
+ num_skipped += 1
+ except IOError as e:
+ print("WARNING: Unable to parse file {0} due to {1}".format(file_name, e))
if wrong_sorted_files:
exit(1)
diff --git a/pythonFiles/isort/natural.py b/pythonFiles/isort/natural.py
index aac8c4a36157..c02b42c37e48 100644
--- a/pythonFiles/isort/natural.py
+++ b/pythonFiles/isort/natural.py
@@ -8,7 +8,7 @@
Copyright (C) 2013 Timothy Edmund Crosley
Implementation originally from @HappyLeapSecond stack overflow user in response to:
- http://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside
+ https://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
diff --git a/pythonFiles/isort/pie_slice.py b/pythonFiles/isort/pie_slice.py
index bfb341a7f7ec..178cf33e87c3 100644
--- a/pythonFiles/isort/pie_slice.py
+++ b/pythonFiles/isort/pie_slice.py
@@ -21,11 +21,8 @@
"""
from __future__ import absolute_import
-import abc
import collections
-import functools
import sys
-from numbers import Integral
__version__ = "1.1.0"
@@ -47,7 +44,7 @@
common = ['native_dict', 'native_round', 'native_filter', 'native_map', 'native_range', 'native_str', 'native_chr',
'native_input', 'PY2', 'PY3', 'u', 'itemsview', 'valuesview', 'keysview', 'execute', 'integer_types',
- 'native_next', 'native_object', 'with_metaclass', 'OrderedDict', 'lru_cache']
+ 'native_next', 'native_object', 'with_metaclass', 'lru_cache']
def with_metaclass(meta, *bases):
@@ -85,32 +82,12 @@ def unmodified_isinstance(*bases):
"""
class UnmodifiedIsInstance(type):
- if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
-
- @classmethod
- def __instancecheck__(cls, instance):
- if cls.__name__ in (str(base.__name__) for base in bases):
- return isinstance(instance, bases)
-
- subclass = getattr(instance, '__class__', None)
- subtype = type(instance)
- instance_type = getattr(abc, '_InstanceType', None)
- if not instance_type:
- class test_object:
- pass
- instance_type = type(test_object)
- if subtype is instance_type:
- subtype = subclass
- if subtype is subclass or subclass is None:
- return cls.__subclasscheck__(subtype)
- return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
- else:
- @classmethod
- def __instancecheck__(cls, instance):
- if cls.__name__ in (str(base.__name__) for base in bases):
- return isinstance(instance, bases)
+ @classmethod
+ def __instancecheck__(cls, instance):
+ if cls.__name__ in (str(base.__name__) for base in bases):
+ return isinstance(instance, bases)
- return type.__instancecheck__(cls, instance)
+ return type.__instancecheck__(cls, instance)
return with_metaclass(UnmodifiedIsInstance, *bases)
@@ -148,12 +125,11 @@ def callable(entity):
__all__ = common + ['urllib']
else:
- from itertools import ifilter as filter
- from itertools import imap as map
- from itertools import izip as zip
+ from itertools import ifilter as filter # noqa: F401
+ from itertools import imap as map # noqa: F401
+ from itertools import izip as zip # noqa: F401
from decimal import Decimal, ROUND_HALF_EVEN
- import codecs
str = unicode
chr = unichr
input = raw_input
@@ -281,28 +257,10 @@ def __new__(cls, name, bases, dct):
dct['__str__'] = lambda self: self.__unicode__().encode('utf-8')
return type.__new__(cls, name, bases, dct)
- if sys.version_info[1] <= 6:
- def __instancecheck__(cls, instance):
- if cls.__name__ == "object":
- return isinstance(instance, native_object)
-
- subclass = getattr(instance, '__class__', None)
- subtype = type(instance)
- instance_type = getattr(abc, '_InstanceType', None)
- if not instance_type:
- class test_object:
- pass
- instance_type = type(test_object)
- if subtype is instance_type:
- subtype = subclass
- if subtype is subclass or subclass is None:
- return cls.__subclasscheck__(subtype)
- return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
- else:
- def __instancecheck__(cls, instance):
- if cls.__name__ == "object":
- return isinstance(instance, native_object)
- return type.__instancecheck__(cls, instance)
+ def __instancecheck__(cls, instance):
+ if cls.__name__ == "object":
+ return isinstance(instance, native_object)
+ return type.__instancecheck__(cls, instance)
class object(with_metaclass(FixStr, object)):
pass
@@ -310,138 +268,6 @@ class object(with_metaclass(FixStr, object)):
__all__ = common + ['round', 'dict', 'apply', 'cmp', 'coerce', 'execfile', 'raw_input', 'unpacks', 'str', 'chr',
'input', 'range', 'filter', 'map', 'zip', 'object']
-if sys.version_info[0] == 2 and sys.version_info[1] < 7:
- # OrderedDict
- # Copyright (c) 2009 Raymond Hettinger
- #
- # Permission is hereby granted, free of charge, to any person
- # obtaining a copy of this software and associated documentation files
- # (the "Software"), to deal in the Software without restriction,
- # including without limitation the rights to use, copy, modify, merge,
- # publish, distribute, sublicense, and/or sell copies of the Software,
- # and to permit persons to whom the Software is furnished to do so,
- # subject to the following conditions:
- #
- # The above copyright notice and this permission notice shall be
- # included in all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- # OTHER DEALINGS IN THE SOFTWARE.
-
- from UserDict import DictMixin
-
- class OrderedDict(dict, DictMixin):
-
- def __init__(self, *args, **kwds):
- if len(args) > 1:
- raise TypeError('expected at most 1 arguments, got %d' % len(args))
- try:
- self.__end
- except AttributeError:
- self.clear()
- self.update(*args, **kwds)
-
- def clear(self):
- self.__end = end = []
- end += [None, end, end] # sentinel node for doubly linked list
- self.__map = {} # key --> [key, prev, next]
- dict.clear(self)
-
- def __setitem__(self, key, value):
- if key not in self:
- end = self.__end
- curr = end[1]
- curr[2] = end[1] = self.__map[key] = [key, curr, end]
- dict.__setitem__(self, key, value)
-
- def __delitem__(self, key):
- dict.__delitem__(self, key)
- key, prev, next = self.__map.pop(key)
- prev[2] = next
- next[1] = prev
-
- def __iter__(self):
- end = self.__end
- curr = end[2]
- while curr is not end:
- yield curr[0]
- curr = curr[2]
-
- def __reversed__(self):
- end = self.__end
- curr = end[1]
- while curr is not end:
- yield curr[0]
- curr = curr[1]
-
- def popitem(self, last=True):
- if not self:
- raise KeyError('dictionary is empty')
- if last:
- key = reversed(self).next()
- else:
- key = iter(self).next()
- value = self.pop(key)
- return key, value
-
- def __reduce__(self):
- items = [[k, self[k]] for k in self]
- tmp = self.__map, self.__end
- del self.__map, self.__end
- inst_dict = vars(self).copy()
- self.__map, self.__end = tmp
- if inst_dict:
- return (self.__class__, (items,), inst_dict)
- return self.__class__, (items,)
-
- def keys(self):
- return list(self)
-
- setdefault = DictMixin.setdefault
- update = DictMixin.update
- pop = DictMixin.pop
- values = DictMixin.values
- items = DictMixin.items
- iterkeys = DictMixin.iterkeys
- itervalues = DictMixin.itervalues
- iteritems = DictMixin.iteritems
-
- def __repr__(self):
- if not self:
- return '%s()' % (self.__class__.__name__,)
- return '%s(%r)' % (self.__class__.__name__, self.items())
-
- def copy(self):
- return self.__class__(self)
-
- @classmethod
- def fromkeys(cls, iterable, value=None):
- d = cls()
- for key in iterable:
- d[key] = value
- return d
-
- def __eq__(self, other):
- if isinstance(other, OrderedDict):
- if len(self) != len(other):
- return False
- for p, q in zip(self.items(), other.items()):
- if p != q:
- return False
- return True
- return dict.__eq__(self, other)
-
- def __ne__(self, other):
- return not self == other
-else:
- from collections import OrderedDict
-
if sys.version_info < (3, 2):
try:
@@ -451,6 +277,8 @@ def __ne__(self, other):
from functools import wraps
+ _CacheInfo = collections.namedtuple("CacheInfo", "hits misses maxsize currsize")
+
def lru_cache(maxsize=100):
"""Least-recently-used cache decorator.
Taking from: https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py
@@ -461,7 +289,7 @@ def lru_cache(maxsize=100):
View the cache statistics named tuple (hits, misses, maxsize, currsize) with
f.cache_info(). Clear the cache and statistics with f.cache_clear().
Access the underlying function with f.__wrapped__.
- See: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
+ See: https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
"""
def decorating_function(user_function, tuple=tuple, sorted=sorted, len=len, KeyError=KeyError):
@@ -470,7 +298,7 @@ def decorating_function(user_function, tuple=tuple, sorted=sorted, len=len, KeyE
lock = Lock()
if maxsize is None:
- CACHE = dict()
+ CACHE = {}
@wraps(user_function)
def wrapper(*args, **kwds):
@@ -488,7 +316,7 @@ def wrapper(*args, **kwds):
misses[0] += 1
return result
else:
- CACHE = OrderedDict()
+ CACHE = collections.OrderedDict()
@wraps(user_function)
def wrapper(*args, **kwds):
@@ -528,7 +356,7 @@ def cache_clear():
return decorating_function
else:
- from functools import lru_cache
+ from functools import lru_cache # noqa: F401
class OrderedSet(collections.MutableSet):
diff --git a/pythonFiles/isort/settings.py b/pythonFiles/isort/settings.py
index 15cdb21094ac..dd0a71102405 100644
--- a/pythonFiles/isort/settings.py
+++ b/pythonFiles/isort/settings.py
@@ -25,8 +25,10 @@
from __future__ import absolute_import, division, print_function, unicode_literals
import fnmatch
+import io
import os
import posixpath
+import sys
from collections import namedtuple
from .pie_slice import itemsview, lru_cache, native_str
@@ -36,10 +38,11 @@
except ImportError:
import ConfigParser as configparser
-MAX_CONFIG_SEARCH_DEPTH = 25 # The number of parent directories isort will look for a config file within
+MAX_CONFIG_SEARCH_DEPTH = 25 # The number of parent directories isort will look for a config file within
DEFAULT_SECTIONS = ('FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER')
-WrapModes = ('GRID', 'VERTICAL', 'HANGING_INDENT', 'VERTICAL_HANGING_INDENT', 'VERTICAL_GRID', 'VERTICAL_GRID_GROUPED', 'NOQA')
+WrapModes = ('GRID', 'VERTICAL', 'HANGING_INDENT', 'VERTICAL_HANGING_INDENT', 'VERTICAL_GRID', 'VERTICAL_GRID_GROUPED',
+ 'VERTICAL_GRID_GROUPED_NO_COMMA', 'NOQA')
WrapModes = namedtuple('WrapModes', WrapModes)(*range(len(WrapModes)))
# Note that none of these lists must be complete as they are simply fallbacks for when included auto-detection fails.
@@ -48,6 +51,7 @@
'skip_glob': [],
'line_length': 79,
'wrap_length': 0,
+ 'line_ending': None,
'sections': DEFAULT_SECTIONS,
'no_sections': False,
'known_future_library': ['__future__'],
@@ -101,6 +105,7 @@
'multi_line_output': WrapModes.GRID,
'forced_separate': [],
'indent': ' ' * 4,
+ 'comment_prefix': ' #',
'length_sort': False,
'add_imports': [],
'remove_imports': [],
@@ -120,6 +125,7 @@
'lines_between_types': 0,
'combine_as_imports': False,
'combine_star': False,
+ 'keep_direct_and_as_imports': False,
'include_trailing_comma': False,
'from_first': False,
'verbose': False,
@@ -130,7 +136,9 @@
'force_grid_wrap': 0,
'force_sort_within_sections': False,
'show_diff': False,
- 'ignore_whitespace': False}
+ 'ignore_whitespace': False,
+ 'no_lines_before': [],
+ 'no_inline_sort': False}
@lru_cache()
@@ -214,7 +222,7 @@ def _as_list(value):
@lru_cache()
def _get_config_data(file_path, sections):
- with open(file_path, 'rU') as config_file:
+ with io.open(file_path, 'r') as config_file:
if file_path.endswith('.editorconfig'):
line = '\n'
last_position = config_file.tell()
@@ -225,9 +233,14 @@ def _get_config_data(file_path, sections):
break
last_position = config_file.tell()
- config = configparser.SafeConfigParser()
- config.readfp(config_file)
- settings = dict()
+ if sys.version_info >= (3, 2):
+ config = configparser.ConfigParser()
+ config.read_file(config_file)
+ else:
+ config = configparser.SafeConfigParser()
+ config.readfp(config_file)
+
+ settings = {}
for section in sections:
if config.has_section(section):
settings.update(dict(config.items(section)))
diff --git a/pythonFiles/jedi/__init__.py b/pythonFiles/jedi/__init__.py
index 1a1080ad2fd4..ff2de906d9cd 100644
--- a/pythonFiles/jedi/__init__.py
+++ b/pythonFiles/jedi/__init__.py
@@ -36,8 +36,12 @@
good text editor, while still having very good IDE features for Python.
"""
-__version__ = '0.11.1'
+__version__ = '0.12.0'
from jedi.api import Script, Interpreter, set_debug_function, \
preload_module, names
from jedi import settings
+from jedi.api.environment import find_virtualenvs, find_system_environments, \
+ get_default_environment, InvalidPythonEnvironment, create_environment, \
+ get_system_environment
+from jedi.api.exceptions import InternalError
diff --git a/pythonFiles/jedi/_compatibility.py b/pythonFiles/jedi/_compatibility.py
index 52a20fe2c07c..8b55fb8f4a1d 100644
--- a/pythonFiles/jedi/_compatibility.py
+++ b/pythonFiles/jedi/_compatibility.py
@@ -1,25 +1,25 @@
"""
-To ensure compatibility from Python ``2.6`` - ``3.3``, a module has been
+To ensure compatibility from Python ``2.7`` - ``3.x``, a module has been
created. Clearly there is huge need to use conforming syntax.
"""
+import binascii
+import errno
import sys
-import imp
import os
import re
import pkgutil
import warnings
+import inspect
+import subprocess
try:
import importlib
except ImportError:
pass
-# Cannot use sys.version.major and minor names, because in Python 2.6 it's not
-# a namedtuple.
is_py3 = sys.version_info[0] >= 3
is_py33 = is_py3 and sys.version_info[1] >= 3
is_py34 = is_py3 and sys.version_info[1] >= 4
is_py35 = is_py3 and sys.version_info[1] >= 5
-is_py26 = not is_py3 and sys.version_info[1] < 7
py_version = int(str(sys.version_info[0]) + str(sys.version_info[1]))
@@ -35,28 +35,24 @@ def close(self):
del self.loader
-def find_module_py34(string, path=None, fullname=None):
- implicit_namespace_pkg = False
+def find_module_py34(string, path=None, full_name=None):
spec = None
loader = None
spec = importlib.machinery.PathFinder.find_spec(string, path)
- if hasattr(spec, 'origin'):
- origin = spec.origin
- implicit_namespace_pkg = origin == 'namespace'
-
- # We try to disambiguate implicit namespace pkgs with non implicit namespace pkgs
- if implicit_namespace_pkg:
- fullname = string if not path else fullname
- implicit_ns_info = ImplicitNSInfo(fullname, spec.submodule_search_locations._path)
- return None, implicit_ns_info, False
-
- # we have found the tail end of the dotted path
- if hasattr(spec, 'loader'):
+ if spec is not None:
+ # We try to disambiguate implicit namespace pkgs with non implicit namespace pkgs
+ if not spec.has_location:
+ full_name = string if not path else full_name
+ implicit_ns_info = ImplicitNSInfo(full_name, spec.submodule_search_locations._path)
+ return None, implicit_ns_info, False
+
+ # we have found the tail end of the dotted path
loader = spec.loader
return find_module_py33(string, path, loader)
-def find_module_py33(string, path=None, loader=None, fullname=None):
+
+def find_module_py33(string, path=None, loader=None, full_name=None):
loader = loader or importlib.machinery.PathFinder.find_module(string, path)
if loader is None and path is None: # Fallback to find builtins
@@ -74,7 +70,7 @@ def find_module_py33(string, path=None, loader=None, fullname=None):
raise ImportError("Originally " + repr(e))
if loader is None:
- raise ImportError("Couldn't find a loader for {0}".format(string))
+ raise ImportError("Couldn't find a loader for {}".format(string))
try:
is_package = loader.is_package(string)
@@ -109,7 +105,10 @@ def find_module_py33(string, path=None, loader=None, fullname=None):
return module_file, module_path, is_package
-def find_module_pre_py33(string, path=None, fullname=None):
+def find_module_pre_py33(string, path=None, full_name=None):
+ # This import is here, because in other places it will raise a
+ # DeprecationWarning.
+ import imp
try:
module_file, module_path, description = imp.find_module(string, path)
module_type = description[2]
@@ -127,14 +126,7 @@ def find_module_pre_py33(string, path=None, fullname=None):
if loader:
is_package = loader.is_package(string)
is_archive = hasattr(loader, 'archive')
- try:
- module_path = loader.get_filename(string)
- except AttributeError:
- # fallback for py26
- try:
- module_path = loader._get_filename(string)
- except AttributeError:
- continue
+ module_path = loader.get_filename(string)
if is_package:
module_path = os.path.dirname(module_path)
if is_archive:
@@ -142,14 +134,14 @@ def find_module_pre_py33(string, path=None, fullname=None):
file = None
if not is_package or is_archive:
file = DummyFile(loader, string)
- return (file, module_path, is_package)
+ return file, module_path, is_package
except ImportError:
pass
- raise ImportError("No module named {0}".format(string))
+ raise ImportError("No module named {}".format(string))
find_module = find_module_py33 if is_py33 else find_module_pre_py33
-find_module = find_module_py34 if is_py34 else find_module
+find_module = find_module_py34 if is_py34 else find_module
find_module.__doc__ = """
Provides information about a module.
@@ -161,12 +153,80 @@ def find_module_pre_py33(string, path=None, fullname=None):
"""
+def _iter_modules(paths, prefix=''):
+ # Copy of pkgutil.iter_modules adapted to work with namespaces
+
+ for path in paths:
+ importer = pkgutil.get_importer(path)
+
+ if not isinstance(importer, importlib.machinery.FileFinder):
+ # We're only modifying the case for FileFinder. All the other cases
+ # still need to be checked (like zip-importing). Do this by just
+ # calling the pkgutil version.
+ for mod_info in pkgutil.iter_modules([path], prefix):
+ yield mod_info
+ continue
+
+ # START COPY OF pkutils._iter_file_finder_modules.
+ if importer.path is None or not os.path.isdir(importer.path):
+ return
+
+ yielded = {}
+
+ try:
+ filenames = os.listdir(importer.path)
+ except OSError:
+ # ignore unreadable directories like import does
+ filenames = []
+ filenames.sort() # handle packages before same-named modules
+
+ for fn in filenames:
+ modname = inspect.getmodulename(fn)
+ if modname == '__init__' or modname in yielded:
+ continue
+
+ # jedi addition: Avoid traversing special directories
+ if fn.startswith('.') or fn == '__pycache__':
+ continue
+
+ path = os.path.join(importer.path, fn)
+ ispkg = False
+
+ if not modname and os.path.isdir(path) and '.' not in fn:
+ modname = fn
+ # A few jedi modifications: Don't check if there's an
+ # __init__.py
+ try:
+ os.listdir(path)
+ except OSError:
+ # ignore unreadable directories like import does
+ continue
+ ispkg = True
+
+ if modname and '.' not in modname:
+ yielded[modname] = 1
+ yield importer, prefix + modname, ispkg
+ # END COPY
+
+iter_modules = _iter_modules if py_version >= 34 else pkgutil.iter_modules
+
+
class ImplicitNSInfo(object):
"""Stores information returned from an implicit namespace spec"""
def __init__(self, name, paths):
self.name = name
self.paths = paths
+
+if is_py3:
+ all_suffixes = importlib.machinery.all_suffixes
+else:
+ def all_suffixes():
+ # Is deprecated and raises a warning in Python 3.6.
+ import imp
+ return [suffix for suffix, _, _ in imp.get_suffixes()]
+
+
# unicode function
try:
unicode = unicode
@@ -208,7 +268,7 @@ def use_metaclass(meta, *bases):
""" Create a class with a metaclass. """
if not bases:
bases = (object,)
- return meta("HackClass", bases, {})
+ return meta("Py2CompatibilityMetaClass", bases, {})
try:
@@ -219,19 +279,37 @@ def use_metaclass(meta, *bases):
encoding = 'ascii'
-def u(string):
+def u(string, errors='strict'):
"""Cast to unicode DAMMIT!
Written because Python2 repr always implicitly casts to a string, so we
have to cast back to a unicode (and we now that we always deal with valid
unicode, because we check that in the beginning).
"""
- if is_py3:
- return str(string)
-
- if not isinstance(string, unicode):
- return unicode(str(string), 'UTF-8')
+ if isinstance(string, bytes):
+ return unicode(string, encoding='UTF-8', errors=errors)
return string
+
+def cast_path(obj):
+ """
+ Take a bytes or str path and cast it to unicode.
+
+ Apparently it is perfectly fine to pass both byte and unicode objects into
+ the sys.path. This probably means that byte paths are normal at other
+ places as well.
+
+ Since this just really complicates everything and Python 2.7 will be EOL
+ soon anyway, just go with always strings.
+ """
+ return u(obj, errors='replace')
+
+
+def force_unicode(obj):
+ # Intentionally don't mix those two up, because those two code paths might
+ # be different in the future (maybe windows?).
+ return cast_path(obj)
+
+
try:
import builtins # module name in python 3
except ImportError:
@@ -242,11 +320,6 @@ def u(string):
def literal_eval(string):
- # py3.0, py3.1 and py32 don't support unicode literals. Support those, I
- # don't want to write two versions of the tokenizer.
- if is_py3 and sys.version_info.minor < 3:
- if re.match('[uU][\'"]', string):
- string = string[1:]
return ast.literal_eval(string)
@@ -260,6 +333,11 @@ def literal_eval(string):
except NameError:
FileNotFoundError = IOError
+try:
+ NotADirectoryError = NotADirectoryError
+except NameError:
+ NotADirectoryError = IOError
+
def no_unicode_pprint(dct):
"""
@@ -273,6 +351,13 @@ def no_unicode_pprint(dct):
print(re.sub("u'", "'", s))
+def print_to_stderr(*args):
+ if is_py3:
+ eval("print(*args, file=sys.stderr)")
+ else:
+ print >> sys.stderr, args
+
+
def utf8_repr(func):
"""
``__repr__`` methods in Python 2 don't allow unicode objects to be
@@ -289,3 +374,142 @@ def wrapper(self):
return func
else:
return wrapper
+
+
+if is_py3:
+ import queue
+else:
+ import Queue as queue
+
+
+import pickle
+if sys.version_info[:2] == (3, 3):
+ """
+ Monkeypatch the unpickler in Python 3.3. This is needed, because the
+ argument `encoding='bytes'` is not supported in 3.3, but badly needed to
+ communicate with Python 2.
+ """
+
+ class NewUnpickler(pickle._Unpickler):
+ dispatch = dict(pickle._Unpickler.dispatch)
+
+ def _decode_string(self, value):
+ # Used to allow strings from Python 2 to be decoded either as
+ # bytes or Unicode strings. This should be used only with the
+ # STRING, BINSTRING and SHORT_BINSTRING opcodes.
+ if self.encoding == "bytes":
+ return value
+ else:
+ return value.decode(self.encoding, self.errors)
+
+ def load_string(self):
+ data = self.readline()[:-1]
+ # Strip outermost quotes
+ if len(data) >= 2 and data[0] == data[-1] and data[0] in b'"\'':
+ data = data[1:-1]
+ else:
+ raise pickle.UnpicklingError("the STRING opcode argument must be quoted")
+ self.append(self._decode_string(pickle.codecs.escape_decode(data)[0]))
+ dispatch[pickle.STRING[0]] = load_string
+
+ def load_binstring(self):
+ # Deprecated BINSTRING uses signed 32-bit length
+ len, = pickle.struct.unpack('>> defs[0].type
+ >>> defs = [str(d.type) for d in defs] # It's unicode and in Py2 has u before it.
+ >>> defs[0]
'module'
- >>> defs[1].type
+ >>> defs[1]
'class'
- >>> defs[2].type
+ >>> defs[2]
'instance'
- >>> defs[3].type
+ >>> defs[3]
'function'
"""
@@ -159,7 +157,7 @@ def to_reverse():
except IndexError:
pass
- if name.api_type == 'module':
+ if name.api_type in 'module':
module_contexts = name.infer()
if module_contexts:
module_context, = module_contexts
@@ -259,7 +257,7 @@ def docstring(self, raw=False, fast=True):
@property
def description(self):
"""A textual description of the object."""
- return u(self._name.string_name)
+ return self._name.string_name
@property
def full_name(self):
@@ -324,9 +322,9 @@ def get_param_names(context):
param_names = param_names[1:]
elif isinstance(context, (instance.AbstractInstanceContext, ClassContext)):
if isinstance(context, ClassContext):
- search = '__init__'
+ search = u'__init__'
else:
- search = '__call__'
+ search = u'__call__'
names = context.get_function_slot_names(search)
if not names:
return []
@@ -377,8 +375,7 @@ def get_line_code(self, before=0, after=0):
if self.in_builtin_module():
return ''
- path = self._name.get_root_context().py__file__()
- lines = parser_cache[self._evaluator.grammar._hashed][path].lines
+ lines = self._name.get_root_context().code_lines
index = self._name.start_pos[0] - 1
start_index = max(index - before, 0)
@@ -406,7 +403,7 @@ def _complete(self, like_name):
and self.type == 'Function':
append = '('
- if isinstance(self._name, ParamName) and self._stack is not None:
+ if self._name.api_type == 'param' and self._stack is not None:
node_names = list(self._stack.get_node_names(self._evaluator.grammar._pgen_grammar))
if 'trailer' in node_names and 'argument' not in node_names:
append += '='
@@ -525,7 +522,7 @@ def description(self):
if typ == 'function':
# For the description we want a short and a pythonic way.
typ = 'def'
- return typ + ' ' + u(self._name.string_name)
+ return typ + ' ' + self._name.string_name
elif typ == 'param':
code = search_ancestor(tree_name, 'param').get_code(
include_prefix=False,
@@ -533,7 +530,6 @@ def description(self):
)
return typ + ' ' + code
-
definition = tree_name.get_definition() or tree_name
# Remove the prefix, because that's not what we want for get_code
# here.
@@ -555,7 +551,7 @@ def desc_with_module(self):
.. todo:: Add full path. This function is should return a
`module.class.function` path.
"""
- position = '' if self.in_builtin_module else '@%s' % (self.line)
+ position = '' if self.in_builtin_module else '@%s' % self.line
return "%s:%s%s" % (self.module_name, self.description, position)
@memoize_method
diff --git a/pythonFiles/jedi/api/completion.py b/pythonFiles/jedi/api/completion.py
index 559a4d3f8320..c88a031e4679 100644
--- a/pythonFiles/jedi/api/completion.py
+++ b/pythonFiles/jedi/api/completion.py
@@ -2,6 +2,7 @@
from parso.python import tree
from parso.tree import search_ancestor, Leaf
+from jedi._compatibility import Parameter
from jedi import debug
from jedi import settings
from jedi.api import classes
@@ -18,24 +19,21 @@ def get_call_signature_param_names(call_signatures):
for call_sig in call_signatures:
for p in call_sig.params:
# Allow protected access, because it's a public API.
- tree_name = p._name.tree_name
- # Compiled modules typically don't allow keyword arguments.
- if tree_name is not None:
- # Allow access on _definition here, because it's a
- # public API and we don't want to make the internal
- # Name object public.
- tree_param = tree.search_ancestor(tree_name, 'param')
- if tree_param.star_count == 0: # no *args/**kwargs
- yield p._name
+ if p._name.get_kind() in (Parameter.POSITIONAL_OR_KEYWORD,
+ Parameter.KEYWORD_ONLY):
+ yield p._name
def filter_names(evaluator, completion_names, stack, like_name):
comp_dct = {}
+ if settings.case_insensitive_completion:
+ like_name = like_name.lower()
for name in completion_names:
- if settings.case_insensitive_completion \
- and name.string_name.lower().startswith(like_name.lower()) \
- or name.string_name.startswith(like_name):
+ string = name.string_name
+ if settings.case_insensitive_completion:
+ string = string.lower()
+ if string.startswith(like_name):
new = classes.Completion(
evaluator,
name,
@@ -208,7 +206,7 @@ def _get_context_completions(self):
def _get_keyword_completion_names(self, keywords_):
for k in keywords_:
- yield keywords.keyword(self._evaluator, k).name
+ yield keywords.KeywordName(self._evaluator, k)
def _global_completions(self):
context = get_user_scope(self._module_context, self._position)
diff --git a/pythonFiles/jedi/api/environment.py b/pythonFiles/jedi/api/environment.py
new file mode 100644
index 000000000000..51b390f36ab4
--- /dev/null
+++ b/pythonFiles/jedi/api/environment.py
@@ -0,0 +1,393 @@
+"""
+Environments are a way to activate different Python versions or Virtualenvs for
+static analysis. The Python binary in that environment is going to be executed.
+"""
+import os
+import re
+import sys
+import hashlib
+import filecmp
+from subprocess import PIPE
+from collections import namedtuple
+# When dropping Python 2.7 support we should consider switching to
+# `shutil.which`.
+from distutils.spawn import find_executable
+
+from jedi._compatibility import GeneralizedPopen
+from jedi.cache import memoize_method, time_cache
+from jedi.evaluate.compiled.subprocess import get_subprocess, \
+ EvaluatorSameProcess, EvaluatorSubprocess
+
+import parso
+
+_VersionInfo = namedtuple('VersionInfo', 'major minor micro')
+
+_SUPPORTED_PYTHONS = ['3.6', '3.5', '3.4', '3.3', '2.7']
+_SAFE_PATHS = ['/usr/bin', '/usr/local/bin']
+_CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor)
+
+
+class InvalidPythonEnvironment(Exception):
+ """
+ If you see this exception, the Python executable or Virtualenv you have
+ been trying to use is probably not a correct Python version.
+ """
+
+
+class _BaseEnvironment(object):
+ @memoize_method
+ def get_grammar(self):
+ version_string = '%s.%s' % (self.version_info.major, self.version_info.minor)
+ return parso.load_grammar(version=version_string)
+
+ @property
+ def _sha256(self):
+ try:
+ return self._hash
+ except AttributeError:
+ self._hash = _calculate_sha256_for_file(self.executable)
+ return self._hash
+
+
+class Environment(_BaseEnvironment):
+ """
+ This class is supposed to be created by internal Jedi architecture. You
+ should not create it directly. Please use create_environment or the other
+ functions instead. It is then returned by that function.
+ """
+ def __init__(self, path, executable):
+ self.path = os.path.abspath(path)
+ """
+ The path to an environment, matches ``sys.prefix``.
+ """
+ self.executable = os.path.abspath(executable)
+ """
+ The Python executable, matches ``sys.executable``.
+ """
+ self.version_info = self._get_version()
+ """
+
+ Like ``sys.version_info``. A tuple to show the current Environment's
+ Python version.
+ """
+
+ def _get_version(self):
+ try:
+ process = GeneralizedPopen([self.executable, '--version'], stdout=PIPE, stderr=PIPE)
+ stdout, stderr = process.communicate()
+ retcode = process.poll()
+ if retcode:
+ raise InvalidPythonEnvironment()
+ except OSError:
+ raise InvalidPythonEnvironment()
+
+ # Until Python 3.4 wthe version string is part of stderr, after that
+ # stdout.
+ output = stdout + stderr
+ match = re.match(br'Python (\d+)\.(\d+)\.(\d+)', output)
+ if match is None:
+ raise InvalidPythonEnvironment("--version not working")
+
+ return _VersionInfo(*[int(m) for m in match.groups()])
+
+ def __repr__(self):
+ version = '.'.join(str(i) for i in self.version_info)
+ return '<%s: %s in %s>' % (self.__class__.__name__, version, self.path)
+
+ def get_evaluator_subprocess(self, evaluator):
+ return EvaluatorSubprocess(evaluator, self._get_subprocess())
+
+ def _get_subprocess(self):
+ return get_subprocess(self.executable)
+
+ @memoize_method
+ def get_sys_path(self):
+ """
+ The sys path for this environment. Does not include potential
+ modifications like ``sys.path.append``.
+
+ :returns: list of str
+ """
+ # It's pretty much impossible to generate the sys path without actually
+ # executing Python. The sys path (when starting with -S) itself depends
+ # on how the Python version was compiled (ENV variables).
+ # If you omit -S when starting Python (normal case), additionally
+ # site.py gets executed.
+ return self._get_subprocess().get_sys_path()
+
+
+class SameEnvironment(Environment):
+ def __init__(self):
+ super(SameEnvironment, self).__init__(sys.prefix, sys.executable)
+
+ def _get_version(self):
+ return _VersionInfo(*sys.version_info[:3])
+
+
+class InterpreterEnvironment(_BaseEnvironment):
+ def __init__(self):
+ self.version_info = _VersionInfo(*sys.version_info[:3])
+
+ def get_evaluator_subprocess(self, evaluator):
+ return EvaluatorSameProcess(evaluator)
+
+ def get_sys_path(self):
+ return sys.path
+
+
+def _get_virtual_env_from_var():
+ var = os.environ.get('VIRTUAL_ENV')
+ if var is not None:
+ if var == sys.prefix:
+ return SameEnvironment()
+
+ try:
+ return create_environment(var)
+ except InvalidPythonEnvironment:
+ pass
+
+
+def _calculate_sha256_for_file(path):
+ sha256 = hashlib.sha256()
+ with open(path, 'rb') as f:
+ for block in iter(lambda: f.read(filecmp.BUFSIZE), b''):
+ sha256.update(block)
+ return sha256.hexdigest()
+
+
+def get_default_environment():
+ """
+ Tries to return an active Virtualenv. If there is no VIRTUAL_ENV variable
+ set it will return the latest Python version installed on the system. This
+ makes it possible to use as many new Python features as possible when using
+ autocompletion and other functionality.
+
+ :returns: :class:`Environment`
+ """
+ virtual_env = _get_virtual_env_from_var()
+ if virtual_env is not None:
+ return virtual_env
+
+ for environment in find_system_environments():
+ return environment
+
+ # If no Python Environment is found, use the environment we're already
+ # using.
+ return SameEnvironment()
+
+
+@time_cache(seconds=10 * 60) # 10 Minutes
+def get_cached_default_environment():
+ return get_default_environment()
+
+
+def find_virtualenvs(paths=None, **kwargs):
+ """
+ :param paths: A list of paths in your file system to be scanned for
+ Virtualenvs. It will search in these paths and potentially execute the
+ Python binaries. Also the VIRTUAL_ENV variable will be checked if it
+ contains a valid Virtualenv.
+ :param safe: Default True. In case this is False, it will allow this
+ function to execute potential `python` environments. An attacker might
+ be able to drop an executable in a path this function is searching by
+ default. If the executable has not been installed by root, it will not
+ be executed.
+
+ :yields: :class:`Environment`
+ """
+ def py27_comp(paths=None, safe=True):
+ if paths is None:
+ paths = []
+
+ _used_paths = set()
+
+ # Using this variable should be safe, because attackers might be able
+ # to drop files (via git) but not environment variables.
+ virtual_env = _get_virtual_env_from_var()
+ if virtual_env is not None:
+ yield virtual_env
+ _used_paths.add(virtual_env.path)
+
+ for directory in paths:
+ if not os.path.isdir(directory):
+ continue
+
+ directory = os.path.abspath(directory)
+ for path in os.listdir(directory):
+ path = os.path.join(directory, path)
+ if path in _used_paths:
+ # A path shouldn't be evaluated twice.
+ continue
+ _used_paths.add(path)
+
+ try:
+ executable = _get_executable_path(path, safe=safe)
+ yield Environment(path, executable)
+ except InvalidPythonEnvironment:
+ pass
+
+ return py27_comp(paths, **kwargs)
+
+
+def find_system_environments():
+ """
+ Ignores virtualenvs and returns the Python versions that were installed on
+ your system. This might return nothing, if you're running Python e.g. from
+ a portable version.
+
+ The environments are sorted from latest to oldest Python version.
+
+ :yields: :class:`Environment`
+ """
+ for version_string in _SUPPORTED_PYTHONS:
+ try:
+ yield get_system_environment(version_string)
+ except InvalidPythonEnvironment:
+ pass
+
+
+# TODO: the logic to find the Python prefix is much more complicated than that.
+# See Modules/getpath.c for UNIX and PC/getpathp.c for Windows in CPython's
+# source code. A solution would be to deduce it by running the Python
+# interpreter and printing the value of sys.prefix.
+def _get_python_prefix(executable):
+ if os.name != 'nt':
+ return os.path.dirname(os.path.dirname(executable))
+ landmark = os.path.join('Lib', 'os.py')
+ prefix = os.path.dirname(executable)
+ while prefix:
+ if os.path.join(prefix, landmark):
+ return prefix
+ prefix = os.path.dirname(prefix)
+ raise InvalidPythonEnvironment(
+ "Cannot find prefix of executable %s." % executable)
+
+
+# TODO: this function should probably return a list of environments since
+# multiple Python installations can be found on a system for the same version.
+def get_system_environment(version):
+ """
+ Return the first Python environment found for a string of the form 'X.Y'
+ where X and Y are the major and minor versions of Python.
+
+ :raises: :exc:`.InvalidPythonEnvironment`
+ :returns: :class:`Environment`
+ """
+ exe = find_executable('python' + version)
+ if exe:
+ if exe == sys.executable:
+ return SameEnvironment()
+ return Environment(_get_python_prefix(exe), exe)
+
+ if os.name == 'nt':
+ for prefix, exe in _get_executables_from_windows_registry(version):
+ return Environment(prefix, exe)
+ raise InvalidPythonEnvironment("Cannot find executable python%s." % version)
+
+
+def create_environment(path, safe=True):
+ """
+ Make it possible to create an environment by hand.
+
+ :raises: :exc:`.InvalidPythonEnvironment`
+ :returns: :class:`Environment`
+ """
+ return Environment(path, _get_executable_path(path, safe=safe))
+
+
+def _get_executable_path(path, safe=True):
+ """
+ Returns None if it's not actually a virtual env.
+ """
+
+ if os.name == 'nt':
+ python = os.path.join(path, 'Scripts', 'python.exe')
+ else:
+ python = os.path.join(path, 'bin', 'python')
+ if not os.path.exists(python):
+ raise InvalidPythonEnvironment("%s seems to be missing." % python)
+
+ if safe and not _is_safe(python):
+ raise InvalidPythonEnvironment("The python binary is potentially unsafe.")
+ return python
+
+
+def _get_executables_from_windows_registry(version):
+ # The winreg module is named _winreg on Python 2.
+ try:
+ import winreg
+ except ImportError:
+ import _winreg as winreg
+
+ # TODO: support Python Anaconda.
+ sub_keys = [
+ r'SOFTWARE\Python\PythonCore\{version}\InstallPath',
+ r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}\InstallPath',
+ r'SOFTWARE\Python\PythonCore\{version}-32\InstallPath',
+ r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}-32\InstallPath'
+ ]
+ for root_key in [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]:
+ for sub_key in sub_keys:
+ sub_key = sub_key.format(version=version)
+ try:
+ with winreg.OpenKey(root_key, sub_key) as key:
+ prefix = winreg.QueryValueEx(key, '')[0]
+ exe = os.path.join(prefix, 'python.exe')
+ if os.path.isfile(exe):
+ yield prefix, exe
+ except WindowsError:
+ pass
+
+
+def _is_safe(executable_path):
+ # Resolve sym links. A venv typically is a symlink to a known Python
+ # binary. Only virtualenvs copy symlinks around.
+ real_path = os.path.realpath(executable_path)
+
+ if _is_unix_safe_simple(real_path):
+ return True
+
+ # Just check the list of known Python versions. If it's not in there,
+ # it's likely an attacker or some Python that was not properly
+ # installed in the system.
+ for environment in find_system_environments():
+ if environment.executable == real_path:
+ return True
+
+ # If the versions don't match, just compare the binary files. If we
+ # don't do that, only venvs will be working and not virtualenvs.
+ # venvs are symlinks while virtualenvs are actual copies of the
+ # Python files.
+ # This still means that if the system Python is updated and the
+ # virtualenv's Python is not (which is probably never going to get
+ # upgraded), it will not work with Jedi. IMO that's fine, because
+ # people should just be using venv. ~ dave
+ if environment._sha256 == _calculate_sha256_for_file(real_path):
+ return True
+ return False
+
+
+def _is_unix_safe_simple(real_path):
+ if _is_unix_admin():
+ # In case we are root, just be conservative and
+ # only execute known paths.
+ return any(real_path.startswith(p) for p in _SAFE_PATHS)
+
+ uid = os.stat(real_path).st_uid
+ # The interpreter needs to be owned by root. This means that it wasn't
+ # written by a user and therefore attacking Jedi is not as simple.
+ # The attack could look like the following:
+ # 1. A user clones a repository.
+ # 2. The repository has an innocent looking folder called foobar. jedi
+ # searches for the folder and executes foobar/bin/python --version if
+ # there's also a foobar/bin/activate.
+ # 3. The bin/python is obviously not a python script but a bash script or
+ # whatever the attacker wants.
+ return uid == 0
+
+
+def _is_unix_admin():
+ try:
+ return os.getuid() == 0
+ except AttributeError:
+ return False # Windows
diff --git a/pythonFiles/jedi/api/exceptions.py b/pythonFiles/jedi/api/exceptions.py
new file mode 100644
index 000000000000..99cebdb7ddb5
--- /dev/null
+++ b/pythonFiles/jedi/api/exceptions.py
@@ -0,0 +1,10 @@
+class _JediError(Exception):
+ pass
+
+
+class InternalError(_JediError):
+ pass
+
+
+class WrongVersion(_JediError):
+ pass
diff --git a/pythonFiles/jedi/api/helpers.py b/pythonFiles/jedi/api/helpers.py
index 2c4d8e0d10fc..221fc4dfe0d4 100644
--- a/pythonFiles/jedi/api/helpers.py
+++ b/pythonFiles/jedi/api/helpers.py
@@ -7,12 +7,13 @@
from parso.python.parser import Parser
from parso.python import tree
-from parso import split_lines
from jedi._compatibility import u
from jedi.evaluate.syntax_tree import eval_atom
from jedi.evaluate.helpers import evaluate_call_of_leaf
-from jedi.cache import time_cache
+from jedi.evaluate.compiled import get_string_context_set
+from jedi.evaluate.base_context import ContextSet
+from jedi.cache import call_signature_time_cache
CompletionParts = namedtuple('CompletionParts', ['path', 'has_dot', 'name'])
@@ -44,7 +45,7 @@ def _get_code(code_lines, start_pos, end_pos):
lines[-1] = lines[-1][:end_pos[1]]
# Remove first line indentation.
lines[0] = lines[0][start_pos[1]:]
- return '\n'.join(lines)
+ return ''.join(lines)
class OnErrorLeaf(Exception):
@@ -53,28 +54,11 @@ def error_leaf(self):
return self.args[0]
-def _is_on_comment(leaf, position):
- comment_lines = split_lines(leaf.prefix)
- difference = leaf.start_pos[0] - position[0]
- prefix_start_pos = leaf.get_start_pos_of_prefix()
- if difference == 0:
- indent = leaf.start_pos[1]
- elif position[0] == prefix_start_pos[0]:
- indent = prefix_start_pos[1]
- else:
- indent = 0
- line = comment_lines[-difference - 1][:position[1] - indent]
- return '#' in line
-
-
def _get_code_for_stack(code_lines, module_node, position):
leaf = module_node.get_leaf_for_position(position, include_prefixes=True)
# It might happen that we're on whitespace or on a comment. This means
# that we would not get the right leaf.
if leaf.start_pos >= position:
- if _is_on_comment(leaf, position):
- return u('')
-
# If we're not on a comment simply get the previous leaf and proceed.
leaf = leaf.get_previous_leaf()
if leaf is None:
@@ -125,6 +109,9 @@ def tokenize_without_endmarker(code):
for token_ in tokens:
if token_.string == safeword:
raise EndMarkerReached()
+ elif token_.prefix.endswith(safeword):
+ # This happens with comments.
+ raise EndMarkerReached()
else:
yield token_
@@ -134,7 +121,7 @@ def tokenize_without_endmarker(code):
# completion.
# Use Z as a prefix because it's not part of a number suffix.
safeword = 'ZZZ_USER_WANTS_TO_COMPLETE_HERE_WITH_JEDI'
- code = code + safeword
+ code = code + ' ' + safeword
p = Parser(grammar._pgen_grammar, error_recovery=True)
try:
@@ -208,6 +195,8 @@ def evaluate_goto_definition(evaluator, context, leaf):
return evaluate_call_of_leaf(context, leaf)
elif isinstance(leaf, tree.Literal):
return eval_atom(context, leaf)
+ elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'):
+ return get_string_context_set(evaluator)
return []
@@ -294,14 +283,14 @@ def get_call_signature_details(module, position):
return None
-@time_cache("call_signatures_validity")
+@call_signature_time_cache("call_signatures_validity")
def cache_call_signatures(evaluator, context, bracket_leaf, code_lines, user_pos):
"""This function calculates the cache key."""
- index = user_pos[0] - 1
+ line_index = user_pos[0] - 1
- before_cursor = code_lines[index][:user_pos[1]]
- other_lines = code_lines[bracket_leaf.start_pos[0]:index]
- whole = '\n'.join(other_lines + [before_cursor])
+ before_cursor = code_lines[line_index][:user_pos[1]]
+ other_lines = code_lines[bracket_leaf.start_pos[0]:line_index]
+ whole = ''.join(other_lines + [before_cursor])
before_bracket = re.match(r'.*\(', whole, re.DOTALL)
module_path = context.get_root_context().py__file__()
diff --git a/pythonFiles/jedi/api/interpreter.py b/pythonFiles/jedi/api/interpreter.py
index 202f345e94b9..c9b7bd69bbe0 100644
--- a/pythonFiles/jedi/api/interpreter.py
+++ b/pythonFiles/jedi/api/interpreter.py
@@ -5,24 +5,34 @@
from jedi.evaluate.context import ModuleContext
from jedi.evaluate import compiled
from jedi.evaluate.compiled import mixed
+from jedi.evaluate.compiled.access import create_access_path
from jedi.evaluate.base_context import Context
+def _create(evaluator, obj):
+ return compiled.create_from_access_path(
+ evaluator, create_access_path(evaluator, obj)
+ )
+
+
class NamespaceObject(object):
def __init__(self, dct):
self.__dict__ = dct
class MixedModuleContext(Context):
- resets_positions = True
type = 'mixed_module'
- def __init__(self, evaluator, tree_module, namespaces, path):
+ def __init__(self, evaluator, tree_module, namespaces, path, code_lines):
self.evaluator = evaluator
self._namespaces = namespaces
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
- self._module_context = ModuleContext(evaluator, tree_module, path=path)
+ self._module_context = ModuleContext(
+ evaluator, tree_module,
+ path=path,
+ code_lines=code_lines
+ )
self.tree_node = tree_module
def get_node(self):
@@ -33,7 +43,7 @@ def get_filters(self, *args, **kwargs):
yield filter
for namespace_obj in self._namespace_objects:
- compiled_object = compiled.create(self.evaluator, namespace_obj)
+ compiled_object = _create(self.evaluator, namespace_obj)
mixed_object = mixed.MixedObject(
self.evaluator,
parent_context=self,
@@ -43,5 +53,9 @@ def get_filters(self, *args, **kwargs):
for filter in mixed_object.get_filters(*args, **kwargs):
yield filter
+ @property
+ def code_lines(self):
+ return self._module_context.code_lines
+
def __getattr__(self, name):
return getattr(self._module_context, name)
diff --git a/pythonFiles/jedi/api/keywords.py b/pythonFiles/jedi/api/keywords.py
index a1bc4e7f8556..2991a0f81a56 100644
--- a/pythonFiles/jedi/api/keywords.py
+++ b/pythonFiles/jedi/api/keywords.py
@@ -1,10 +1,7 @@
import pydoc
-import keyword
-from jedi._compatibility import is_py3, is_py35
from jedi.evaluate.utils import ignored
from jedi.evaluate.filters import AbstractNameDefinition
-from parso.python.tree import Leaf
try:
from pydoc_data import topics as pydoc_topics
@@ -17,87 +14,30 @@
# pydoc_data module in its file python3x.zip.
pydoc_topics = None
-if is_py3:
- if is_py35:
- # in python 3.5 async and await are not proper keywords, but for
- # completion pursposes should as as though they are
- keys = keyword.kwlist + ["async", "await"]
- else:
- keys = keyword.kwlist
-else:
- keys = keyword.kwlist + ['None', 'False', 'True']
-
-
-def has_inappropriate_leaf_keyword(pos, module):
- relevant_errors = filter(
- lambda error: error.first_pos[0] == pos[0],
- module.error_statement_stacks)
-
- for error in relevant_errors:
- if error.next_token in keys:
- return True
-
- return False
-
-
-def completion_names(evaluator, stmt, pos, module):
- keyword_list = all_keywords(evaluator)
-
- if not isinstance(stmt, Leaf) or has_inappropriate_leaf_keyword(pos, module):
- keyword_list = filter(
- lambda keyword: not keyword.only_valid_as_leaf,
- keyword_list
- )
- return [keyword.name for keyword in keyword_list]
-
-
-def all_keywords(evaluator, pos=(0, 0)):
- return set([Keyword(evaluator, k, pos) for k in keys])
-
-
-def keyword(evaluator, string, pos=(0, 0)):
- if string in keys:
- return Keyword(evaluator, string, pos)
- else:
- return None
-
def get_operator(evaluator, string, pos):
return Keyword(evaluator, string, pos)
-keywords_only_valid_as_leaf = (
- 'continue',
- 'break',
-)
-
-
class KeywordName(AbstractNameDefinition):
- api_type = 'keyword'
+ api_type = u'keyword'
def __init__(self, evaluator, name):
self.evaluator = evaluator
self.string_name = name
- self.parent_context = evaluator.BUILTINS
-
- def eval(self):
- return set()
+ self.parent_context = evaluator.builtins_module
def infer(self):
return [Keyword(self.evaluator, self.string_name, (0, 0))]
class Keyword(object):
- api_type = 'keyword'
+ api_type = u'keyword'
def __init__(self, evaluator, name, pos):
self.name = KeywordName(evaluator, name)
self.start_pos = pos
- self.parent = evaluator.BUILTINS
-
- @property
- def only_valid_as_leaf(self):
- return self.name.value in keywords_only_valid_as_leaf
+ self.parent = evaluator.builtins_module
@property
def names(self):
diff --git a/pythonFiles/jedi/api/project.py b/pythonFiles/jedi/api/project.py
new file mode 100644
index 000000000000..ca6992b5db7f
--- /dev/null
+++ b/pythonFiles/jedi/api/project.py
@@ -0,0 +1,200 @@
+import os
+import json
+
+from jedi._compatibility import FileNotFoundError, NotADirectoryError
+from jedi.api.environment import SameEnvironment, \
+ get_cached_default_environment
+from jedi.api.exceptions import WrongVersion
+from jedi._compatibility import force_unicode
+from jedi.evaluate.sys_path import discover_buildout_paths
+from jedi.evaluate.cache import evaluator_as_method_param_cache
+from jedi.common.utils import traverse_parents
+
+_CONFIG_FOLDER = '.jedi'
+_CONTAINS_POTENTIAL_PROJECT = 'setup.py', '.git', '.hg', 'requirements.txt', 'MANIFEST.in'
+
+_SERIALIZER_VERSION = 1
+
+
+def _remove_duplicates_from_path(path):
+ used = set()
+ for p in path:
+ if p in used:
+ continue
+ used.add(p)
+ yield p
+
+
+def _force_unicode_list(lst):
+ return list(map(force_unicode, lst))
+
+
+class Project(object):
+ # TODO serialize environment
+ _serializer_ignore_attributes = ('_environment',)
+ _environment = None
+
+ @staticmethod
+ def _get_json_path(base_path):
+ return os.path.join(base_path, _CONFIG_FOLDER, 'project.json')
+
+ @classmethod
+ def load(cls, path):
+ """
+ :param path: The path of the directory you want to use as a project.
+ """
+ with open(cls._get_json_path(path)) as f:
+ version, data = json.load(f)
+
+ if version == 1:
+ self = cls.__new__()
+ self.__dict__.update(data)
+ return self
+ else:
+ raise WrongVersion(
+ "The Jedi version of this project seems newer than what we can handle."
+ )
+
+ def __init__(self, path, **kwargs):
+ """
+ :param path: The base path for this project.
+ :param sys_path: list of str. You can override the sys path if you
+ want. By default the ``sys.path.`` is generated from the
+ environment (virtualenvs, etc).
+ :param smart_sys_path: If this is enabled (default), adds paths from
+ local directories. Otherwise you will have to rely on your packages
+ being properly configured on the ``sys.path``.
+ """
+ def py2_comp(path, environment=None, sys_path=None,
+ smart_sys_path=True, _django=False):
+ self._path = path
+ if isinstance(environment, SameEnvironment):
+ self._environment = environment
+
+ self._sys_path = sys_path
+ self._smart_sys_path = smart_sys_path
+ self._django = _django
+
+ py2_comp(path, **kwargs)
+
+ def _get_base_sys_path(self, environment=None):
+ if self._sys_path is not None:
+ return self._sys_path
+
+ # The sys path has not been set explicitly.
+ if environment is None:
+ environment = self.get_environment()
+
+ sys_path = environment.get_sys_path()
+ try:
+ sys_path.remove('')
+ except ValueError:
+ pass
+ return sys_path
+
+ @evaluator_as_method_param_cache()
+ def _get_sys_path(self, evaluator, environment=None):
+ """
+ Keep this method private for all users of jedi. However internally this
+ one is used like a public method.
+ """
+ suffixed = []
+ prefixed = []
+
+ sys_path = list(self._get_base_sys_path(environment))
+ if self._smart_sys_path:
+ prefixed.append(self._path)
+
+ if evaluator.script_path is not None:
+ suffixed += discover_buildout_paths(evaluator, evaluator.script_path)
+
+ traversed = []
+ for parent in traverse_parents(evaluator.script_path):
+ traversed.append(parent)
+ if parent == self._path:
+ # Don't go futher than the project path.
+ break
+
+ # AFAIK some libraries have imports like `foo.foo.bar`, which
+ # leads to the conclusion to by default prefer longer paths
+ # rather than shorter ones by default.
+ suffixed += reversed(traversed)
+
+ if self._django:
+ prefixed.append(self._path)
+
+ path = prefixed + sys_path + suffixed
+ return list(_force_unicode_list(_remove_duplicates_from_path(path)))
+
+ def save(self):
+ data = dict(self.__dict__)
+ for attribute in self._serializer_ignore_attributes:
+ data.pop(attribute, None)
+
+ with open(self._get_json_path(self._path), 'wb') as f:
+ return json.dump((_SERIALIZER_VERSION, data), f)
+
+ def get_environment(self):
+ if self._environment is None:
+ return get_cached_default_environment()
+
+ return self._environment
+
+ def __repr__(self):
+ return '<%s: %s>' % (self.__class__.__name__, self._path)
+
+
+def _is_potential_project(path):
+ for name in _CONTAINS_POTENTIAL_PROJECT:
+ if os.path.exists(os.path.join(path, name)):
+ return True
+ return False
+
+
+def _is_django_path(directory):
+ """ Detects the path of the very well known Django library (if used) """
+ try:
+ with open(os.path.join(directory, 'manage.py'), 'rb') as f:
+ return b"DJANGO_SETTINGS_MODULE" in f.read()
+ except (FileNotFoundError, NotADirectoryError):
+ return False
+
+ return False
+
+
+def get_default_project(path=None):
+ if path is None:
+ path = os.getcwd()
+
+ check = os.path.realpath(path)
+ probable_path = None
+ first_no_init_file = None
+ for dir in traverse_parents(check, include_current=True):
+ try:
+ return Project.load(dir)
+ except (FileNotFoundError, NotADirectoryError):
+ pass
+
+ if first_no_init_file is None:
+ if os.path.exists(os.path.join(dir, '__init__.py')):
+ # In the case that a __init__.py exists, it's in 99% just a
+ # Python package and the project sits at least one level above.
+ continue
+ else:
+ first_no_init_file = dir
+
+ if _is_django_path(dir):
+ return Project(dir, _django=True)
+
+ if probable_path is None and _is_potential_project(dir):
+ probable_path = dir
+
+ if probable_path is not None:
+ # TODO search for setup.py etc
+ return Project(probable_path)
+
+ if first_no_init_file is not None:
+ return Project(first_no_init_file)
+
+ curdir = path if os.path.isdir(path) else os.path.dirname(path)
+ return Project(curdir)
diff --git a/pythonFiles/jedi/api/replstartup.py b/pythonFiles/jedi/api/replstartup.py
index 5bfcc8ce889e..4c44a626b775 100644
--- a/pythonFiles/jedi/api/replstartup.py
+++ b/pythonFiles/jedi/api/replstartup.py
@@ -11,8 +11,8 @@
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
- >>> os.path.join().split().in # doctest: +SKIP
- os.path.join().split().index os.path.join().split().insert
+ >>> os.path.join('a', 'b').split().in # doctest: +SKIP
+ ..dex ..sert
"""
import jedi.utils
diff --git a/pythonFiles/jedi/cache.py b/pythonFiles/jedi/cache.py
index 01138e75a99b..6c0c2a830942 100644
--- a/pythonFiles/jedi/cache.py
+++ b/pythonFiles/jedi/cache.py
@@ -12,6 +12,7 @@
these variables are being cleaned after every API usage.
"""
import time
+from functools import wraps
from jedi import settings
from parso.cache import parser_cache
@@ -74,7 +75,7 @@ def clear_time_caches(delete_all=False):
del tc[key]
-def time_cache(time_add_setting):
+def call_signature_time_cache(time_add_setting):
"""
This decorator works as follows: Call it with a setting and after that
use the function with a callable that returns the key.
@@ -106,8 +107,31 @@ def wrapper(*args, **kwargs):
return _temp
+def time_cache(seconds):
+ def decorator(func):
+ cache = {}
+
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ key = (args, frozenset(kwargs.items()))
+ try:
+ created, result = cache[key]
+ if time.time() < created + seconds:
+ return result
+ except KeyError:
+ pass
+ result = func(*args, **kwargs)
+ cache[key] = time.time(), result
+ return result
+
+ wrapper.clear_cache = lambda: cache.clear()
+ return wrapper
+ return decorator
+
+
def memoize_method(method):
"""A normal memoize function."""
+ @wraps(method)
def wrapper(self, *args, **kwargs):
cache_dict = self.__dict__.setdefault('_memoize_method_dct', {})
dct = cache_dict.setdefault(method, {})
diff --git a/pythonFiles/jedi/common/utils.py b/pythonFiles/jedi/common/utils.py
new file mode 100644
index 000000000000..72726a4696e6
--- /dev/null
+++ b/pythonFiles/jedi/common/utils.py
@@ -0,0 +1,12 @@
+import os
+
+
+def traverse_parents(path, include_current=False):
+ if not include_current:
+ path = os.path.dirname(path)
+
+ previous = None
+ while previous != path:
+ yield path
+ previous = path
+ path = os.path.dirname(path)
diff --git a/pythonFiles/jedi/debug.py b/pythonFiles/jedi/debug.py
index 8caf1accb17f..a4fd86465bac 100644
--- a/pythonFiles/jedi/debug.py
+++ b/pythonFiles/jedi/debug.py
@@ -35,7 +35,7 @@ def _lazy_colorama_init():
# need this.
initialise.atexit_done = True
try:
- init()
+ init(strip=False)
except Exception:
# Colorama fails with initializing under vim and is buggy in
# version 0.3.6.
diff --git a/pythonFiles/jedi/evaluate/__init__.py b/pythonFiles/jedi/evaluate/__init__.py
index 20461071abdb..3ba52b89f408 100644
--- a/pythonFiles/jedi/evaluate/__init__.py
+++ b/pythonFiles/jedi/evaluate/__init__.py
@@ -17,7 +17,8 @@
``eval_expr_stmt``. There's separate logic for autocompletion in the API, the
evaluator is all about evaluating an expression.
-TODO this paragraph is not what jedi does anymore.
+TODO this paragraph is not what jedi does anymore, it's similar, but not the
+same.
Now you need to understand what follows after ``eval_expr_stmt``. Let's
make an example::
@@ -62,10 +63,9 @@
that are not used are just being ignored.
"""
-import sys
-
from parso.python import tree
import parso
+from parso import python_bytes_to_unicode
from jedi import debug
from jedi import parser_utils
@@ -86,31 +86,42 @@
class Evaluator(object):
- def __init__(self, grammar, project):
- self.grammar = grammar
+ def __init__(self, project, environment=None, script_path=None):
+ if environment is None:
+ environment = project.get_environment()
+ self.environment = environment
+ self.script_path = script_path
+ self.compiled_subprocess = environment.get_evaluator_subprocess(self)
+ self.grammar = environment.get_grammar()
+
self.latest_grammar = parso.load_grammar(version='3.6')
self.memoize_cache = {} # for memoize decorators
- # To memorize modules -> equals `sys.modules`.
- self.modules = {} # like `sys.modules`.
+ self.module_cache = imports.ModuleCache() # does the job of `sys.modules`.
self.compiled_cache = {} # see `evaluate.compiled.create()`
self.inferred_element_counts = {}
self.mixed_cache = {} # see `evaluate.compiled.mixed._create()`
self.analysis = []
self.dynamic_params_depth = 0
self.is_analysis = False
- self.python_version = sys.version_info[:2]
self.project = project
- project.add_evaluator(self)
+ self.access_cache = {}
self.reset_recursion_limitations()
+ self.allow_different_encoding = True
- # Constants
- self.BUILTINS = compiled.get_special_object(self, 'BUILTINS')
+ @property
+ @evaluator_function_cache()
+ def builtins_module(self):
+ return compiled.get_special_object(self, u'BUILTINS')
def reset_recursion_limitations(self):
self.recursion_detector = recursion.RecursionDetector()
self.execution_recursion_detector = recursion.ExecutionRecursionDetector(self)
+ def get_sys_path(self):
+ """Convenience function"""
+ return self.project._get_sys_path(self, environment=self.environment)
+
def eval_element(self, context, element):
if isinstance(context, CompForContext):
return eval_node(context, element)
@@ -124,7 +135,11 @@ def eval_element(self, context, element):
if_stmt = None
break
predefined_if_name_dict = context.predefined_names.get(if_stmt)
- if predefined_if_name_dict is None and if_stmt and if_stmt.type == 'if_stmt':
+ # TODO there's a lot of issues with this one. We actually should do
+ # this in a different way. Caching should only be active in certain
+ # cases and this all sucks.
+ if predefined_if_name_dict is None and if_stmt \
+ and if_stmt.type == 'if_stmt' and self.is_analysis:
if_stmt_test = if_stmt.children[1]
name_dicts = [{}]
# If we already did a check, we don't want to do it again -> If
@@ -357,3 +372,15 @@ def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True, node_is_o
node = node.parent
scope_node = parent_scope(node)
return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object)
+
+ def parse_and_get_code(self, code=None, path=None, **kwargs):
+ if self.allow_different_encoding:
+ if code is None:
+ with open(path, 'rb') as f:
+ code = f.read()
+ code = python_bytes_to_unicode(code, errors='replace')
+
+ return self.grammar.parse(code=code, path=path, **kwargs), code
+
+ def parse(self, *args, **kwargs):
+ return self.parse_and_get_code(*args, **kwargs)[0]
diff --git a/pythonFiles/jedi/evaluate/analysis.py b/pythonFiles/jedi/evaluate/analysis.py
index c825e5fef9e9..ded4e9f20880 100644
--- a/pythonFiles/jedi/evaluate/analysis.py
+++ b/pythonFiles/jedi/evaluate/analysis.py
@@ -1,9 +1,12 @@
"""
Module for statical analysis.
"""
-from jedi import debug
from parso.python import tree
+
+from jedi._compatibility import force_unicode
+from jedi import debug
from jedi.evaluate.compiled import CompiledObject
+from jedi.evaluate.helpers import is_string
CODES = {
@@ -114,9 +117,10 @@ def add_attribute_error(name_context, lookup_context, name):
# instead of an error, if that happens.
typ = Error
if isinstance(lookup_context, AbstractInstanceContext):
- slot_names = lookup_context.get_function_slot_names('__getattr__') + \
- lookup_context.get_function_slot_names('__getattribute__')
+ slot_names = lookup_context.get_function_slot_names(u'__getattr__') + \
+ lookup_context.get_function_slot_names(u'__getattribute__')
for n in slot_names:
+ # TODO do we even get here?
if isinstance(name, CompiledInstanceName) and \
n.parent_context.obj == object:
typ = Warning
@@ -139,7 +143,7 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
"""
def check_match(cls, exception):
try:
- return isinstance(cls, CompiledObject) and issubclass(exception, cls.obj)
+ return isinstance(cls, CompiledObject) and cls.is_super_class(exception)
except TypeError:
return False
@@ -160,7 +164,7 @@ def check_try_for_except(obj, exception):
except_classes = node_context.eval_node(node)
for cls in except_classes:
from jedi.evaluate.context import iterable
- if isinstance(cls, iterable.AbstractIterable) and \
+ if isinstance(cls, iterable.Sequence) and \
cls.array_type == 'tuple':
# multiple exceptions
for lazy_context in cls.py__iter__():
@@ -189,8 +193,8 @@ def check_hasattr(node, suite):
# Check name
key, lazy_context = args[1]
names = list(lazy_context.infer())
- assert len(names) == 1 and isinstance(names[0], CompiledObject)
- assert names[0].obj == payload[1].value
+ assert len(names) == 1 and is_string(names[0])
+ assert force_unicode(names[0].get_safe_value()) == payload[1].value
# Check objects
key, lazy_context = args[0]
diff --git a/pythonFiles/jedi/evaluate/arguments.py b/pythonFiles/jedi/evaluate/arguments.py
index 32b9238c6f4d..beab4c8c9541 100644
--- a/pythonFiles/jedi/evaluate/arguments.py
+++ b/pythonFiles/jedi/evaluate/arguments.py
@@ -10,6 +10,7 @@
from jedi.evaluate.context import iterable
from jedi.evaluate.param import get_params, ExecutedParam
+
def try_iter_content(types, depth=0):
"""Helper method for static analysis."""
if depth > 10:
@@ -29,6 +30,8 @@ def try_iter_content(types, depth=0):
class AbstractArguments(object):
context = None
+ argument_node = None
+ trailer = None
def eval_argument_clinic(self, parameters):
"""Uses a list with argument clinic information (see PEP 436)."""
@@ -95,29 +98,30 @@ def __init__(self, evaluator, context, argument_node, trailer=None):
self.trailer = trailer # Can be None, e.g. in a class definition.
def _split(self):
- if isinstance(self.argument_node, (tuple, list)):
- for el in self.argument_node:
- yield 0, el
- else:
- if not (self.argument_node.type == 'arglist' or (
- # in python 3.5 **arg is an argument, not arglist
- (self.argument_node.type == 'argument') and
- self.argument_node.children[0] in ('*', '**'))):
- yield 0, self.argument_node
- return
-
- iterator = iter(self.argument_node.children)
- for child in iterator:
- if child == ',':
- continue
- elif child in ('*', '**'):
- yield len(child.value), next(iterator)
- elif child.type == 'argument' and \
- child.children[0] in ('*', '**'):
- assert len(child.children) == 2
- yield len(child.children[0].value), child.children[1]
- else:
- yield 0, child
+ if self.argument_node is None:
+ return
+
+ # Allow testlist here as well for Python2's class inheritance
+ # definitions.
+ if not (self.argument_node.type in ('arglist', 'testlist') or (
+ # in python 3.5 **arg is an argument, not arglist
+ (self.argument_node.type == 'argument') and
+ self.argument_node.children[0] in ('*', '**'))):
+ yield 0, self.argument_node
+ return
+
+ iterator = iter(self.argument_node.children)
+ for child in iterator:
+ if child == ',':
+ continue
+ elif child in ('*', '**'):
+ yield len(child.value), next(iterator)
+ elif child.type == 'argument' and \
+ child.children[0] in ('*', '**'):
+ assert len(child.children) == 2
+ yield len(child.children[0].value), child.children[1]
+ else:
+ yield 0, child
def unpack(self, funcdef=None):
named_args = []
@@ -126,7 +130,6 @@ def unpack(self, funcdef=None):
arrays = self.context.eval_node(el)
iterators = [_iterate_star_args(self.context, a, el, funcdef)
for a in arrays]
- iterators = list(iterators)
for values in list(zip_longest(*iterators)):
# TODO zip_longest yields None, that means this would raise
# an exception?
@@ -134,7 +137,7 @@ def unpack(self, funcdef=None):
[v for v in values if v is not None]
)
elif star_count == 2:
- arrays = self._evaluator.eval_element(self.context, el)
+ arrays = self.context.eval_node(el)
for dct in arrays:
for key, values in _star_star_dict(self.context, dct, el, funcdef):
yield key, values
@@ -197,7 +200,11 @@ def get_calling_nodes(self):
arguments = param.var_args
break
- return [arguments.argument_node or arguments.trailer]
+ if arguments.argument_node is not None:
+ return [arguments.argument_node]
+ if arguments.trailer is not None:
+ return [arguments.trailer]
+ return []
class ValuesArguments(AbstractArguments):
@@ -235,7 +242,7 @@ def _star_star_dict(context, array, input_node, funcdef):
# For now ignore this case. In the future add proper iterators and just
# make one call without crazy isinstance checks.
return {}
- elif isinstance(array, iterable.AbstractIterable) and array.array_type == 'dict':
+ elif isinstance(array, iterable.Sequence) and array.array_type == 'dict':
return array.exact_key_items()
else:
if funcdef is not None:
diff --git a/pythonFiles/jedi/evaluate/base_context.py b/pythonFiles/jedi/evaluate/base_context.py
index 693a99aae7aa..2c6fe6cd2c88 100644
--- a/pythonFiles/jedi/evaluate/base_context.py
+++ b/pythonFiles/jedi/evaluate/base_context.py
@@ -1,3 +1,11 @@
+"""
+Contexts are the "values" that Python would return. However Contexts are at the
+same time also the "contexts" that a user is currently sitting in.
+
+A ContextSet is typically used to specify the return of a function or any other
+static analysis operation. In jedi there are always multiple returns and not
+just one.
+"""
from parso.python.tree import ExprStmt, CompFor
from jedi import debug
@@ -63,10 +71,13 @@ def execute_evaluated(self, *value_list):
arguments = ValuesArguments([ContextSet(value) for value in value_list])
return self.execute(arguments)
- def iterate(self, contextualized_node=None):
- debug.dbg('iterate')
+ def iterate(self, contextualized_node=None, is_async=False):
+ debug.dbg('iterate %s', self)
try:
- iter_method = self.py__iter__
+ if is_async:
+ iter_method = self.py__aiter__
+ else:
+ iter_method = self.py__iter__
except AttributeError:
if contextualized_node is not None:
from jedi.evaluate import analysis
@@ -81,17 +92,22 @@ def iterate(self, contextualized_node=None):
def get_item(self, index_contexts, contextualized_node):
from jedi.evaluate.compiled import CompiledObject
- from jedi.evaluate.context.iterable import Slice, AbstractIterable
+ from jedi.evaluate.context.iterable import Slice, Sequence
result = ContextSet()
for index in index_contexts:
- if isinstance(index, (CompiledObject, Slice)):
+ if isinstance(index, Slice):
index = index.obj
+ if isinstance(index, CompiledObject):
+ try:
+ index = index.get_safe_value()
+ except ValueError:
+ pass
- if type(index) not in (float, int, str, unicode, slice, type(Ellipsis)):
+ if type(index) not in (float, int, str, unicode, slice, bytes):
# If the index is not clearly defined, we have to get all the
# possiblities.
- if isinstance(self, AbstractIterable) and self.array_type == 'dict':
+ if isinstance(self, Sequence) and self.array_type == 'dict':
result |= self.dict_values()
else:
result |= iterate_contexts(ContextSet(self))
@@ -139,10 +155,6 @@ def py__getattribute__(self, name_or_str, name_context=None, position=None,
return f.filter_name(filters)
return f.find(filters, attribute_lookup=not search_global)
- return self.evaluator.find_types(
- self, name_or_str, name_context, position, search_global, is_goto,
- analysis_errors)
-
def create_context(self, node, node_is_context=False, node_is_object=False):
return self.evaluator.create_context(self, node, node_is_context, node_is_object)
@@ -169,14 +181,14 @@ def py__doc__(self, include_call_signature=False):
return None
-def iterate_contexts(contexts, contextualized_node=None):
+def iterate_contexts(contexts, contextualized_node=None, is_async=False):
"""
Calls `iterate`, on all contexts but ignores the ordering and just returns
all contexts that the iterate functions yield.
"""
return ContextSet.from_sets(
lazy_context.infer()
- for lazy_context in contexts.iterate(contextualized_node)
+ for lazy_context in contexts.iterate(contextualized_node, is_async=is_async)
)
@@ -241,9 +253,9 @@ class ContextSet(BaseContextSet):
def py__class__(self):
return ContextSet.from_iterable(c.py__class__() for c in self._set)
- def iterate(self, contextualized_node=None):
+ def iterate(self, contextualized_node=None, is_async=False):
from jedi.evaluate.lazy_context import get_merged_lazy_context
- type_iters = [c.iterate(contextualized_node) for c in self._set]
+ type_iters = [c.iterate(contextualized_node, is_async=is_async) for c in self._set]
for lazy_contexts in zip_longest(*type_iters):
yield get_merged_lazy_context(
[l for l in lazy_contexts if l is not None]
diff --git a/pythonFiles/jedi/evaluate/cache.py b/pythonFiles/jedi/evaluate/cache.py
index b7c7cd7e979f..c619e698a3c8 100644
--- a/pythonFiles/jedi/evaluate/cache.py
+++ b/pythonFiles/jedi/evaluate/cache.py
@@ -59,7 +59,7 @@ def decorator(func):
return decorator
-def _memoize_meta_class():
+def evaluator_as_method_param_cache():
def decorator(call):
return _memoize_default(second_arg_is_evaluator=True)(call)
@@ -72,6 +72,6 @@ class CachedMetaClass(type):
class initializations. Either you do it this way or with decorators, but
with decorators you lose class access (isinstance, etc).
"""
- @_memoize_meta_class()
+ @evaluator_as_method_param_cache()
def __call__(self, *args, **kwargs):
return super(CachedMetaClass, self).__call__(*args, **kwargs)
diff --git a/pythonFiles/jedi/evaluate/compiled/__init__.py b/pythonFiles/jedi/evaluate/compiled/__init__.py
index f9f2e0781e13..357d26cc87fc 100644
--- a/pythonFiles/jedi/evaluate/compiled/__init__.py
+++ b/pythonFiles/jedi/evaluate/compiled/__init__.py
@@ -1,638 +1,39 @@
-"""
-Imitate the parser representation.
-"""
-import inspect
-import re
-import sys
-import os
-import types
-from functools import partial
+from jedi._compatibility import unicode
+from jedi.evaluate.compiled.context import CompiledObject, CompiledName, \
+ CompiledObjectFilter, CompiledContextName, create_from_access_path, \
+ create_from_name
-from jedi._compatibility import builtins as _builtins, unicode, py_version
-from jedi import debug
-from jedi.cache import underscore_memoization, memoize_method
-from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition, \
- ContextNameMixin
-from jedi.evaluate.base_context import Context, ContextSet
-from jedi.evaluate.lazy_context import LazyKnownContext
-from jedi.evaluate.compiled.getattr_static import getattr_static
-from . import fake
-
-_sep = os.path.sep
-if os.path.altsep is not None:
- _sep += os.path.altsep
-_path_re = re.compile('(?:\.[^{0}]+|[{0}]__init__\.py)$'.format(re.escape(_sep)))
-del _sep
-
-# Those types don't exist in typing.
-MethodDescriptorType = type(str.replace)
-WrapperDescriptorType = type(set.__iter__)
-# `object.__subclasshook__` is an already executed descriptor.
-object_class_dict = type.__dict__["__dict__"].__get__(object)
-ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
-
-ALLOWED_DESCRIPTOR_ACCESS = (
- types.FunctionType,
- types.GetSetDescriptorType,
- types.MemberDescriptorType,
- MethodDescriptorType,
- WrapperDescriptorType,
- ClassMethodDescriptorType,
- staticmethod,
- classmethod,
-)
-
-class CheckAttribute(object):
- """Raises an AttributeError if the attribute X isn't available."""
- def __init__(self, func):
- self.func = func
- # Remove the py in front of e.g. py__call__.
- self.check_name = func.__name__[2:]
-
- def __get__(self, instance, owner):
- # This might raise an AttributeError. That's wanted.
- if self.check_name == '__iter__':
- # Python iterators are a bit strange, because there's no need for
- # the __iter__ function as long as __getitem__ is defined (it will
- # just start with __getitem__(0). This is especially true for
- # Python 2 strings, where `str.__iter__` is not even defined.
- try:
- iter(instance.obj)
- except TypeError:
- raise AttributeError
- else:
- getattr(instance.obj, self.check_name)
- return partial(self.func, instance)
-
-
-class CompiledObject(Context):
- path = None # modules have this attribute - set it to None.
- used_names = lambda self: {} # To be consistent with modules.
-
- def __init__(self, evaluator, obj, parent_context=None, faked_class=None):
- super(CompiledObject, self).__init__(evaluator, parent_context)
- self.obj = obj
- # This attribute will not be set for most classes, except for fakes.
- self.tree_node = faked_class
-
- def get_root_node(self):
- # To make things a bit easier with filters we add this method here.
- return self.get_root_context()
-
- @CheckAttribute
- def py__call__(self, params):
- if inspect.isclass(self.obj):
- from jedi.evaluate.context import CompiledInstance
- return ContextSet(CompiledInstance(self.evaluator, self.parent_context, self, params))
- else:
- return ContextSet.from_iterable(self._execute_function(params))
-
- @CheckAttribute
- def py__class__(self):
- return create(self.evaluator, self.obj.__class__)
-
- @CheckAttribute
- def py__mro__(self):
- return (self,) + tuple(create(self.evaluator, cls) for cls in self.obj.__mro__[1:])
-
- @CheckAttribute
- def py__bases__(self):
- return tuple(create(self.evaluator, cls) for cls in self.obj.__bases__)
-
- def py__bool__(self):
- return bool(self.obj)
-
- def py__file__(self):
- try:
- return self.obj.__file__
- except AttributeError:
- return None
-
- def is_class(self):
- return inspect.isclass(self.obj)
-
- def py__doc__(self, include_call_signature=False):
- return inspect.getdoc(self.obj) or ''
-
- def get_param_names(self):
- obj = self.obj
- try:
- if py_version < 33:
- raise ValueError("inspect.signature was introduced in 3.3")
- if py_version == 34:
- # In 3.4 inspect.signature are wrong for str and int. This has
- # been fixed in 3.5. The signature of object is returned,
- # because no signature was found for str. Here we imitate 3.5
- # logic and just ignore the signature if the magic methods
- # don't match object.
- # 3.3 doesn't even have the logic and returns nothing for str
- # and classes that inherit from object.
- user_def = inspect._signature_get_user_defined_method
- if (inspect.isclass(obj)
- and not user_def(type(obj), '__init__')
- and not user_def(type(obj), '__new__')
- and (obj.__init__ != object.__init__
- or obj.__new__ != object.__new__)):
- raise ValueError
-
- signature = inspect.signature(obj)
- except ValueError: # Has no signature
- params_str, ret = self._parse_function_doc()
- tokens = params_str.split(',')
- if inspect.ismethoddescriptor(obj):
- tokens.insert(0, 'self')
- for p in tokens:
- parts = p.strip().split('=')
- yield UnresolvableParamName(self, parts[0])
- else:
- for signature_param in signature.parameters.values():
- yield SignatureParamName(self, signature_param)
-
- def __repr__(self):
- return '<%s: %s>' % (self.__class__.__name__, repr(self.obj))
-
- @underscore_memoization
- def _parse_function_doc(self):
- doc = self.py__doc__()
- if doc is None:
- return '', ''
-
- return _parse_function_doc(doc)
-
- @property
- def api_type(self):
- obj = self.obj
- if inspect.isclass(obj):
- return 'class'
- elif inspect.ismodule(obj):
- return 'module'
- elif inspect.isbuiltin(obj) or inspect.ismethod(obj) \
- or inspect.ismethoddescriptor(obj) or inspect.isfunction(obj):
- return 'function'
- # Everything else...
- return 'instance'
-
- @property
- def type(self):
- """Imitate the tree.Node.type values."""
- cls = self._get_class()
- if inspect.isclass(cls):
- return 'classdef'
- elif inspect.ismodule(cls):
- return 'file_input'
- elif inspect.isbuiltin(cls) or inspect.ismethod(cls) or \
- inspect.ismethoddescriptor(cls):
- return 'funcdef'
-
- @underscore_memoization
- def _cls(self):
- """
- We used to limit the lookups for instantiated objects like list(), but
- this is not the case anymore. Python itself
- """
- # Ensures that a CompiledObject is returned that is not an instance (like list)
- return self
-
- def _get_class(self):
- if not fake.is_class_instance(self.obj) or \
- inspect.ismethoddescriptor(self.obj): # slots
- return self.obj
-
- try:
- return self.obj.__class__
- except AttributeError:
- # happens with numpy.core.umath._UFUNC_API (you get it
- # automatically by doing `import numpy`.
- return type
-
- def get_filters(self, search_global=False, is_instance=False,
- until_position=None, origin_scope=None):
- yield self._ensure_one_filter(is_instance)
-
- @memoize_method
- def _ensure_one_filter(self, is_instance):
- """
- search_global shouldn't change the fact that there's one dict, this way
- there's only one `object`.
- """
- return CompiledObjectFilter(self.evaluator, self, is_instance)
-
- @CheckAttribute
- def py__getitem__(self, index):
- if type(self.obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
- # Get rid of side effects, we won't call custom `__getitem__`s.
- return ContextSet()
-
- return ContextSet(create(self.evaluator, self.obj[index]))
-
- @CheckAttribute
- def py__iter__(self):
- if type(self.obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
- # Get rid of side effects, we won't call custom `__getitem__`s.
- return
-
- for i, part in enumerate(self.obj):
- if i > 20:
- # Should not go crazy with large iterators
- break
- yield LazyKnownContext(create(self.evaluator, part))
-
- def py__name__(self):
- try:
- return self._get_class().__name__
- except AttributeError:
- return None
-
- @property
- def name(self):
- try:
- name = self._get_class().__name__
- except AttributeError:
- name = repr(self.obj)
- return CompiledContextName(self, name)
-
- def _execute_function(self, params):
- from jedi.evaluate import docstrings
- if self.type != 'funcdef':
- return
- for name in self._parse_function_doc()[1].split():
- try:
- bltn_obj = getattr(_builtins, name)
- except AttributeError:
- continue
- else:
- if bltn_obj is None:
- # We want to evaluate everything except None.
- # TODO do we?
- continue
- bltn_obj = create(self.evaluator, bltn_obj)
- for result in bltn_obj.execute(params):
- yield result
- for type_ in docstrings.infer_return_types(self):
- yield type_
-
- def get_self_attributes(self):
- return [] # Instance compatibility
-
- def get_imports(self):
- return [] # Builtins don't have imports
-
- def dict_values(self):
- return ContextSet.from_iterable(
- create(self.evaluator, v) for v in self.obj.values()
- )
-
-
-class CompiledName(AbstractNameDefinition):
- def __init__(self, evaluator, parent_context, name):
- self._evaluator = evaluator
- self.parent_context = parent_context
- self.string_name = name
-
- def __repr__(self):
- try:
- name = self.parent_context.name # __name__ is not defined all the time
- except AttributeError:
- name = None
- return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
-
- @property
- def api_type(self):
- return next(iter(self.infer())).api_type
-
- @underscore_memoization
- def infer(self):
- module = self.parent_context.get_root_context()
- return ContextSet(_create_from_name(
- self._evaluator, module, self.parent_context, self.string_name
- ))
-
-
-class SignatureParamName(AbstractNameDefinition):
- api_type = 'param'
-
- def __init__(self, compiled_obj, signature_param):
- self.parent_context = compiled_obj.parent_context
- self._signature_param = signature_param
-
- @property
- def string_name(self):
- return self._signature_param.name
-
- def infer(self):
- p = self._signature_param
- evaluator = self.parent_context.evaluator
- contexts = ContextSet()
- if p.default is not p.empty:
- contexts = ContextSet(create(evaluator, p.default))
- if p.annotation is not p.empty:
- annotation = create(evaluator, p.annotation)
- contexts |= annotation.execute_evaluated()
- return contexts
-
-
-class UnresolvableParamName(AbstractNameDefinition):
- api_type = 'param'
-
- def __init__(self, compiled_obj, name):
- self.parent_context = compiled_obj.parent_context
- self.string_name = name
-
- def infer(self):
- return ContextSet()
-
-
-class CompiledContextName(ContextNameMixin, AbstractNameDefinition):
- def __init__(self, context, name):
- self.string_name = name
- self._context = context
- self.parent_context = context.parent_context
-
-
-class EmptyCompiledName(AbstractNameDefinition):
- """
- Accessing some names will raise an exception. To avoid not having any
- completions, just give Jedi the option to return this object. It infers to
- nothing.
- """
- def __init__(self, evaluator, name):
- self.parent_context = evaluator.BUILTINS
- self.string_name = name
-
- def infer(self):
- return ContextSet()
-
-
-class CompiledObjectFilter(AbstractFilter):
- name_class = CompiledName
-
- def __init__(self, evaluator, compiled_object, is_instance=False):
- self._evaluator = evaluator
- self._compiled_object = compiled_object
- self._is_instance = is_instance
-
- @memoize_method
- def get(self, name):
- name = str(name)
- obj = self._compiled_object.obj
- try:
- attr, is_get_descriptor = getattr_static(obj, name)
- except AttributeError:
- return []
- else:
- if is_get_descriptor \
- and not type(attr) in ALLOWED_DESCRIPTOR_ACCESS:
- # In case of descriptors that have get methods we cannot return
- # it's value, because that would mean code execution.
- return [EmptyCompiledName(self._evaluator, name)]
- if self._is_instance and name not in dir(obj):
- return []
- return [self._create_name(name)]
-
- def values(self):
- obj = self._compiled_object.obj
-
- names = []
- for name in dir(obj):
- names += self.get(name)
-
- is_instance = self._is_instance or fake.is_class_instance(obj)
- # ``dir`` doesn't include the type names.
- if not inspect.ismodule(obj) and (obj is not type) and not is_instance:
- for filter in create(self._evaluator, type).get_filters():
- names += filter.values()
- return names
-
- def _create_name(self, name):
- return self.name_class(self._evaluator, self._compiled_object, name)
-
-
-def dotted_from_fs_path(fs_path, sys_path):
- """
- Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
- compares the path with sys.path and then returns the dotted_path. If the
- path is not in the sys.path, just returns None.
- """
- if os.path.basename(fs_path).startswith('__init__.'):
- # We are calculating the path. __init__ files are not interesting.
- fs_path = os.path.dirname(fs_path)
-
- # prefer
- # - UNIX
- # /path/to/pythonX.Y/lib-dynload
- # /path/to/pythonX.Y/site-packages
- # - Windows
- # C:\path\to\DLLs
- # C:\path\to\Lib\site-packages
- # over
- # - UNIX
- # /path/to/pythonX.Y
- # - Windows
- # C:\path\to\Lib
- path = ''
- for s in sys_path:
- if (fs_path.startswith(s) and len(path) < len(s)):
- path = s
-
- # - Window
- # X:\path\to\lib-dynload/datetime.pyd => datetime
- module_path = fs_path[len(path):].lstrip(os.path.sep).lstrip('/')
- # - Window
- # Replace like X:\path\to\something/foo/bar.py
- return _path_re.sub('', module_path).replace(os.path.sep, '.').replace('/', '.')
-
-
-def load_module(evaluator, path=None, name=None):
- sys_path = list(evaluator.project.sys_path)
- if path is not None:
- dotted_path = dotted_from_fs_path(path, sys_path=sys_path)
- else:
- dotted_path = name
-
- temp, sys.path = sys.path, sys_path
- try:
- __import__(dotted_path)
- except RuntimeError:
- if 'PySide' in dotted_path or 'PyQt' in dotted_path:
- # RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap
- # the QObject class.
- # See https://github.com/davidhalter/jedi/pull/483
- return None
- raise
- except ImportError:
- # If a module is "corrupt" or not really a Python module or whatever.
- debug.warning('Module %s not importable in path %s.', dotted_path, path)
- return None
- finally:
- sys.path = temp
-
- # Just access the cache after import, because of #59 as well as the very
- # complicated import structure of Python.
- module = sys.modules[dotted_path]
-
- return create(evaluator, module)
-
-
-docstr_defaults = {
- 'floating point number': 'float',
- 'character': 'str',
- 'integer': 'int',
- 'dictionary': 'dict',
- 'string': 'str',
-}
+def builtin_from_name(evaluator, string):
+ builtins = evaluator.builtins_module
+ return create_from_name(evaluator, builtins, string)
-def _parse_function_doc(doc):
+def create_simple_object(evaluator, obj):
"""
- Takes a function and returns the params and return value as a tuple.
- This is nothing more than a docstring parser.
-
- TODO docstrings like utime(path, (atime, mtime)) and a(b [, b]) -> None
- TODO docstrings like 'tuple of integers'
+ Only allows creations of objects that are easily picklable across Python
+ versions.
"""
- # parse round parentheses: def func(a, (b,c))
- try:
- count = 0
- start = doc.index('(')
- for i, s in enumerate(doc[start:]):
- if s == '(':
- count += 1
- elif s == ')':
- count -= 1
- if count == 0:
- end = start + i
- break
- param_str = doc[start + 1:end]
- except (ValueError, UnboundLocalError):
- # ValueError for doc.index
- # UnboundLocalError for undefined end in last line
- debug.dbg('no brackets found - no param')
- end = 0
- param_str = ''
- else:
- # remove square brackets, that show an optional param ( = None)
- def change_options(m):
- args = m.group(1).split(',')
- for i, a in enumerate(args):
- if a and '=' not in a:
- args[i] += '=None'
- return ','.join(args)
-
- while True:
- param_str, changes = re.subn(r' ?\[([^\[\]]+)\]',
- change_options, param_str)
- if changes == 0:
- break
- param_str = param_str.replace('-', '_') # see: isinstance.__doc__
-
- # parse return value
- r = re.search('-[>-]* ', doc[end:end + 7])
- if r is None:
- ret = ''
- else:
- index = end + r.end()
- # get result type, which can contain newlines
- pattern = re.compile(r'(,\n|[^\n-])+')
- ret_str = pattern.match(doc, index).group(0).strip()
- # New object -> object()
- ret_str = re.sub(r'[nN]ew (.*)', r'\1()', ret_str)
-
- ret = docstr_defaults.get(ret_str, ret_str)
-
- return param_str, ret
-
-
-def _create_from_name(evaluator, module, compiled_object, name):
- obj = compiled_object.obj
- faked = None
- try:
- faked = fake.get_faked(evaluator, module, obj, parent_context=compiled_object, name=name)
- if faked.type == 'funcdef':
- from jedi.evaluate.context.function import FunctionContext
- return FunctionContext(evaluator, compiled_object, faked)
- except fake.FakeDoesNotExist:
- pass
-
- try:
- obj = getattr(obj, name)
- except AttributeError:
- # Happens e.g. in properties of
- # PyQt4.QtGui.QStyleOptionComboBox.currentText
- # -> just set it to None
- obj = None
- return create(evaluator, obj, parent_context=compiled_object, faked=faked)
-
-
-def builtin_from_name(evaluator, string):
- bltn_obj = getattr(_builtins, string)
- return create(evaluator, bltn_obj)
-
-
-def _a_generator(foo):
- """Used to have an object to return for generators."""
- yield 42
- yield foo
-
-
-_SPECIAL_OBJECTS = {
- 'FUNCTION_CLASS': type(load_module),
- 'METHOD_CLASS': type(CompiledObject.is_class),
- 'MODULE_CLASS': type(os),
- 'GENERATOR_OBJECT': _a_generator(1.0),
- 'BUILTINS': _builtins,
-}
+ assert isinstance(obj, (int, float, str, bytes, unicode, slice, complex))
+ return create_from_access_path(
+ evaluator,
+ evaluator.compiled_subprocess.create_simple_object(obj)
+ )
def get_special_object(evaluator, identifier):
- obj = _SPECIAL_OBJECTS[identifier]
- return create(evaluator, obj, parent_context=create(evaluator, _builtins))
+ return create_from_access_path(
+ evaluator,
+ evaluator.compiled_subprocess.get_special_object(identifier)
+ )
-def compiled_objects_cache(attribute_name):
- def decorator(func):
- """
- This decorator caches just the ids, oopposed to caching the object itself.
- Caching the id has the advantage that an object doesn't need to be
- hashable.
- """
- def wrapper(evaluator, obj, parent_context=None, module=None, faked=None):
- cache = getattr(evaluator, attribute_name)
- # Do a very cheap form of caching here.
- key = id(obj), id(parent_context)
- try:
- return cache[key][0]
- except KeyError:
- # TODO this whole decorator is way too ugly
- result = func(evaluator, obj, parent_context, module, faked)
- # Need to cache all of them, otherwise the id could be overwritten.
- cache[key] = result, obj, parent_context, module, faked
- return result
- return wrapper
+def get_string_context_set(evaluator):
+ return builtin_from_name(evaluator, u'str').execute_evaluated()
- return decorator
-
-@compiled_objects_cache('compiled_cache')
-def create(evaluator, obj, parent_context=None, module=None, faked=None):
- """
- A very weird interface class to this module. The more options provided the
- more acurate loading compiled objects is.
- """
- if inspect.ismodule(obj):
- if parent_context is not None:
- # Modules don't have parents, be careful with caching: recurse.
- return create(evaluator, obj)
- else:
- if parent_context is None and obj is not _builtins:
- return create(evaluator, obj, create(evaluator, _builtins))
-
- try:
- faked = fake.get_faked(evaluator, module, obj, parent_context=parent_context)
- if faked.type == 'funcdef':
- from jedi.evaluate.context.function import FunctionContext
- return FunctionContext(evaluator, parent_context, faked)
- except fake.FakeDoesNotExist:
- pass
-
- return CompiledObject(evaluator, obj, parent_context, faked)
+def load_module(evaluator, **kwargs):
+ access_path = evaluator.compiled_subprocess.load_module(**kwargs)
+ if access_path is None:
+ return None
+ return create_from_access_path(evaluator, access_path)
diff --git a/pythonFiles/jedi/evaluate/compiled/access.py b/pythonFiles/jedi/evaluate/compiled/access.py
new file mode 100644
index 000000000000..97a8dd0b5c3d
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/compiled/access.py
@@ -0,0 +1,490 @@
+import inspect
+import types
+import sys
+from textwrap import dedent
+import operator as op
+from collections import namedtuple
+
+from jedi import debug
+from jedi._compatibility import unicode, is_py3, is_py34, builtins, \
+ py_version, force_unicode, print_to_stderr
+from jedi.evaluate.compiled.getattr_static import getattr_static
+from jedi.evaluate.utils import dotted_from_fs_path
+
+
+MethodDescriptorType = type(str.replace)
+# These are not considered classes and access is granted even though they have
+# a __class__ attribute.
+NOT_CLASS_TYPES = (
+ types.BuiltinFunctionType,
+ types.CodeType,
+ types.FrameType,
+ types.FunctionType,
+ types.GeneratorType,
+ types.GetSetDescriptorType,
+ types.LambdaType,
+ types.MemberDescriptorType,
+ types.MethodType,
+ types.ModuleType,
+ types.TracebackType,
+ MethodDescriptorType
+)
+
+if is_py3:
+ NOT_CLASS_TYPES += (
+ types.MappingProxyType,
+ types.SimpleNamespace
+ )
+ if is_py34:
+ NOT_CLASS_TYPES += (types.DynamicClassAttribute,)
+
+
+# Those types don't exist in typing.
+MethodDescriptorType = type(str.replace)
+WrapperDescriptorType = type(set.__iter__)
+# `object.__subclasshook__` is an already executed descriptor.
+object_class_dict = type.__dict__["__dict__"].__get__(object)
+ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
+
+def _a_generator(foo):
+ """Used to have an object to return for generators."""
+ yield 42
+ yield foo
+
+
+_sentinel = object()
+
+# Maps Python syntax to the operator module.
+COMPARISON_OPERATORS = {
+ '==': op.eq,
+ '!=': op.ne,
+ 'is': op.is_,
+ 'is not': op.is_not,
+ '<': op.lt,
+ '<=': op.le,
+ '>': op.gt,
+ '>=': op.ge,
+}
+
+_OPERATORS = {
+ '+': op.add,
+ '-': op.sub,
+}
+_OPERATORS.update(COMPARISON_OPERATORS)
+
+ALLOWED_DESCRIPTOR_ACCESS = (
+ types.FunctionType,
+ types.GetSetDescriptorType,
+ types.MemberDescriptorType,
+ MethodDescriptorType,
+ WrapperDescriptorType,
+ ClassMethodDescriptorType,
+ staticmethod,
+ classmethod,
+)
+
+
+def safe_getattr(obj, name, default=_sentinel):
+ try:
+ attr, is_get_descriptor = getattr_static(obj, name)
+ except AttributeError:
+ if default is _sentinel:
+ raise
+ return default
+ else:
+ if type(attr) in ALLOWED_DESCRIPTOR_ACCESS:
+ # In case of descriptors that have get methods we cannot return
+ # it's value, because that would mean code execution.
+ return getattr(obj, name)
+ return attr
+
+
+SignatureParam = namedtuple(
+ 'SignatureParam',
+ 'name has_default default has_annotation annotation kind_name'
+)
+
+
+def compiled_objects_cache(attribute_name):
+ def decorator(func):
+ """
+ This decorator caches just the ids, oopposed to caching the object itself.
+ Caching the id has the advantage that an object doesn't need to be
+ hashable.
+ """
+ def wrapper(evaluator, obj, parent_context=None):
+ cache = getattr(evaluator, attribute_name)
+ # Do a very cheap form of caching here.
+ key = id(obj)
+ try:
+ cache[key]
+ return cache[key][0]
+ except KeyError:
+ # TODO wuaaaarrghhhhhhhh
+ if attribute_name == 'mixed_cache':
+ result = func(evaluator, obj, parent_context)
+ else:
+ result = func(evaluator, obj)
+ # Need to cache all of them, otherwise the id could be overwritten.
+ cache[key] = result, obj, parent_context
+ return result
+ return wrapper
+
+ return decorator
+
+
+def create_access(evaluator, obj):
+ return evaluator.compiled_subprocess.get_or_create_access_handle(obj)
+
+
+def load_module(evaluator, path=None, name=None, sys_path=None):
+ if sys_path is None:
+ sys_path = list(evaluator.get_sys_path())
+ if path is not None:
+ dotted_path = dotted_from_fs_path(path, sys_path=sys_path)
+ else:
+ dotted_path = name
+
+ temp, sys.path = sys.path, sys_path
+ try:
+ __import__(dotted_path)
+ except ImportError:
+ # If a module is "corrupt" or not really a Python module or whatever.
+ debug.warning('Module %s not importable in path %s.', dotted_path, path)
+ return None
+ except Exception:
+ # Since __import__ pretty much makes code execution possible, just
+ # catch any error here and print it.
+ import traceback
+ print_to_stderr("Cannot import:\n%s" % traceback.format_exc())
+ return None
+ finally:
+ sys.path = temp
+
+ # Just access the cache after import, because of #59 as well as the very
+ # complicated import structure of Python.
+ module = sys.modules[dotted_path]
+ return create_access_path(evaluator, module)
+
+
+class AccessPath(object):
+ def __init__(self, accesses):
+ self.accesses = accesses
+
+ # Writing both of these methods here looks a bit ridiculous. However with
+ # the differences of Python 2/3 it's actually necessary, because we will
+ # otherwise have a accesses attribute that is bytes instead of unicode.
+ def __getstate__(self):
+ return self.accesses
+
+ def __setstate__(self, value):
+ self.accesses = value
+
+
+def create_access_path(evaluator, obj):
+ access = create_access(evaluator, obj)
+ return AccessPath(access.get_access_path_tuples())
+
+
+def _force_unicode_decorator(func):
+ return lambda *args, **kwargs: force_unicode(func(*args, **kwargs))
+
+
+class DirectObjectAccess(object):
+ def __init__(self, evaluator, obj):
+ self._evaluator = evaluator
+ self._obj = obj
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.get_repr())
+
+ def _create_access(self, obj):
+ return create_access(self._evaluator, obj)
+
+ def _create_access_path(self, obj):
+ return create_access_path(self._evaluator, obj)
+
+ def py__bool__(self):
+ return bool(self._obj)
+
+ def py__file__(self):
+ try:
+ return self._obj.__file__
+ except AttributeError:
+ return None
+
+ def py__doc__(self, include_call_signature=False):
+ return force_unicode(inspect.getdoc(self._obj)) or u''
+
+ def py__name__(self):
+ if not _is_class_instance(self._obj) or \
+ inspect.ismethoddescriptor(self._obj): # slots
+ cls = self._obj
+ else:
+ try:
+ cls = self._obj.__class__
+ except AttributeError:
+ # happens with numpy.core.umath._UFUNC_API (you get it
+ # automatically by doing `import numpy`.
+ return None
+
+ try:
+ return force_unicode(cls.__name__)
+ except AttributeError:
+ return None
+
+ def py__mro__accesses(self):
+ return tuple(self._create_access_path(cls) for cls in self._obj.__mro__[1:])
+
+ def py__getitem__(self, index):
+ if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
+ # Get rid of side effects, we won't call custom `__getitem__`s.
+ return None
+
+ return self._create_access_path(self._obj[index])
+
+ def py__iter__list(self):
+ if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
+ # Get rid of side effects, we won't call custom `__getitem__`s.
+ return []
+
+ lst = []
+ for i, part in enumerate(self._obj):
+ if i > 20:
+ # Should not go crazy with large iterators
+ break
+ lst.append(self._create_access_path(part))
+ return lst
+
+ def py__class__(self):
+ return self._create_access_path(self._obj.__class__)
+
+ def py__bases__(self):
+ return [self._create_access_path(base) for base in self._obj.__bases__]
+
+ @_force_unicode_decorator
+ def get_repr(self):
+ builtins = 'builtins', '__builtin__'
+
+ if inspect.ismodule(self._obj):
+ return repr(self._obj)
+ # Try to avoid execution of the property.
+ if safe_getattr(self._obj, '__module__', default='') in builtins:
+ return repr(self._obj)
+
+ type_ = type(self._obj)
+ if type_ == type:
+ return type.__repr__(self._obj)
+
+ if safe_getattr(type_, '__module__', default='') in builtins:
+ # Allow direct execution of repr for builtins.
+ return repr(self._obj)
+ return object.__repr__(self._obj)
+
+ def is_class(self):
+ return inspect.isclass(self._obj)
+
+ def ismethoddescriptor(self):
+ return inspect.ismethoddescriptor(self._obj)
+
+ def dir(self):
+ return list(map(force_unicode, dir(self._obj)))
+
+ def has_iter(self):
+ try:
+ iter(self._obj)
+ return True
+ except TypeError:
+ return False
+
+ def is_allowed_getattr(self, name):
+ # TODO this API is ugly.
+ try:
+ attr, is_get_descriptor = getattr_static(self._obj, name)
+ except AttributeError:
+ return False, False
+ else:
+ if is_get_descriptor and type(attr) not in ALLOWED_DESCRIPTOR_ACCESS:
+ # In case of descriptors that have get methods we cannot return
+ # it's value, because that would mean code execution.
+ return True, True
+ return True, False
+
+ def getattr(self, name, default=_sentinel):
+ try:
+ return self._create_access(getattr(self._obj, name))
+ except AttributeError:
+ # Happens e.g. in properties of
+ # PyQt4.QtGui.QStyleOptionComboBox.currentText
+ # -> just set it to None
+ if default is _sentinel:
+ raise
+ return self._create_access(default)
+
+ def get_safe_value(self):
+ if type(self._obj) in (bool, bytes, float, int, str, unicode, slice):
+ return self._obj
+ raise ValueError("Object is type %s and not simple" % type(self._obj))
+
+ def get_api_type(self):
+ obj = self._obj
+ if self.is_class():
+ return u'class'
+ elif inspect.ismodule(obj):
+ return u'module'
+ elif inspect.isbuiltin(obj) or inspect.ismethod(obj) \
+ or inspect.ismethoddescriptor(obj) or inspect.isfunction(obj):
+ return u'function'
+ # Everything else...
+ return u'instance'
+
+ def get_access_path_tuples(self):
+ accesses = [create_access(self._evaluator, o) for o in self._get_objects_path()]
+ return [(access.py__name__(), access) for access in accesses]
+
+ def _get_objects_path(self):
+ def get():
+ obj = self._obj
+ yield obj
+ try:
+ obj = obj.__objclass__
+ except AttributeError:
+ pass
+ else:
+ yield obj
+
+ try:
+ # Returns a dotted string path.
+ imp_plz = obj.__module__
+ except AttributeError:
+ # Unfortunately in some cases like `int` there's no __module__
+ if not inspect.ismodule(obj):
+ yield builtins
+ else:
+ if imp_plz is None:
+ # Happens for example in `(_ for _ in []).send.__module__`.
+ yield builtins
+ else:
+ try:
+ # TODO use sys.modules, __module__ can be faked.
+ yield sys.modules[imp_plz]
+ except KeyError:
+ # __module__ can be something arbitrary that doesn't exist.
+ yield builtins
+
+ return list(reversed(list(get())))
+
+ def execute_operation(self, other_access_handle, operator):
+ other_access = other_access_handle.access
+ op = _OPERATORS[operator]
+ return self._create_access_path(op(self._obj, other_access._obj))
+
+ def needs_type_completions(self):
+ return inspect.isclass(self._obj) and self._obj != type
+
+ def get_signature_params(self):
+ obj = self._obj
+ if py_version < 33:
+ raise ValueError("inspect.signature was introduced in 3.3")
+ if py_version == 34:
+ # In 3.4 inspect.signature are wrong for str and int. This has
+ # been fixed in 3.5. The signature of object is returned,
+ # because no signature was found for str. Here we imitate 3.5
+ # logic and just ignore the signature if the magic methods
+ # don't match object.
+ # 3.3 doesn't even have the logic and returns nothing for str
+ # and classes that inherit from object.
+ user_def = inspect._signature_get_user_defined_method
+ if (inspect.isclass(obj)
+ and not user_def(type(obj), '__init__')
+ and not user_def(type(obj), '__new__')
+ and (obj.__init__ != object.__init__
+ or obj.__new__ != object.__new__)):
+ raise ValueError
+
+ try:
+ signature = inspect.signature(obj)
+ except (RuntimeError, TypeError):
+ # Reading the code of the function in Python 3.6 implies there are
+ # at least these errors that might occur if something is wrong with
+ # the signature. In that case we just want a simple escape for now.
+ raise ValueError
+ return [
+ SignatureParam(
+ name=p.name,
+ has_default=p.default is not p.empty,
+ default=self._create_access_path(p.default),
+ has_annotation=p.annotation is not p.empty,
+ annotation=self._create_access_path(p.annotation),
+ kind_name=str(p.kind)
+ ) for p in signature.parameters.values()
+ ]
+
+ def negate(self):
+ return self._create_access_path(-self._obj)
+
+ def dict_values(self):
+ return [self._create_access_path(v) for v in self._obj.values()]
+
+ def is_super_class(self, exception):
+ return issubclass(exception, self._obj)
+
+ def get_dir_infos(self):
+ """
+ Used to return a couple of infos that are needed when accessing the sub
+ objects of an objects
+ """
+ # TODO is_allowed_getattr might raise an AttributeError
+ tuples = dict(
+ (force_unicode(name), self.is_allowed_getattr(name))
+ for name in self.dir()
+ )
+ return self.needs_type_completions(), tuples
+
+
+def _is_class_instance(obj):
+ """Like inspect.* methods."""
+ try:
+ cls = obj.__class__
+ except AttributeError:
+ return False
+ else:
+ return cls != type and not issubclass(cls, NOT_CLASS_TYPES)
+
+
+if py_version >= 35:
+ exec(compile(dedent("""
+ async def _coroutine(): pass
+ _coroutine = _coroutine()
+ CoroutineType = type(_coroutine)
+ _coroutine.close() # Prevent ResourceWarning
+ """), 'blub', 'exec'))
+ _coroutine_wrapper = _coroutine.__await__()
+else:
+ _coroutine = None
+ _coroutine_wrapper = None
+
+if py_version >= 36:
+ exec(compile(dedent("""
+ async def _async_generator():
+ yield
+ _async_generator = _async_generator()
+ AsyncGeneratorType = type(_async_generator)
+ """), 'blub', 'exec'))
+else:
+ _async_generator = None
+
+class _SPECIAL_OBJECTS(object):
+ FUNCTION_CLASS = types.FunctionType
+ METHOD_CLASS = type(DirectObjectAccess.py__bool__)
+ MODULE_CLASS = types.ModuleType
+ GENERATOR_OBJECT = _a_generator(1.0)
+ BUILTINS = builtins
+ COROUTINE = _coroutine
+ COROUTINE_WRAPPER = _coroutine_wrapper
+ ASYNC_GENERATOR = _async_generator
+
+
+def get_special_object(evaluator, identifier):
+ obj = getattr(_SPECIAL_OBJECTS, identifier)
+ return create_access_path(evaluator, obj)
diff --git a/pythonFiles/jedi/evaluate/compiled/context.py b/pythonFiles/jedi/evaluate/compiled/context.py
new file mode 100644
index 000000000000..f81509d73f72
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/compiled/context.py
@@ -0,0 +1,474 @@
+"""
+Imitate the parser representation.
+"""
+import re
+from functools import partial
+
+from jedi import debug
+from jedi._compatibility import force_unicode, Parameter
+from jedi.cache import underscore_memoization, memoize_method
+from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition, \
+ ContextNameMixin
+from jedi.evaluate.base_context import Context, ContextSet
+from jedi.evaluate.lazy_context import LazyKnownContext
+from jedi.evaluate.compiled.access import _sentinel
+from jedi.evaluate.cache import evaluator_function_cache
+from . import fake
+
+
+class CheckAttribute(object):
+ """Raises an AttributeError if the attribute X isn't available."""
+ def __init__(self, func):
+ self.func = func
+ # Remove the py in front of e.g. py__call__.
+ self.check_name = force_unicode(func.__name__[2:])
+
+ def __get__(self, instance, owner):
+ if instance is None:
+ return self
+
+ # This might raise an AttributeError. That's wanted.
+ if self.check_name == '__iter__':
+ # Python iterators are a bit strange, because there's no need for
+ # the __iter__ function as long as __getitem__ is defined (it will
+ # just start with __getitem__(0). This is especially true for
+ # Python 2 strings, where `str.__iter__` is not even defined.
+ if not instance.access_handle.has_iter():
+ raise AttributeError
+ else:
+ instance.access_handle.getattr(self.check_name)
+ return partial(self.func, instance)
+
+
+class CompiledObject(Context):
+ def __init__(self, evaluator, access_handle, parent_context=None, faked_class=None):
+ super(CompiledObject, self).__init__(evaluator, parent_context)
+ self.access_handle = access_handle
+ # This attribute will not be set for most classes, except for fakes.
+ self.tree_node = faked_class
+
+ @CheckAttribute
+ def py__call__(self, params):
+ if self.tree_node is not None and self.tree_node.type == 'funcdef':
+ from jedi.evaluate.context.function import FunctionContext
+ return FunctionContext(
+ self.evaluator,
+ parent_context=self.parent_context,
+ funcdef=self.tree_node
+ ).py__call__(params)
+ if self.access_handle.is_class():
+ from jedi.evaluate.context import CompiledInstance
+ return ContextSet(CompiledInstance(self.evaluator, self.parent_context, self, params))
+ else:
+ return ContextSet.from_iterable(self._execute_function(params))
+
+ @CheckAttribute
+ def py__class__(self):
+ return create_from_access_path(self.evaluator, self.access_handle.py__class__())
+
+ @CheckAttribute
+ def py__mro__(self):
+ return (self,) + tuple(
+ create_from_access_path(self.evaluator, access)
+ for access in self.access_handle.py__mro__accesses()
+ )
+
+ @CheckAttribute
+ def py__bases__(self):
+ return tuple(
+ create_from_access_path(self.evaluator, access)
+ for access in self.access_handle.py__bases__()
+ )
+
+ def py__bool__(self):
+ return self.access_handle.py__bool__()
+
+ def py__file__(self):
+ return self.access_handle.py__file__()
+
+ def is_class(self):
+ return self.access_handle.is_class()
+
+ def py__doc__(self, include_call_signature=False):
+ return self.access_handle.py__doc__()
+
+ def get_param_names(self):
+ try:
+ signature_params = self.access_handle.get_signature_params()
+ except ValueError: # Has no signature
+ params_str, ret = self._parse_function_doc()
+ tokens = params_str.split(',')
+ if self.access_handle.ismethoddescriptor():
+ tokens.insert(0, 'self')
+ for p in tokens:
+ parts = p.strip().split('=')
+ yield UnresolvableParamName(self, parts[0])
+ else:
+ for signature_param in signature_params:
+ yield SignatureParamName(self, signature_param)
+
+ def __repr__(self):
+ return '<%s: %s>' % (self.__class__.__name__, self.access_handle.get_repr())
+
+ @underscore_memoization
+ def _parse_function_doc(self):
+ doc = self.py__doc__()
+ if doc is None:
+ return '', ''
+
+ return _parse_function_doc(doc)
+
+ @property
+ def api_type(self):
+ return self.access_handle.get_api_type()
+
+ @underscore_memoization
+ def _cls(self):
+ """
+ We used to limit the lookups for instantiated objects like list(), but
+ this is not the case anymore. Python itself
+ """
+ # Ensures that a CompiledObject is returned that is not an instance (like list)
+ return self
+
+ def get_filters(self, search_global=False, is_instance=False,
+ until_position=None, origin_scope=None):
+ yield self._ensure_one_filter(is_instance)
+
+ @memoize_method
+ def _ensure_one_filter(self, is_instance):
+ """
+ search_global shouldn't change the fact that there's one dict, this way
+ there's only one `object`.
+ """
+ return CompiledObjectFilter(self.evaluator, self, is_instance)
+
+ @CheckAttribute
+ def py__getitem__(self, index):
+ access = self.access_handle.py__getitem__(index)
+ if access is None:
+ return ContextSet()
+
+ return ContextSet(create_from_access_path(self.evaluator, access))
+
+ @CheckAttribute
+ def py__iter__(self):
+ for access in self.access_handle.py__iter__list():
+ yield LazyKnownContext(create_from_access_path(self.evaluator, access))
+
+ def py__name__(self):
+ return self.access_handle.py__name__()
+
+ @property
+ def name(self):
+ name = self.py__name__()
+ if name is None:
+ name = self.access_handle.get_repr()
+ return CompiledContextName(self, name)
+
+ def _execute_function(self, params):
+ from jedi.evaluate import docstrings
+ from jedi.evaluate.compiled import builtin_from_name
+ if self.api_type != 'function':
+ return
+
+ for name in self._parse_function_doc()[1].split():
+ try:
+ # TODO wtf is this? this is exactly the same as the thing
+ # below. It uses getattr as well.
+ self.evaluator.builtins_module.access_handle.getattr(name)
+ except AttributeError:
+ continue
+ else:
+ bltn_obj = builtin_from_name(self.evaluator, name)
+ for result in bltn_obj.execute(params):
+ yield result
+ for type_ in docstrings.infer_return_types(self):
+ yield type_
+
+ def dict_values(self):
+ return ContextSet.from_iterable(
+ create_from_access_path(self.evaluator, access)
+ for access in self.access_handle.dict_values()
+ )
+
+ def get_safe_value(self, default=_sentinel):
+ try:
+ return self.access_handle.get_safe_value()
+ except ValueError:
+ if default == _sentinel:
+ raise
+ return default
+
+ def execute_operation(self, other, operator):
+ return create_from_access_path(
+ self.evaluator,
+ self.access_handle.execute_operation(other.access_handle, operator)
+ )
+
+ def negate(self):
+ return create_from_access_path(self.evaluator, self.access_handle.negate())
+
+ def is_super_class(self, exception):
+ return self.access_handle.is_super_class(exception)
+
+
+class CompiledName(AbstractNameDefinition):
+ def __init__(self, evaluator, parent_context, name):
+ self._evaluator = evaluator
+ self.parent_context = parent_context
+ self.string_name = name
+
+ def __repr__(self):
+ try:
+ name = self.parent_context.name # __name__ is not defined all the time
+ except AttributeError:
+ name = None
+ return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
+
+ @property
+ def api_type(self):
+ return next(iter(self.infer())).api_type
+
+ @underscore_memoization
+ def infer(self):
+ return ContextSet(create_from_name(
+ self._evaluator, self.parent_context, self.string_name
+ ))
+
+
+class SignatureParamName(AbstractNameDefinition):
+ api_type = u'param'
+
+ def __init__(self, compiled_obj, signature_param):
+ self.parent_context = compiled_obj.parent_context
+ self._signature_param = signature_param
+
+ @property
+ def string_name(self):
+ return self._signature_param.name
+
+ def get_kind(self):
+ return getattr(Parameter, self._signature_param.kind_name)
+
+ def is_keyword_param(self):
+ return self._signature_param
+
+ def infer(self):
+ p = self._signature_param
+ evaluator = self.parent_context.evaluator
+ contexts = ContextSet()
+ if p.has_default:
+ contexts = ContextSet(create_from_access_path(evaluator, p.default))
+ if p.has_annotation:
+ annotation = create_from_access_path(evaluator, p.annotation)
+ contexts |= annotation.execute_evaluated()
+ return contexts
+
+
+class UnresolvableParamName(AbstractNameDefinition):
+ api_type = u'param'
+
+ def __init__(self, compiled_obj, name):
+ self.parent_context = compiled_obj.parent_context
+ self.string_name = name
+
+ def get_kind(self):
+ return Parameter.POSITIONAL_ONLY
+
+ def infer(self):
+ return ContextSet()
+
+
+class CompiledContextName(ContextNameMixin, AbstractNameDefinition):
+ def __init__(self, context, name):
+ self.string_name = name
+ self._context = context
+ self.parent_context = context.parent_context
+
+
+class EmptyCompiledName(AbstractNameDefinition):
+ """
+ Accessing some names will raise an exception. To avoid not having any
+ completions, just give Jedi the option to return this object. It infers to
+ nothing.
+ """
+ def __init__(self, evaluator, name):
+ self.parent_context = evaluator.builtins_module
+ self.string_name = name
+
+ def infer(self):
+ return ContextSet()
+
+
+class CompiledObjectFilter(AbstractFilter):
+ name_class = CompiledName
+
+ def __init__(self, evaluator, compiled_object, is_instance=False):
+ self._evaluator = evaluator
+ self._compiled_object = compiled_object
+ self._is_instance = is_instance
+
+ def get(self, name):
+ return self._get(
+ name,
+ lambda: self._compiled_object.access_handle.is_allowed_getattr(name),
+ lambda: self._compiled_object.access_handle.dir(),
+ check_has_attribute=True
+ )
+
+ def _get(self, name, allowed_getattr_callback, dir_callback, check_has_attribute=False):
+ """
+ To remove quite a few access calls we introduced the callback here.
+ """
+ has_attribute, is_descriptor = allowed_getattr_callback()
+ if check_has_attribute and not has_attribute:
+ return []
+
+ # Always use unicode objects in Python 2 from here.
+ name = force_unicode(name)
+
+ if is_descriptor or not has_attribute:
+ return [self._get_cached_name(name, is_empty=True)]
+
+ if self._is_instance and name not in dir_callback():
+ return []
+ return [self._get_cached_name(name)]
+
+ @memoize_method
+ def _get_cached_name(self, name, is_empty=False):
+ if is_empty:
+ return EmptyCompiledName(self._evaluator, name)
+ else:
+ return self._create_name(name)
+
+ def values(self):
+ from jedi.evaluate.compiled import builtin_from_name
+ names = []
+ needs_type_completions, dir_infos = self._compiled_object.access_handle.get_dir_infos()
+ for name in dir_infos:
+ names += self._get(
+ name,
+ lambda: dir_infos[name],
+ lambda: dir_infos.keys(),
+ )
+
+ # ``dir`` doesn't include the type names.
+ if not self._is_instance and needs_type_completions:
+ for filter in builtin_from_name(self._evaluator, u'type').get_filters():
+ names += filter.values()
+ return names
+
+ def _create_name(self, name):
+ return self.name_class(self._evaluator, self._compiled_object, name)
+
+
+docstr_defaults = {
+ 'floating point number': u'float',
+ 'character': u'str',
+ 'integer': u'int',
+ 'dictionary': u'dict',
+ 'string': u'str',
+}
+
+
+def _parse_function_doc(doc):
+ """
+ Takes a function and returns the params and return value as a tuple.
+ This is nothing more than a docstring parser.
+
+ TODO docstrings like utime(path, (atime, mtime)) and a(b [, b]) -> None
+ TODO docstrings like 'tuple of integers'
+ """
+ doc = force_unicode(doc)
+ # parse round parentheses: def func(a, (b,c))
+ try:
+ count = 0
+ start = doc.index('(')
+ for i, s in enumerate(doc[start:]):
+ if s == '(':
+ count += 1
+ elif s == ')':
+ count -= 1
+ if count == 0:
+ end = start + i
+ break
+ param_str = doc[start + 1:end]
+ except (ValueError, UnboundLocalError):
+ # ValueError for doc.index
+ # UnboundLocalError for undefined end in last line
+ debug.dbg('no brackets found - no param')
+ end = 0
+ param_str = u''
+ else:
+ # remove square brackets, that show an optional param ( = None)
+ def change_options(m):
+ args = m.group(1).split(',')
+ for i, a in enumerate(args):
+ if a and '=' not in a:
+ args[i] += '=None'
+ return ','.join(args)
+
+ while True:
+ param_str, changes = re.subn(r' ?\[([^\[\]]+)\]',
+ change_options, param_str)
+ if changes == 0:
+ break
+ param_str = param_str.replace('-', '_') # see: isinstance.__doc__
+
+ # parse return value
+ r = re.search(u'-[>-]* ', doc[end:end + 7])
+ if r is None:
+ ret = u''
+ else:
+ index = end + r.end()
+ # get result type, which can contain newlines
+ pattern = re.compile(r'(,\n|[^\n-])+')
+ ret_str = pattern.match(doc, index).group(0).strip()
+ # New object -> object()
+ ret_str = re.sub(r'[nN]ew (.*)', r'\1()', ret_str)
+
+ ret = docstr_defaults.get(ret_str, ret_str)
+
+ return param_str, ret
+
+
+def create_from_name(evaluator, compiled_object, name):
+ faked = None
+ try:
+ faked = fake.get_faked_with_parent_context(compiled_object, name)
+ except fake.FakeDoesNotExist:
+ pass
+
+ access = compiled_object.access_handle.getattr(name, default=None)
+ return create_cached_compiled_object(
+ evaluator, access, parent_context=compiled_object, faked=faked
+ )
+
+
+def _normalize_create_args(func):
+ """The cache doesn't care about keyword vs. normal args."""
+ def wrapper(evaluator, obj, parent_context=None, faked=None):
+ return func(evaluator, obj, parent_context, faked)
+ return wrapper
+
+
+def create_from_access_path(evaluator, access_path):
+ parent_context = None
+ for name, access in access_path.accesses:
+ try:
+ if parent_context is None:
+ faked = fake.get_faked_module(evaluator, access_path.accesses[0][0])
+ else:
+ faked = fake.get_faked_with_parent_context(parent_context, name)
+ except fake.FakeDoesNotExist:
+ faked = None
+
+ parent_context = create_cached_compiled_object(evaluator, access, parent_context, faked)
+ return parent_context
+
+
+@_normalize_create_args
+@evaluator_function_cache()
+def create_cached_compiled_object(evaluator, access_handle, parent_context, faked):
+ return CompiledObject(evaluator, access_handle, parent_context, faked)
diff --git a/pythonFiles/jedi/evaluate/compiled/fake.py b/pythonFiles/jedi/evaluate/compiled/fake.py
index 60dbefe4acac..ac43ea286b48 100644
--- a/pythonFiles/jedi/evaluate/compiled/fake.py
+++ b/pythonFiles/jedi/evaluate/compiled/fake.py
@@ -5,73 +5,59 @@
"""
import os
-import inspect
-import types
from itertools import chain
-from parso.python import tree
+from jedi._compatibility import unicode
-from jedi._compatibility import is_py3, builtins, unicode, is_py34
+fake_modules = {}
-modules = {}
+def _get_path_dict():
+ path = os.path.dirname(os.path.abspath(__file__))
+ base_path = os.path.join(path, 'fake')
+ dct = {}
+ for file_name in os.listdir(base_path):
+ if file_name.endswith('.pym'):
+ dct[file_name[:-4]] = os.path.join(base_path, file_name)
+ return dct
-MethodDescriptorType = type(str.replace)
-# These are not considered classes and access is granted even though they have
-# a __class__ attribute.
-NOT_CLASS_TYPES = (
- types.BuiltinFunctionType,
- types.CodeType,
- types.FrameType,
- types.FunctionType,
- types.GeneratorType,
- types.GetSetDescriptorType,
- types.LambdaType,
- types.MemberDescriptorType,
- types.MethodType,
- types.ModuleType,
- types.TracebackType,
- MethodDescriptorType
-)
-if is_py3:
- NOT_CLASS_TYPES += (
- types.MappingProxyType,
- types.SimpleNamespace
- )
- if is_py34:
- NOT_CLASS_TYPES += (types.DynamicClassAttribute,)
+_path_dict = _get_path_dict()
class FakeDoesNotExist(Exception):
pass
-def _load_faked_module(grammar, module):
- module_name = module.__name__
- if module_name == '__builtin__' and not is_py3:
- module_name = 'builtins'
+def _load_faked_module(evaluator, module_name):
+ try:
+ return fake_modules[module_name]
+ except KeyError:
+ pass
+
+ check_module_name = module_name
+ if module_name == '__builtin__' and evaluator.environment.version_info.major == 2:
+ check_module_name = 'builtins'
try:
- return modules[module_name]
+ path = _path_dict[check_module_name]
except KeyError:
- path = os.path.dirname(os.path.abspath(__file__))
- try:
- with open(os.path.join(path, 'fake', module_name) + '.pym') as f:
- source = f.read()
- except IOError:
- modules[module_name] = None
- return
- modules[module_name] = m = grammar.parse(unicode(source))
-
- if module_name == 'builtins' and not is_py3:
- # There are two implementations of `open` for either python 2/3.
- # -> Rename the python2 version (`look at fake/builtins.pym`).
- open_func = _search_scope(m, 'open')
- open_func.children[1].value = 'open_python3'
- open_func = _search_scope(m, 'open_python2')
- open_func.children[1].value = 'open'
- return m
+ fake_modules[module_name] = None
+ return
+
+ with open(path) as f:
+ source = f.read()
+
+ fake_modules[module_name] = m = evaluator.latest_grammar.parse(unicode(source))
+
+ if check_module_name != module_name:
+ # There are two implementations of `open` for either python 2/3.
+ # -> Rename the python2 version (`look at fake/builtins.pym`).
+ open_func = _search_scope(m, 'open')
+ open_func.children[1].value = 'open_python3'
+ open_func = _search_scope(m, 'open_python2')
+ open_func.children[1].value = 'open'
+ return m
def _search_scope(scope, obj_name):
@@ -80,134 +66,17 @@ def _search_scope(scope, obj_name):
return s
-def get_module(obj):
- if inspect.ismodule(obj):
- return obj
- try:
- obj = obj.__objclass__
- except AttributeError:
- pass
-
- try:
- imp_plz = obj.__module__
- except AttributeError:
- # Unfortunately in some cases like `int` there's no __module__
- return builtins
- else:
- if imp_plz is None:
- # Happens for example in `(_ for _ in []).send.__module__`.
- return builtins
- else:
- try:
- return __import__(imp_plz)
- except ImportError:
- # __module__ can be something arbitrary that doesn't exist.
- return builtins
-
-
-def _faked(grammar, module, obj, name):
- # Crazy underscore actions to try to escape all the internal madness.
- if module is None:
- module = get_module(obj)
-
- faked_mod = _load_faked_module(grammar, module)
- if faked_mod is None:
- return None, None
-
- # Having the module as a `parser.python.tree.Module`, we need to scan
- # for methods.
- if name is None:
- if inspect.isbuiltin(obj) or inspect.isclass(obj):
- return _search_scope(faked_mod, obj.__name__), faked_mod
- elif not inspect.isclass(obj):
- # object is a method or descriptor
- try:
- objclass = obj.__objclass__
- except AttributeError:
- return None, None
- else:
- cls = _search_scope(faked_mod, objclass.__name__)
- if cls is None:
- return None, None
- return _search_scope(cls, obj.__name__), faked_mod
- else:
- if obj is module:
- return _search_scope(faked_mod, name), faked_mod
- else:
- try:
- cls_name = obj.__name__
- except AttributeError:
- return None, None
- cls = _search_scope(faked_mod, cls_name)
- if cls is None:
- return None, None
- return _search_scope(cls, name), faked_mod
- return None, None
-
-
-def memoize_faked(obj):
- """
- A typical memoize function that ignores issues with non hashable results.
- """
- cache = obj.cache = {}
-
- def memoizer(*args, **kwargs):
- key = (obj, args, frozenset(kwargs.items()))
- try:
- result = cache[key]
- except (TypeError, ValueError):
- return obj(*args, **kwargs)
- except KeyError:
- result = obj(*args, **kwargs)
- if result is not None:
- cache[key] = obj(*args, **kwargs)
- return result
- else:
- return result
- return memoizer
-
-
-@memoize_faked
-def _get_faked(grammar, module, obj, name=None):
- result, fake_module = _faked(grammar, module, obj, name)
- if result is None:
- # We're not interested in classes. What we want is functions.
- raise FakeDoesNotExist
- elif result.type == 'classdef':
- return result, fake_module
- else:
- # Set the docstr which was previously not set (faked modules don't
- # contain it).
- assert result.type == 'funcdef'
- doc = '"""%s"""' % obj.__doc__ # TODO need escapes.
- suite = result.children[-1]
- string = tree.String(doc, (0, 0), '')
- new_line = tree.Newline('\n', (0, 0))
- docstr_node = tree.PythonNode('simple_stmt', [string, new_line])
- suite.children.insert(1, docstr_node)
- return result, fake_module
-
-
-def get_faked(evaluator, module, obj, name=None, parent_context=None):
- if parent_context and parent_context.tree_node is not None:
+def get_faked_with_parent_context(parent_context, name):
+ if parent_context.tree_node is not None:
# Try to search in already clearly defined stuff.
found = _search_scope(parent_context.tree_node, name)
if found is not None:
return found
- else:
- raise FakeDoesNotExist
+ raise FakeDoesNotExist
- faked, fake_module = _get_faked(evaluator.latest_grammar, module and module.obj, obj, name)
- if module is not None:
- module.get_used_names = fake_module.get_used_names
- return faked
-
-def is_class_instance(obj):
- """Like inspect.* methods."""
- try:
- cls = obj.__class__
- except AttributeError:
- return False
- else:
- return cls != type and not issubclass(cls, NOT_CLASS_TYPES)
+def get_faked_module(evaluator, string_name):
+ module = _load_faked_module(evaluator, string_name)
+ if module is None:
+ raise FakeDoesNotExist
+ return module
diff --git a/pythonFiles/jedi/evaluate/compiled/fake/builtins.pym b/pythonFiles/jedi/evaluate/compiled/fake/builtins.pym
index 1225929c2cb7..46ec619fb420 100644
--- a/pythonFiles/jedi/evaluate/compiled/fake/builtins.pym
+++ b/pythonFiles/jedi/evaluate/compiled/fake/builtins.pym
@@ -201,10 +201,13 @@ class dict():
# has a strange docstr
pass
+ def __getitem__(self, obj):
+ return self.__elements[obj]
+
def get(self, k, d=None):
# TODO implement
try:
- #return self.__elements[k]
+ return self.__elements[k]
pass
except KeyError:
return d
diff --git a/pythonFiles/jedi/evaluate/compiled/getattr_static.py b/pythonFiles/jedi/evaluate/compiled/getattr_static.py
index 9f8cd8a838cf..946ac09b6b06 100644
--- a/pythonFiles/jedi/evaluate/compiled/getattr_static.py
+++ b/pythonFiles/jedi/evaluate/compiled/getattr_static.py
@@ -10,6 +10,7 @@
_sentinel = object()
+
def _check_instance(obj, attr):
instance_dict = {}
try:
@@ -28,6 +29,7 @@ def _check_class(klass, attr):
pass
return _sentinel
+
def _is_type(obj):
try:
_static_getmro(obj)
@@ -87,7 +89,7 @@ class Foo(object): pass
return getattr(klass, '__dict__', _sentinel)
return _shadowed_dict_newstyle(klass)
- class _OldStyleClass():
+ class _OldStyleClass:
pass
_oldstyle_instance_type = type(_OldStyleClass())
@@ -122,7 +124,7 @@ def _safe_hasattr(obj, name):
def _safe_is_data_descriptor(obj):
- return (_safe_hasattr(obj, '__set__') or _safe_hasattr(obj, '__delete__'))
+ return _safe_hasattr(obj, '__set__') or _safe_hasattr(obj, '__delete__')
def getattr_static(obj, attr, default=_sentinel):
@@ -143,8 +145,7 @@ def getattr_static(obj, attr, default=_sentinel):
if not _is_type(obj):
klass = _get_type(obj)
dict_attr = _shadowed_dict(klass)
- if (dict_attr is _sentinel or
- type(dict_attr) is types.MemberDescriptorType):
+ if (dict_attr is _sentinel or type(dict_attr) is types.MemberDescriptorType):
instance_result = _check_instance(obj, attr)
else:
klass = obj
diff --git a/pythonFiles/jedi/evaluate/compiled/mixed.py b/pythonFiles/jedi/evaluate/compiled/mixed.py
index ac0f6dd614db..b8003502e3d7 100644
--- a/pythonFiles/jedi/evaluate/compiled/mixed.py
+++ b/pythonFiles/jedi/evaluate/compiled/mixed.py
@@ -5,6 +5,8 @@
import inspect
import os
+from jedi.parser_utils import get_cached_code_lines
+
from jedi import settings
from jedi.evaluate import compiled
from jedi.cache import underscore_memoization
@@ -13,6 +15,8 @@
from jedi.evaluate.context import ModuleContext
from jedi.evaluate.cache import evaluator_function_cache
from jedi.evaluate.compiled.getattr_static import getattr_static
+from jedi.evaluate.compiled.access import compiled_objects_cache
+from jedi.evaluate.compiled.context import create_cached_compiled_object
class MixedObject(object):
@@ -37,7 +41,7 @@ def __init__(self, evaluator, parent_context, compiled_object, tree_context):
self.parent_context = parent_context
self.compiled_object = compiled_object
self._context = tree_context
- self.obj = compiled_object.obj
+ self.access_handle = compiled_object.access_handle
# We have to overwrite everything that has to do with trailers, name
# lookups and filters to make it possible to route name lookups towards
@@ -49,7 +53,7 @@ def get_filters(self, *args, **kwargs):
yield MixedObjectFilter(self.evaluator, self)
def __repr__(self):
- return '<%s: %s>' % (type(self).__name__, repr(self.obj))
+ return '<%s: %s>' % (type(self).__name__, self.access_handle.get_repr())
def __getattr__(self, name):
return getattr(self._context, name)
@@ -64,7 +68,7 @@ def start_pos(self):
contexts = list(self.infer())
if not contexts:
# This means a start_pos that doesn't exist (compiled objects).
- return (0, 0)
+ return 0, 0
return contexts[0].name.start_pos
@start_pos.setter
@@ -74,17 +78,11 @@ def start_pos(self, value):
@underscore_memoization
def infer(self):
- obj = self.parent_context.obj
- try:
- # TODO use logic from compiled.CompiledObjectFilter
- obj = getattr(obj, self.string_name)
- except AttributeError:
- # Happens e.g. in properties of
- # PyQt4.QtGui.QStyleOptionComboBox.currentText
- # -> just set it to None
- obj = None
+ access_handle = self.parent_context.access_handle
+ # TODO use logic from compiled.CompiledObjectFilter
+ access_handle = access_handle.getattr(self.string_name, default=None)
return ContextSet(
- _create(self._evaluator, obj, parent_context=self.parent_context)
+ _create(self._evaluator, access_handle, parent_context=self.parent_context)
)
@property
@@ -105,17 +103,17 @@ def __init__(self, evaluator, mixed_object, is_instance=False):
@evaluator_function_cache()
-def _load_module(evaluator, path, python_object):
- module = evaluator.grammar.parse(
+def _load_module(evaluator, path):
+ module_node = evaluator.grammar.parse(
path=path,
cache=True,
diff_cache=True,
cache_path=settings.cache_directory
).get_root_node()
- python_module = inspect.getmodule(python_object)
-
- evaluator.modules[python_module.__name__] = module
- return module
+ # python_module = inspect.getmodule(python_object)
+ # TODO we should actually make something like this possible.
+ #evaluator.modules[python_module.__name__] = module_node
+ return module_node
def _get_object_to_check(python_object):
@@ -135,39 +133,43 @@ def _get_object_to_check(python_object):
raise TypeError # Prevents computation of `repr` within inspect.
-def find_syntax_node_name(evaluator, python_object):
+def _find_syntax_node_name(evaluator, access_handle):
+ # TODO accessing this is bad, but it probably doesn't matter that much,
+ # because we're working with interpreteters only here.
+ python_object = access_handle.access._obj
try:
python_object = _get_object_to_check(python_object)
path = inspect.getsourcefile(python_object)
except TypeError:
# The type might not be known (e.g. class_with_dict.__weakref__)
- return None, None
+ return None
if path is None or not os.path.exists(path):
# The path might not exist or be e.g. .
- return None, None
+ return None
- module = _load_module(evaluator, path, python_object)
+ module_node = _load_module(evaluator, path)
if inspect.ismodule(python_object):
# We don't need to check names for modules, because there's not really
# a way to write a module in a module in Python (and also __name__ can
# be something like ``email.utils``).
- return module, path
+ code_lines = get_cached_code_lines(evaluator.grammar, path)
+ return module_node, module_node, path, code_lines
try:
name_str = python_object.__name__
except AttributeError:
# Stuff like python_function.__code__.
- return None, None
+ return None
if name_str == '':
- return None, None # It's too hard to find lambdas.
+ return None # It's too hard to find lambdas.
# Doesn't always work (e.g. os.stat_result)
try:
- names = module.get_used_names()[name_str]
+ names = module_node.get_used_names()[name_str]
except KeyError:
- return None, None
+ return None
names = [n for n in names if n.is_definition()]
try:
@@ -184,33 +186,40 @@ def find_syntax_node_name(evaluator, python_object):
# There's a chance that the object is not available anymore, because
# the code has changed in the background.
if line_names:
- return line_names[-1].parent, path
+ names = line_names
+ code_lines = get_cached_code_lines(evaluator.grammar, path)
# It's really hard to actually get the right definition, here as a last
# resort we just return the last one. This chance might lead to odd
# completions at some points but will lead to mostly correct type
# inference, because people tend to define a public name in a module only
# once.
- return names[-1].parent, path
+ return module_node, names[-1].parent, path, code_lines
-@compiled.compiled_objects_cache('mixed_cache')
-def _create(evaluator, obj, parent_context=None, *args):
- tree_node, path = find_syntax_node_name(evaluator, obj)
+@compiled_objects_cache('mixed_cache')
+def _create(evaluator, access_handle, parent_context, *args):
+ compiled_object = create_cached_compiled_object(
+ evaluator, access_handle, parent_context=parent_context.compiled_object)
- compiled_object = compiled.create(
- evaluator, obj, parent_context=parent_context.compiled_object)
- if tree_node is None:
+ result = _find_syntax_node_name(evaluator, access_handle)
+ if result is None:
return compiled_object
- module_node = tree_node.get_root_node()
+ module_node, tree_node, path, code_lines = result
+
if parent_context.tree_node.get_root_node() == module_node:
module_context = parent_context.get_root_context()
else:
- module_context = ModuleContext(evaluator, module_node, path=path)
+ module_context = ModuleContext(
+ evaluator, module_node,
+ path=path,
+ code_lines=code_lines,
+ )
# TODO this __name__ is probably wrong.
name = compiled_object.get_root_context().py__name__()
- imports.add_module(evaluator, name, module_context)
+ if name is not None:
+ imports.add_module_to_cache(evaluator, name, module_context)
tree_context = module_context.create_context(
tree_node,
@@ -218,7 +227,7 @@ def _create(evaluator, obj, parent_context=None, *args):
node_is_object=True
)
if tree_node.type == 'classdef':
- if not inspect.isclass(obj):
+ if not access_handle.is_class():
# Is an instance, not a class.
tree_context, = tree_context.execute_evaluated()
@@ -228,4 +237,3 @@ def _create(evaluator, obj, parent_context=None, *args):
compiled_object,
tree_context=tree_context
)
-
diff --git a/pythonFiles/jedi/evaluate/compiled/subprocess/__init__.py b/pythonFiles/jedi/evaluate/compiled/subprocess/__init__.py
new file mode 100644
index 000000000000..9cc8704a457e
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/compiled/subprocess/__init__.py
@@ -0,0 +1,340 @@
+"""
+Makes it possible to do the compiled analysis in a subprocess. This has two
+goals:
+
+1. Making it safer - Segfaults and RuntimeErrors as well as stdout/stderr can
+ be ignored and dealt with.
+2. Make it possible to handle different Python versions as well as virtualenvs.
+"""
+
+import os
+import sys
+import subprocess
+import socket
+import errno
+import weakref
+import traceback
+from functools import partial
+
+from jedi._compatibility import queue, is_py3, force_unicode, \
+ pickle_dump, pickle_load, GeneralizedPopen
+from jedi.cache import memoize_method
+from jedi.evaluate.compiled.subprocess import functions
+from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
+ SignatureParam
+from jedi.api.exceptions import InternalError
+
+_subprocesses = {}
+
+_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
+
+
+def get_subprocess(executable):
+ try:
+ return _subprocesses[executable]
+ except KeyError:
+ sub = _subprocesses[executable] = _CompiledSubprocess(executable)
+ return sub
+
+
+def _get_function(name):
+ return getattr(functions, name)
+
+
+class _EvaluatorProcess(object):
+ def __init__(self, evaluator):
+ self._evaluator_weakref = weakref.ref(evaluator)
+ self._evaluator_id = id(evaluator)
+ self._handles = {}
+
+ def get_or_create_access_handle(self, obj):
+ id_ = id(obj)
+ try:
+ return self.get_access_handle(id_)
+ except KeyError:
+ access = DirectObjectAccess(self._evaluator_weakref(), obj)
+ handle = AccessHandle(self, access, id_)
+ self.set_access_handle(handle)
+ return handle
+
+ def get_access_handle(self, id_):
+ return self._handles[id_]
+
+ def set_access_handle(self, handle):
+ self._handles[handle.id] = handle
+
+
+class EvaluatorSameProcess(_EvaluatorProcess):
+ """
+ Basically just an easy access to functions.py. It has the same API
+ as EvaluatorSubprocess and does the same thing without using a subprocess.
+ This is necessary for the Interpreter process.
+ """
+ def __getattr__(self, name):
+ return partial(_get_function(name), self._evaluator_weakref())
+
+
+class EvaluatorSubprocess(_EvaluatorProcess):
+ def __init__(self, evaluator, compiled_subprocess):
+ super(EvaluatorSubprocess, self).__init__(evaluator)
+ self._used = False
+ self._compiled_subprocess = compiled_subprocess
+
+ def __getattr__(self, name):
+ func = _get_function(name)
+
+ def wrapper(*args, **kwargs):
+ self._used = True
+
+ result = self._compiled_subprocess.run(
+ self._evaluator_weakref(),
+ func,
+ args=args,
+ kwargs=kwargs,
+ )
+ # IMO it should be possible to create a hook in pickle.load to
+ # mess with the loaded objects. However it's extremely complicated
+ # to work around this so just do it with this call. ~ dave
+ return self._convert_access_handles(result)
+
+ return wrapper
+
+ def _convert_access_handles(self, obj):
+ if isinstance(obj, SignatureParam):
+ return SignatureParam(*self._convert_access_handles(tuple(obj)))
+ elif isinstance(obj, tuple):
+ return tuple(self._convert_access_handles(o) for o in obj)
+ elif isinstance(obj, list):
+ return [self._convert_access_handles(o) for o in obj]
+ elif isinstance(obj, AccessHandle):
+ try:
+ # Rewrite the access handle to one we're already having.
+ obj = self.get_access_handle(obj.id)
+ except KeyError:
+ obj.add_subprocess(self)
+ self.set_access_handle(obj)
+ elif isinstance(obj, AccessPath):
+ return AccessPath(self._convert_access_handles(obj.accesses))
+ return obj
+
+ def __del__(self):
+ if self._used:
+ self._compiled_subprocess.delete_evaluator(self._evaluator_id)
+
+
+class _CompiledSubprocess(object):
+ _crashed = False
+
+ def __init__(self, executable):
+ self._executable = executable
+ self._evaluator_deletion_queue = queue.deque()
+
+ @property
+ @memoize_method
+ def _process(self):
+ parso_path = sys.modules['parso'].__file__
+ args = (
+ self._executable,
+ _MAIN_PATH,
+ os.path.dirname(os.path.dirname(parso_path))
+ )
+ return GeneralizedPopen(
+ args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ )
+
+ def run(self, evaluator, function, args=(), kwargs={}):
+ # Delete old evaluators.
+ while True:
+ try:
+ evaluator_id = self._evaluator_deletion_queue.pop()
+ except IndexError:
+ break
+ else:
+ self._send(evaluator_id, None)
+
+ assert callable(function)
+ return self._send(id(evaluator), function, args, kwargs)
+
+ def get_sys_path(self):
+ return self._send(None, functions.get_sys_path, (), {})
+
+ def kill(self):
+ self._crashed = True
+ try:
+ subprocess = _subprocesses[self._executable]
+ except KeyError:
+ # Fine it was already removed from the cache.
+ pass
+ else:
+ # In the `!=` case there is already a new subprocess in place
+ # and we don't need to do anything here anymore.
+ if subprocess == self:
+ del _subprocesses[self._executable]
+
+ self._process.kill()
+ self._process.wait()
+
+ def _send(self, evaluator_id, function, args=(), kwargs={}):
+ if self._crashed:
+ raise InternalError("The subprocess %s has crashed." % self._executable)
+
+ if not is_py3:
+ # Python 2 compatibility
+ kwargs = {force_unicode(key): value for key, value in kwargs.items()}
+
+ data = evaluator_id, function, args, kwargs
+ try:
+ pickle_dump(data, self._process.stdin)
+ except (socket.error, IOError) as e:
+ # Once Python2 will be removed we can just use `BrokenPipeError`.
+ # Also, somehow in windows it returns EINVAL instead of EPIPE if
+ # the subprocess dies.
+ if e.errno not in (errno.EPIPE, errno.EINVAL):
+ # Not a broken pipe
+ raise
+ self.kill()
+ raise InternalError("The subprocess %s was killed. Maybe out of memory?"
+ % self._executable)
+
+ try:
+ is_exception, traceback, result = pickle_load(self._process.stdout)
+ except EOFError:
+ self.kill()
+ raise InternalError("The subprocess %s has crashed." % self._executable)
+
+ if is_exception:
+ # Replace the attribute error message with a the traceback. It's
+ # way more informative.
+ result.args = (traceback,)
+ raise result
+ return result
+
+ def delete_evaluator(self, evaluator_id):
+ """
+ Currently we are not deleting evalutors instantly. They only get
+ deleted once the subprocess is used again. It would probably a better
+ solution to move all of this into a thread. However, the memory usage
+ of a single evaluator shouldn't be that high.
+ """
+ # With an argument - the evaluator gets deleted.
+ self._evaluator_deletion_queue.append(evaluator_id)
+
+
+class Listener(object):
+ def __init__(self):
+ self._evaluators = {}
+ # TODO refactor so we don't need to process anymore just handle
+ # controlling.
+ self._process = _EvaluatorProcess(Listener)
+
+ def _get_evaluator(self, function, evaluator_id):
+ from jedi.evaluate import Evaluator
+
+ try:
+ evaluator = self._evaluators[evaluator_id]
+ except KeyError:
+ from jedi.api.environment import InterpreterEnvironment
+ evaluator = Evaluator(
+ # The project is not actually needed. Nothing should need to
+ # access it.
+ project=None,
+ environment=InterpreterEnvironment()
+ )
+ self._evaluators[evaluator_id] = evaluator
+ return evaluator
+
+ def _run(self, evaluator_id, function, args, kwargs):
+ if evaluator_id is None:
+ return function(*args, **kwargs)
+ elif function is None:
+ del self._evaluators[evaluator_id]
+ else:
+ evaluator = self._get_evaluator(function, evaluator_id)
+
+ # Exchange all handles
+ args = list(args)
+ for i, arg in enumerate(args):
+ if isinstance(arg, AccessHandle):
+ args[i] = evaluator.compiled_subprocess.get_access_handle(arg.id)
+ for key, value in kwargs.items():
+ if isinstance(value, AccessHandle):
+ kwargs[key] = evaluator.compiled_subprocess.get_access_handle(value.id)
+
+ return function(evaluator, *args, **kwargs)
+
+ def listen(self):
+ stdout = sys.stdout
+ # Mute stdout/stderr. Nobody should actually be able to write to those,
+ # because stdout is used for IPC and stderr will just be annoying if it
+ # leaks (on module imports).
+ sys.stdout = open(os.devnull, 'w')
+ sys.stderr = open(os.devnull, 'w')
+ stdin = sys.stdin
+ if sys.version_info[0] > 2:
+ stdout = stdout.buffer
+ stdin = stdin.buffer
+
+ while True:
+ try:
+ payload = pickle_load(stdin)
+ except EOFError:
+ # It looks like the parent process closed. Don't make a big fuss
+ # here and just exit.
+ exit(1)
+ try:
+ result = False, None, self._run(*payload)
+ except Exception as e:
+ result = True, traceback.format_exc(), e
+
+ pickle_dump(result, file=stdout)
+
+
+class AccessHandle(object):
+ def __init__(self, subprocess, access, id_):
+ self.access = access
+ self._subprocess = subprocess
+ self.id = id_
+
+ def add_subprocess(self, subprocess):
+ self._subprocess = subprocess
+
+ def __repr__(self):
+ try:
+ detail = self.access
+ except AttributeError:
+ detail = '#' + str(self.id)
+ return '<%s of %s>' % (self.__class__.__name__, detail)
+
+ def __getstate__(self):
+ return self.id
+
+ def __setstate__(self, state):
+ self.id = state
+
+ def __getattr__(self, name):
+ if name in ('id', 'access') or name.startswith('_'):
+ raise AttributeError("Something went wrong with unpickling")
+
+ #if not is_py3: print >> sys.stderr, name
+ #print('getattr', name, file=sys.stderr)
+ return partial(self._workaround, force_unicode(name))
+
+ def _workaround(self, name, *args, **kwargs):
+ """
+ TODO Currently we're passing slice objects around. This should not
+ happen. They are also the only unhashable objects that we're passing
+ around.
+ """
+ if args and isinstance(args[0], slice):
+ return self._subprocess.get_compiled_method_return(self.id, name, *args, **kwargs)
+ return self._cached_results(name, *args, **kwargs)
+
+ @memoize_method
+ def _cached_results(self, name, *args, **kwargs):
+ #if type(self._subprocess) == EvaluatorSubprocess:
+ #print(name, args, kwargs,
+ #self._subprocess.get_compiled_method_return(self.id, name, *args, **kwargs)
+ #)
+ return self._subprocess.get_compiled_method_return(self.id, name, *args, **kwargs)
diff --git a/pythonFiles/jedi/evaluate/compiled/subprocess/__main__.py b/pythonFiles/jedi/evaluate/compiled/subprocess/__main__.py
new file mode 100644
index 000000000000..8a0148ce5040
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/compiled/subprocess/__main__.py
@@ -0,0 +1,49 @@
+import sys
+import os
+
+
+def _get_paths():
+ # Get the path to jedi.
+ _d = os.path.dirname
+ _jedi_path = _d(_d(_d(_d(_d(__file__)))))
+ _parso_path = sys.argv[1]
+ # The paths are the directory that jedi and parso lie in.
+ return {'jedi': _jedi_path, 'parso': _parso_path}
+
+
+# Remove the first entry, because it's simply a directory entry that equals
+# this directory.
+del sys.path[0]
+
+if sys.version_info > (3, 4):
+ from importlib.machinery import PathFinder
+
+ class _ExactImporter(object):
+ def __init__(self, path_dct):
+ self._path_dct = path_dct
+
+ def find_module(self, fullname, path=None):
+ if path is None and fullname in self._path_dct:
+ p = self._path_dct[fullname]
+ loader = PathFinder.find_module(fullname, path=[p])
+ return loader
+ return None
+
+ # Try to import jedi/parso.
+ sys.meta_path.insert(0, _ExactImporter(_get_paths()))
+ from jedi.evaluate.compiled import subprocess # NOQA
+ sys.meta_path.pop(0)
+else:
+ import imp
+
+ def load(name):
+ paths = list(_get_paths().values())
+ fp, pathname, description = imp.find_module(name, paths)
+ return imp.load_module(name, fp, pathname, description)
+
+ load('parso')
+ load('jedi')
+ from jedi.evaluate.compiled import subprocess # NOQA
+
+# And finally start the client.
+subprocess.Listener().listen()
diff --git a/pythonFiles/jedi/evaluate/compiled/subprocess/functions.py b/pythonFiles/jedi/evaluate/compiled/subprocess/functions.py
new file mode 100644
index 000000000000..593ff91e8caf
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/compiled/subprocess/functions.py
@@ -0,0 +1,113 @@
+import sys
+import os
+
+from jedi._compatibility import find_module, cast_path, force_unicode, \
+ iter_modules, all_suffixes, print_to_stderr
+from jedi.evaluate.compiled import access
+from jedi import parser_utils
+
+
+def get_sys_path():
+ return list(map(cast_path, sys.path))
+
+
+def load_module(evaluator, **kwargs):
+ return access.load_module(evaluator, **kwargs)
+
+
+def get_compiled_method_return(evaluator, id, attribute, *args, **kwargs):
+ handle = evaluator.compiled_subprocess.get_access_handle(id)
+ return getattr(handle.access, attribute)(*args, **kwargs)
+
+
+def get_special_object(evaluator, identifier):
+ return access.get_special_object(evaluator, identifier)
+
+
+def create_simple_object(evaluator, obj):
+ return access.create_access_path(evaluator, obj)
+
+
+def get_module_info(evaluator, sys_path=None, full_name=None, **kwargs):
+ if sys_path is not None:
+ sys.path, temp = sys_path, sys.path
+ try:
+ module_file, module_path, is_pkg = find_module(full_name=full_name, **kwargs)
+ except ImportError:
+ return None, None, None
+ finally:
+ if sys_path is not None:
+ sys.path = temp
+
+ code = None
+ if is_pkg:
+ # In this case, we don't have a file yet. Search for the
+ # __init__ file.
+ if module_path.endswith(('.zip', '.egg')):
+ code = module_file.loader.get_source(full_name)
+ else:
+ module_path = _get_init_path(module_path)
+ elif module_file:
+ if module_path.endswith(('.zip', '.egg')):
+ # Unfortunately we are reading unicode here already, not byes.
+ # It seems however hard to get bytes, because the zip importer
+ # logic just unpacks the zip file and returns a file descriptor
+ # that we cannot as easily access. Therefore we just read it as
+ # a string.
+ code = module_file.read()
+ else:
+ # Read the code with a binary file, because the binary file
+ # might not be proper unicode. This is handled by the parser
+ # wrapper.
+ with open(module_path, 'rb') as f:
+ code = f.read()
+
+ module_file.close()
+
+ return code, cast_path(module_path), is_pkg
+
+
+def list_module_names(evaluator, search_path):
+ return [
+ name
+ for module_loader, name, is_pkg in iter_modules(search_path)
+ ]
+
+
+def get_builtin_module_names(evaluator):
+ return list(map(force_unicode, sys.builtin_module_names))
+
+
+def _test_raise_error(evaluator, exception_type):
+ """
+ Raise an error to simulate certain problems for unit tests.
+ """
+ raise exception_type
+
+
+def _test_print(evaluator, stderr=None, stdout=None):
+ """
+ Force some prints in the subprocesses. This exists for unit tests.
+ """
+ if stderr is not None:
+ print_to_stderr(stderr)
+ sys.stderr.flush()
+ if stdout is not None:
+ print(stdout)
+ sys.stdout.flush()
+
+
+def _get_init_path(directory_path):
+ """
+ The __init__ file can be searched in a directory. If found return it, else
+ None.
+ """
+ for suffix in all_suffixes():
+ path = os.path.join(directory_path, '__init__' + suffix)
+ if os.path.exists(path):
+ return path
+ return None
+
+
+def safe_literal_eval(evaluator, value):
+ return parser_utils.safe_literal_eval(value)
diff --git a/pythonFiles/jedi/evaluate/context/asynchronous.py b/pythonFiles/jedi/evaluate/context/asynchronous.py
new file mode 100644
index 000000000000..51e59a48261e
--- /dev/null
+++ b/pythonFiles/jedi/evaluate/context/asynchronous.py
@@ -0,0 +1,38 @@
+from jedi.evaluate.filters import publish_method, BuiltinOverwrite
+from jedi.evaluate.base_context import ContextSet
+
+
+class AsyncBase(BuiltinOverwrite):
+ def __init__(self, evaluator, func_execution_context):
+ super(AsyncBase, self).__init__(evaluator)
+ self.func_execution_context = func_execution_context
+
+ @property
+ def name(self):
+ return self.get_object().name
+
+ def __repr__(self):
+ return "<%s of %s>" % (type(self).__name__, self.func_execution_context)
+
+
+class Coroutine(AsyncBase):
+ special_object_identifier = u'COROUTINE'
+
+ @publish_method('__await__')
+ def _await(self):
+ return ContextSet(CoroutineWrapper(self.evaluator, self.func_execution_context))
+
+
+class CoroutineWrapper(AsyncBase):
+ special_object_identifier = u'COROUTINE_WRAPPER'
+
+ def py__stop_iteration_returns(self):
+ return self.func_execution_context.get_return_values()
+
+
+class AsyncGenerator(AsyncBase):
+ """Handling of `yield` functions."""
+ special_object_identifier = u'ASYNC_GENERATOR'
+
+ def py__aiter__(self):
+ return self.func_execution_context.get_yield_lazy_contexts(is_async=True)
diff --git a/pythonFiles/jedi/evaluate/context/function.py b/pythonFiles/jedi/evaluate/context/function.py
index 0dba9c91d707..2bb3a9b88bc3 100644
--- a/pythonFiles/jedi/evaluate/context/function.py
+++ b/pythonFiles/jedi/evaluate/context/function.py
@@ -17,17 +17,20 @@
from jedi.evaluate.lazy_context import LazyKnownContexts, LazyKnownContext, \
LazyTreeContext
from jedi.evaluate.context import iterable
+from jedi.evaluate.context import asynchronous
from jedi import parser_utils
from jedi.evaluate.parser_cache import get_yield_exprs
class LambdaName(AbstractNameDefinition):
string_name = ''
+ api_type = u'function'
def __init__(self, lambda_context):
self._lambda_context = lambda_context
self.parent_context = lambda_context.parent_context
+ @property
def start_pos(self):
return self._lambda_context.tree_node.start_pos
@@ -39,7 +42,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, TreeContext)):
"""
Needed because of decorators. Decorators are evaluated here.
"""
- api_type = 'function'
+ api_type = u'function'
def __init__(self, evaluator, parent_context, funcdef):
""" This should not be called directly """
@@ -63,11 +66,23 @@ def infer_function_execution(self, function_execution):
"""
Created to be used by inheritance.
"""
- yield_exprs = get_yield_exprs(self.evaluator, self.tree_node)
- if yield_exprs:
- return ContextSet(iterable.Generator(self.evaluator, function_execution))
+ is_coroutine = self.tree_node.parent.type == 'async_stmt'
+ is_generator = bool(get_yield_exprs(self.evaluator, self.tree_node))
+
+ if is_coroutine:
+ if is_generator:
+ if self.evaluator.environment.version_info < (3, 6):
+ return NO_CONTEXTS
+ return ContextSet(asynchronous.AsyncGenerator(self.evaluator, function_execution))
+ else:
+ if self.evaluator.environment.version_info < (3, 5):
+ return NO_CONTEXTS
+ return ContextSet(asynchronous.Coroutine(self.evaluator, function_execution))
else:
- return function_execution.get_return_values()
+ if is_generator:
+ return ContextSet(iterable.Generator(self.evaluator, function_execution))
+ else:
+ return function_execution.get_return_values()
def get_function_execution(self, arguments=None):
if arguments is None:
@@ -83,9 +98,9 @@ def py__class__(self):
# This differentiation is only necessary for Python2. Python3 does not
# use a different method class.
if isinstance(parser_utils.get_parent_scope(self.tree_node), tree.Class):
- name = 'METHOD_CLASS'
+ name = u'METHOD_CLASS'
else:
- name = 'FUNCTION_CLASS'
+ name = u'FUNCTION_CLASS'
return compiled.get_special_object(self.evaluator, name)
@property
@@ -122,7 +137,7 @@ def __init__(self, evaluator, parent_context, function_context, var_args):
def get_return_values(self, check_yields=False):
funcdef = self.tree_node
if funcdef.type == 'lambdef':
- return self.evaluator.eval_element(self, funcdef.children[-1])
+ return self.eval_node(funcdef.children[-1])
if check_yields:
context_set = NO_CONTEXTS
@@ -140,13 +155,14 @@ def get_return_values(self, check_yields=False):
if check_yields:
context_set |= ContextSet.from_sets(
lazy_context.infer()
- for lazy_context in self._eval_yield(r)
+ for lazy_context in self._get_yield_lazy_context(r)
)
else:
try:
children = r.children
except AttributeError:
- context_set |= ContextSet(compiled.create(self.evaluator, None))
+ ctx = compiled.builtin_from_name(self.evaluator, u'None')
+ context_set |= ContextSet(ctx)
else:
context_set |= self.eval_node(children[1])
if check is flow_analysis.REACHABLE:
@@ -154,10 +170,11 @@ def get_return_values(self, check_yields=False):
break
return context_set
- def _eval_yield(self, yield_expr):
+ def _get_yield_lazy_context(self, yield_expr):
if yield_expr.type == 'keyword':
# `yield` just yields None.
- yield LazyKnownContext(compiled.create(self.evaluator, None))
+ ctx = compiled.builtin_from_name(self.evaluator, u'None')
+ yield LazyKnownContext(ctx)
return
node = yield_expr.children[1]
@@ -169,7 +186,8 @@ def _eval_yield(self, yield_expr):
yield LazyTreeContext(self, node)
@recursion.execution_recursion_decorator(default=iter([]))
- def get_yield_values(self):
+ def get_yield_lazy_contexts(self, is_async=False):
+ # TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend
for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef',
'while_stmt', 'if_stmt'))
for y in get_yield_exprs(self.evaluator, self.tree_node)]
@@ -202,7 +220,7 @@ def get_yield_values(self):
if for_stmt is None:
# No for_stmt, just normal yields.
for yield_ in yields:
- for result in self._eval_yield(yield_):
+ for result in self._get_yield_lazy_context(yield_):
yield result
else:
input_node = for_stmt.get_testlist()
@@ -213,7 +231,7 @@ def get_yield_values(self):
dct = {str(for_stmt.children[1].value): lazy_context.infer()}
with helpers.predefine_names(self, for_stmt, dct):
for yield_in_same_for_stmt in yields:
- for result in self._eval_yield(yield_in_same_for_stmt):
+ for result in self._get_yield_lazy_context(yield_in_same_for_stmt):
yield result
def get_filters(self, search_global, until_position=None, origin_scope=None):
diff --git a/pythonFiles/jedi/evaluate/context/instance.py b/pythonFiles/jedi/evaluate/context/instance.py
index 2c8d796c9c6d..def5e19a2da9 100644
--- a/pythonFiles/jedi/evaluate/context/instance.py
+++ b/pythonFiles/jedi/evaluate/context/instance.py
@@ -1,6 +1,5 @@
from abc import abstractproperty
-from jedi._compatibility import is_py3
from jedi import debug
from jedi.evaluate import compiled
from jedi.evaluate import filters
@@ -16,30 +15,34 @@
from jedi.parser_utils import get_parent_scope
+class BaseInstanceFunctionExecution(FunctionExecutionContext):
+ def __init__(self, instance, *args, **kwargs):
+ self.instance = instance
+ super(BaseInstanceFunctionExecution, self).__init__(
+ instance.evaluator, *args, **kwargs)
+
-class InstanceFunctionExecution(FunctionExecutionContext):
+class InstanceFunctionExecution(BaseInstanceFunctionExecution):
def __init__(self, instance, parent_context, function_context, var_args):
- self.instance = instance
var_args = InstanceVarArgs(self, var_args)
super(InstanceFunctionExecution, self).__init__(
- instance.evaluator, parent_context, function_context, var_args)
+ instance, parent_context, function_context, var_args)
-class AnonymousInstanceFunctionExecution(FunctionExecutionContext):
+class AnonymousInstanceFunctionExecution(BaseInstanceFunctionExecution):
function_execution_filter = filters.AnonymousInstanceFunctionExecutionFilter
def __init__(self, instance, parent_context, function_context, var_args):
- self.instance = instance
super(AnonymousInstanceFunctionExecution, self).__init__(
- instance.evaluator, parent_context, function_context, var_args)
+ instance, parent_context, function_context, var_args)
class AbstractInstanceContext(Context):
"""
This class is used to evaluate instances.
"""
- api_type = 'instance'
+ api_type = u'instance'
function_execution_cls = InstanceFunctionExecution
def __init__(self, evaluator, parent_context, class_context, var_args):
@@ -54,7 +57,7 @@ def is_class(self):
@property
def py__call__(self):
- names = self.get_function_slot_names('__call__')
+ names = self.get_function_slot_names(u'__call__')
if not names:
# Means the Instance is not callable.
raise AttributeError
@@ -90,12 +93,12 @@ def execute_function_slots(self, names, *evaluated_args):
def py__get__(self, obj):
# Arguments in __get__ descriptors are obj, class.
# `method` is the new parent of the array, don't know if that's good.
- names = self.get_function_slot_names('__get__')
+ names = self.get_function_slot_names(u'__get__')
if names:
if isinstance(obj, AbstractInstanceContext):
return self.execute_function_slots(names, obj, obj.class_context)
else:
- none_obj = compiled.create(self.evaluator, None)
+ none_obj = compiled.builtin_from_name(self.evaluator, u'None')
return self.execute_function_slots(names, none_obj, obj)
else:
return ContextSet(self)
@@ -104,14 +107,12 @@ def get_filters(self, search_global=None, until_position=None,
origin_scope=None, include_self_names=True):
if include_self_names:
for cls in self.class_context.py__mro__():
- if isinstance(cls, compiled.CompiledObject):
- if cls.tree_node is not None:
- # In this case we're talking about a fake object, it
- # doesn't make sense for normal compiled objects to
- # search for self variables.
- yield SelfNameFilter(self.evaluator, self, cls, origin_scope)
- else:
- yield SelfNameFilter(self.evaluator, self, cls, origin_scope)
+ if not isinstance(cls, compiled.CompiledObject) \
+ or cls.tree_node is not None:
+ # In this case we're excluding compiled objects that are
+ # not fake objects. It doesn't make sense for normal
+ # compiled objects to search for self variables.
+ yield SelfAttributeFilter(self.evaluator, self, cls, origin_scope)
for cls in self.class_context.py__mro__():
if isinstance(cls, compiled.CompiledObject):
@@ -121,16 +122,16 @@ def get_filters(self, search_global=None, until_position=None,
def py__getitem__(self, index):
try:
- names = self.get_function_slot_names('__getitem__')
+ names = self.get_function_slot_names(u'__getitem__')
except KeyError:
debug.warning('No __getitem__, cannot access the array.')
return NO_CONTEXTS
else:
- index_obj = compiled.create(self.evaluator, index)
+ index_obj = compiled.create_simple_object(self.evaluator, index)
return self.execute_function_slots(names, index_obj)
def py__iter__(self):
- iter_slot_names = self.get_function_slot_names('__iter__')
+ iter_slot_names = self.get_function_slot_names(u'__iter__')
if not iter_slot_names:
debug.warning('No __iter__ on %s.' % self)
return
@@ -138,7 +139,10 @@ def py__iter__(self):
for generator in self.execute_function_slots(iter_slot_names):
if isinstance(generator, AbstractInstanceContext):
# `__next__` logic.
- name = '__next__' if is_py3 else 'next'
+ if self.evaluator.environment.version_info.major == 2:
+ name = u'next'
+ else:
+ name = u'__next__'
iter_slot_names = generator.get_function_slot_names(name)
if iter_slot_names:
yield LazyKnownContexts(
@@ -166,8 +170,8 @@ def _create_init_execution(self, class_context, func_node):
)
def create_init_executions(self):
- for name in self.get_function_slot_names('__init__'):
- if isinstance(name, LazyInstanceName):
+ for name in self.get_function_slot_names(u'__init__'):
+ if isinstance(name, SelfName):
yield self._create_init_execution(name.class_context, name.tree_name.parent)
@evaluator_method_cache()
@@ -189,7 +193,7 @@ def create_instance_context(self, class_context, node):
)
return bound_method.get_function_execution()
elif scope.type == 'classdef':
- class_context = ClassContext(self.evaluator, scope, parent_context)
+ class_context = ClassContext(self.evaluator, parent_context, scope)
return class_context
elif scope.type == 'comp_for':
# Comprehensions currently don't have a special scope in Jedi.
@@ -208,8 +212,10 @@ def __init__(self, *args, **kwargs):
super(CompiledInstance, self).__init__(*args, **kwargs)
# I don't think that dynamic append lookups should happen here. That
# sounds more like something that should go to py__iter__.
+ self._original_var_args = self.var_args
+
if self.class_context.name.string_name in ['list', 'set'] \
- and self.parent_context.get_root_context() == self.evaluator.BUILTINS:
+ and self.parent_context.get_root_context() == self.evaluator.builtins_module:
# compare the module path with the builtin name.
self.var_args = iterable.get_dynamic_array_instance(self)
@@ -223,6 +229,13 @@ def create_instance_context(self, class_context, node):
else:
return super(CompiledInstance, self).create_instance_context(class_context, node)
+ def get_first_non_keyword_argument_contexts(self):
+ key, lazy_context = next(self._original_var_args.unpack(), ('', None))
+ if key is not None:
+ return NO_CONTEXTS
+
+ return lazy_context.infer()
+
class TreeInstance(AbstractInstanceContext):
def __init__(self, evaluator, parent_context, class_context, var_args):
@@ -255,7 +268,8 @@ def __init__(self, evaluator, instance, parent_context, name):
@iterator_to_context_set
def infer(self):
for result_context in super(CompiledInstanceName, self).infer():
- if isinstance(result_context, FunctionContext):
+ is_function = result_context.api_type == 'function'
+ if result_context.tree_node is not None and is_function:
parent_context = result_context.parent_context
while parent_context.is_class():
parent_context = parent_context.parent_context
@@ -265,7 +279,7 @@ def infer(self):
parent_context, result_context.tree_node
)
else:
- if result_context.api_type == 'function':
+ if is_function:
yield CompiledBoundMethod(result_context)
else:
yield result_context
@@ -306,7 +320,7 @@ def get_function_execution(self, arguments=None):
class CompiledBoundMethod(compiled.CompiledObject):
def __init__(self, func):
super(CompiledBoundMethod, self).__init__(
- func.evaluator, func.obj, func.parent_context, func.tree_node)
+ func.evaluator, func.access_handle, func.parent_context, func.tree_node)
def get_param_names(self):
return list(super(CompiledBoundMethod, self).get_param_names())[1:]
@@ -317,7 +331,7 @@ def infer(self):
return super(InstanceNameDefinition, self).infer()
-class LazyInstanceName(filters.TreeNameDefinition):
+class SelfName(filters.TreeNameDefinition):
"""
This name calculates the parent_context lazily.
"""
@@ -331,7 +345,7 @@ def parent_context(self):
return self._instance.create_instance_context(self.class_context, self.tree_name)
-class LazyInstanceClassName(LazyInstanceName):
+class LazyInstanceClassName(SelfName):
@iterator_to_context_set
def infer(self):
for result_context in super(LazyInstanceClassName, self).infer():
@@ -384,8 +398,11 @@ def _convert_names(self, names):
return [self.name_class(self.context, self._class_context, name) for name in names]
-class SelfNameFilter(InstanceClassFilter):
- name_class = LazyInstanceName
+class SelfAttributeFilter(InstanceClassFilter):
+ """
+ This class basically filters all the use cases where `self.*` was assigned.
+ """
+ name_class = SelfName
def _filter(self, names):
names = self._filter_self_names(names)
diff --git a/pythonFiles/jedi/evaluate/context/iterable.py b/pythonFiles/jedi/evaluate/context/iterable.py
index d0f468e43425..df012f50dd8a 100644
--- a/pythonFiles/jedi/evaluate/context/iterable.py
+++ b/pythonFiles/jedi/evaluate/context/iterable.py
@@ -22,74 +22,56 @@
"""
from jedi import debug
from jedi import settings
+from jedi._compatibility import force_unicode, is_py3
+from jedi.cache import memoize_method
from jedi.evaluate import compiled
from jedi.evaluate import analysis
from jedi.evaluate import recursion
from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts, \
LazyTreeContext
-from jedi.evaluate.helpers import is_string, predefine_names, evaluate_call_of_leaf
+from jedi.evaluate.helpers import get_int_or_none, is_string, \
+ predefine_names, evaluate_call_of_leaf
from jedi.evaluate.utils import safe_property
from jedi.evaluate.utils import to_list
from jedi.evaluate.cache import evaluator_method_cache
-from jedi.evaluate.filters import ParserTreeFilter, has_builtin_methods, \
- register_builtin_method, SpecialMethodFilter
+from jedi.evaluate.filters import ParserTreeFilter, BuiltinOverwrite, \
+ publish_method
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, Context, \
TreeContext, ContextualizedNode
from jedi.parser_utils import get_comp_fors
-class AbstractIterable(Context):
- builtin_methods = {}
- api_type = 'instance'
+class IterableMixin(object):
+ def py__stop_iteration_returns(self):
+ return ContextSet(compiled.builtin_from_name(self.evaluator, u'None'))
- def __init__(self, evaluator):
- super(AbstractIterable, self).__init__(evaluator, evaluator.BUILTINS)
- def get_filters(self, search_global, until_position=None, origin_scope=None):
- raise NotImplementedError
-
- @property
- def name(self):
- return compiled.CompiledContextName(self, self.array_type)
-
-
-@has_builtin_methods
-class GeneratorMixin(object):
+class GeneratorBase(BuiltinOverwrite, IterableMixin):
array_type = None
+ special_object_identifier = u'GENERATOR_OBJECT'
- @register_builtin_method('send')
- @register_builtin_method('next', python_version_match=2)
- @register_builtin_method('__next__', python_version_match=3)
+ @publish_method('send')
+ @publish_method('next', python_version_match=2)
+ @publish_method('__next__', python_version_match=3)
def py__next__(self):
- # TODO add TypeError if params are given.
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
- def get_filters(self, search_global, until_position=None, origin_scope=None):
- gen_obj = compiled.get_special_object(self.evaluator, 'GENERATOR_OBJECT')
- yield SpecialMethodFilter(self, self.builtin_methods, gen_obj)
- for filter in gen_obj.get_filters(search_global):
- yield filter
-
- def py__bool__(self):
- return True
-
- def py__class__(self):
- gen_obj = compiled.get_special_object(self.evaluator, 'GENERATOR_OBJECT')
- return gen_obj.py__class__()
-
@property
def name(self):
return compiled.CompiledContextName(self, 'generator')
-class Generator(GeneratorMixin, Context):
+class Generator(GeneratorBase):
"""Handling of `yield` functions."""
def __init__(self, evaluator, func_execution_context):
- super(Generator, self).__init__(evaluator, parent_context=evaluator.BUILTINS)
+ super(Generator, self).__init__(evaluator)
self._func_execution_context = func_execution_context
def py__iter__(self):
- return self._func_execution_context.get_yield_values()
+ return self._func_execution_context.get_yield_lazy_contexts()
+
+ def py__stop_iteration_returns(self):
+ return self._func_execution_context.get_return_values()
def __repr__(self):
return "<%s of %s>" % (type(self).__name__, self._func_execution_context)
@@ -111,32 +93,33 @@ def get_filters(self, search_global, until_position=None, origin_scope=None):
yield ParserTreeFilter(self.evaluator, self)
-class Comprehension(AbstractIterable):
- @staticmethod
- def from_atom(evaluator, context, atom):
- bracket = atom.children[0]
- if bracket == '{':
- if atom.children[1].children[1] == ':':
- cls = DictComprehension
- else:
- cls = SetComprehension
- elif bracket == '(':
- cls = GeneratorComprehension
- elif bracket == '[':
- cls = ListComprehension
- return cls(evaluator, context, atom)
+def comprehension_from_atom(evaluator, context, atom):
+ bracket = atom.children[0]
+ if bracket == '{':
+ if atom.children[1].children[1] == ':':
+ cls = DictComprehension
+ else:
+ cls = SetComprehension
+ elif bracket == '(':
+ cls = GeneratorComprehension
+ elif bracket == '[':
+ cls = ListComprehension
+ return cls(evaluator, context, atom)
+
+class ComprehensionMixin(object):
def __init__(self, evaluator, defining_context, atom):
- super(Comprehension, self).__init__(evaluator)
+ super(ComprehensionMixin, self).__init__(evaluator)
self._defining_context = defining_context
self._atom = atom
def _get_comprehension(self):
+ "return 'a for a in b'"
# The atom contains a testlist_comp
return self._atom.children[1]
def _get_comp_for(self):
- # The atom contains a testlist_comp
+ "return CompFor('for a in b')"
return self._get_comprehension().children[1]
def _eval_node(self, index=0):
@@ -154,13 +137,17 @@ def _get_comp_for_context(self, parent_context, comp_for):
def _nested(self, comp_fors, parent_context=None):
comp_for = comp_fors[0]
- input_node = comp_for.children[3]
+
+ is_async = 'async' == comp_for.children[comp_for.children.index('for') - 1]
+
+ input_node = comp_for.children[comp_for.children.index('in') + 1]
parent_context = parent_context or self._defining_context
input_types = parent_context.eval_node(input_node)
+ # TODO: simulate await if self.is_async
cn = ContextualizedNode(parent_context, input_node)
- iterated = input_types.iterate(cn)
- exprlist = comp_for.children[1]
+ iterated = input_types.iterate(cn, is_async=is_async)
+ exprlist = comp_for.children[comp_for.children.index('for') + 1]
for i, lazy_context in enumerate(iterated):
types = lazy_context.infer()
dct = unpack_tuple_to_dict(parent_context, types, exprlist)
@@ -194,14 +181,18 @@ def __repr__(self):
return "<%s of %s>" % (type(self).__name__, self._atom)
-class ArrayMixin(object):
- def get_filters(self, search_global, until_position=None, origin_scope=None):
- # `array.type` is a string with the type, e.g. 'list'.
+class Sequence(BuiltinOverwrite, IterableMixin):
+ api_type = u'instance'
+
+ @property
+ def name(self):
+ return compiled.CompiledContextName(self, self.array_type)
+
+ @memoize_method
+ def get_object(self):
compiled_obj = compiled.builtin_from_name(self.evaluator, self.array_type)
- yield SpecialMethodFilter(self, self.builtin_methods, compiled_obj)
- for typ in compiled_obj.execute_evaluated(self):
- for filter in typ.get_filters():
- yield filter
+ only_obj, = compiled_obj.execute_evaluated(self)
+ return only_obj
def py__bool__(self):
return None # We don't know the length, because of appends.
@@ -211,7 +202,7 @@ def py__class__(self):
@safe_property
def parent(self):
- return self.evaluator.BUILTINS
+ return self.evaluator.builtins_module
def dict_values(self):
return ContextSet.from_sets(
@@ -220,8 +211,8 @@ def dict_values(self):
)
-class ListComprehension(ArrayMixin, Comprehension):
- array_type = 'list'
+class ListComprehension(ComprehensionMixin, Sequence):
+ array_type = u'list'
def py__getitem__(self, index):
if isinstance(index, slice):
@@ -231,13 +222,12 @@ def py__getitem__(self, index):
return all_types[index].infer()
-class SetComprehension(ArrayMixin, Comprehension):
- array_type = 'set'
+class SetComprehension(ComprehensionMixin, Sequence):
+ array_type = u'set'
-@has_builtin_methods
-class DictComprehension(ArrayMixin, Comprehension):
- array_type = 'dict'
+class DictComprehension(ComprehensionMixin, Sequence):
+ array_type = u'dict'
def _get_comp_for(self):
return self._get_comprehension().children[3]
@@ -250,38 +240,38 @@ def py__getitem__(self, index):
for keys, values in self._iterate():
for k in keys:
if isinstance(k, compiled.CompiledObject):
- if k.obj == index:
+ if k.get_safe_value(default=object()) == index:
return values
return self.dict_values()
def dict_values(self):
return ContextSet.from_sets(values for keys, values in self._iterate())
- @register_builtin_method('values')
+ @publish_method('values')
def _imitate_values(self):
lazy_context = LazyKnownContexts(self.dict_values())
- return ContextSet(FakeSequence(self.evaluator, 'list', [lazy_context]))
+ return ContextSet(FakeSequence(self.evaluator, u'list', [lazy_context]))
- @register_builtin_method('items')
+ @publish_method('items')
def _imitate_items(self):
items = ContextSet.from_iterable(
FakeSequence(
- self.evaluator, 'tuple'
+ self.evaluator, u'tuple'
(LazyKnownContexts(keys), LazyKnownContexts(values))
) for keys, values in self._iterate()
)
- return create_evaluated_sequence_set(self.evaluator, items, sequence_type='list')
+ return create_evaluated_sequence_set(self.evaluator, items, sequence_type=u'list')
-class GeneratorComprehension(GeneratorMixin, Comprehension):
+class GeneratorComprehension(ComprehensionMixin, GeneratorBase):
pass
-class SequenceLiteralContext(ArrayMixin, AbstractIterable):
- mapping = {'(': 'tuple',
- '[': 'list',
- '{': 'set'}
+class SequenceLiteralContext(Sequence):
+ mapping = {'(': u'tuple',
+ '[': u'list',
+ '{': u'set'}
def __init__(self, evaluator, defining_context, atom):
super(SequenceLiteralContext, self).__init__(evaluator)
@@ -289,18 +279,19 @@ def __init__(self, evaluator, defining_context, atom):
self._defining_context = defining_context
if self.atom.type in ('testlist_star_expr', 'testlist'):
- self.array_type = 'tuple'
+ self.array_type = u'tuple'
else:
self.array_type = SequenceLiteralContext.mapping[atom.children[0]]
"""The builtin name of the array (list, set, tuple or dict)."""
def py__getitem__(self, index):
"""Here the index is an int/str. Raises IndexError/KeyError."""
- if self.array_type == 'dict':
+ if self.array_type == u'dict':
+ compiled_obj_index = compiled.create_simple_object(self.evaluator, index)
for key, value in self._items():
for k in self._defining_context.eval_node(key):
if isinstance(k, compiled.CompiledObject) \
- and index == k.obj:
+ and k.execute_operation(compiled_obj_index, u'==').get_safe_value():
return self._defining_context.eval_node(value)
raise KeyError('No key found in dictionary %s.' % self)
@@ -315,7 +306,7 @@ def py__iter__(self):
While values returns the possible values for any array field, this
function returns the value for a certain index.
"""
- if self.array_type == 'dict':
+ if self.array_type == u'dict':
# Get keys.
types = ContextSet()
for k, _ in self._items():
@@ -333,7 +324,7 @@ def py__iter__(self):
def _values(self):
"""Returns a list of a list of node."""
- if self.array_type == 'dict':
+ if self.array_type == u'dict':
return ContextSet.from_sets(v for k, v in self._items())
else:
return self._items()
@@ -373,37 +364,36 @@ def exact_key_items(self):
for key_node, value in self._items():
for key in self._defining_context.eval_node(key_node):
if is_string(key):
- yield key.obj, LazyTreeContext(self._defining_context, value)
+ yield key.get_safe_value(), LazyTreeContext(self._defining_context, value)
def __repr__(self):
return "<%s of %s>" % (self.__class__.__name__, self.atom)
-@has_builtin_methods
class DictLiteralContext(SequenceLiteralContext):
- array_type = 'dict'
+ array_type = u'dict'
def __init__(self, evaluator, defining_context, atom):
super(SequenceLiteralContext, self).__init__(evaluator)
self._defining_context = defining_context
self.atom = atom
- @register_builtin_method('values')
+ @publish_method('values')
def _imitate_values(self):
lazy_context = LazyKnownContexts(self.dict_values())
- return ContextSet(FakeSequence(self.evaluator, 'list', [lazy_context]))
+ return ContextSet(FakeSequence(self.evaluator, u'list', [lazy_context]))
- @register_builtin_method('items')
+ @publish_method('items')
def _imitate_items(self):
lazy_contexts = [
LazyKnownContext(FakeSequence(
- self.evaluator, 'tuple',
+ self.evaluator, u'tuple',
(LazyTreeContext(self._defining_context, key_node),
LazyTreeContext(self._defining_context, value_node))
)) for key_node, value_node in self._items()
]
- return ContextSet(FakeSequence(self.evaluator, 'list', lazy_contexts))
+ return ContextSet(FakeSequence(self.evaluator, u'list', lazy_contexts))
class _FakeArray(SequenceLiteralContext):
@@ -437,16 +427,38 @@ def __repr__(self):
class FakeDict(_FakeArray):
def __init__(self, evaluator, dct):
- super(FakeDict, self).__init__(evaluator, dct, 'dict')
+ super(FakeDict, self).__init__(evaluator, dct, u'dict')
self._dct = dct
def py__iter__(self):
for key in self._dct:
- yield LazyKnownContext(compiled.create(self.evaluator, key))
+ yield LazyKnownContext(compiled.create_simple_object(self.evaluator, key))
def py__getitem__(self, index):
+ if is_py3 and self.evaluator.environment.version_info.major == 2:
+ # In Python 2 bytes and unicode compare.
+ if isinstance(index, bytes):
+ index_unicode = force_unicode(index)
+ try:
+ return self._dct[index_unicode].infer()
+ except KeyError:
+ pass
+ elif isinstance(index, str):
+ index_bytes = index.encode('utf-8')
+ try:
+ return self._dct[index_bytes].infer()
+ except KeyError:
+ pass
+
return self._dct[index].infer()
+ @publish_method('values')
+ def _values(self):
+ return ContextSet(FakeSequence(
+ self.evaluator, u'tuple',
+ [LazyKnownContexts(self.dict_values())]
+ ))
+
def dict_values(self):
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self._dct.values())
@@ -649,7 +661,7 @@ def py__iter__(self):
for addition in additions:
yield addition
- def iterate(self, contextualized_node=None):
+ def iterate(self, contextualized_node=None, is_async=False):
return self.py__iter__()
@@ -657,7 +669,7 @@ class Slice(Context):
def __init__(self, context, start, stop, step):
super(Slice, self).__init__(
context.evaluator,
- parent_context=context.evaluator.BUILTINS
+ parent_context=context.evaluator.builtins_module
)
self._context = context
# all of them are either a Precedence or None.
@@ -680,10 +692,9 @@ def get(element):
# For simplicity, we want slices to be clear defined with just
# one type. Otherwise we will return an empty slice object.
raise IndexError
- try:
- return list(result)[0].obj
- except AttributeError:
- return None
+
+ context, = result
+ return get_int_or_none(context)
try:
return slice(get(self._start), get(self._stop), get(self._step))
diff --git a/pythonFiles/jedi/evaluate/context/klass.py b/pythonFiles/jedi/evaluate/context/klass.py
index b7d61d3e16bf..3157250161e2 100644
--- a/pythonFiles/jedi/evaluate/context/klass.py
+++ b/pythonFiles/jedi/evaluate/context/klass.py
@@ -89,7 +89,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
This class is not only important to extend `tree.Class`, it is also a
important for descriptors (if the descriptor methods are evaluated or not).
"""
- api_type = 'class'
+ api_type = u'class'
def __init__(self, evaluator, parent_context, classdef):
super(ClassContext, self).__init__(evaluator, parent_context=parent_context)
@@ -136,17 +136,17 @@ def py__bases__(self):
arglist = self.tree_node.get_super_arglist()
if arglist:
from jedi.evaluate import arguments
- args = arguments.TreeArguments(self.evaluator, self, arglist)
+ args = arguments.TreeArguments(self.evaluator, self.parent_context, arglist)
return [value for key, value in args.unpack() if key is None]
else:
- return [LazyKnownContext(compiled.create(self.evaluator, object))]
+ return [LazyKnownContext(compiled.builtin_from_name(self.evaluator, u'object'))]
def py__call__(self, params):
from jedi.evaluate.context import TreeInstance
return ContextSet(TreeInstance(self.evaluator, self.parent_context, self, params))
def py__class__(self):
- return compiled.create(self.evaluator, type)
+ return compiled.builtin_from_name(self.evaluator, u'type')
def get_params(self):
from jedi.evaluate.context import AnonymousInstance
@@ -182,7 +182,7 @@ def get_function_slot_names(self, name):
return []
def get_param_names(self):
- for name in self.get_function_slot_names('__init__'):
+ for name in self.get_function_slot_names(u'__init__'):
for context_ in name.infer():
try:
method = context_.get_param_names
diff --git a/pythonFiles/jedi/evaluate/context/module.py b/pythonFiles/jedi/evaluate/context/module.py
index 5ba92cdb1c3e..8d4da11bc91a 100644
--- a/pythonFiles/jedi/evaluate/context/module.py
+++ b/pythonFiles/jedi/evaluate/context/module.py
@@ -1,14 +1,12 @@
-import pkgutil
-import imp
import re
import os
from parso import python_bytes_to_unicode
-from jedi._compatibility import use_metaclass
-from jedi.evaluate.cache import CachedMetaClass, evaluator_method_cache
+from jedi.evaluate.cache import evaluator_method_cache
+from jedi._compatibility import iter_modules, all_suffixes
from jedi.evaluate.filters import GlobalNameFilter, ContextNameMixin, \
- AbstractNameDefinition, ParserTreeFilter, DictFilter
+ AbstractNameDefinition, ParserTreeFilter, DictFilter, MergedFilter
from jedi.evaluate import compiled
from jedi.evaluate.base_context import TreeContext
from jedi.evaluate.imports import SubModuleName, infer_import
@@ -18,14 +16,14 @@ class _ModuleAttributeName(AbstractNameDefinition):
"""
For module attributes like __file__, __str__ and so on.
"""
- api_type = 'instance'
+ api_type = u'instance'
def __init__(self, parent_module, string_name):
self.parent_context = parent_module
self.string_name = string_name
def infer(self):
- return compiled.create(self.parent_context.evaluator, str).execute_evaluated()
+ return compiled.get_string_context_set(self.parent_context.evaluator)
class ModuleName(ContextNameMixin, AbstractNameDefinition):
@@ -40,23 +38,26 @@ def string_name(self):
return self._name
-class ModuleContext(use_metaclass(CachedMetaClass, TreeContext)):
- api_type = 'module'
+class ModuleContext(TreeContext):
+ api_type = u'module'
parent_context = None
- def __init__(self, evaluator, module_node, path):
+ def __init__(self, evaluator, module_node, path, code_lines):
super(ModuleContext, self).__init__(evaluator, parent_context=None)
self.tree_node = module_node
self._path = path
+ self.code_lines = code_lines
def get_filters(self, search_global, until_position=None, origin_scope=None):
- yield ParserTreeFilter(
- self.evaluator,
- context=self,
- until_position=until_position,
- origin_scope=origin_scope
+ yield MergedFilter(
+ ParserTreeFilter(
+ self.evaluator,
+ context=self,
+ until_position=until_position,
+ origin_scope=origin_scope
+ ),
+ GlobalNameFilter(self, self.tree_node),
)
- yield GlobalNameFilter(self, self.tree_node)
yield DictFilter(self._sub_modules_dict())
yield DictFilter(self._module_attributes_dict())
for star_module in self.star_imports():
@@ -64,7 +65,7 @@ def get_filters(self, search_global, until_position=None, origin_scope=None):
# I'm not sure if the star import cache is really that effective anymore
# with all the other really fast import caches. Recheck. Also we would need
- # to push the star imports into Evaluator.modules, if we reenable this.
+ # to push the star imports into Evaluator.module_cache, if we reenable this.
@evaluator_method_cache([])
def star_imports(self):
modules = []
@@ -93,7 +94,7 @@ def _string_name(self):
sep = (re.escape(os.path.sep),) * 2
r = re.search(r'([^%s]*?)(%s__init__)?(\.py|\.so)?$' % sep, self._path)
# Remove PEP 3149 names
- return re.sub('\.[a-z]+-\d{2}[mud]{0,3}$', '', r.group(1))
+ return re.sub(r'\.[a-z]+-\d{2}[mud]{0,3}$', '', r.group(1))
@property
@evaluator_method_cache()
@@ -105,7 +106,7 @@ def _get_init_directory(self):
:return: The path to the directory of a package. None in case it's not
a package.
"""
- for suffix, _, _ in imp.get_suffixes():
+ for suffix in all_suffixes():
ending = '__init__' + suffix
py__file__ = self.py__file__()
if py__file__ is not None and py__file__.endswith(ending):
@@ -114,7 +115,7 @@ def _get_init_directory(self):
return None
def py__name__(self):
- for name, module in self.evaluator.modules.items():
+ for name, module in self.evaluator.module_cache.iterate_modules_with_names():
if module == self and name != '':
return name
@@ -131,12 +132,12 @@ def py__file__(self):
def py__package__(self):
if self._get_init_directory() is None:
- return re.sub(r'\.?[^\.]+$', '', self.py__name__())
+ return re.sub(r'\.?[^.]+$', '', self.py__name__())
else:
return self.py__name__()
def _py__path__(self):
- search_path = self.evaluator.project.sys_path
+ search_path = self.evaluator.get_sys_path()
init_path = self.py__file__()
if os.path.basename(init_path) == '__init__.py':
with open(init_path, 'rb') as f:
@@ -188,7 +189,7 @@ def _sub_modules_dict(self):
path = self._path
names = {}
if path is not None and path.endswith(os.path.sep + '__init__.py'):
- mods = pkgutil.iter_modules([os.path.dirname(path)])
+ mods = iter_modules([os.path.dirname(path)])
for module_loader, name, is_pkg in mods:
# It's obviously a relative import to the current module.
names[name] = SubModuleName(self, name)
@@ -203,11 +204,9 @@ def _sub_modules_dict(self):
return names
def py__class__(self):
- return compiled.get_special_object(self.evaluator, 'MODULE_CLASS')
+ return compiled.get_special_object(self.evaluator, u'MODULE_CLASS')
def __repr__(self):
return "<%s: %s@%s-%s>" % (
self.__class__.__name__, self._string_name,
self.tree_node.start_pos[0], self.tree_node.end_pos[0])
-
-
diff --git a/pythonFiles/jedi/evaluate/context/namespace.py b/pythonFiles/jedi/evaluate/context/namespace.py
index e40c23a5e8ca..380d7c2270b9 100644
--- a/pythonFiles/jedi/evaluate/context/namespace.py
+++ b/pythonFiles/jedi/evaluate/context/namespace.py
@@ -1,11 +1,10 @@
import os
from itertools import chain
-from jedi._compatibility import use_metaclass
-from jedi.evaluate.cache import evaluator_method_cache, CachedMetaClass
+from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate import imports
from jedi.evaluate.filters import DictFilter, AbstractNameDefinition
-from jedi.evaluate.base_context import NO_CONTEXTS, TreeContext
+from jedi.evaluate.base_context import TreeContext, ContextSet
class ImplicitNSName(AbstractNameDefinition):
@@ -14,27 +13,31 @@ class ImplicitNSName(AbstractNameDefinition):
This object will prevent Jedi from raising exceptions
"""
def __init__(self, implicit_ns_context, string_name):
- self.implicit_ns_context = implicit_ns_context
+ self.parent_context = implicit_ns_context
self.string_name = string_name
def infer(self):
- return NO_CONTEXTS
+ return ContextSet(self.parent_context)
def get_root_context(self):
- return self.implicit_ns_context
+ return self.parent_context
-class ImplicitNamespaceContext(use_metaclass(CachedMetaClass, TreeContext)):
+class ImplicitNamespaceContext(TreeContext):
"""
Provides support for implicit namespace packages
"""
- api_type = 'module'
+ # Is a module like every other module, because if you import an empty
+ # folder foobar it will be available as an object:
+ # .
+ api_type = u'module'
parent_context = None
- def __init__(self, evaluator, fullname):
+ def __init__(self, evaluator, fullname, paths):
super(ImplicitNamespaceContext, self).__init__(evaluator, parent_context=None)
self.evaluator = evaluator
- self.fullname = fullname
+ self._fullname = fullname
+ self.paths = paths
def get_filters(self, search_global, until_position=None, origin_scope=None):
yield DictFilter(self._sub_modules_dict())
@@ -51,7 +54,7 @@ def py__file__(self):
def py__package__(self):
"""Return the fullname
"""
- return self.fullname
+ return self._fullname
@property
def py__path__(self):
@@ -61,8 +64,7 @@ def py__path__(self):
def _sub_modules_dict(self):
names = {}
- paths = self.paths
- file_names = chain.from_iterable(os.listdir(path) for path in paths)
+ file_names = chain.from_iterable(os.listdir(path) for path in self.paths)
mods = [
file_name.rpartition('.')[0] if '.' in file_name else file_name
for file_name in file_names
diff --git a/pythonFiles/jedi/evaluate/docstrings.py b/pythonFiles/jedi/evaluate/docstrings.py
index f9c1141226e9..a927abd09028 100644
--- a/pythonFiles/jedi/evaluate/docstrings.py
+++ b/pythonFiles/jedi/evaluate/docstrings.py
@@ -18,7 +18,7 @@
import re
from textwrap import dedent
-from parso import parse
+from parso import parse, ParserSyntaxError
from jedi._compatibility import u
from jedi.evaluate.utils import indent_block
@@ -42,49 +42,59 @@
REST_ROLE_PATTERN = re.compile(r':[^`]+:`([^`]+)`')
-try:
- from numpydoc.docscrape import NumpyDocString
-except ImportError:
- def _search_param_in_numpydocstr(docstr, param_str):
- return []
+_numpy_doc_string_cache = None
- def _search_return_in_numpydocstr(docstr):
- return []
-else:
- def _search_param_in_numpydocstr(docstr, param_str):
- """Search `docstr` (in numpydoc format) for type(-s) of `param_str`."""
- try:
- # This is a non-public API. If it ever changes we should be
- # prepared and return gracefully.
- params = NumpyDocString(docstr)._parsed_data['Parameters']
- except (KeyError, AttributeError):
- return []
- for p_name, p_type, p_descr in params:
- if p_name == param_str:
- m = re.match('([^,]+(,[^,]+)*?)(,[ ]*optional)?$', p_type)
- if m:
- p_type = m.group(1)
- return list(_expand_typestr(p_type))
+
+def _get_numpy_doc_string_cls():
+ global _numpy_doc_string_cache
+ try:
+ from numpydoc.docscrape import NumpyDocString
+ _numpy_doc_string_cache = NumpyDocString
+ except ImportError as e:
+ _numpy_doc_string_cache = e
+ if isinstance(_numpy_doc_string_cache, ImportError):
+ raise _numpy_doc_string_cache
+ return _numpy_doc_string_cache
+
+
+def _search_param_in_numpydocstr(docstr, param_str):
+ """Search `docstr` (in numpydoc format) for type(-s) of `param_str`."""
+ try:
+ # This is a non-public API. If it ever changes we should be
+ # prepared and return gracefully.
+ params = _get_numpy_doc_string_cls()(docstr)._parsed_data['Parameters']
+ except (KeyError, AttributeError, ImportError):
return []
+ for p_name, p_type, p_descr in params:
+ if p_name == param_str:
+ m = re.match('([^,]+(,[^,]+)*?)(,[ ]*optional)?$', p_type)
+ if m:
+ p_type = m.group(1)
+ return list(_expand_typestr(p_type))
+ return []
- def _search_return_in_numpydocstr(docstr):
- """
- Search `docstr` (in numpydoc format) for type(-s) of function returns.
- """
- doc = NumpyDocString(docstr)
- try:
- # This is a non-public API. If it ever changes we should be
- # prepared and return gracefully.
- returns = doc._parsed_data['Returns']
- returns += doc._parsed_data['Yields']
- except (KeyError, AttributeError):
- raise StopIteration
- for r_name, r_type, r_descr in returns:
- #Return names are optional and if so the type is in the name
- if not r_type:
- r_type = r_name
- for type_ in _expand_typestr(r_type):
- yield type_
+
+def _search_return_in_numpydocstr(docstr):
+ """
+ Search `docstr` (in numpydoc format) for type(-s) of function returns.
+ """
+ try:
+ doc = _get_numpy_doc_string_cls()(docstr)
+ except ImportError:
+ return
+ try:
+ # This is a non-public API. If it ever changes we should be
+ # prepared and return gracefully.
+ returns = doc._parsed_data['Returns']
+ returns += doc._parsed_data['Yields']
+ except (KeyError, AttributeError):
+ return
+ for r_name, r_type, r_descr in returns:
+ # Return names are optional and if so the type is in the name
+ if not r_type:
+ r_type = r_name
+ for type_ in _expand_typestr(r_type):
+ yield type_
def _expand_typestr(type_str):
@@ -145,8 +155,7 @@ def _search_param_in_docstr(docstr, param_str):
if match:
return [_strip_rst_role(match.group(1))]
- return (_search_param_in_numpydocstr(docstr, param_str) or
- [])
+ return _search_param_in_numpydocstr(docstr, param_str)
def _strip_rst_role(type_str):
@@ -179,7 +188,7 @@ def pseudo_docstring_stuff():
Need this docstring so that if the below part is not valid Python this
is still a function.
'''
- {0}
+ {}
"""))
if string is None:
return []
@@ -193,7 +202,10 @@ def pseudo_docstring_stuff():
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
# don't need to conform with the current grammar.
grammar = module_context.evaluator.latest_grammar
- module = grammar.parse(code.format(indent_block(string)))
+ try:
+ module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
+ except ParserSyntaxError:
+ return []
try:
funcdef = next(module.iter_funcdefs())
# First pick suite, then simple_stmt and then the node,
@@ -243,7 +255,7 @@ def _execute_array_values(evaluator, array):
for typ in lazy_context.infer()
)
values.append(LazyKnownContexts(objects))
- return set([FakeSequence(evaluator, array.array_type, values)])
+ return {FakeSequence(evaluator, array.array_type, values)}
else:
return array.execute_evaluated()
diff --git a/pythonFiles/jedi/evaluate/dynamic.py b/pythonFiles/jedi/evaluate/dynamic.py
index 7d05000dc9d5..9e8d57144bdb 100644
--- a/pythonFiles/jedi/evaluate/dynamic.py
+++ b/pythonFiles/jedi/evaluate/dynamic.py
@@ -73,24 +73,33 @@ def search_params(evaluator, execution_context, funcdef):
# you will see the slowdown, especially in 3.6.
return create_default_params(execution_context, funcdef)
- debug.dbg('Dynamic param search in %s.', funcdef.name.value, color='MAGENTA')
-
- module_context = execution_context.get_root_context()
- function_executions = _search_function_executions(
- evaluator,
- module_context,
- funcdef
- )
- if function_executions:
- zipped_params = zip(*list(
- function_execution.get_params()
- for function_execution in function_executions
- ))
- params = [MergedExecutedParams(executed_params) for executed_params in zipped_params]
- # Evaluate the ExecutedParams to types.
+ if funcdef.type == 'lambdef':
+ string_name = _get_lambda_name(funcdef)
+ if string_name is None:
+ return create_default_params(execution_context, funcdef)
else:
- return create_default_params(execution_context, funcdef)
- debug.dbg('Dynamic param result finished', color='MAGENTA')
+ string_name = funcdef.name.value
+ debug.dbg('Dynamic param search in %s.', string_name, color='MAGENTA')
+
+ try:
+ module_context = execution_context.get_root_context()
+ function_executions = _search_function_executions(
+ evaluator,
+ module_context,
+ funcdef,
+ string_name=string_name,
+ )
+ if function_executions:
+ zipped_params = zip(*list(
+ function_execution.get_params()
+ for function_execution in function_executions
+ ))
+ params = [MergedExecutedParams(executed_params) for executed_params in zipped_params]
+ # Evaluate the ExecutedParams to types.
+ else:
+ return create_default_params(execution_context, funcdef)
+ finally:
+ debug.dbg('Dynamic param result finished', color='MAGENTA')
return params
finally:
evaluator.dynamic_params_depth -= 1
@@ -98,25 +107,24 @@ def search_params(evaluator, execution_context, funcdef):
@evaluator_function_cache(default=None)
@to_list
-def _search_function_executions(evaluator, module_context, funcdef):
+def _search_function_executions(evaluator, module_context, funcdef, string_name):
"""
Returns a list of param names.
"""
- func_string_name = funcdef.name.value
compare_node = funcdef
- if func_string_name == '__init__':
+ if string_name == '__init__':
cls = get_parent_scope(funcdef)
if isinstance(cls, tree.Class):
- func_string_name = cls.name.value
+ string_name = cls.name.value
compare_node = cls
found_executions = False
i = 0
for for_mod_context in imports.get_modules_containing_name(
- evaluator, [module_context], func_string_name):
+ evaluator, [module_context], string_name):
if not isinstance(module_context, ModuleContext):
return
- for name, trailer in _get_possible_nodes(for_mod_context, func_string_name):
+ for name, trailer in _get_possible_nodes(for_mod_context, string_name):
i += 1
# This is a simple way to stop Jedi's dynamic param recursion
@@ -137,6 +145,18 @@ def _search_function_executions(evaluator, module_context, funcdef):
return
+def _get_lambda_name(node):
+ stmt = node.parent
+ if stmt.type == 'expr_stmt':
+ first_operator = next(stmt.yield_operators(), None)
+ if first_operator == '=':
+ first = stmt.children[0]
+ if first.type == 'name':
+ return first.value
+
+ return None
+
+
def _get_possible_nodes(module_context, func_string_name):
try:
names = module_context.tree_node.get_used_names()[func_string_name]
@@ -156,11 +176,9 @@ def _check_name_for_execution(evaluator, context, compare_node, name, trailer):
def create_func_excs():
arglist = trailer.children[1]
if arglist == ')':
- arglist = ()
+ arglist = None
args = TreeArguments(evaluator, context, arglist, trailer)
- if value_node.type == 'funcdef':
- yield value.get_function_execution(args)
- else:
+ if value_node.type == 'classdef':
created_instance = instance.TreeInstance(
evaluator,
value.parent_context,
@@ -169,6 +187,8 @@ def create_func_excs():
)
for execution in created_instance.create_init_executions():
yield execution
+ else:
+ yield value.get_function_execution(args)
for value in evaluator.goto_definitions(context, name):
value_node = value.tree_node
diff --git a/pythonFiles/jedi/evaluate/filters.py b/pythonFiles/jedi/evaluate/filters.py
index 35dff9dace65..4294f2a60004 100644
--- a/pythonFiles/jedi/evaluate/filters.py
+++ b/pythonFiles/jedi/evaluate/filters.py
@@ -6,7 +6,8 @@
from parso.tree import search_ancestor
-from jedi._compatibility import is_py3
+from jedi._compatibility import use_metaclass, Parameter
+from jedi.cache import memoize_method
from jedi.evaluate import flow_analysis
from jedi.evaluate.base_context import ContextSet, Context
from jedi.parser_utils import get_parent_scope
@@ -27,7 +28,7 @@ def infer(self):
def goto(self):
# Typically names are already definitions and therefore a goto on that
# name will always result on itself.
- return set([self])
+ return {self}
def get_root_context(self):
return self.parent_context.get_root_context()
@@ -43,6 +44,9 @@ def execute(self, arguments):
def execute_evaluated(self, *args, **kwargs):
return self.infer().execute_evaluated(*args, **kwargs)
+ def is_import(self):
+ return False
+
@property
def api_type(self):
return self.parent_context.api_type
@@ -56,6 +60,10 @@ def __init__(self, parent_context, tree_name):
def goto(self):
return self.parent_context.evaluator.goto(self.parent_context, self.tree_name)
+ def is_import(self):
+ imp = search_ancestor(self.tree_name, 'import_from', 'import_name')
+ return imp is not None
+
@property
def string_name(self):
return self.tree_name.value
@@ -108,12 +116,28 @@ def api_type(self):
class ParamName(AbstractTreeName):
- api_type = 'param'
+ api_type = u'param'
def __init__(self, parent_context, tree_name):
self.parent_context = parent_context
self.tree_name = tree_name
+ def get_kind(self):
+ tree_param = search_ancestor(self.tree_name, 'param')
+ if tree_param.star_count == 1: # *args
+ return Parameter.VAR_POSITIONAL
+ if tree_param.star_count == 2: # **kwargs
+ return Parameter.VAR_KEYWORD
+
+ parent = tree_param.parent
+ for p in parent.children:
+ if p.type == 'param':
+ if p.star_count:
+ return Parameter.KEYWORD_ONLY
+ if p == tree_param:
+ break
+ return Parameter.POSITIONAL_OR_KEYWORD
+
def infer(self):
return self.get_param().infer()
@@ -163,7 +187,7 @@ def __init__(self, context, parser_scope):
def get(self, name):
try:
- names = self._used_names[str(name)]
+ names = self._used_names[name]
except KeyError:
return []
@@ -213,7 +237,10 @@ def _is_name_reachable(self, name):
def _check_flows(self, names):
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
check = flow_analysis.reachability_check(
- self._node_context, self._parser_scope, name, self._origin_scope
+ context=self._node_context,
+ context_scope=self._parser_scope,
+ node=name,
+ origin_scope=self._origin_scope
)
if check is not flow_analysis.UNREACHABLE:
yield name
@@ -266,22 +293,42 @@ def __init__(self, dct):
def get(self, name):
try:
- value = self._convert(name, self._dct[str(name)])
+ value = self._convert(name, self._dct[name])
except KeyError:
return []
-
- return list(self._filter([value]))
+ else:
+ return list(self._filter([value]))
def values(self):
- return self._filter(self._convert(*item) for item in self._dct.items())
+ def yielder():
+ for item in self._dct.items():
+ try:
+ yield self._convert(*item)
+ except KeyError:
+ pass
+ return self._filter(yielder())
def _convert(self, name, value):
return value
+class MergedFilter(object):
+ def __init__(self, *filters):
+ self._filters = filters
+
+ def get(self, name):
+ return [n for filter in self._filters for n in filter.get(name)]
+
+ def values(self):
+ return [n for filter in self._filters for n in filter.values()]
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(str(f) for f in self._filters))
+
+
class _BuiltinMappedMethod(Context):
"""``Generator.__next__`` ``dict.values`` methods and so on."""
- api_type = 'function'
+ api_type = u'function'
def __init__(self, builtin_context, method, builtin_func):
super(_BuiltinMappedMethod, self).__init__(
@@ -292,6 +339,7 @@ def __init__(self, builtin_context, method, builtin_func):
self._builtin_func = builtin_func
def py__call__(self, params):
+ # TODO add TypeError if params are given/or not correct.
return self._method(self.parent_context)
def __getattr__(self, name):
@@ -304,21 +352,33 @@ class SpecialMethodFilter(DictFilter):
classes like Generator (for __next__, etc).
"""
class SpecialMethodName(AbstractNameDefinition):
- api_type = 'function'
+ api_type = u'function'
+
+ def __init__(self, parent_context, string_name, value, builtin_context):
+ callable_, python_version = value
+ if python_version is not None and \
+ python_version != parent_context.evaluator.environment.version_info.major:
+ raise KeyError
- def __init__(self, parent_context, string_name, callable_, builtin_context):
self.parent_context = parent_context
self.string_name = string_name
self._callable = callable_
self._builtin_context = builtin_context
def infer(self):
- filter = next(self._builtin_context.get_filters())
- # We can take the first index, because on builtin methods there's
- # always only going to be one name. The same is true for the
- # inferred values.
- builtin_func = next(iter(filter.get(self.string_name)[0].infer()))
- return ContextSet(_BuiltinMappedMethod(self.parent_context, self._callable, builtin_func))
+ for filter in self._builtin_context.get_filters():
+ # We can take the first index, because on builtin methods there's
+ # always only going to be one name. The same is true for the
+ # inferred values.
+ for name in filter.get(self.string_name):
+ builtin_func = next(iter(name.infer()))
+ break
+ else:
+ continue
+ break
+ return ContextSet(
+ _BuiltinMappedMethod(self.parent_context, self._callable, builtin_func)
+ )
def __init__(self, context, dct, builtin_context):
super(SpecialMethodFilter, self).__init__(dct)
@@ -335,34 +395,58 @@ def _convert(self, name, value):
return self.SpecialMethodName(self.context, name, value, self._builtin_context)
-def has_builtin_methods(cls):
- base_dct = {}
- # Need to care properly about inheritance. Builtin Methods should not get
- # lost, just because they are not mentioned in a class.
- for base_cls in reversed(cls.__bases__):
- try:
- base_dct.update(base_cls.builtin_methods)
- except AttributeError:
- pass
+class _OverwriteMeta(type):
+ def __init__(cls, name, bases, dct):
+ super(_OverwriteMeta, cls).__init__(name, bases, dct)
- cls.builtin_methods = base_dct
- for func in cls.__dict__.values():
- try:
- cls.builtin_methods.update(func.registered_builtin_methods)
- except AttributeError:
- pass
- return cls
-
-
-def register_builtin_method(method_name, python_version_match=None):
- def wrapper(func):
- if python_version_match and python_version_match != 2 + int(is_py3):
- # Some functions do only apply to certain versions.
- return func
- dct = func.__dict__.setdefault('registered_builtin_methods', {})
- dct[method_name] = func
+ base_dct = {}
+ for base_cls in reversed(cls.__bases__):
+ try:
+ base_dct.update(base_cls.overwritten_methods)
+ except AttributeError:
+ pass
+
+ for func in cls.__dict__.values():
+ try:
+ base_dct.update(func.registered_overwritten_methods)
+ except AttributeError:
+ pass
+ cls.overwritten_methods = base_dct
+
+
+class AbstractObjectOverwrite(use_metaclass(_OverwriteMeta, object)):
+ def get_object(self):
+ raise NotImplementedError
+
+ def get_filters(self, search_global, *args, **kwargs):
+ yield SpecialMethodFilter(self, self.overwritten_methods, self.get_object())
+
+ for filter in self.get_object().get_filters(search_global):
+ yield filter
+
+
+class BuiltinOverwrite(Context, AbstractObjectOverwrite):
+ special_object_identifier = None
+
+ def __init__(self, evaluator):
+ super(BuiltinOverwrite, self).__init__(evaluator, evaluator.builtins_module)
+
+ @memoize_method
+ def get_object(self):
+ from jedi.evaluate import compiled
+ assert self.special_object_identifier
+ return compiled.get_special_object(self.evaluator, self.special_object_identifier)
+
+ def py__class__(self):
+ return self.get_object().py__class__()
+
+
+def publish_method(method_name, python_version_match=None):
+ def decorator(func):
+ dct = func.__dict__.setdefault('registered_overwritten_methods', {})
+ dct[method_name] = func, python_version_match
return func
- return wrapper
+ return decorator
def get_global_filters(evaluator, context, until_position, origin_scope):
@@ -379,40 +463,37 @@ def get_global_filters(evaluator, context, until_position, origin_scope):
... def func():
... y = None
... '''))
- >>> module_node = script._get_module_node()
+ >>> module_node = script._module_node
>>> scope = next(module_node.iter_funcdefs())
>>> scope
>>> context = script._get_module().create_context(scope)
>>> filters = list(get_global_filters(context.evaluator, context, (4, 0), None))
- First we get the names names from the function scope.
+ First we get the names from the function scope.
- >>> no_unicode_pprint(filters[0])
- >
+ >>> no_unicode_pprint(filters[0]) #doctest: +ELLIPSIS
+ MergedFilter(, )
>>> sorted(str(n) for n in filters[0].values())
['', '']
- >>> filters[0]._until_position
+ >>> filters[0]._filters[0]._until_position
(4, 0)
+ >>> filters[0]._filters[1]._until_position
Then it yields the names from one level "lower". In this example, this is
- the module scope. As a side note, you can see, that the position in the
- filter is now None, because typically the whole module is loaded before the
- function is called.
+ the module scope (including globals).
+ As a side note, you can see, that the position in the filter is None on the
+ globals filter, because there the whole module is searched.
- >>> filters[1].values() # global names -> there are none in our example.
- []
- >>> list(filters[2].values()) # package modules -> Also empty.
+ >>> list(filters[1].values()) # package modules -> Also empty.
[]
- >>> sorted(name.string_name for name in filters[3].values()) # Module attributes
+ >>> sorted(name.string_name for name in filters[2].values()) # Module attributes
['__doc__', '__file__', '__name__', '__package__']
- >>> print(filters[1]._until_position)
- None
Finally, it yields the builtin filter, if `include_builtin` is
true (default).
- >>> filters[4].values() #doctest: +ELLIPSIS
+ >>> filters[3].values() #doctest: +ELLIPSIS
[, ...]
"""
from jedi.evaluate.context.function import FunctionExecutionContext
@@ -430,5 +511,5 @@ def get_global_filters(evaluator, context, until_position, origin_scope):
context = context.parent_context
# Add builtins to the global scope.
- for filter in evaluator.BUILTINS.get_filters(search_global=True):
+ for filter in evaluator.builtins_module.get_filters(search_global=True):
yield filter
diff --git a/pythonFiles/jedi/evaluate/finder.py b/pythonFiles/jedi/evaluate/finder.py
index 96032ae9b792..5e7043f79600 100644
--- a/pythonFiles/jedi/evaluate/finder.py
+++ b/pythonFiles/jedi/evaluate/finder.py
@@ -56,7 +56,10 @@ def find(self, filters, attribute_lookup):
names = self.filter_name(filters)
if self._found_predefined_types is not None and names:
check = flow_analysis.reachability_check(
- self._context, self._context.tree_node, self._name)
+ context=self._context,
+ context_scope=self._context.tree_node,
+ node=self._name,
+ )
if check is flow_analysis.UNREACHABLE:
return ContextSet()
return self._found_predefined_types
@@ -92,7 +95,26 @@ def _get_origin_scope(self):
def get_filters(self, search_global=False):
origin_scope = self._get_origin_scope()
if search_global:
- return get_global_filters(self._evaluator, self._context, self._position, origin_scope)
+ position = self._position
+
+ # For functions and classes the defaults don't belong to the
+ # function and get evaluated in the context before the function. So
+ # make sure to exclude the function/class name.
+ if origin_scope is not None:
+ ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef', 'lambdef')
+ lambdef = None
+ if ancestor == 'lambdef':
+ # For lambdas it's even more complicated since parts will
+ # be evaluated later.
+ lambdef = ancestor
+ ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef')
+ if ancestor is not None:
+ colon = ancestor.children[-2]
+ if position < colon.start_pos:
+ if lambdef is None or position < lambdef.children[-2].start_pos:
+ position = ancestor.start_pos
+
+ return get_global_filters(self._evaluator, self._context, position, origin_scope)
else:
return self._context.get_filters(search_global, self._position, origin_scope=origin_scope)
@@ -102,8 +124,7 @@ def filter_name(self, filters):
``filters``), until a name fits.
"""
names = []
- if self._context.predefined_names:
- # TODO is this ok? node might not always be a tree.Name
+ if self._context.predefined_names and isinstance(self._name, tree.Name):
node = self._name
while node is not None and not is_scope(node):
node = node.parent
@@ -133,14 +154,14 @@ def filter_name(self, filters):
continue
break
- debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self._string_name,
- self._context, names, self._position)
+ debug.dbg('finder.filter_name %s in (%s): %s@%s',
+ self._string_name, self._context, names, self._position)
return list(names)
def _check_getattr(self, inst):
"""Checks for both __getattr__ and __getattribute__ methods"""
# str is important, because it shouldn't be `Name`!
- name = compiled.create(self._evaluator, self._string_name)
+ name = compiled.create_simple_object(self._evaluator, self._string_name)
# This is a little bit special. `__getattribute__` is in Python
# executed before `__getattr__`. But: I know no use case, where
@@ -149,8 +170,8 @@ def _check_getattr(self, inst):
# We are inversing this, because a hand-crafted `__getattribute__`
# could still call another hand-crafted `__getattr__`, but not the
# other way around.
- names = (inst.get_function_slot_names('__getattr__') or
- inst.get_function_slot_names('__getattribute__'))
+ names = (inst.get_function_slot_names(u'__getattr__') or
+ inst.get_function_slot_names(u'__getattribute__'))
return inst.execute_function_slots(names, name)
def _names_to_types(self, names, attribute_lookup):
@@ -248,8 +269,7 @@ def _check_isinstance_type(context, element, search_name):
context_set = ContextSet()
for cls_or_tup in lazy_context_cls.infer():
- if isinstance(cls_or_tup, iterable.AbstractIterable) and \
- cls_or_tup.array_type == 'tuple':
+ if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
for lazy_context in cls_or_tup.py__iter__():
for context in lazy_context.infer():
context_set |= context.execute_evaluated()
diff --git a/pythonFiles/jedi/evaluate/flow_analysis.py b/pythonFiles/jedi/evaluate/flow_analysis.py
index 670b7a71934c..946f5a2ecaf0 100644
--- a/pythonFiles/jedi/evaluate/flow_analysis.py
+++ b/pythonFiles/jedi/evaluate/flow_analysis.py
@@ -1,4 +1,5 @@
from jedi.parser_utils import get_flow_branch_keyword, is_scope, get_parent_scope
+from jedi.evaluate.recursion import execution_allowed
class Status(object):
@@ -104,9 +105,13 @@ def _break_check(context, context_scope, flow_scope, node):
def _check_if(context, node):
- types = context.eval_node(node)
- values = set(x.py__bool__() for x in types)
- if len(values) == 1:
- return Status.lookup_table[values.pop()]
- else:
- return UNSURE
+ with execution_allowed(context.evaluator, node) as allowed:
+ if not allowed:
+ return UNSURE
+
+ types = context.eval_node(node)
+ values = set(x.py__bool__() for x in types)
+ if len(values) == 1:
+ return Status.lookup_table[values.pop()]
+ else:
+ return UNSURE
diff --git a/pythonFiles/jedi/evaluate/helpers.py b/pythonFiles/jedi/evaluate/helpers.py
index 3b21e01bda9e..c6226cde2b70 100644
--- a/pythonFiles/jedi/evaluate/helpers.py
+++ b/pythonFiles/jedi/evaluate/helpers.py
@@ -176,8 +176,6 @@ def get_module_names(module, all_scopes):
@contextmanager
def predefine_names(context, flow_scope, dct):
predefined = context.predefined_names
- if flow_scope in predefined:
- raise NotImplementedError('Why does this happen?')
predefined[flow_scope] = dct
try:
yield
@@ -190,12 +188,27 @@ def is_compiled(context):
def is_string(context):
- return is_compiled(context) and isinstance(context.obj, (str, unicode))
+ if context.evaluator.environment.version_info.major == 2:
+ str_classes = (unicode, bytes)
+ else:
+ str_classes = (unicode,)
+ return is_compiled(context) and isinstance(context.get_safe_value(default=None), str_classes)
def is_literal(context):
return is_number(context) or is_string(context)
+def _get_safe_value_or_none(context, accept):
+ if is_compiled(context):
+ value = context.get_safe_value(default=None)
+ if isinstance(value, accept):
+ return value
+
+
+def get_int_or_none(context):
+ return _get_safe_value_or_none(context, int)
+
+
def is_number(context):
- return is_compiled(context) and isinstance(context.obj, (int, float))
+ return _get_safe_value_or_none(context, (int, float)) is not None
diff --git a/pythonFiles/jedi/evaluate/imports.py b/pythonFiles/jedi/evaluate/imports.py
index ecf656b1a676..bcd3bdc74a4d 100644
--- a/pythonFiles/jedi/evaluate/imports.py
+++ b/pythonFiles/jedi/evaluate/imports.py
@@ -9,31 +9,48 @@
correct implementation is delegated to _compatibility.
This module also supports import autocompletion, which means to complete
-statements like ``from datetim`` (curser at the end would return ``datetime``).
+statements like ``from datetim`` (cursor at the end would return ``datetime``).
"""
-import imp
import os
-import pkgutil
-import sys
from parso.python import tree
from parso.tree import search_ancestor
-from parso.cache import parser_cache
from parso import python_bytes_to_unicode
-from jedi._compatibility import find_module, unicode, ImplicitNSInfo
+from jedi._compatibility import unicode, ImplicitNSInfo, force_unicode
from jedi import debug
from jedi import settings
+from jedi.parser_utils import get_cached_code_lines
from jedi.evaluate import sys_path
from jedi.evaluate import helpers
from jedi.evaluate import compiled
from jedi.evaluate import analysis
-from jedi.evaluate.utils import unite
+from jedi.evaluate.utils import unite, dotted_from_fs_path
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.filters import AbstractNameDefinition
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS
+class ModuleCache(object):
+ def __init__(self):
+ self._path_cache = {}
+ self._name_cache = {}
+
+ def add(self, module, name):
+ path = module.py__file__()
+ self._path_cache[path] = module
+ self._name_cache[name] = module
+
+ def iterate_modules_with_names(self):
+ return self._name_cache.items()
+
+ def get(self, name):
+ return self._name_cache[name]
+
+ def get_from_path(self, path):
+ return self._path_cache[path]
+
+
# This memoization is needed, because otherwise we will infinitely loop on
# certain imports.
@evaluator_method_cache(default=NO_CONTEXTS)
@@ -130,20 +147,13 @@ def __repr__(self):
def _add_error(context, name, message=None):
# Should be a name, not a string!
+ if message is None:
+ name_str = str(name.value) if isinstance(name, tree.Name) else name
+ message = 'No module named ' + name_str
if hasattr(name, 'parent'):
analysis.add(context, 'import-error', name, message)
-
-
-def get_init_path(directory_path):
- """
- The __init__ file can be searched in a directory. If found return it, else
- None.
- """
- for suffix, _, _ in imp.get_suffixes():
- path = os.path.join(directory_path, '__init__' + suffix)
- if os.path.exists(path):
- return path
- return None
+ else:
+ debug.warning('ImportError without origin: ' + message)
class ImportName(AbstractNameDefinition):
@@ -204,7 +214,7 @@ def __init__(self, evaluator, import_path, module_context, level=0):
if level:
base = module_context.py__package__().split('.')
- if base == ['']:
+ if base == [''] or base == ['__main__']:
base = []
if level > len(base):
path = module_context.py__file__()
@@ -226,10 +236,11 @@ def __init__(self, evaluator, import_path, module_context, level=0):
else:
import_path.insert(0, dir_name)
else:
- _add_error(module_context, import_path[-1])
+ _add_error(
+ module_context, import_path[-1],
+ message='Attempted relative import beyond top-level package.'
+ )
import_path = []
- # TODO add import error.
- debug.warning('Attempted relative import beyond top-level package.')
# If no path is defined in the module we have no ideas where we
# are in the file system. Therefore we cannot know what to do.
# In this case we just let the path there and ignore that it's
@@ -248,27 +259,19 @@ def str_import_path(self):
"""Returns the import path as pure strings instead of `Name`."""
return tuple(
name.value if isinstance(name, tree.Name) else name
- for name in self.import_path)
+ for name in self.import_path
+ )
def sys_path_with_modifications(self):
- in_path = []
- sys_path_mod = self._evaluator.project.sys_path \
+ sys_path_mod = self._evaluator.get_sys_path() \
+ sys_path.check_sys_path_modifications(self.module_context)
- if self.file_path is not None:
- # If you edit e.g. gunicorn, there will be imports like this:
- # `from gunicorn import something`. But gunicorn is not in the
- # sys.path. Therefore look if gunicorn is a parent directory, #56.
- if self.import_path: # TODO is this check really needed?
- for path in sys_path.traverse_parents(self.file_path):
- if os.path.basename(path) == self.str_import_path[0]:
- in_path.append(os.path.dirname(path))
-
- # Since we know nothing about the call location of the sys.path,
- # it's a possibility that the current directory is the origin of
- # the Python execution.
- sys_path_mod.insert(0, os.path.dirname(self.file_path))
-
- return in_path + sys_path_mod
+
+ if self.import_path and self.file_path is not None \
+ and self._evaluator.environment.version_info.major == 2:
+ # Python2 uses an old strange way of importing relative imports.
+ sys_path_mod.append(force_unicode(os.path.dirname(self.file_path)))
+
+ return sys_path_mod
def follow(self):
if not self.import_path:
@@ -280,7 +283,7 @@ def _do_import(self, import_path, sys_path):
This method is very similar to importlib's `_gcd_import`.
"""
import_parts = [
- i.value if isinstance(i, tree.Name) else i
+ force_unicode(i.value if isinstance(i, tree.Name) else i)
for i in import_path
]
@@ -298,7 +301,7 @@ def _do_import(self, import_path, sys_path):
module_name = '.'.join(import_parts)
try:
- return ContextSet(self._evaluator.modules[module_name])
+ return ContextSet(self._evaluator.module_cache.get(module_name))
except KeyError:
pass
@@ -332,62 +335,43 @@ def _do_import(self, import_path, sys_path):
for path in paths:
# At the moment we are only using one path. So this is
# not important to be correct.
- try:
- if not isinstance(path, list):
- path = [path]
- module_file, module_path, is_pkg = \
- find_module(import_parts[-1], path, fullname=module_name)
+ if not isinstance(path, list):
+ path = [path]
+ code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info(
+ string=import_parts[-1],
+ path=path,
+ full_name=module_name
+ )
+ if module_path is not None:
break
- except ImportError:
- module_path = None
- if module_path is None:
+ else:
_add_error(self.module_context, import_path[-1])
return NO_CONTEXTS
else:
- parent_module = None
- try:
- debug.dbg('search_module %s in %s', import_parts[-1], self.file_path)
- # Override the sys.path. It works only good that way.
- # Injecting the path directly into `find_module` did not work.
- sys.path, temp = sys_path, sys.path
- try:
- module_file, module_path, is_pkg = \
- find_module(import_parts[-1], fullname=module_name)
- finally:
- sys.path = temp
- except ImportError:
+ debug.dbg('search_module %s in %s', import_parts[-1], self.file_path)
+ # Override the sys.path. It works only good that way.
+ # Injecting the path directly into `find_module` did not work.
+ code, module_path, is_pkg = self._evaluator.compiled_subprocess.get_module_info(
+ string=import_parts[-1],
+ full_name=module_name,
+ sys_path=sys_path,
+ )
+ if module_path is None:
# The module is not a package.
_add_error(self.module_context, import_path[-1])
return NO_CONTEXTS
- code = None
- if is_pkg:
- # In this case, we don't have a file yet. Search for the
- # __init__ file.
- if module_path.endswith(('.zip', '.egg')):
- code = module_file.loader.get_source(module_name)
- else:
- module_path = get_init_path(module_path)
- elif module_file:
- code = module_file.read()
- module_file.close()
-
- if isinstance(module_path, ImplicitNSInfo):
- from jedi.evaluate.context.namespace import ImplicitNamespaceContext
- fullname, paths = module_path.name, module_path.paths
- module = ImplicitNamespaceContext(self._evaluator, fullname=fullname)
- module.paths = paths
- elif module_file is None and not module_path.endswith(('.py', '.zip', '.egg')):
- module = compiled.load_module(self._evaluator, module_path)
- else:
- module = _load_module(self._evaluator, module_path, code, sys_path, parent_module)
+ module = _load_module(
+ self._evaluator, module_path, code, sys_path,
+ module_name=module_name,
+ safe_module_name=True,
+ )
if module is None:
# The file might raise an ImportError e.g. and therefore not be
# importable.
return NO_CONTEXTS
- self._evaluator.modules[module_name] = module
return ContextSet(module)
def _generate_name(self, name, in_module=None):
@@ -401,15 +385,17 @@ def _get_module_names(self, search_path=None, in_module=None):
Get the names of all modules in the search_path. This means file names
and not names defined in the files.
"""
+ sub = self._evaluator.compiled_subprocess
names = []
# add builtin module names
if search_path is None and in_module is None:
- names += [self._generate_name(name) for name in sys.builtin_module_names]
+ names += [self._generate_name(name) for name in sub.get_builtin_module_names()]
if search_path is None:
search_path = self.sys_path_with_modifications()
- for module_loader, name, is_pkg in pkgutil.iter_modules(search_path):
+
+ for name in sub.list_module_names(search_path):
names.append(self._generate_name(name, in_module=in_module))
return names
@@ -448,7 +434,7 @@ def completion_names(self, evaluator, only_modules=False):
# implicit namespace packages
elif isinstance(context, ImplicitNamespaceContext):
paths = context.paths
- names += self._get_module_names(paths)
+ names += self._get_module_names(paths, in_module=context)
if only_modules:
# In the case of an import like `from x.` we don't need to
@@ -476,38 +462,65 @@ def completion_names(self, evaluator, only_modules=False):
return names
-def _load_module(evaluator, path=None, code=None, sys_path=None, parent_module=None):
- if sys_path is None:
- sys_path = evaluator.project.sys_path
+def _load_module(evaluator, path=None, code=None, sys_path=None,
+ module_name=None, safe_module_name=False):
+ try:
+ return evaluator.module_cache.get(module_name)
+ except KeyError:
+ pass
+ try:
+ return evaluator.module_cache.get_from_path(path)
+ except KeyError:
+ pass
- dotted_path = path and compiled.dotted_from_fs_path(path, sys_path)
- if path is not None and path.endswith(('.py', '.zip', '.egg')) \
- and dotted_path not in settings.auto_import_modules:
+ if isinstance(path, ImplicitNSInfo):
+ from jedi.evaluate.context.namespace import ImplicitNamespaceContext
+ module = ImplicitNamespaceContext(
+ evaluator,
+ fullname=path.name,
+ paths=path.paths,
+ )
+ else:
+ if sys_path is None:
+ sys_path = evaluator.get_sys_path()
+
+ dotted_path = path and dotted_from_fs_path(path, sys_path)
+ if path is not None and path.endswith(('.py', '.zip', '.egg')) \
+ and dotted_path not in settings.auto_import_modules:
+
+ module_node = evaluator.parse(
+ code=code, path=path, cache=True, diff_cache=True,
+ cache_path=settings.cache_directory)
+
+ from jedi.evaluate.context import ModuleContext
+ module = ModuleContext(
+ evaluator, module_node,
+ path=path,
+ code_lines=get_cached_code_lines(evaluator.grammar, path),
+ )
+ else:
+ module = compiled.load_module(evaluator, path=path, sys_path=sys_path)
- module_node = evaluator.grammar.parse(
- code=code, path=path, cache=True, diff_cache=True,
- cache_path=settings.cache_directory)
+ if module is not None and module_name is not None:
+ add_module_to_cache(evaluator, module_name, module, safe=safe_module_name)
- from jedi.evaluate.context import ModuleContext
- return ModuleContext(evaluator, module_node, path=path)
- else:
- return compiled.load_module(evaluator, path)
+ return module
-def add_module(evaluator, module_name, module):
- if '.' not in module_name:
+def add_module_to_cache(evaluator, module_name, module, safe=False):
+ if not safe and '.' not in module_name:
# We cannot add paths with dots, because that would collide with
# the sepatator dots for nested packages. Therefore we return
# `__main__` in ModuleWrapper.py__name__(), which is similar to
# Python behavior.
- evaluator.modules[module_name] = module
+ return
+ evaluator.module_cache.add(module, module_name)
def get_modules_containing_name(evaluator, modules, name):
"""
Search a name in the directories of modules.
"""
- from jedi.evaluate.context import ModuleContext
def check_directories(paths):
for p in paths:
if p is not None:
@@ -519,28 +532,16 @@ def check_directories(paths):
if file_name.endswith('.py'):
yield path
- def check_python_file(path):
- try:
- # TODO I don't think we should use the cache here?!
- node_cache_item = parser_cache[evaluator.grammar._hashed][path]
- except KeyError:
- try:
- return check_fs(path)
- except IOError:
- return None
- else:
- module_node = node_cache_item.node
- return ModuleContext(evaluator, module_node, path=path)
-
def check_fs(path):
with open(path, 'rb') as f:
code = python_bytes_to_unicode(f.read(), errors='replace')
if name in code:
- module = _load_module(evaluator, path, code)
-
- module_name = sys_path.dotted_path_in_sys_path(evaluator.project.sys_path, path)
- if module_name is not None:
- add_module(evaluator, module_name, module)
+ e_sys_path = evaluator.get_sys_path()
+ module_name = sys_path.dotted_path_in_sys_path(e_sys_path, path)
+ module = _load_module(
+ evaluator, path, code,
+ sys_path=e_sys_path, module_name=module_name
+ )
return module
# skip non python modules
@@ -565,6 +566,6 @@ def check_fs(path):
# Sort here to make issues less random.
for p in sorted(paths):
# make testing easier, sort it - same results on every interpreter
- m = check_python_file(p)
+ m = check_fs(p)
if m is not None and not isinstance(m, compiled.CompiledObject):
yield m
diff --git a/pythonFiles/jedi/evaluate/param.py b/pythonFiles/jedi/evaluate/param.py
index a46394ce8a81..1445ef0c8ff6 100644
--- a/pythonFiles/jedi/evaluate/param.py
+++ b/pythonFiles/jedi/evaluate/param.py
@@ -97,7 +97,7 @@ def get_params(execution_context, var_args):
var_arg_iterator.push_back((key, argument))
break
lazy_context_list.append(argument)
- seq = iterable.FakeSequence(execution_context.evaluator, 'tuple', lazy_context_list)
+ seq = iterable.FakeSequence(execution_context.evaluator, u'tuple', lazy_context_list)
result_arg = LazyKnownContext(seq)
elif param.star_count == 2:
# **kwargs param
@@ -176,7 +176,7 @@ def _error_argument_count(funcdef, actual_count):
def _create_default_param(execution_context, param):
if param.star_count == 1:
result_arg = LazyKnownContext(
- iterable.FakeSequence(execution_context.evaluator, 'tuple', [])
+ iterable.FakeSequence(execution_context.evaluator, u'tuple', [])
)
elif param.star_count == 2:
result_arg = LazyKnownContext(
@@ -192,4 +192,3 @@ def _create_default_param(execution_context, param):
def create_default_params(execution_context, funcdef):
return [_create_default_param(execution_context, p)
for p in funcdef.get_params()]
-
diff --git a/pythonFiles/jedi/evaluate/pep0484.py b/pythonFiles/jedi/evaluate/pep0484.py
index 820f112c54e0..f23943e1a8a5 100644
--- a/pythonFiles/jedi/evaluate/pep0484.py
+++ b/pythonFiles/jedi/evaluate/pep0484.py
@@ -22,16 +22,17 @@
import os
import re
-from parso import ParserSyntaxError
+from parso import ParserSyntaxError, parse, split_lines
from parso.python import tree
+from jedi._compatibility import unicode, force_unicode
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate import compiled
from jedi.evaluate.base_context import NO_CONTEXTS, ContextSet
from jedi.evaluate.lazy_context import LazyTreeContext
from jedi.evaluate.context import ModuleContext
+from jedi.evaluate.helpers import is_string
from jedi import debug
-from jedi import _compatibility
from jedi import parser_utils
@@ -41,17 +42,23 @@ def _evaluate_for_annotation(context, annotation, index=None):
If index is not None, the annotation is expected to be a tuple
and we're interested in that index
"""
- if annotation is not None:
- context_set = context.eval_node(_fix_forward_reference(context, annotation))
- if index is not None:
- context_set = context_set.filter(
- lambda context: context.array_type == 'tuple' \
- and len(list(context.py__iter__())) >= index
- ).py__getitem__(index)
- return context_set.execute_evaluated()
- else:
+ context_set = context.eval_node(_fix_forward_reference(context, annotation))
+ return context_set.execute_evaluated()
+
+
+def _evaluate_annotation_string(context, string, index=None):
+ node = _get_forward_reference_node(context, string)
+ if node is None:
return NO_CONTEXTS
+ context_set = context.eval_node(node)
+ if index is not None:
+ context_set = context_set.filter(
+ lambda context: context.array_type == u'tuple'
+ and len(list(context.py__iter__())) >= index
+ ).py__getitem__(index)
+ return context_set.execute_evaluated()
+
def _fix_forward_reference(context, node):
evaled_nodes = context.eval_node(node)
@@ -59,30 +66,111 @@ def _fix_forward_reference(context, node):
debug.warning("Eval'ed typing index %s should lead to 1 object, "
" not %s" % (node, evaled_nodes))
return node
- evaled_node = list(evaled_nodes)[0]
- if isinstance(evaled_node, compiled.CompiledObject) and \
- isinstance(evaled_node.obj, str):
- try:
- new_node = context.evaluator.grammar.parse(
- _compatibility.unicode(evaled_node.obj),
- start_symbol='eval_input',
- error_recovery=False
- )
- except ParserSyntaxError:
- debug.warning('Annotation not parsed: %s' % evaled_node.obj)
- return node
- else:
- module = node.get_root_node()
- parser_utils.move(new_node, module.end_pos[0])
- new_node.parent = context.tree_node
- return new_node
+
+ evaled_context = list(evaled_nodes)[0]
+ if is_string(evaled_context):
+ result = _get_forward_reference_node(context, evaled_context.get_safe_value())
+ if result is not None:
+ return result
+
+ return node
+
+
+def _get_forward_reference_node(context, string):
+ try:
+ new_node = context.evaluator.grammar.parse(
+ force_unicode(string),
+ start_symbol='eval_input',
+ error_recovery=False
+ )
+ except ParserSyntaxError:
+ debug.warning('Annotation not parsed: %s' % string)
+ return None
else:
- return node
+ module = context.tree_node.get_root_node()
+ parser_utils.move(new_node, module.end_pos[0])
+ new_node.parent = context.tree_node
+ return new_node
+
+
+def _split_comment_param_declaration(decl_text):
+ """
+ Split decl_text on commas, but group generic expressions
+ together.
+
+ For example, given "foo, Bar[baz, biz]" we return
+ ['foo', 'Bar[baz, biz]'].
+
+ """
+ try:
+ node = parse(decl_text, error_recovery=False).children[0]
+ except ParserSyntaxError:
+ debug.warning('Comment annotation is not valid Python: %s' % decl_text)
+ return []
+
+ if node.type == 'name':
+ return [node.get_code().strip()]
+
+ params = []
+ try:
+ children = node.children
+ except AttributeError:
+ return []
+ else:
+ for child in children:
+ if child.type in ['name', 'atom_expr', 'power']:
+ params.append(child.get_code().strip())
+
+ return params
@evaluator_method_cache()
def infer_param(execution_context, param):
+ """
+ Infers the type of a function parameter, using type annotations.
+ """
annotation = param.annotation
+ if annotation is None:
+ # If no Python 3-style annotation, look for a Python 2-style comment
+ # annotation.
+ # Identify parameters to function in the same sequence as they would
+ # appear in a type comment.
+ all_params = [child for child in param.parent.children
+ if child.type == 'param']
+
+ node = param.parent.parent
+ comment = parser_utils.get_following_comment_same_line(node)
+ if comment is None:
+ return NO_CONTEXTS
+
+ match = re.match(r"^#\s*type:\s*\(([^#]*)\)\s*->", comment)
+ if not match:
+ return NO_CONTEXTS
+ params_comments = _split_comment_param_declaration(match.group(1))
+
+ # Find the specific param being investigated
+ index = all_params.index(param)
+ # If the number of parameters doesn't match length of type comment,
+ # ignore first parameter (assume it's self).
+ if len(params_comments) != len(all_params):
+ debug.warning(
+ "Comments length != Params length %s %s",
+ params_comments, all_params
+ )
+ from jedi.evaluate.context.instance import BaseInstanceFunctionExecution
+ if isinstance(execution_context, BaseInstanceFunctionExecution):
+ if index == 0:
+ # Assume it's self, which is already handled
+ return NO_CONTEXTS
+ index -= 1
+ if index >= len(params_comments):
+ return NO_CONTEXTS
+
+ param_comment = params_comments[index]
+ return _evaluate_annotation_string(
+ execution_context.get_root_context(),
+ param_comment
+ )
module_context = execution_context.get_root_context()
return _evaluate_for_annotation(module_context, annotation)
@@ -102,12 +190,33 @@ def py__annotations__(funcdef):
@evaluator_method_cache()
def infer_return_types(function_context):
+ """
+ Infers the type of a function's return value,
+ according to type annotations.
+ """
annotation = py__annotations__(function_context.tree_node).get("return", None)
+ if annotation is None:
+ # If there is no Python 3-type annotation, look for a Python 2-type annotation
+ node = function_context.tree_node
+ comment = parser_utils.get_following_comment_same_line(node)
+ if comment is None:
+ return NO_CONTEXTS
+
+ match = re.match(r"^#\s*type:\s*\([^#]*\)\s*->\s*([^#]*)", comment)
+ if not match:
+ return NO_CONTEXTS
+
+ return _evaluate_annotation_string(
+ function_context.get_root_context(),
+ match.group(1).strip()
+ )
+
module_context = function_context.get_root_context()
return _evaluate_for_annotation(module_context, annotation)
_typing_module = None
+_typing_module_code_lines = None
def _get_typing_replacement_module(grammar):
@@ -115,14 +224,15 @@ def _get_typing_replacement_module(grammar):
The idea is to return our jedi replacement for the PEP-0484 typing module
as discussed at https://github.com/davidhalter/jedi/issues/663
"""
- global _typing_module
+ global _typing_module, _typing_module_code_lines
if _typing_module is None:
typing_path = \
os.path.abspath(os.path.join(__file__, "../jedi_typing.py"))
with open(typing_path) as f:
- code = _compatibility.unicode(f.read())
+ code = unicode(f.read())
_typing_module = grammar.parse(code)
- return _typing_module
+ _typing_module_code_lines = split_lines(code, keepends=True)
+ return _typing_module, _typing_module_code_lines
def py__getitem__(context, typ, node):
@@ -152,10 +262,12 @@ def py__getitem__(context, typ, node):
# check for the instance typing._Optional (Python 3.6).
return context.eval_node(nodes[0])
+ module_node, code_lines = _get_typing_replacement_module(context.evaluator.latest_grammar)
typing = ModuleContext(
context.evaluator,
- module_node=_get_typing_replacement_module(context.evaluator.latest_grammar),
- path=None
+ module_node=module_node,
+ path=None,
+ code_lines=code_lines,
)
factories = typing.py__getattribute__("factory")
assert len(factories) == 1
@@ -167,12 +279,12 @@ def py__getitem__(context, typ, node):
if isinstance(child, tree.Class))
if type_name not in valid_classnames:
return None
- compiled_classname = compiled.create(context.evaluator, type_name)
+ compiled_classname = compiled.create_simple_object(context.evaluator, type_name)
from jedi.evaluate.context.iterable import FakeSequence
args = FakeSequence(
context.evaluator,
- "tuple",
+ u'tuple',
[LazyTreeContext(context, n) for n in nodes]
)
@@ -213,10 +325,6 @@ def _find_type_from_comment_hint(context, node, varlist, name):
if comment is None:
return []
match = re.match(r"^#\s*type:\s*([^#]*)", comment)
- if not match:
+ if match is None:
return []
- annotation = tree.String(
- repr(str(match.group(1).strip())),
- node.start_pos)
- annotation.parent = node.parent
- return _evaluate_for_annotation(context, annotation, index)
+ return _evaluate_annotation_string(context, match.group(1).strip(), index)
diff --git a/pythonFiles/jedi/evaluate/project.py b/pythonFiles/jedi/evaluate/project.py
deleted file mode 100644
index b90f0f0c3be8..000000000000
--- a/pythonFiles/jedi/evaluate/project.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import os
-import sys
-
-from jedi.evaluate.sys_path import get_venv_path, detect_additional_paths
-from jedi.cache import underscore_memoization
-
-
-class Project(object):
- def __init__(self, sys_path=None):
- if sys_path is not None:
- self._sys_path = sys_path
-
- venv = os.getenv('VIRTUAL_ENV')
- if venv:
- sys_path = get_venv_path(venv)
-
- if sys_path is None:
- sys_path = sys.path
-
- base_sys_path = list(sys_path)
- try:
- base_sys_path.remove('')
- except ValueError:
- pass
-
- self._base_sys_path = base_sys_path
-
- def add_script_path(self, script_path):
- self._script_path = script_path
-
- def add_evaluator(self, evaluator):
- self._evaluator = evaluator
-
- @property
- @underscore_memoization
- def sys_path(self):
- if self._script_path is None:
- return self._base_sys_path
-
- return self._base_sys_path + detect_additional_paths(self._evaluator, self._script_path)
diff --git a/pythonFiles/jedi/evaluate/recursion.py b/pythonFiles/jedi/evaluate/recursion.py
index e2f34a4a9a06..5be3f8be4d29 100644
--- a/pythonFiles/jedi/evaluate/recursion.py
+++ b/pythonFiles/jedi/evaluate/recursion.py
@@ -49,6 +49,7 @@
A function may not be executed more than this number of times recursively.
"""
+
class RecursionDetector(object):
def __init__(self):
self.pushed_nodes = []
@@ -67,9 +68,11 @@ def execution_allowed(evaluator, node):
node.start_pos)
yield False
else:
- pushed_nodes.append(node)
- yield True
- pushed_nodes.pop()
+ try:
+ pushed_nodes.append(node)
+ yield True
+ finally:
+ pushed_nodes.pop()
def execution_recursion_decorator(default=NO_CONTEXTS):
@@ -113,7 +116,7 @@ def push_execution(self, execution):
self._parent_execution_funcs.append(funcdef)
module = execution.get_root_context()
- if module == self._evaluator.BUILTINS:
+ if module == self._evaluator.builtins_module:
# We have control over builtins so we know they are not recursing
# like crazy. Therefore we just let them execute always, because
# they usually just help a lot with getting good results.
diff --git a/pythonFiles/jedi/evaluate/site.py b/pythonFiles/jedi/evaluate/site.py
deleted file mode 100644
index bf884faefaaf..000000000000
--- a/pythonFiles/jedi/evaluate/site.py
+++ /dev/null
@@ -1,110 +0,0 @@
-"""An adapted copy of relevant site-packages functionality from Python stdlib.
-
-This file contains some functions related to handling site-packages in Python
-with jedi-specific modifications:
-
-- the functions operate on sys_path argument rather than global sys.path
-
-- in .pth files "import ..." lines that allow execution of arbitrary code are
- skipped to prevent code injection into jedi interpreter
-
-"""
-
-# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved
-
-from __future__ import print_function
-
-import sys
-import os
-
-
-def makepath(*paths):
- dir = os.path.join(*paths)
- try:
- dir = os.path.abspath(dir)
- except OSError:
- pass
- return dir, os.path.normcase(dir)
-
-
-def _init_pathinfo(sys_path):
- """Return a set containing all existing directory entries from sys_path"""
- d = set()
- for dir in sys_path:
- try:
- if os.path.isdir(dir):
- dir, dircase = makepath(dir)
- d.add(dircase)
- except TypeError:
- continue
- return d
-
-
-def addpackage(sys_path, sitedir, name, known_paths):
- """Process a .pth file within the site-packages directory:
- For each line in the file, either combine it with sitedir to a path
- and add that to known_paths, or execute it if it starts with 'import '.
- """
- if known_paths is None:
- known_paths = _init_pathinfo(sys_path)
- reset = 1
- else:
- reset = 0
- fullname = os.path.join(sitedir, name)
- try:
- f = open(fullname, "r")
- except OSError:
- return
- with f:
- for n, line in enumerate(f):
- if line.startswith("#"):
- continue
- try:
- if line.startswith(("import ", "import\t")):
- # Change by immerrr: don't evaluate import lines to prevent
- # code injection into jedi through pth files.
- #
- # exec(line)
- continue
- line = line.rstrip()
- dir, dircase = makepath(sitedir, line)
- if not dircase in known_paths and os.path.exists(dir):
- sys_path.append(dir)
- known_paths.add(dircase)
- except Exception:
- print("Error processing line {:d} of {}:\n".format(n+1, fullname),
- file=sys.stderr)
- import traceback
- for record in traceback.format_exception(*sys.exc_info()):
- for line in record.splitlines():
- print(' '+line, file=sys.stderr)
- print("\nRemainder of file ignored", file=sys.stderr)
- break
- if reset:
- known_paths = None
- return known_paths
-
-
-def addsitedir(sys_path, sitedir, known_paths=None):
- """Add 'sitedir' argument to sys_path if missing and handle .pth files in
- 'sitedir'"""
- if known_paths is None:
- known_paths = _init_pathinfo(sys_path)
- reset = 1
- else:
- reset = 0
- sitedir, sitedircase = makepath(sitedir)
- if not sitedircase in known_paths:
- sys_path.append(sitedir) # Add path component
- known_paths.add(sitedircase)
- try:
- names = os.listdir(sitedir)
- except OSError:
- return
- names = [name for name in names if name.endswith(".pth")]
- for name in sorted(names):
- addpackage(sys_path, sitedir, name, known_paths)
- if reset:
- known_paths = None
- return known_paths
diff --git a/pythonFiles/jedi/evaluate/stdlib.py b/pythonFiles/jedi/evaluate/stdlib.py
index 259d692733db..06296d938183 100644
--- a/pythonFiles/jedi/evaluate/stdlib.py
+++ b/pythonFiles/jedi/evaluate/stdlib.py
@@ -9,9 +9,11 @@
the standard library. The usual way to understand the standard library is the
compiled module that returns the types for C-builtins.
"""
-import collections
import re
+import parso
+
+from jedi._compatibility import force_unicode
from jedi import debug
from jedi.evaluate.arguments import ValuesArguments
from jedi.evaluate import analysis
@@ -57,7 +59,7 @@ def execute(evaluator, obj, arguments):
except AttributeError:
pass
else:
- if obj.parent_context == evaluator.BUILTINS:
+ if obj.parent_context == evaluator.builtins_module:
module_name = 'builtins'
elif isinstance(obj.parent_context, ModuleContext):
module_name = obj.parent_context.name.string_name
@@ -107,10 +109,11 @@ def argument_clinic(string, want_obj=False, want_context=False, want_arguments=F
def f(func):
def wrapper(evaluator, obj, arguments):
debug.dbg('builtin start %s' % obj, color='MAGENTA')
+ result = NO_CONTEXTS
try:
lst = list(arguments.eval_argument_clinic(clinic_args))
except ValueError:
- return NO_CONTEXTS
+ pass
else:
kwargs = {}
if want_context:
@@ -119,9 +122,10 @@ def wrapper(evaluator, obj, arguments):
kwargs['obj'] = obj
if want_arguments:
kwargs['arguments'] = arguments
- return func(evaluator, *lst, **kwargs)
+ result = func(evaluator, *lst, **kwargs)
finally:
- debug.dbg('builtin end', color='MAGENTA')
+ debug.dbg('builtin end: %s', result, color='MAGENTA')
+ return result
return wrapper
return f
@@ -133,7 +137,7 @@ def builtins_next(evaluator, iterators, defaults):
TODO this function is currently not used. It's a stab at implementing next
in a different way than fake objects. This would be a bit more flexible.
"""
- if evaluator.python_version[0] == 2:
+ if evaluator.environment.version_info.major == 2:
name = 'next'
else:
name = '__next__'
@@ -157,7 +161,7 @@ def builtins_getattr(evaluator, objects, names, defaults=None):
for obj in objects:
for name in names:
if is_string(name):
- return obj.py__getattribute__(name.obj)
+ return obj.py__getattribute__(force_unicode(name.get_safe_value()))
else:
debug.warning('getattr called without str')
continue
@@ -207,22 +211,24 @@ def builtins_reversed(evaluator, sequences, obj, arguments):
# necessary, because `reversed` is a function and autocompletion
# would fail in certain cases like `reversed(x).__iter__` if we
# just returned the result directly.
- seq = iterable.FakeSequence(evaluator, 'list', rev)
+ seq = iterable.FakeSequence(evaluator, u'list', rev)
arguments = ValuesArguments([ContextSet(seq)])
- return ContextSet(CompiledInstance(evaluator, evaluator.BUILTINS, obj, arguments))
+ return ContextSet(CompiledInstance(evaluator, evaluator.builtins_module, obj, arguments))
@argument_clinic('obj, type, /', want_arguments=True)
def builtins_isinstance(evaluator, objects, types, arguments):
bool_results = set()
for o in objects:
+ cls = o.py__class__()
try:
- mro_func = o.py__class__().py__mro__
+ mro_func = cls.py__mro__
except AttributeError:
# This is temporary. Everything should have a class attribute in
# Python?! Maybe we'll leave it here, because some numpy objects or
# whatever might not.
- return ContextSet(compiled.create(True), compiled.create(False))
+ bool_results = set([True, False])
+ break
mro = mro_func()
@@ -230,7 +236,7 @@ def builtins_isinstance(evaluator, objects, types, arguments):
if cls_or_tup.is_class():
bool_results.add(cls_or_tup in mro)
elif cls_or_tup.name.string_name == 'tuple' \
- and cls_or_tup.get_root_context() == evaluator.BUILTINS:
+ and cls_or_tup.get_root_context() == evaluator.builtins_module:
# Check for tuples.
classes = ContextSet.from_sets(
lazy_context.infer()
@@ -246,7 +252,10 @@ def builtins_isinstance(evaluator, objects, types, arguments):
'not %s.' % cls_or_tup
analysis.add(lazy_context._context, 'type-error-isinstance', node, message)
- return ContextSet.from_iterable(compiled.create(evaluator, x) for x in bool_results)
+ return ContextSet.from_iterable(
+ compiled.builtin_from_name(evaluator, force_unicode(str(b)))
+ for b in bool_results
+ )
def collections_namedtuple(evaluator, obj, arguments):
@@ -256,45 +265,54 @@ def collections_namedtuple(evaluator, obj, arguments):
This has to be done by processing the namedtuple class template and
evaluating the result.
- .. note:: |jedi| only supports namedtuples on Python >2.6.
-
"""
- # Namedtuples are not supported on Python 2.6
- if not hasattr(collections, '_class_template'):
+ collections_context = obj.parent_context
+ _class_template_set = collections_context.py__getattribute__(u'_class_template')
+ if not _class_template_set:
+ # Namedtuples are not supported on Python 2.6, early 2.7, because the
+ # _class_template variable is not defined, there.
return NO_CONTEXTS
# Process arguments
# TODO here we only use one of the types, we should use all.
- name = list(_follow_param(evaluator, arguments, 0))[0].obj
+ # TODO this is buggy, doesn't need to be a string
+ name = list(_follow_param(evaluator, arguments, 0))[0].get_safe_value()
_fields = list(_follow_param(evaluator, arguments, 1))[0]
if isinstance(_fields, compiled.CompiledObject):
- fields = _fields.obj.replace(',', ' ').split()
- elif isinstance(_fields, iterable.AbstractIterable):
+ fields = _fields.get_safe_value().replace(',', ' ').split()
+ elif isinstance(_fields, iterable.Sequence):
fields = [
- v.obj
+ v.get_safe_value()
for lazy_context in _fields.py__iter__()
- for v in lazy_context.infer() if hasattr(v, 'obj')
+ for v in lazy_context.infer() if is_string(v)
]
else:
return NO_CONTEXTS
- base = collections._class_template
+ def get_var(name):
+ x, = collections_context.py__getattribute__(name)
+ return x.get_safe_value()
+
+ base = next(iter(_class_template_set)).get_safe_value()
base += _NAMEDTUPLE_INIT
- # Build source
- source = base.format(
+ # Build source code
+ code = base.format(
typename=name,
field_names=tuple(fields),
num_fields=len(fields),
- arg_list = repr(tuple(fields)).replace("'", "")[1:-1],
- repr_fmt=', '.join(collections._repr_template.format(name=name) for name in fields),
- field_defs='\n'.join(collections._field_template.format(index=index, name=name)
+ arg_list=repr(tuple(fields)).replace("u'", "").replace("'", "")[1:-1],
+ repr_fmt=', '.join(get_var(u'_repr_template').format(name=name) for name in fields),
+ field_defs='\n'.join(get_var(u'_field_template').format(index=index, name=name)
for index, name in enumerate(fields))
)
- # Parse source
- module = evaluator.grammar.parse(source)
+ # Parse source code
+ module = evaluator.grammar.parse(code)
generated_class = next(module.iter_classdefs())
- parent_context = ModuleContext(evaluator, module, '')
+ parent_context = ModuleContext(
+ evaluator, module, None,
+ code_lines=parso.split_lines(code, keepends=True),
+ )
return ContextSet(ClassContext(evaluator, parent_context, generated_class))
diff --git a/pythonFiles/jedi/evaluate/syntax_tree.py b/pythonFiles/jedi/evaluate/syntax_tree.py
index 1d847a4960de..4efe845d476d 100644
--- a/pythonFiles/jedi/evaluate/syntax_tree.py
+++ b/pythonFiles/jedi/evaluate/syntax_tree.py
@@ -2,10 +2,10 @@
Functions evaluating the syntax tree.
"""
import copy
-import operator as op
from parso.python import tree
+from jedi._compatibility import force_unicode, unicode
from jedi import debug
from jedi import parser_utils
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, ContextualizedNode, \
@@ -17,11 +17,13 @@
from jedi.evaluate import analysis
from jedi.evaluate import imports
from jedi.evaluate import arguments
+from jedi.evaluate.pep0484 import _evaluate_for_annotation
from jedi.evaluate.context import ClassContext, FunctionContext
from jedi.evaluate.context import iterable
from jedi.evaluate.context import TreeInstance, CompiledInstance
from jedi.evaluate.finder import NameFinder
from jedi.evaluate.helpers import is_string, is_literal, is_number, is_compiled
+from jedi.evaluate.compiled.access import COMPARISON_OPERATORS
def _limit_context_infers(func):
@@ -48,13 +50,25 @@ def wrapper(context, *args, **kwargs):
return wrapper
+def _py__stop_iteration_returns(generators):
+ results = ContextSet()
+ for generator in generators:
+ try:
+ method = generator.py__stop_iteration_returns
+ except AttributeError:
+ debug.warning('%s is not actually a generator', generator)
+ else:
+ results |= method()
+ return results
+
+
@debug.increase_indent
@_limit_context_infers
def eval_node(context, element):
- debug.dbg('eval_element %s@%s', element, element.start_pos)
+ debug.dbg('eval_node %s@%s', element, element.start_pos)
evaluator = context.evaluator
typ = element.type
- if typ in ('name', 'number', 'string', 'atom'):
+ if typ in ('name', 'number', 'string', 'atom', 'strings'):
return eval_atom(context, element)
elif typ == 'keyword':
# For False/True/None
@@ -68,22 +82,33 @@ def eval_node(context, element):
return eval_expr_stmt(context, element)
elif typ in ('power', 'atom_expr'):
first_child = element.children[0]
- if not (first_child.type == 'keyword' and first_child.value == 'await'):
- context_set = eval_atom(context, first_child)
- for trailer in element.children[1:]:
- if trailer == '**': # has a power operation.
- right = evaluator.eval_element(context, element.children[2])
- context_set = _eval_comparison(
- evaluator,
- context,
- context_set,
- trailer,
- right
- )
- break
- context_set = eval_trailer(context, context_set, trailer)
- return context_set
- return NO_CONTEXTS
+ children = element.children[1:]
+ had_await = False
+ if first_child.type == 'keyword' and first_child.value == 'await':
+ had_await = True
+ first_child = children.pop(0)
+
+ context_set = eval_atom(context, first_child)
+ for trailer in children:
+ if trailer == '**': # has a power operation.
+ right = context.eval_node(children[1])
+ context_set = _eval_comparison(
+ evaluator,
+ context,
+ context_set,
+ trailer,
+ right
+ )
+ break
+ context_set = eval_trailer(context, context_set, trailer)
+
+ if had_await:
+ await_context_set = context_set.py__getattribute__(u"__await__")
+ if not await_context_set:
+ debug.warning('Tried to run py__await__ on context %s', context)
+ context_set = ContextSet()
+ return _py__stop_iteration_returns(await_context_set.execute_evaluated())
+ return context_set
elif typ in ('testlist_star_expr', 'testlist',):
# The implicit tuple in statements.
return ContextSet(iterable.SequenceLiteralContext(evaluator, context, element))
@@ -100,8 +125,10 @@ def eval_node(context, element):
# Must be an ellipsis, other operators are not evaluated.
# In Python 2 ellipsis is coded as three single dot tokens, not
# as one token 3 dot token.
- assert element.value in ('.', '...')
- return ContextSet(compiled.create(evaluator, Ellipsis))
+ if element.value not in ('.', '...'):
+ origin = element.parent
+ raise AssertionError("unhandled operator %s in %s " % (repr(element.value), origin))
+ return ContextSet(compiled.builtin_from_name(evaluator, u'Ellipsis'))
elif typ == 'dotted_name':
context_set = eval_atom(context, element.children[0])
for next_name in element.children[2::2]:
@@ -112,6 +139,15 @@ def eval_node(context, element):
return eval_node(context, element.children[0])
elif typ == 'annassign':
return pep0484._evaluate_for_annotation(context, element.children[1])
+ elif typ == 'yield_expr':
+ if len(element.children) and element.children[1].type == 'yield_arg':
+ # Implies that it's a yield from.
+ element = element.children[1].children[1]
+ generators = context.eval_node(element)
+ return _py__stop_iteration_returns(generators)
+
+ # Generator.send() is not implemented.
+ return NO_CONTEXTS
else:
return eval_or_test(context, element)
@@ -119,7 +155,7 @@ def eval_node(context, element):
def eval_trailer(context, base_contexts, trailer):
trailer_op, node = trailer.children[:2]
if node == ')': # `arglist` is optional.
- node = ()
+ node = None
if trailer_op == '[':
trailer_op, node, _ = trailer.children
@@ -148,7 +184,7 @@ def eval_trailer(context, base_contexts, trailer):
name_or_str=node
)
else:
- assert trailer_op == '('
+ assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op
args = arguments.TreeArguments(context.evaluator, context, node, trailer)
return base_contexts.execute(args)
@@ -173,19 +209,19 @@ def eval_atom(context, atom):
)
elif isinstance(atom, tree.Literal):
- string = parser_utils.safe_literal_eval(atom.value)
- return ContextSet(compiled.create(context.evaluator, string))
+ string = context.evaluator.compiled_subprocess.safe_literal_eval(atom.value)
+ return ContextSet(compiled.create_simple_object(context.evaluator, string))
+ elif atom.type == 'strings':
+ # Will be multiple string.
+ context_set = eval_atom(context, atom.children[0])
+ for string in atom.children[1:]:
+ right = eval_atom(context, string)
+ context_set = _eval_comparison(context.evaluator, context, context_set, u'+', right)
+ return context_set
else:
c = atom.children
- if c[0].type == 'string':
- # Will be one string.
- context_set = eval_atom(context, c[0])
- for string in c[1:]:
- right = eval_atom(context, string)
- context_set = _eval_comparison(context.evaluator, context, context_set, '+', right)
- return context_set
# Parentheses without commas are not tuples.
- elif c[0] == '(' and not len(c) == 2 \
+ if c[0] == '(' and not len(c) == 2 \
and not(c[1].type == 'testlist_comp' and
len(c[1].children) > 1):
return context.eval_node(c[1])
@@ -203,7 +239,9 @@ def eval_atom(context, atom):
pass
if comp_for.type == 'comp_for':
- return ContextSet(iterable.Comprehension.from_atom(context.evaluator, context, atom))
+ return ContextSet(iterable.comprehension_from_atom(
+ context.evaluator, context, atom
+ ))
# It's a dict/list/tuple literal.
array_node = c[1]
@@ -221,7 +259,21 @@ def eval_atom(context, atom):
@_limit_context_infers
def eval_expr_stmt(context, stmt, seek_name=None):
with recursion.execution_allowed(context.evaluator, stmt) as allowed:
- if allowed or context.get_root_context() == context.evaluator.BUILTINS:
+ # Here we allow list/set to recurse under certain conditions. To make
+ # it possible to resolve stuff like list(set(list(x))), this is
+ # necessary.
+ if not allowed and context.get_root_context() == context.evaluator.builtins_module:
+ try:
+ instance = context.instance
+ except AttributeError:
+ pass
+ else:
+ if instance.name.string_name in ('list', 'set'):
+ c = instance.get_first_non_keyword_argument_contexts()
+ if instance not in c:
+ allowed = True
+
+ if allowed:
return _eval_expr_stmt(context, stmt, seek_name)
return NO_CONTEXTS
@@ -286,16 +338,16 @@ def eval_or_test(context, or_test):
# handle lazy evaluation of and/or here.
if operator in ('and', 'or'):
left_bools = set(left.py__bool__() for left in types)
- if left_bools == set([True]):
+ if left_bools == {True}:
if operator == 'and':
types = context.eval_node(right)
- elif left_bools == set([False]):
+ elif left_bools == {False}:
if operator != 'and':
types = context.eval_node(right)
# Otherwise continue, because of uncertainty.
else:
types = _eval_comparison(context.evaluator, context, types, operator,
- context.eval_node(right))
+ context.eval_node(right))
debug.dbg('eval_or_test types %s', types)
return types
@@ -308,29 +360,16 @@ def eval_factor(context_set, operator):
for context in context_set:
if operator == '-':
if is_number(context):
- yield compiled.create(context.evaluator, -context.obj)
+ yield context.negate()
elif operator == 'not':
value = context.py__bool__()
if value is None: # Uncertainty.
return
- yield compiled.create(context.evaluator, not value)
+ yield compiled.create_simple_object(context.evaluator, not value)
else:
yield context
-# Maps Python syntax to the operator module.
-COMPARISON_OPERATORS = {
- '==': op.eq,
- '!=': op.ne,
- 'is': op.is_,
- 'is not': op.is_not,
- '<': op.lt,
- '<=': op.le,
- '>': op.gt,
- '>=': op.ge,
-}
-
-
def _literals_to_types(evaluator, result):
# Changes literals ('a', 1, 1.0, etc) to its type instances (str(),
# int(), float(), etc).
@@ -366,49 +405,59 @@ def _eval_comparison(evaluator, context, left_contexts, operator, right_contexts
def _is_tuple(context):
- return isinstance(context, iterable.AbstractIterable) and context.array_type == 'tuple'
+ return isinstance(context, iterable.Sequence) and context.array_type == 'tuple'
def _is_list(context):
- return isinstance(context, iterable.AbstractIterable) and context.array_type == 'list'
+ return isinstance(context, iterable.Sequence) and context.array_type == 'list'
+
+
+def _bool_to_context(evaluator, bool_):
+ return compiled.builtin_from_name(evaluator, force_unicode(str(bool_)))
def _eval_comparison_part(evaluator, context, left, operator, right):
l_is_num = is_number(left)
r_is_num = is_number(right)
- if operator == '*':
+ if isinstance(operator, unicode):
+ str_operator = operator
+ else:
+ str_operator = force_unicode(str(operator.value))
+
+ if str_operator == '*':
# for iterables, ignore * operations
- if isinstance(left, iterable.AbstractIterable) or is_string(left):
+ if isinstance(left, iterable.Sequence) or is_string(left):
return ContextSet(left)
- elif isinstance(right, iterable.AbstractIterable) or is_string(right):
+ elif isinstance(right, iterable.Sequence) or is_string(right):
return ContextSet(right)
- elif operator == '+':
+ elif str_operator == '+':
if l_is_num and r_is_num or is_string(left) and is_string(right):
- return ContextSet(compiled.create(evaluator, left.obj + right.obj))
+ return ContextSet(left.execute_operation(right, str_operator))
elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
return ContextSet(iterable.MergedArray(evaluator, (left, right)))
- elif operator == '-':
+ elif str_operator == '-':
if l_is_num and r_is_num:
- return ContextSet(compiled.create(evaluator, left.obj - right.obj))
- elif operator == '%':
+ return ContextSet(left.execute_operation(right, str_operator))
+ elif str_operator == '%':
# With strings and numbers the left type typically remains. Except for
# `int() % float()`.
return ContextSet(left)
- elif operator in COMPARISON_OPERATORS:
- operation = COMPARISON_OPERATORS[operator]
+ elif str_operator in COMPARISON_OPERATORS:
if is_compiled(left) and is_compiled(right):
# Possible, because the return is not an option. Just compare.
- left = left.obj
- right = right.obj
-
- try:
- result = operation(left, right)
- except TypeError:
- # Could be True or False.
- return ContextSet(compiled.create(evaluator, True), compiled.create(evaluator, False))
+ try:
+ return ContextSet(left.execute_operation(right, str_operator))
+ except TypeError:
+ # Could be True or False.
+ pass
else:
- return ContextSet(compiled.create(evaluator, result))
- elif operator == 'in':
+ if str_operator in ('is', '!=', '==', 'is not'):
+ operation = COMPARISON_OPERATORS[str_operator]
+ bool_ = operation(left, right)
+ return ContextSet(_bool_to_context(evaluator, bool_))
+
+ return ContextSet(_bool_to_context(evaluator, True), _bool_to_context(evaluator, False))
+ elif str_operator == 'in':
return NO_CONTEXTS
def check(obj):
@@ -417,7 +466,7 @@ def check(obj):
obj.name.string_name in ('int', 'float')
# Static analysis, one is a number, the other one is not.
- if operator in ('+', '-') and l_is_num != r_is_num \
+ if str_operator in ('+', '-') and l_is_num != r_is_num \
and not (check(left) or check(right)):
message = "TypeError: unsupported operand type(s) for +: %s and %s"
analysis.add(context, 'type-error-operation', operator,
@@ -442,6 +491,22 @@ def _remove_statements(evaluator, context, stmt, name):
def tree_name_to_contexts(evaluator, context, tree_name):
+
+ context_set = ContextSet()
+ module_node = context.get_root_context().tree_node
+ if module_node is not None:
+ names = module_node.get_used_names().get(tree_name.value, [])
+ for name in names:
+ expr_stmt = name.parent
+
+ correct_scope = parser_utils.get_parent_scope(name) == context.tree_node
+
+ if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign" and correct_scope:
+ context_set |= _evaluate_for_annotation(context, expr_stmt.children[1].children[1])
+
+ if context_set:
+ return context_set
+
types = []
node = tree_name.get_definition(import_name_always=True)
if node is None:
@@ -455,7 +520,7 @@ def tree_name_to_contexts(evaluator, context, tree_name):
filters = [next(filters)]
return finder.find(filters, attribute_lookup=False)
elif node.type not in ('import_from', 'import_name'):
- raise ValueError("Should not happen.")
+ raise ValueError("Should not happen. type: %s", node.type)
typ = node.type
if typ == 'for_stmt':
@@ -472,14 +537,18 @@ def tree_name_to_contexts(evaluator, context, tree_name):
types = context.predefined_names[node][tree_name.value]
except KeyError:
cn = ContextualizedNode(context, node.children[3])
- for_types = iterate_contexts(cn.infer(), cn)
+ for_types = iterate_contexts(
+ cn.infer(),
+ contextualized_node=cn,
+ is_async=node.parent.type == 'async_stmt',
+ )
c_node = ContextualizedName(context, tree_name)
types = check_tuple_assignments(evaluator, c_node, for_types)
elif typ == 'expr_stmt':
types = _remove_statements(evaluator, context, node, tree_name)
elif typ == 'with_stmt':
context_managers = context.eval_node(node.get_test_node_from_name(tree_name))
- enter_methods = context_managers.py__getattribute__('__enter__')
+ enter_methods = context_managers.py__getattribute__(u'__enter__')
return enter_methods.execute_evaluated()
elif typ in ('import_from', 'import_name'):
types = imports.infer_import(context, tree_name)
@@ -492,7 +561,7 @@ def tree_name_to_contexts(evaluator, context, tree_name):
exceptions = context.eval_node(tree_name.get_previous_sibling().get_previous_sibling())
types = exceptions.execute_evaluated()
else:
- raise ValueError("Should not happen.")
+ raise ValueError("Should not happen. type: %s" % typ)
return types
@@ -583,6 +652,8 @@ def eval_subscript_list(evaluator, context, index):
result += [None] * (3 - len(result))
return ContextSet(iterable.Slice(context, *result))
+ elif index.type == 'subscriptlist':
+ return NO_CONTEXTS
# No slices
return context.eval_node(index)
diff --git a/pythonFiles/jedi/evaluate/sys_path.py b/pythonFiles/jedi/evaluate/sys_path.py
index 82e5e9df9ceb..d765a6653c02 100644
--- a/pythonFiles/jedi/evaluate/sys_path.py
+++ b/pythonFiles/jedi/evaluate/sys_path.py
@@ -1,85 +1,27 @@
-import glob
import os
-import sys
-import imp
-from jedi.evaluate.site import addsitedir
-from jedi._compatibility import unicode
+from jedi._compatibility import unicode, force_unicode, all_suffixes
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.base_context import ContextualizedNode
from jedi.evaluate.helpers import is_string
+from jedi.common.utils import traverse_parents
+from jedi.parser_utils import get_cached_code_lines
from jedi import settings
from jedi import debug
-from jedi.evaluate.utils import ignored
-
-
-def get_venv_path(venv):
- """Get sys.path for specified virtual environment."""
- sys_path = _get_venv_path_dirs(venv)
- with ignored(ValueError):
- sys_path.remove('')
- sys_path = _get_sys_path_with_egglinks(sys_path)
- # As of now, get_venv_path_dirs does not scan built-in pythonpath and
- # user-local site-packages, let's approximate them using path from Jedi
- # interpreter.
- return sys_path + sys.path
-
-
-def _get_sys_path_with_egglinks(sys_path):
- """Find all paths including those referenced by egg-links.
-
- Egg-link-referenced directories are inserted into path immediately before
- the directory on which their links were found. Such directories are not
- taken into consideration by normal import mechanism, but they are traversed
- when doing pkg_resources.require.
- """
- result = []
- for p in sys_path:
- # pkg_resources does not define a specific order for egg-link files
- # using os.listdir to enumerate them, we're sorting them to have
- # reproducible tests.
- for egg_link in sorted(glob.glob(os.path.join(p, '*.egg-link'))):
- with open(egg_link) as fd:
- for line in fd:
- line = line.strip()
- if line:
- result.append(os.path.join(p, line))
- # pkg_resources package only interprets the first
- # non-empty line in egg-link files.
- break
- result.append(p)
- return result
-
-
-def _get_venv_path_dirs(venv):
- """Get sys.path for venv without starting up the interpreter."""
- venv = os.path.abspath(venv)
- sitedir = _get_venv_sitepackages(venv)
- sys_path = []
- addsitedir(sys_path, sitedir)
- return sys_path
-
-
-def _get_venv_sitepackages(venv):
- if os.name == 'nt':
- p = os.path.join(venv, 'lib', 'site-packages')
- else:
- p = os.path.join(venv, 'lib', 'python%d.%d' % sys.version_info[:2],
- 'site-packages')
- return p
def _abs_path(module_context, path):
- module_path = module_context.py__file__()
if os.path.isabs(path):
return path
+ module_path = module_context.py__file__()
if module_path is None:
# In this case we have no idea where we actually are in the file
# system.
return None
base_dir = os.path.dirname(module_path)
+ path = force_unicode(path)
return os.path.abspath(os.path.join(base_dir, path))
@@ -87,7 +29,7 @@ def _paths_from_assignment(module_context, expr_stmt):
"""
Extracts the assigned strings from an assignment that looks as follows::
- >>> sys.path[0:0] = ['module/path', 'another/module/path']
+ sys.path[0:0] = ['module/path', 'another/module/path']
This function is in general pretty tolerant (and therefore 'buggy').
However, it's not a big issue usually to add more paths to Jedi's sys_path,
@@ -121,7 +63,7 @@ def _paths_from_assignment(module_context, expr_stmt):
for lazy_context in cn.infer().iterate(cn):
for context in lazy_context.infer():
if is_string(context):
- abs_path = _abs_path(module_context, context.obj)
+ abs_path = _abs_path(module_context, context.get_safe_value())
if abs_path is not None:
yield abs_path
@@ -144,7 +86,7 @@ def _paths_from_list_modifications(module_context, trailer1, trailer2):
for context in module_context.create_context(arg).eval_node(arg):
if is_string(context):
- abs_path = _abs_path(module_context, context.obj)
+ abs_path = _abs_path(module_context, context.get_safe_value())
if abs_path is not None:
yield abs_path
@@ -187,24 +129,19 @@ def get_sys_path_powers(names):
return added
-def sys_path_with_modifications(evaluator, module_context):
- return evaluator.project.sys_path + check_sys_path_modifications(module_context)
-
-
-def detect_additional_paths(evaluator, script_path):
- django_paths = _detect_django_path(script_path)
+def discover_buildout_paths(evaluator, script_path):
buildout_script_paths = set()
for buildout_script_path in _get_buildout_script_paths(script_path):
for path in _get_paths_from_buildout_script(evaluator, buildout_script_path):
buildout_script_paths.add(path)
- return django_paths + list(buildout_script_paths)
+ return buildout_script_paths
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
try:
- module_node = evaluator.grammar.parse(
+ module_node = evaluator.parse(
path=buildout_script_path,
cache=True,
cache_path=settings.cache_directory
@@ -214,20 +151,14 @@ def _get_paths_from_buildout_script(evaluator, buildout_script_path):
return
from jedi.evaluate.context import ModuleContext
- module = ModuleContext(evaluator, module_node, buildout_script_path)
+ module = ModuleContext(
+ evaluator, module_node, buildout_script_path,
+ code_lines=get_cached_code_lines(evaluator.grammar, buildout_script_path),
+ )
for path in check_sys_path_modifications(module):
yield path
-def traverse_parents(path):
- while True:
- new = os.path.dirname(path)
- if new == path:
- return
- path = new
- yield path
-
-
def _get_parent_dir_with_file(path, filename):
for parent in traverse_parents(path):
if os.path.isfile(os.path.join(parent, filename)):
@@ -235,47 +166,34 @@ def _get_parent_dir_with_file(path, filename):
return None
-def _detect_django_path(module_path):
- """ Detects the path of the very well known Django library (if used) """
- result = []
-
- for parent in traverse_parents(module_path):
- with ignored(IOError):
- with open(parent + os.path.sep + 'manage.py'):
- debug.dbg('Found django path: %s', module_path)
- result.append(parent)
- return result
-
-
-def _get_buildout_script_paths(module_path):
+def _get_buildout_script_paths(search_path):
"""
if there is a 'buildout.cfg' file in one of the parent directories of the
given module it will return a list of all files in the buildout bin
directory that look like python files.
- :param module_path: absolute path to the module.
- :type module_path: str
+ :param search_path: absolute path to the module.
+ :type search_path: str
"""
- project_root = _get_parent_dir_with_file(module_path, 'buildout.cfg')
+ project_root = _get_parent_dir_with_file(search_path, 'buildout.cfg')
if not project_root:
- return []
+ return
bin_path = os.path.join(project_root, 'bin')
if not os.path.exists(bin_path):
- return []
- extra_module_paths = []
+ return
+
for filename in os.listdir(bin_path):
try:
filepath = os.path.join(bin_path, filename)
with open(filepath, 'r') as f:
firstline = f.readline()
if firstline.startswith('#!') and 'python' in firstline:
- extra_module_paths.append(filepath)
+ yield filepath
except (UnicodeDecodeError, IOError) as e:
- # Probably a binary file; permission error or race cond. because file got deleted
- # ignore
+ # Probably a binary file; permission error or race cond. because
+ # file got deleted. Ignore it.
debug.warning(unicode(e))
continue
- return extra_module_paths
def dotted_path_in_sys_path(sys_path, module_path):
@@ -283,7 +201,7 @@ def dotted_path_in_sys_path(sys_path, module_path):
Returns the dotted path inside a sys.path.
"""
# First remove the suffix.
- for suffix, _, _ in imp.get_suffixes():
+ for suffix in all_suffixes():
if module_path.endswith(suffix):
module_path = module_path[:-len(suffix)]
break
diff --git a/pythonFiles/jedi/evaluate/utils.py b/pythonFiles/jedi/evaluate/utils.py
index 7fc1c246de0d..e00e477441de 100644
--- a/pythonFiles/jedi/evaluate/utils.py
+++ b/pythonFiles/jedi/evaluate/utils.py
@@ -2,10 +2,19 @@
import sys
import contextlib
import functools
+import re
+import os
from jedi._compatibility import reraise
+_sep = os.path.sep
+if os.path.altsep is not None:
+ _sep += os.path.altsep
+_path_re = re.compile('(?:\.[^{0}]+|[{0}]__init__\.py)$'.format(re.escape(_sep)))
+del _sep
+
+
def to_list(func):
def wrapper(*args, **kwargs):
return list(func(*args, **kwargs))
@@ -108,3 +117,38 @@ def indent_block(text, indention=' '):
text = text[:-1]
lines = text.split('\n')
return '\n'.join(map(lambda s: indention + s, lines)) + temp
+
+
+def dotted_from_fs_path(fs_path, sys_path):
+ """
+ Changes `/usr/lib/python3.4/email/utils.py` to `email.utils`. I.e.
+ compares the path with sys.path and then returns the dotted_path. If the
+ path is not in the sys.path, just returns None.
+ """
+ if os.path.basename(fs_path).startswith('__init__.'):
+ # We are calculating the path. __init__ files are not interesting.
+ fs_path = os.path.dirname(fs_path)
+
+ # prefer
+ # - UNIX
+ # /path/to/pythonX.Y/lib-dynload
+ # /path/to/pythonX.Y/site-packages
+ # - Windows
+ # C:\path\to\DLLs
+ # C:\path\to\Lib\site-packages
+ # over
+ # - UNIX
+ # /path/to/pythonX.Y
+ # - Windows
+ # C:\path\to\Lib
+ path = ''
+ for s in sys_path:
+ if (fs_path.startswith(s) and len(path) < len(s)):
+ path = s
+
+ # - Window
+ # X:\path\to\lib-dynload/datetime.pyd => datetime
+ module_path = fs_path[len(path):].lstrip(os.path.sep).lstrip('/')
+ # - Window
+ # Replace like X:\path\to\something/foo/bar.py
+ return _path_re.sub('', module_path).replace(os.path.sep, '.').replace('/', '.')
diff --git a/pythonFiles/jedi/parser_utils.py b/pythonFiles/jedi/parser_utils.py
index 59c6408ea1c6..e630265314e4 100644
--- a/pythonFiles/jedi/parser_utils.py
+++ b/pythonFiles/jedi/parser_utils.py
@@ -1,14 +1,15 @@
import textwrap
from inspect import cleandoc
-from jedi._compatibility import literal_eval, is_py3
from parso.python import tree
+from parso.cache import parser_cache
-_EXECUTE_NODES = set([
- 'funcdef', 'classdef', 'import_from', 'import_name', 'test', 'or_test',
- 'and_test', 'not_test', 'comparison', 'expr', 'xor_expr', 'and_expr',
- 'shift_expr', 'arith_expr', 'atom_expr', 'term', 'factor', 'power', 'atom'
-])
+from jedi._compatibility import literal_eval, force_unicode
+
+_EXECUTE_NODES = {'funcdef', 'classdef', 'import_from', 'import_name', 'test',
+ 'or_test', 'and_test', 'not_test', 'comparison', 'expr',
+ 'xor_expr', 'and_expr', 'shift_expr', 'arith_expr',
+ 'atom_expr', 'term', 'factor', 'power', 'atom'}
_FLOW_KEYWORDS = (
'try', 'except', 'finally', 'else', 'if', 'elif', 'with', 'for', 'while'
@@ -112,10 +113,7 @@ def clean_scope_docstring(scope_node):
cleaned = cleandoc(safe_literal_eval(node.value))
# Since we want the docstr output to be always unicode, just
# force it.
- if is_py3 or isinstance(cleaned, unicode):
- return cleaned
- else:
- return unicode(cleaned, 'UTF-8', 'replace')
+ return force_unicode(cleaned)
return ''
@@ -205,6 +203,9 @@ def get_following_comment_same_line(node):
whitespace = node.children[5].get_first_leaf().prefix
elif node.type == 'with_stmt':
whitespace = node.children[3].get_first_leaf().prefix
+ elif node.type == 'funcdef':
+ # actually on the next line
+ whitespace = node.children[4].get_first_leaf().get_next_leaf().prefix
else:
whitespace = node.get_last_leaf().get_next_leaf().prefix
except AttributeError:
@@ -239,3 +240,11 @@ def get_parent_scope(node, include_flows=False):
break
scope = scope.parent
return scope
+
+
+def get_cached_code_lines(grammar, path):
+ """
+ Basically access the cached code lines in parso. This is not the nicest way
+ to do this, but we avoid splitting all the lines again.
+ """
+ return parser_cache[grammar._hashed][path].lines
diff --git a/pythonFiles/jedi/refactoring.py b/pythonFiles/jedi/refactoring.py
index ee938427fcee..6c1d74d1bdb8 100644
--- a/pythonFiles/jedi/refactoring.py
+++ b/pythonFiles/jedi/refactoring.py
@@ -1,11 +1,14 @@
"""
+THIS is not in active development, please check
+https://github.com/davidhalter/jedi/issues/667 first before editing.
+
Introduce some basic refactoring functions to |jedi|. This module is still in a
very early development stage and needs much testing and improvement.
.. warning:: I won't do too much here, but if anyone wants to step in, please
do. Refactoring is none of my priorities
-It uses the |jedi| `API `_ and supports currently the
+It uses the |jedi| `API `_ and supports currently the
following functions (sometimes bug-prone):
- rename
@@ -50,9 +53,8 @@ def diff(self):
def rename(script, new_name):
""" The `args` / `kwargs` params are the same as in `api.Script`.
- :param operation: The refactoring operation to execute.
- :type operation: str
- :type source: str
+ :param new_name: The new name of the script.
+ :param script: The source Script object.
:return: list of changed lines/changed files
"""
return Refactoring(_rename(script.usages(), new_name))
@@ -105,11 +107,12 @@ def extract(script, new_name):
user_stmt = script._parser.user_stmt()
- # TODO care for multiline extracts
+ # TODO care for multi-line extracts
dct = {}
if user_stmt:
pos = script._pos
line_index = pos[0] - 1
+ # Be careful here. 'array_for_pos' does not exist in 'helpers'.
arr, index = helpers.array_for_pos(user_stmt, pos)
if arr is not None:
start_pos = arr[index].start_pos
@@ -120,7 +123,7 @@ def extract(script, new_name):
start_line = new_lines[start_pos[0] - 1]
text = start_line[start_pos[1]:e]
for l in range(start_pos[0], end_pos[0] - 1):
- text += '\n' + l
+ text += '\n' + str(l)
if e is None:
end_line = new_lines[end_pos[0] - 1]
text += '\n' + end_line[:end_pos[1]]
@@ -140,7 +143,7 @@ def extract(script, new_name):
new_lines[start_pos[0] - 1] = start_line
new_lines[start_pos[0]:end_pos[0] - 1] = []
- # add parentheses in multiline case
+ # add parentheses in multi-line case
open_brackets = ['(', '[', '{']
close_brackets = [')', ']', '}']
if '\n' in text and not (text[0] in open_brackets and text[-1] ==
@@ -172,7 +175,7 @@ def inline(script):
inlines = sorted(inlines, key=lambda x: (x.module_path, x.line, x.column),
reverse=True)
expression_list = stmt.expression_list()
- # don't allow multiline refactorings for now.
+ # don't allow multi-line refactorings for now.
assert stmt.start_pos[0] == stmt.end_pos[0]
index = stmt.start_pos[0] - 1
diff --git a/pythonFiles/jedi/utils.py b/pythonFiles/jedi/utils.py
index 177524c50168..0f42e7d55858 100644
--- a/pythonFiles/jedi/utils.py
+++ b/pythonFiles/jedi/utils.py
@@ -89,12 +89,13 @@ def complete(self, text, state):
lines = split_lines(text)
position = (len(lines), len(lines[-1]))
name = get_on_completion_name(
- interpreter._get_module_node(),
+ interpreter._module_node,
lines,
position
)
before = text[:len(text) - len(name)]
completions = interpreter.completions()
+ logging.debug("REPL completions: %s", completions)
except:
logging.error("REPL Completion error:\n" + traceback.format_exc())
raise
@@ -108,6 +109,11 @@ def complete(self, text, state):
return None
try:
+ # Need to import this one as well to make sure it's executed before
+ # this code. This didn't use to be an issue until 3.3. Starting with
+ # 3.4 this is different, it always overwrites the completer if it's not
+ # already imported here.
+ import rlcompleter
import readline
except ImportError:
print("Jedi: Module readline not available.")
diff --git a/pythonFiles/normalizeForInterpreter.py b/pythonFiles/normalizeForInterpreter.py
new file mode 100644
index 000000000000..678ce8caec4e
--- /dev/null
+++ b/pythonFiles/normalizeForInterpreter.py
@@ -0,0 +1,122 @@
+import ast
+import io
+import operator
+import os
+import sys
+import token
+import tokenize
+
+
+class Visitor(ast.NodeVisitor):
+ def __init__(self, lines):
+ self._lines = lines
+ self.line_numbers_with_nodes = set()
+ self.line_numbers_with_statements = []
+
+ def generic_visit(self, node):
+ if hasattr(node, 'col_offset') and hasattr(node, 'lineno') and node.col_offset == 0:
+ self.line_numbers_with_nodes.add(node.lineno)
+ if isinstance(node, ast.stmt):
+ self.line_numbers_with_statements.append(node.lineno)
+
+ ast.NodeVisitor.generic_visit(self, node)
+
+
+def _tokenize(source):
+ """Tokenize Python source code."""
+ # Using an undocumented API as the documented one in Python 2.7 does not work as needed
+ # cross-version.
+ return tokenize.generate_tokens(io.StringIO(source).readline)
+
+
+def _indent_size(line):
+ for index, char in enumerate(line):
+ if not char.isspace():
+ return index
+
+
+def _get_global_statement_blocks(source, lines):
+ """Return a list of all global statement blocks.
+
+ The list comprises of 3-item tuples that contain the starting line number,
+ ending line number and whether the statement is a single line.
+
+ """
+ tree = ast.parse(source)
+ visitor = Visitor(lines)
+ visitor.visit(tree)
+
+ statement_ranges = []
+ for index, line_number in enumerate(visitor.line_numbers_with_statements):
+ remaining_line_numbers = visitor.line_numbers_with_statements[index+1:]
+ end_line_number = len(lines) if len(remaining_line_numbers) == 0 else min(remaining_line_numbers) - 1
+ current_statement_is_oneline = line_number == end_line_number
+
+ if len(statement_ranges) == 0:
+ statement_ranges.append((line_number, end_line_number, current_statement_is_oneline))
+ continue
+
+ previous_statement = statement_ranges[-1]
+ previous_statement_is_oneline = previous_statement[2]
+ if previous_statement_is_oneline and current_statement_is_oneline:
+ statement_ranges[-1] = previous_statement[0], end_line_number, True
+ else:
+ statement_ranges.append((line_number, end_line_number, current_statement_is_oneline))
+
+ return statement_ranges
+
+
+def normalize_lines(source):
+ """Normalize blank lines for sending to the terminal.
+
+ Blank lines within a statement block are removed to prevent the REPL
+ from thinking the block is finished. Newlines are added to separate
+ top-level statements so that the REPL does not think there is a syntax
+ error.
+
+ """
+ lines = source.splitlines(False)
+ # Find out if we have any trailing blank lines
+ if len(lines[-1].strip()) == 0 or source.endswith('\n'):
+ trailing_newline = '\n'
+ else:
+ trailing_newline = ''
+
+ # Step 1: Remove empty lines.
+ tokens = _tokenize(source)
+ newlines_indexes_to_remove = (spos[0] for (toknum, tokval, spos, epos, line) in tokens
+ if len(line.strip()) == 0
+ and token.tok_name[toknum] == 'NL'
+ and spos[0] == epos[0])
+
+ for line_number in reversed(list(newlines_indexes_to_remove)):
+ del lines[line_number-1]
+
+ # Step 2: Add blank lines between each global statement block.
+ # A consequtive single lines blocks of code will be treated as a single statement,
+ # just to ensure we do not unnecessarily add too many blank lines.
+ source = '\n'.join(lines)
+ tokens = _tokenize(source)
+ dedent_indexes = (spos[0] for (toknum, tokval, spos, epos, line) in tokens
+ if toknum == token.DEDENT and _indent_size(line) == 0)
+
+ global_statement_ranges = _get_global_statement_blocks(source, lines)
+ start_positions = map(operator.itemgetter(0), reversed(global_statement_ranges))
+ for line_number in filter(lambda x: x > 1, start_positions):
+ lines.insert(line_number-1, '')
+
+ sys.stdout.write('\n'.join(lines) + trailing_newline)
+ sys.stdout.flush()
+
+
+if __name__ == '__main__':
+ contents = sys.argv[1]
+ try:
+ default_encoding = sys.getdefaultencoding()
+ encoded_contents = contents.encode(default_encoding, 'surrogateescape')
+ contents = encoded_contents.decode(default_encoding, 'replace')
+ except (UnicodeError, LookupError):
+ pass
+ if isinstance(contents, bytes):
+ contents = contents.decode('utf8')
+ normalize_lines(contents)
diff --git a/pythonFiles/parso/__init__.py b/pythonFiles/parso/__init__.py
index f0a0fc4f5015..9654389dea9f 100644
--- a/pythonFiles/parso/__init__.py
+++ b/pythonFiles/parso/__init__.py
@@ -43,7 +43,7 @@
from parso.utils import split_lines, python_bytes_to_unicode
-__version__ = '0.1.1'
+__version__ = '0.2.1'
def parse(code=None, **kwargs):
diff --git a/pythonFiles/parso/_compatibility.py b/pythonFiles/parso/_compatibility.py
index 9ddf23dc6786..db411eebf981 100644
--- a/pythonFiles/parso/_compatibility.py
+++ b/pythonFiles/parso/_compatibility.py
@@ -36,7 +36,7 @@ def use_metaclass(meta, *bases):
def u(string):
"""Cast to unicode DAMMIT!
Written because Python2 repr always implicitly casts to a string, so we
- have to cast back to a unicode (and we now that we always deal with valid
+ have to cast back to a unicode (and we know that we always deal with valid
unicode, because we check that in the beginning).
"""
if py_version >= 30:
diff --git a/pythonFiles/parso/grammar.py b/pythonFiles/parso/grammar.py
index 2cf26d77fb27..6c13f002f90d 100644
--- a/pythonFiles/parso/grammar.py
+++ b/pythonFiles/parso/grammar.py
@@ -12,7 +12,6 @@
from parso.python.parser import Parser as PythonParser
from parso.python.errors import ErrorFinderConfig
from parso.python import pep8
-from parso.python import fstring
_loaded_grammars = {}
@@ -21,7 +20,7 @@ class Grammar(object):
"""
:py:func:`parso.load_grammar` returns instances of this class.
- Creating custom grammars by calling this is not supported, yet.
+ Creating custom none-python grammars by calling this is not supported, yet.
"""
#:param text: A BNF representation of your grammar.
_error_normalizer_config = None
@@ -73,7 +72,7 @@ def parse(self, code=None, **kwargs):
:py:class:`parso.python.tree.Module`.
"""
if 'start_pos' in kwargs:
- raise TypeError("parse() got an unexpected keyworda argument.")
+ raise TypeError("parse() got an unexpected keyword argument.")
return self._parse(code=code, **kwargs)
def _parse(self, code=None, error_recovery=True, path=None,
@@ -186,7 +185,6 @@ def _get_normalizer_issues(self, node, normalizer_config=None):
normalizer.walk(node)
return normalizer.issues
-
def __repr__(self):
labels = self._pgen_grammar.number2symbol.values()
txt = ' '.join(list(labels)[:3]) + ' ...'
@@ -215,46 +213,19 @@ def _tokenize(self, code):
return tokenize(code, self.version_info)
-class PythonFStringGrammar(Grammar):
- _token_namespace = fstring.TokenNamespace
- _start_symbol = 'fstring'
-
- def __init__(self):
- super(PythonFStringGrammar, self).__init__(
- text=fstring.GRAMMAR,
- tokenizer=fstring.tokenize,
- parser=fstring.Parser
- )
-
- def parse(self, code, **kwargs):
- return self._parse(code, **kwargs)
-
- def _parse(self, code, error_recovery=True, start_pos=(1, 0)):
- tokens = self._tokenizer(code, start_pos=start_pos)
- p = self._parser(
- self._pgen_grammar,
- error_recovery=error_recovery,
- start_symbol=self._start_symbol,
- )
- return p.parse(tokens=tokens)
-
- def parse_leaf(self, leaf, error_recovery=True):
- code = leaf._get_payload()
- return self.parse(code, error_recovery=True, start_pos=leaf.start_pos)
-
-
def load_grammar(**kwargs):
"""
Loads a :py:class:`parso.Grammar`. The default version is the current Python
version.
:param str version: A python version string, e.g. ``version='3.3'``.
+ :param str path: A path to a grammar file
"""
- def load_grammar(language='python', version=None):
+ def load_grammar(language='python', version=None, path=None):
if language == 'python':
version_info = parse_version_string(version)
- file = os.path.join(
+ file = path or os.path.join(
'python',
'grammar%s%s.txt' % (version_info.major, version_info.minor)
)
@@ -273,10 +244,6 @@ def load_grammar(language='python', version=None):
except FileNotFoundError:
message = "Python version %s is currently not supported." % version
raise NotImplementedError(message)
- elif language == 'python-f-string':
- if version is not None:
- raise NotImplementedError("Currently different versions are not supported.")
- return PythonFStringGrammar()
else:
raise NotImplementedError("No support for language %s." % language)
diff --git a/pythonFiles/parso/pgen2/pgen.py b/pythonFiles/parso/pgen2/pgen.py
index 10ef6ffd1532..a3e39fa5fe74 100644
--- a/pythonFiles/parso/pgen2/pgen.py
+++ b/pythonFiles/parso/pgen2/pgen.py
@@ -28,6 +28,7 @@ def make_grammar(self):
c = grammar.Grammar(self._bnf_text)
names = list(self.dfas.keys())
names.sort()
+ # TODO do we still need this?
names.remove(self.startsymbol)
names.insert(0, self.startsymbol)
for name in names:
@@ -316,8 +317,8 @@ def _parse_atom(self):
def _expect(self, type):
if self.type != type:
- self._raise_error("expected %s, got %s(%s)",
- type, self.type, self.value)
+ self._raise_error("expected %s(%s), got %s(%s)",
+ type, token.tok_name[type], self.type, self.value)
value = self.value
self._gettoken()
return value
diff --git a/pythonFiles/parso/python/diff.py b/pythonFiles/parso/python/diff.py
index c2e44fd3cb21..f8b73c75d3d5 100644
--- a/pythonFiles/parso/python/diff.py
+++ b/pythonFiles/parso/python/diff.py
@@ -133,7 +133,7 @@ def update(self, old_lines, new_lines):
LOG.debug('diff: line_lengths old: %s, new: %s' % (len(old_lines), line_length))
for operation, i1, i2, j1, j2 in opcodes:
- LOG.debug('diff %s old[%s:%s] new[%s:%s]',
+ LOG.debug('diff code[%s] old[%s:%s] new[%s:%s]',
operation, i1 + 1, i2, j1 + 1, j2)
if j2 == line_length and new_lines[-1] == '':
@@ -454,7 +454,7 @@ def _remove_endmarker(self, tree_nodes):
self._last_prefix = ''
if is_endmarker:
try:
- separation = last_leaf.prefix.rindex('\n')
+ separation = last_leaf.prefix.rindex('\n') + 1
except ValueError:
pass
else:
@@ -462,7 +462,7 @@ def _remove_endmarker(self, tree_nodes):
# That is not relevant if parentheses were opened. Always parse
# until the end of a line.
last_leaf.prefix, self._last_prefix = \
- last_leaf.prefix[:separation + 1], last_leaf.prefix[separation + 1:]
+ last_leaf.prefix[:separation], last_leaf.prefix[separation:]
first_leaf = tree_nodes[0].get_first_leaf()
first_leaf.prefix = self.prefix + first_leaf.prefix
@@ -472,7 +472,6 @@ def _remove_endmarker(self, tree_nodes):
self.prefix = last_leaf.prefix
tree_nodes = tree_nodes[:-1]
-
return tree_nodes
def copy_nodes(self, tree_nodes, until_line, line_offset):
@@ -491,12 +490,20 @@ def _copy_nodes(self, tos, nodes, until_line, line_offset):
new_tos = tos
for node in nodes:
+ if node.start_pos[0] > until_line:
+ break
+
if node.type == 'endmarker':
+ # We basically removed the endmarker, but we are not allowed to
+ # remove the newline at the end of the line, otherwise it's
+ # going to be missing.
+ try:
+ self.prefix = node.prefix[:node.prefix.rindex('\n') + 1]
+ except ValueError:
+ pass
# Endmarkers just distort all the checks below. Remove them.
break
- if node.start_pos[0] > until_line:
- break
# TODO this check might take a bit of time for large files. We
# might want to change this to do more intelligent guessing or
# binary search.
diff --git a/pythonFiles/parso/python/errors.py b/pythonFiles/parso/python/errors.py
index 65296568b54c..cfb8380ea743 100644
--- a/pythonFiles/parso/python/errors.py
+++ b/pythonFiles/parso/python/errors.py
@@ -563,7 +563,8 @@ def is_issue(self, leaf):
and self._normalizer.version == (3, 5):
self.add_issue(self.get_node(leaf), message=self.message_async_yield)
-@ErrorFinder.register_rule(type='atom')
+
+@ErrorFinder.register_rule(type='strings')
class _BytesAndStringMix(SyntaxRule):
# e.g. 's' b''
message = "cannot mix bytes and nonbytes literals"
@@ -744,7 +745,12 @@ def is_issue(self, node):
@ErrorFinder.register_rule(type='arglist')
class _ArglistRule(SyntaxRule):
- message = "Generator expression must be parenthesized if not sole argument"
+ @property
+ def message(self):
+ if self._normalizer.version < (3, 7):
+ return "Generator expression must be parenthesized if not sole argument"
+ else:
+ return "Generator expression must be parenthesized"
def is_issue(self, node):
first_arg = node.children[0]
@@ -837,101 +843,36 @@ def is_issue(self, try_stmt):
self.add_issue(default_except, message=self.message)
-@ErrorFinder.register_rule(type='string')
+@ErrorFinder.register_rule(type='fstring')
class _FStringRule(SyntaxRule):
_fstring_grammar = None
- message_empty = "f-string: empty expression not allowed" # f'{}'
- message_single_closing = "f-string: single '}' is not allowed" # f'}'
message_nested = "f-string: expressions nested too deeply"
- message_backslash = "f-string expression part cannot include a backslash" # f'{"\"}' or f'{"\\"}'
- message_comment = "f-string expression part cannot include '#'" # f'{#}'
- message_unterminated_string = "f-string: unterminated string" # f'{"}'
message_conversion = "f-string: invalid conversion character: expected 's', 'r', or 'a'"
- message_incomplete = "f-string: expecting '}'" # f'{'
- message_syntax = "invalid syntax"
- @classmethod
- def _load_grammar(cls):
- import parso
+ def _check_format_spec(self, format_spec, depth):
+ self._check_fstring_contents(format_spec.children[1:], depth)
- if cls._fstring_grammar is None:
- cls._fstring_grammar = parso.load_grammar(language='python-f-string')
- return cls._fstring_grammar
+ def _check_fstring_expr(self, fstring_expr, depth):
+ if depth >= 2:
+ self.add_issue(fstring_expr, message=self.message_nested)
- def is_issue(self, fstring):
- if 'f' not in fstring.string_prefix.lower():
- return
+ conversion = fstring_expr.children[2]
+ if conversion.type == 'fstring_conversion':
+ name = conversion.children[1]
+ if name.value not in ('s', 'r', 'a'):
+ self.add_issue(name, message=self.message_conversion)
- parsed = self._load_grammar().parse_leaf(fstring)
- for child in parsed.children:
- if child.type == 'expression':
- self._check_expression(child)
- elif child.type == 'error_node':
- next_ = child.get_next_leaf()
- if next_.type == 'error_leaf' and next_.original_type == 'unterminated_string':
- self.add_issue(next_, message=self.message_unterminated_string)
- # At this point nothing more is comming except the error
- # leaf that we've already checked here.
- break
- self.add_issue(child, message=self.message_incomplete)
- elif child.type == 'error_leaf':
- self.add_issue(child, message=self.message_single_closing)
-
- def _check_python_expr(self, python_expr):
- value = python_expr.value
- if '\\' in value:
- self.add_issue(python_expr, message=self.message_backslash)
- return
- if '#' in value:
- self.add_issue(python_expr, message=self.message_comment)
- return
- if re.match('\s*$', value) is not None:
- self.add_issue(python_expr, message=self.message_empty)
- return
-
- # This is now nested parsing. We parsed the fstring and now
- # we're parsing Python again.
- try:
- # CPython has a bit of a special ways to parse Python code within
- # f-strings. It wraps the code in brackets to make sure that
- # whitespace doesn't make problems (indentation/newlines).
- # Just use that algorithm as well here and adapt start positions.
- start_pos = python_expr.start_pos
- start_pos = start_pos[0], start_pos[1] - 1
- eval_input = self._normalizer.grammar._parse(
- '(%s)' % value,
- start_symbol='eval_input',
- start_pos=start_pos,
- error_recovery=False
- )
- except ParserSyntaxError as e:
- self.add_issue(e.error_leaf, message=self.message_syntax)
- return
+ format_spec = fstring_expr.children[-2]
+ if format_spec.type == 'fstring_format_spec':
+ self._check_format_spec(format_spec, depth + 1)
- issues = self._normalizer.grammar.iter_errors(eval_input)
- self._normalizer.issues += issues
-
- def _check_format_spec(self, format_spec):
- for expression in format_spec.children[1:]:
- nested_format_spec = expression.children[-2]
- if nested_format_spec.type == 'format_spec':
- if len(nested_format_spec.children) > 1:
- self.add_issue(
- nested_format_spec.children[1],
- message=self.message_nested
- )
-
- self._check_expression(expression)
+ def is_issue(self, fstring):
+ self._check_fstring_contents(fstring.children[1:-1])
- def _check_expression(self, expression):
- for c in expression.children:
- if c.type == 'python_expr':
- self._check_python_expr(c)
- elif c.type == 'conversion':
- if c.value not in ('s', 'r', 'a'):
- self.add_issue(c, message=self.message_conversion)
- elif c.type == 'format_spec':
- self._check_format_spec(c)
+ def _check_fstring_contents(self, children, depth=0):
+ for fstring_content in children:
+ if fstring_content.type == 'fstring_expr':
+ self._check_fstring_expr(fstring_content, depth)
class _CheckAssignmentRule(SyntaxRule):
@@ -944,7 +885,7 @@ def _check_assignment(self, node, is_deletion=False):
first, second = node.children[:2]
error = _get_comprehension_type(node)
if error is None:
- if second.type in ('dictorsetmaker', 'string'):
+ if second.type == 'dictorsetmaker':
error = 'literal'
elif first in ('(', '['):
if second.type == 'yield_expr':
@@ -963,7 +904,7 @@ def _check_assignment(self, node, is_deletion=False):
error = 'Ellipsis'
elif type_ == 'comparison':
error = 'comparison'
- elif type_ in ('string', 'number'):
+ elif type_ in ('string', 'number', 'strings'):
error = 'literal'
elif type_ == 'yield_expr':
# This one seems to be a slightly different warning in Python.
diff --git a/pythonFiles/parso/python/fstring.py b/pythonFiles/parso/python/fstring.py
deleted file mode 100644
index a8fe7b452df5..000000000000
--- a/pythonFiles/parso/python/fstring.py
+++ /dev/null
@@ -1,211 +0,0 @@
-import re
-
-from itertools import count
-from parso.utils import PythonVersionInfo
-from parso.utils import split_lines
-from parso.python.tokenize import Token
-from parso import parser
-from parso.tree import TypedLeaf, ErrorNode, ErrorLeaf
-
-version36 = PythonVersionInfo(3, 6)
-
-
-class TokenNamespace:
- _c = count()
- LBRACE = next(_c)
- RBRACE = next(_c)
- ENDMARKER = next(_c)
- COLON = next(_c)
- CONVERSION = next(_c)
- PYTHON_EXPR = next(_c)
- EXCLAMATION_MARK = next(_c)
- UNTERMINATED_STRING = next(_c)
-
- token_map = dict((v, k) for k, v in locals().items() if not k.startswith('_'))
-
- @classmethod
- def generate_token_id(cls, string):
- if string == '{':
- return cls.LBRACE
- elif string == '}':
- return cls.RBRACE
- elif string == '!':
- return cls.EXCLAMATION_MARK
- elif string == ':':
- return cls.COLON
- return getattr(cls, string)
-
-
-GRAMMAR = """
-fstring: expression* ENDMARKER
-format_spec: ':' expression*
-expression: '{' PYTHON_EXPR [ '!' CONVERSION ] [ format_spec ] '}'
-"""
-
-_prefix = r'((?:[^{}]+)*)'
-_expr = _prefix + r'(\{|\}|$)'
-_in_expr = r'([^{}\[\]:"\'!]*)(.?)'
-# There's only one conversion character allowed. But the rules have to be
-# checked later anyway, so allow more here. This makes error recovery nicer.
-_conversion = r'([^={}:]*)(.?)'
-
-_compiled_expr = re.compile(_expr)
-_compiled_in_expr = re.compile(_in_expr)
-_compiled_conversion = re.compile(_conversion)
-
-
-def tokenize(code, start_pos=(1, 0)):
- def add_to_pos(string):
- lines = split_lines(string)
- l = len(lines[-1])
- if len(lines) > 1:
- start_pos[0] += len(lines) - 1
- start_pos[1] = l
- else:
- start_pos[1] += l
-
- def tok(value, type=None, prefix=''):
- if type is None:
- type = TokenNamespace.generate_token_id(value)
-
- add_to_pos(prefix)
- token = Token(type, value, tuple(start_pos), prefix)
- add_to_pos(value)
- return token
-
- start = 0
- recursion_level = 0
- added_prefix = ''
- start_pos = list(start_pos)
- while True:
- match = _compiled_expr.match(code, start)
- prefix = added_prefix + match.group(1)
- found = match.group(2)
- start = match.end()
- if not found:
- # We're at the end.
- break
-
- if found == '}':
- if recursion_level == 0 and len(code) > start and code[start] == '}':
- # This is a }} escape.
- added_prefix = prefix + '}}'
- start += 1
- continue
-
- recursion_level = max(0, recursion_level - 1)
- yield tok(found, prefix=prefix)
- added_prefix = ''
- else:
- assert found == '{'
- if recursion_level == 0 and len(code) > start and code[start] == '{':
- # This is a {{ escape.
- added_prefix = prefix + '{{'
- start += 1
- continue
-
- recursion_level += 1
- yield tok(found, prefix=prefix)
- added_prefix = ''
-
- expression = ''
- squared_count = 0
- curly_count = 0
- while True:
- expr_match = _compiled_in_expr.match(code, start)
- expression += expr_match.group(1)
- found = expr_match.group(2)
- start = expr_match.end()
-
- if found == '{':
- curly_count += 1
- expression += found
- elif found == '}' and curly_count > 0:
- curly_count -= 1
- expression += found
- elif found == '[':
- squared_count += 1
- expression += found
- elif found == ']':
- # Use a max function here, because the Python code might
- # just have syntax errors.
- squared_count = max(0, squared_count - 1)
- expression += found
- elif found == ':' and (squared_count or curly_count):
- expression += found
- elif found in ('"', "'"):
- search = found
- if len(code) > start + 1 and \
- code[start] == found == code[start+1]:
- search *= 3
- start += 2
-
- index = code.find(search, start)
- if index == -1:
- yield tok(expression, type=TokenNamespace.PYTHON_EXPR)
- yield tok(
- found + code[start:],
- type=TokenNamespace.UNTERMINATED_STRING,
- )
- start = len(code)
- break
- expression += found + code[start:index+1]
- start = index + 1
- elif found == '!' and len(code) > start and code[start] == '=':
- # This is a python `!=` and not a conversion.
- expression += found
- else:
- yield tok(expression, type=TokenNamespace.PYTHON_EXPR)
- if found:
- yield tok(found)
- break
-
- if found == '!':
- conversion_match = _compiled_conversion.match(code, start)
- found = conversion_match.group(2)
- start = conversion_match.end()
- yield tok(conversion_match.group(1), type=TokenNamespace.CONVERSION)
- if found:
- yield tok(found)
- if found == '}':
- recursion_level -= 1
-
- # We don't need to handle everything after ':', because that is
- # basically new tokens.
-
- yield tok('', type=TokenNamespace.ENDMARKER, prefix=prefix)
-
-
-class Parser(parser.BaseParser):
- def parse(self, tokens):
- node = super(Parser, self).parse(tokens)
- if isinstance(node, self.default_leaf): # Is an endmarker.
- # If there's no curly braces we get back a non-module. We always
- # want an fstring.
- node = self.default_node('fstring', [node])
-
- return node
-
- def convert_leaf(self, pgen_grammar, type, value, prefix, start_pos):
- # TODO this is so ugly.
- leaf_type = TokenNamespace.token_map[type].lower()
- return TypedLeaf(leaf_type, value, start_pos, prefix)
-
- def error_recovery(self, pgen_grammar, stack, arcs, typ, value, start_pos, prefix,
- add_token_callback):
- if not self._error_recovery:
- return super(Parser, self).error_recovery(
- pgen_grammar, stack, arcs, typ, value, start_pos, prefix,
- add_token_callback
- )
-
- token_type = TokenNamespace.token_map[typ].lower()
- if len(stack) == 1:
- error_leaf = ErrorLeaf(token_type, value, start_pos, prefix)
- stack[0][2][1].append(error_leaf)
- else:
- dfa, state, (type_, nodes) = stack[1]
- stack[0][2][1].append(ErrorNode(nodes))
- stack[1:] = []
-
- add_token_callback(typ, value, start_pos, prefix)
diff --git a/pythonFiles/parso/python/grammar26.txt b/pythonFiles/parso/python/grammar26.txt
index b972a41d6a4a..d9cede2e9da9 100644
--- a/pythonFiles/parso/python/grammar26.txt
+++ b/pythonFiles/parso/python/grammar26.txt
@@ -119,7 +119,8 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' |
'{' [dictorsetmaker] '}' |
'`' testlist1 '`' |
- NAME | NUMBER | STRING+)
+ NAME | NUMBER | strings)
+strings: STRING+
listmaker: test ( list_for | (',' test)* [','] )
# Dave: Renamed testlist_gexpr to testlist_comp, because in 2.7+ this is the
# default. It's more consistent like this.
diff --git a/pythonFiles/parso/python/grammar27.txt b/pythonFiles/parso/python/grammar27.txt
index 4c3f33da32d5..359f12b43e1f 100644
--- a/pythonFiles/parso/python/grammar27.txt
+++ b/pythonFiles/parso/python/grammar27.txt
@@ -104,7 +104,8 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' |
'{' [dictorsetmaker] '}' |
'`' testlist1 '`' |
- NAME | NUMBER | STRING+)
+ NAME | NUMBER | strings)
+strings: STRING+
listmaker: test ( list_for | (',' test)* [','] )
testlist_comp: test ( comp_for | (',' test)* [','] )
lambdef: 'lambda' [varargslist] ':' test
diff --git a/pythonFiles/parso/python/grammar33.txt b/pythonFiles/parso/python/grammar33.txt
index d7aaffd60e14..3a5580926797 100644
--- a/pythonFiles/parso/python/grammar33.txt
+++ b/pythonFiles/parso/python/grammar33.txt
@@ -103,7 +103,8 @@ power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
+strings: STRING+
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
diff --git a/pythonFiles/parso/python/grammar34.txt b/pythonFiles/parso/python/grammar34.txt
index 05c3181627db..324bba18753d 100644
--- a/pythonFiles/parso/python/grammar34.txt
+++ b/pythonFiles/parso/python/grammar34.txt
@@ -103,7 +103,8 @@ power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
+strings: STRING+
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
diff --git a/pythonFiles/parso/python/grammar35.txt b/pythonFiles/parso/python/grammar35.txt
index c38217f3f97f..5868b8f7031a 100644
--- a/pythonFiles/parso/python/grammar35.txt
+++ b/pythonFiles/parso/python/grammar35.txt
@@ -110,7 +110,8 @@ atom_expr: ['await'] atom trailer*
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
+strings: STRING+
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
diff --git a/pythonFiles/parso/python/grammar36.txt b/pythonFiles/parso/python/grammar36.txt
index e76147e9e4fc..b82c1fec1145 100644
--- a/pythonFiles/parso/python/grammar36.txt
+++ b/pythonFiles/parso/python/grammar36.txt
@@ -108,7 +108,7 @@ atom_expr: ['await'] atom trailer*
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
@@ -148,3 +148,10 @@ encoding_decl: NAME
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist
+
+strings: (STRING | fstring)+
+fstring: FSTRING_START fstring_content* FSTRING_END
+fstring_content: FSTRING_STRING | fstring_expr
+fstring_conversion: '!' NAME
+fstring_expr: '{' testlist_comp [ fstring_conversion ] [ fstring_format_spec ] '}'
+fstring_format_spec: ':' fstring_content*
diff --git a/pythonFiles/parso/python/grammar37.txt b/pythonFiles/parso/python/grammar37.txt
index e76147e9e4fc..7d112f79852b 100644
--- a/pythonFiles/parso/python/grammar37.txt
+++ b/pythonFiles/parso/python/grammar37.txt
@@ -108,7 +108,7 @@ atom_expr: ['await'] atom trailer*
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+ NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
@@ -148,3 +148,10 @@ encoding_decl: NAME
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist
+
+strings: (STRING | fstring)+
+fstring: FSTRING_START fstring_content* FSTRING_END
+fstring_content: FSTRING_STRING | fstring_expr
+fstring_conversion: '!' NAME
+fstring_expr: '{' testlist [ fstring_conversion ] [ fstring_format_spec ] '}'
+fstring_format_spec: ':' fstring_content*
diff --git a/pythonFiles/parso/python/issue_list.txt b/pythonFiles/parso/python/issue_list.txt
deleted file mode 100644
index e5e2c9dda764..000000000000
--- a/pythonFiles/parso/python/issue_list.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-A list of syntax/indentation errors I've encountered in CPython.
-
-# Python/compile.c
- "'continue' not properly in loop"
- "'continue' not supported inside 'finally' clause" # Until loop
- "default 'except:' must be last"
- "from __future__ imports must occur at the beginning of the file"
- "'return' outside function"
- "'return' with value in async generator"
- "'break' outside loop"
- "two starred expressions in assignment"
- "asynchronous comprehension outside of an asynchronous function"
- "'yield' outside function" # For both yield and yield from
- "'yield from' inside async function"
- "'await' outside function"
- "'await' outside async function"
- "starred assignment target must be in a list or tuple"
- "can't use starred expression here"
- "too many statically nested blocks" # Max. 20
- # This is one of the few places in the cpython code base that I really
- # don't understand. It feels a bit hacky if you look at the implementation
- # of UNPACK_EX.
- "too many expressions in star-unpacking assignment"
-
- # Just ignore this one, newer versions will not be affected anymore and
- # it's a limit of 2^16 - 1.
- "too many annotations" # Only python 3.0 - 3.5, 3.6 is not affected.
-
-# Python/ast.c
- # used with_item exprlist expr_stmt
- "can't %s %s" % ("assign to" or "delete",
- "lambda"
- "function call" # foo()
- "generator expression"
- "list comprehension"
- "set comprehension"
- "dict comprehension"
- "keyword"
- "Ellipsis"
- "comparison"
- Dict: Set: Num: Str: Bytes: JoinedStr: FormattedValue:
- "literal"
- BoolOp: BinOp: UnaryOp:
- "operator"
- Yield: YieldFrom:
- "yield expression"
- Await:
- "await expression"
- IfExp:
- "conditional expression"
- "assignment to keyword" # (keywords + __debug__) # None = 2
- "named arguments must follow bare *" # def foo(*): pass
- "non-default argument follows default argument" # def f(x=3, y): pass
- "iterable unpacking cannot be used in comprehension" # [*[] for a in [1]]
- "dict unpacking cannot be used in dict comprehension" # {**{} for a in [1]}
- "Generator expression must be parenthesized if not sole argument" # foo(x for x in [], b)
- "positional argument follows keyword argument unpacking" # f(**x, y) >= 3.5
- "positional argument follows keyword argument" # f(x=2, y) >= 3.5
- "iterable argument unpacking follows keyword argument unpacking" # foo(**kwargs, *args)
- "lambda cannot contain assignment" # f(lambda: 1=1)
- "keyword can't be an expression" # f(+x=1)
- "keyword argument repeated" # f(x=1, x=2)
- "illegal expression for augmented assignment" # x, y += 1
- "only single target (not list) can be annotated" # [x, y]: int
- "only single target (not tuple) can be annotated" # x, y: str
- "illegal target for annotation" # True: 1`
- "trailing comma not allowed without surrounding parentheses" # from foo import a,
- "bytes can only contain ASCII literal characters." # b'ä' # prob. only python 3
- "cannot mix bytes and nonbytes literals" # 's' b''
- "assignment to yield expression not possible" # x = yield 1 = 3
-
- "f-string: empty expression not allowed" # f'{}'
- "f-string: single '}' is not allowed" # f'}'
- "f-string: expressions nested too deeply" # f'{1:{5:{3}}}'
- "f-string expression part cannot include a backslash" # f'{"\"}' or f'{"\\"}'
- "f-string expression part cannot include '#'" # f'{#}'
- "f-string: unterminated string" # f'{"}'
- "f-string: mismatched '(', '{', or '['"
- "f-string: invalid conversion character: expected 's', 'r', or 'a'" # f'{1!b}'
- "f-string: unexpected end of string" # Doesn't really happen?!
- "f-string: expecting '}'" # f'{'
- "(unicode error) unknown error
- "(value error) unknown error
- "(unicode error) MESSAGE
- MESSAGES = {
- "\\ at end of string"
- "truncated \\xXX escape"
- "truncated \\uXXXX escape"
- "truncated \\UXXXXXXXX escape"
- "illegal Unicode character" # '\Uffffffff'
- "malformed \\N character escape" # '\N{}'
- "unknown Unicode character name" # '\N{foo}'
- }
- "(value error) MESSAGE # bytes
- MESSAGES = {
- "Trailing \\ in string"
- "invalid \\x escape at position %d"
- }
-
- "invalid escape sequence \\%c" # Only happens when used in `python -W error`
- "unexpected node" # Probably irrelevant
- "Unexpected node-type in from-import" # Irrelevant, doesn't happen.
- "malformed 'try' statement" # Irrelevant, doesn't happen.
-
-# Python/symtable.c
- "duplicate argument '%U' in function definition"
- "name '%U' is assigned to before global declaration"
- "name '%U' is assigned to before nonlocal declaration"
- "name '%U' is used prior to global declaration"
- "name '%U' is used prior to nonlocal declaration"
- "annotated name '%U' can't be global"
- "annotated name '%U' can't be nonlocal"
- "import * only allowed at module level"
-
- "name '%U' is parameter and global",
- "name '%U' is nonlocal and global",
- "name '%U' is parameter and nonlocal",
-
- "nonlocal declaration not allowed at module level");
- "no binding for nonlocal '%U' found",
- # RecursionError. Not handled. For all human written code, this is probably
- # not an issue. eval("()"*x) with x>=2998 for example fails, but that's
- # more than 2000 executions on one line.
- "maximum recursion depth exceeded during compilation");
-
-# Python/future.c
- "not a chance"
- "future feature %.100s is not defined"
- "from __future__ imports must occur at the beginning of the file" # Also in compile.c
-
-# Parser/tokenizer.c
- # All the following issues seem to be irrelevant for parso, because the
- # encoding stuff is done before it reaches the tokenizer. It's already
- # unicode at that point.
- "encoding problem: %s"
- "encoding problem: %s with BOM"
- "Non-UTF-8 code starting with '\\x%.2x' in file %U on line %i, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details"
-
-# Parser/pythonrun.c
- E_SYNTAX: "invalid syntax"
- E_LINECONT: "unexpected character after line continuation character"
- E_IDENTIFIER: "invalid character in identifier"
- # Also just use 'invalid syntax'. Happens mostly with stuff like `(`. This
- # message doesn't really help the user, because it only appears very
- # randomly, e.g. `(or` wouldn't yield this error.
- E_EOF: "unexpected EOF while parsing"
- # Even in 3.6 this is implemented kind of shaky. Not implemented, I think
- # cPython needs to fix this one first.
- # e.g. `ast.parse('def x():\n\t if 1:\n \t \tpass')` works :/
- E_TABSPACE: "inconsistent use of tabs and spaces in indentation"
- # Ignored, just shown as "invalid syntax". The error has mostly to do with
- # numbers like 0b2 everywhere or 1.6_ in Python3.6.
- E_TOKEN: "invalid token"
- E_EOFS: "EOF while scanning triple-quoted string literal"
- E_EOLS: "EOL while scanning string literal"
-
- # IndentationError
- E_DEDENT: "unindent does not match any outer indentation level"
- E_TOODEEP: "too many levels of indentation" # 100 levels
- E_SYNTAX: "expected an indented block"
- "unexpected indent"
- # I don't think this actually ever happens.
- "unexpected unindent"
-
-
- # Irrelevant for parso for now.
- E_OVERFLOW: "expression too long"
- E_DECODE: "unknown decode error"
- E_BADSINGLE: "multiple statements found while compiling a single statement"
-
-
-Version specific:
-Python 3.5:
- 'yield' inside async function
-Python 3.3/3.4:
- can use starred expression only as assignment target
diff --git a/pythonFiles/parso/python/parser.py b/pythonFiles/parso/python/parser.py
index 1897f53e8d6f..7cdf987ab365 100644
--- a/pythonFiles/parso/python/parser.py
+++ b/pythonFiles/parso/python/parser.py
@@ -1,6 +1,7 @@
from parso.python import tree
from parso.python.token import (DEDENT, INDENT, ENDMARKER, NEWLINE, NUMBER,
- STRING, tok_name, NAME)
+ STRING, tok_name, NAME, FSTRING_STRING,
+ FSTRING_START, FSTRING_END)
from parso.parser import BaseParser
from parso.pgen2.parse import token_to_ilabel
@@ -50,6 +51,17 @@ class structure of different scopes.
}
default_node = tree.PythonNode
+ # Names/Keywords are handled separately
+ _leaf_map = {
+ STRING: tree.String,
+ NUMBER: tree.Number,
+ NEWLINE: tree.Newline,
+ ENDMARKER: tree.EndMarker,
+ FSTRING_STRING: tree.FStringString,
+ FSTRING_START: tree.FStringStart,
+ FSTRING_END: tree.FStringEnd,
+ }
+
def __init__(self, pgen_grammar, error_recovery=True, start_symbol='file_input'):
super(Parser, self).__init__(pgen_grammar, start_symbol, error_recovery=error_recovery)
@@ -121,16 +133,8 @@ def convert_leaf(self, pgen_grammar, type, value, prefix, start_pos):
return tree.Keyword(value, start_pos, prefix)
else:
return tree.Name(value, start_pos, prefix)
- elif type == STRING:
- return tree.String(value, start_pos, prefix)
- elif type == NUMBER:
- return tree.Number(value, start_pos, prefix)
- elif type == NEWLINE:
- return tree.Newline(value, start_pos, prefix)
- elif type == ENDMARKER:
- return tree.EndMarker(value, start_pos, prefix)
- else:
- return tree.Operator(value, start_pos, prefix)
+
+ return self._leaf_map.get(type, tree.Operator)(value, start_pos, prefix)
def error_recovery(self, pgen_grammar, stack, arcs, typ, value, start_pos, prefix,
add_token_callback):
diff --git a/pythonFiles/parso/python/token.py b/pythonFiles/parso/python/token.py
index fb590a5f28c6..dd849b01daa7 100644
--- a/pythonFiles/parso/python/token.py
+++ b/pythonFiles/parso/python/token.py
@@ -32,6 +32,14 @@
ERROR_DEDENT = next(_counter)
tok_name[ERROR_DEDENT] = 'ERROR_DEDENT'
+FSTRING_START = next(_counter)
+tok_name[FSTRING_START] = 'FSTRING_START'
+FSTRING_END = next(_counter)
+tok_name[FSTRING_END] = 'FSTRING_END'
+FSTRING_STRING = next(_counter)
+tok_name[FSTRING_STRING] = 'FSTRING_STRING'
+EXCLAMATION = next(_counter)
+tok_name[EXCLAMATION] = 'EXCLAMATION'
# Map from operator to number (since tokenize doesn't do this)
@@ -84,6 +92,7 @@
//= DOUBLESLASHEQUAL
-> RARROW
... ELLIPSIS
+! EXCLAMATION
"""
opmap = {}
diff --git a/pythonFiles/parso/python/tokenize.py b/pythonFiles/parso/python/tokenize.py
index ecd2437f5ebb..0ac8a8d5275f 100644
--- a/pythonFiles/parso/python/tokenize.py
+++ b/pythonFiles/parso/python/tokenize.py
@@ -20,14 +20,16 @@
from parso.python.token import (tok_name, ENDMARKER, STRING, NUMBER, opmap,
NAME, ERRORTOKEN, NEWLINE, INDENT, DEDENT,
- ERROR_DEDENT)
+ ERROR_DEDENT, FSTRING_STRING, FSTRING_START,
+ FSTRING_END)
from parso._compatibility import py_version
from parso.utils import split_lines
TokenCollection = namedtuple(
'TokenCollection',
- 'pseudo_token single_quoted triple_quoted endpats always_break_tokens',
+ 'pseudo_token single_quoted triple_quoted endpats whitespace '
+ 'fstring_pattern_map always_break_tokens',
)
BOM_UTF8_STRING = BOM_UTF8.decode('utf-8')
@@ -52,32 +54,35 @@ def group(*choices, **kwargs):
return start + '|'.join(choices) + ')'
-def any(*choices):
- return group(*choices) + '*'
-
-
def maybe(*choices):
return group(*choices) + '?'
# Return the empty string, plus all of the valid string prefixes.
-def _all_string_prefixes(version_info):
+def _all_string_prefixes(version_info, include_fstring=False, only_fstring=False):
def different_case_versions(prefix):
for s in _itertools.product(*[(c, c.upper()) for c in prefix]):
yield ''.join(s)
# The valid string prefixes. Only contain the lower case versions,
# and don't contain any permuations (include 'fr', but not
# 'rf'). The various permutations will be generated.
- _valid_string_prefixes = ['b', 'r', 'u']
+ valid_string_prefixes = ['b', 'r', 'u']
if version_info >= (3, 0):
- _valid_string_prefixes.append('br')
+ valid_string_prefixes.append('br')
- if version_info >= (3, 6):
- _valid_string_prefixes += ['f', 'fr']
+ result = set([''])
+ if version_info >= (3, 6) and include_fstring:
+ f = ['f', 'fr']
+ if only_fstring:
+ valid_string_prefixes = f
+ result = set()
+ else:
+ valid_string_prefixes += f
+ elif only_fstring:
+ return set()
# if we add binary f-strings, add: ['fb', 'fbr']
- result = set([''])
- for prefix in _valid_string_prefixes:
+ for prefix in valid_string_prefixes:
for t in _itertools.permutations(prefix):
# create a list with upper and lower versions of each
# character
@@ -102,10 +107,15 @@ def _get_token_collection(version_info):
return result
+fstring_string_single_line = _compile(r'(?:[^{}\r\n]+|\{\{|\}\})+')
+fstring_string_multi_line = _compile(r'(?:[^{}]+|\{\{|\}\})+')
+
+
def _create_token_collection(version_info):
# Note: we use unicode matching for names ("\w") but ascii matching for
# number literals.
Whitespace = r'[ \f\t]*'
+ whitespace = _compile(Whitespace)
Comment = r'#[^\r\n]*'
Name = r'\w+'
@@ -141,6 +151,9 @@ def _create_token_collection(version_info):
# StringPrefix can be the empty string (making it optional).
possible_prefixes = _all_string_prefixes(version_info)
StringPrefix = group(*possible_prefixes)
+ StringPrefixWithF = group(*_all_string_prefixes(version_info, include_fstring=True))
+ fstring_prefixes = _all_string_prefixes(version_info, include_fstring=True, only_fstring=True)
+ FStringStart = group(*fstring_prefixes)
# Tail end of ' string.
Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
@@ -150,14 +163,14 @@ def _create_token_collection(version_info):
Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
# Tail end of """ string.
Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
- Triple = group(StringPrefix + "'''", StringPrefix + '"""')
+ Triple = group(StringPrefixWithF + "'''", StringPrefixWithF + '"""')
# Because of leftmost-then-longest match semantics, be sure to put the
# longest operators first (e.g., if = came before ==, == would get
# recognized as two instances of =).
- Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
+ Operator = group(r"\*\*=?", r">>=?", r"<<=?",
r"//=?", r"->",
- r"[+\-*/%&@`|^=<>]=?",
+ r"[+\-*/%&@`|^!=<>]=?",
r"~")
Bracket = '[][(){}]'
@@ -174,7 +187,12 @@ def _create_token_collection(version_info):
group("'", r'\\\r?\n'),
StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
group('"', r'\\\r?\n'))
- PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple)
+ pseudo_extra_pool = [Comment, Triple]
+ all_quotes = '"', "'", '"""', "'''"
+ if fstring_prefixes:
+ pseudo_extra_pool.append(FStringStart + group(*all_quotes))
+
+ PseudoExtras = group(r'\\\r?\n|\Z', *pseudo_extra_pool)
PseudoToken = group(Whitespace, capture=True) + \
group(PseudoExtras, Number, Funny, ContStr, Name, capture=True)
@@ -192,18 +210,24 @@ def _create_token_collection(version_info):
# including the opening quotes.
single_quoted = set()
triple_quoted = set()
+ fstring_pattern_map = {}
for t in possible_prefixes:
- for p in (t + '"', t + "'"):
- single_quoted.add(p)
- for p in (t + '"""', t + "'''"):
- triple_quoted.add(p)
+ for quote in '"', "'":
+ single_quoted.add(t + quote)
+
+ for quote in '"""', "'''":
+ triple_quoted.add(t + quote)
+
+ for t in fstring_prefixes:
+ for quote in all_quotes:
+ fstring_pattern_map[t + quote] = quote
ALWAYS_BREAK_TOKENS = (';', 'import', 'class', 'def', 'try', 'except',
'finally', 'while', 'with', 'return')
pseudo_token_compiled = _compile(PseudoToken)
return TokenCollection(
pseudo_token_compiled, single_quoted, triple_quoted, endpats,
- ALWAYS_BREAK_TOKENS
+ whitespace, fstring_pattern_map, ALWAYS_BREAK_TOKENS
)
@@ -222,16 +246,108 @@ def _get_type_name(self, exact=True):
return tok_name[self.type]
def __repr__(self):
- return ('TokenInfo(type=%s, string=%r, start=%r, prefix=%r)' %
+ return ('TokenInfo(type=%s, string=%r, start_pos=%r, prefix=%r)' %
self._replace(type=self._get_type_name()))
+class FStringNode(object):
+ def __init__(self, quote):
+ self.quote = quote
+ self.parentheses_count = 0
+ self.previous_lines = ''
+ self.last_string_start_pos = None
+ # In the syntax there can be multiple format_spec's nested:
+ # {x:{y:3}}
+ self.format_spec_count = 0
+
+ def open_parentheses(self, character):
+ self.parentheses_count += 1
+
+ def close_parentheses(self, character):
+ self.parentheses_count -= 1
+
+ def allow_multiline(self):
+ return len(self.quote) == 3
+
+ def is_in_expr(self):
+ return (self.parentheses_count - self.format_spec_count) > 0
+
+
+def _check_fstring_ending(fstring_stack, token, from_start=False):
+ fstring_end = float('inf')
+ fstring_index = None
+ for i, node in enumerate(fstring_stack):
+ if from_start:
+ if token.startswith(node.quote):
+ fstring_index = i
+ fstring_end = len(node.quote)
+ else:
+ continue
+ else:
+ try:
+ end = token.index(node.quote)
+ except ValueError:
+ pass
+ else:
+ if fstring_index is None or end < fstring_end:
+ fstring_index = i
+ fstring_end = end
+ return fstring_index, fstring_end
+
+
+def _find_fstring_string(fstring_stack, line, lnum, pos):
+ tos = fstring_stack[-1]
+ if tos.is_in_expr():
+ return '', pos
+ else:
+ new_pos = pos
+ allow_multiline = tos.allow_multiline()
+ if allow_multiline:
+ match = fstring_string_multi_line.match(line, pos)
+ else:
+ match = fstring_string_single_line.match(line, pos)
+ if match is None:
+ string = tos.previous_lines
+ else:
+ if not tos.previous_lines:
+ tos.last_string_start_pos = (lnum, pos)
+
+ string = match.group(0)
+ for fstring_stack_node in fstring_stack:
+ try:
+ string = string[:string.index(fstring_stack_node.quote)]
+ except ValueError:
+ pass # The string was not found.
+
+ new_pos += len(string)
+ if allow_multiline and string.endswith('\n'):
+ tos.previous_lines += string
+ string = ''
+ else:
+ string = tos.previous_lines + string
+
+ return string, new_pos
+
+
def tokenize(code, version_info, start_pos=(1, 0)):
"""Generate tokens from a the source code (string)."""
lines = split_lines(code, keepends=True)
return tokenize_lines(lines, version_info, start_pos=start_pos)
+def _print_tokens(func):
+ """
+ A small helper function to help debug the tokenize_lines function.
+ """
+ def wrapper(*args, **kwargs):
+ for token in func(*args, **kwargs):
+ print(token)
+ yield token
+
+ return wrapper
+
+
+# @_print_tokens
def tokenize_lines(lines, version_info, start_pos=(1, 0)):
"""
A heavily modified Python standard library tokenizer.
@@ -240,7 +356,8 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
token. This idea comes from lib2to3. The prefix contains all information
that is irrelevant for the parser like newlines in parentheses or comments.
"""
- pseudo_token, single_quoted, triple_quoted, endpats, always_break_tokens, = \
+ pseudo_token, single_quoted, triple_quoted, endpats, whitespace, \
+ fstring_pattern_map, always_break_tokens, = \
_get_token_collection(version_info)
paren_level = 0 # count parentheses
indents = [0]
@@ -257,6 +374,7 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
additional_prefix = ''
first = True
lnum = start_pos[0] - 1
+ fstring_stack = []
for line in lines: # loop over lines in stream
lnum += 1
pos = 0
@@ -287,12 +405,47 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
continue
while pos < max:
+ if fstring_stack:
+ string, pos = _find_fstring_string(fstring_stack, line, lnum, pos)
+ if string:
+ yield PythonToken(
+ FSTRING_STRING, string,
+ fstring_stack[-1].last_string_start_pos,
+ # Never has a prefix because it can start anywhere and
+ # include whitespace.
+ prefix=''
+ )
+ fstring_stack[-1].previous_lines = ''
+ continue
+
+ if pos == max:
+ break
+
+ rest = line[pos:]
+ fstring_index, end = _check_fstring_ending(fstring_stack, rest, from_start=True)
+
+ if fstring_index is not None:
+ yield PythonToken(
+ FSTRING_END,
+ fstring_stack[fstring_index].quote,
+ (lnum, pos),
+ prefix=additional_prefix,
+ )
+ additional_prefix = ''
+ del fstring_stack[fstring_index:]
+ pos += end
+ continue
+
pseudomatch = pseudo_token.match(line, pos)
if not pseudomatch: # scan for tokens
- txt = line[pos:]
- if txt.endswith('\n'):
+ if line.endswith('\n'):
new_line = True
- yield PythonToken(ERRORTOKEN, txt, (lnum, pos), additional_prefix)
+ match = whitespace.match(line, pos)
+ pos = match.end()
+ yield PythonToken(
+ ERRORTOKEN, line[pos:], (lnum, pos),
+ additional_prefix + match.group(0)
+ )
additional_prefix = ''
break
@@ -311,10 +464,11 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
if new_line and initial not in '\r\n#':
new_line = False
- if paren_level == 0:
+ if paren_level == 0 and not fstring_stack:
i = 0
while line[i] == '\f':
i += 1
+ # TODO don't we need to change spos as well?
start -= 1
if start > indents[-1]:
yield PythonToken(INDENT, '', spos, '')
@@ -326,11 +480,33 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
yield PythonToken(DEDENT, '', spos, '')
indents.pop()
+ if fstring_stack:
+ fstring_index, end = _check_fstring_ending(fstring_stack, token)
+ if fstring_index is not None:
+ if end != 0:
+ yield PythonToken(ERRORTOKEN, token[:end], spos, prefix)
+ prefix = ''
+
+ yield PythonToken(
+ FSTRING_END,
+ fstring_stack[fstring_index].quote,
+ (lnum, spos[1] + 1),
+ prefix=prefix
+ )
+ del fstring_stack[fstring_index:]
+ pos -= len(token) - end
+ continue
+
if (initial in numchars or # ordinary number
(initial == '.' and token != '.' and token != '...')):
yield PythonToken(NUMBER, token, spos, prefix)
elif initial in '\r\n':
- if not new_line and paren_level == 0:
+ if any(not f.allow_multiline() for f in fstring_stack):
+ # Would use fstring_stack.clear, but that's not available
+ # in Python 2.
+ fstring_stack[:] = []
+
+ if not new_line and paren_level == 0 and not fstring_stack:
yield PythonToken(NEWLINE, token, spos, prefix)
else:
additional_prefix = prefix + token
@@ -362,8 +538,12 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
break
else: # ordinary string
yield PythonToken(STRING, token, spos, prefix)
+ elif token in fstring_pattern_map: # The start of an fstring.
+ fstring_stack.append(FStringNode(fstring_pattern_map[token]))
+ yield PythonToken(FSTRING_START, token, spos, prefix)
elif is_identifier(initial): # ordinary name
if token in always_break_tokens:
+ fstring_stack[:] = []
paren_level = 0
while True:
indent = indents.pop()
@@ -378,9 +558,18 @@ def tokenize_lines(lines, version_info, start_pos=(1, 0)):
break
else:
if token in '([{':
- paren_level += 1
+ if fstring_stack:
+ fstring_stack[-1].open_parentheses(token)
+ else:
+ paren_level += 1
elif token in ')]}':
- paren_level -= 1
+ if fstring_stack:
+ fstring_stack[-1].close_parentheses(token)
+ else:
+ paren_level -= 1
+ elif token == ':' and fstring_stack \
+ and fstring_stack[-1].parentheses_count == 1:
+ fstring_stack[-1].format_spec_count += 1
try:
# This check is needed in any case to check if it's a valid
diff --git a/pythonFiles/parso/python/tree.py b/pythonFiles/parso/python/tree.py
index eb977800a607..f6b4dd38fad0 100644
--- a/pythonFiles/parso/python/tree.py
+++ b/pythonFiles/parso/python/tree.py
@@ -60,7 +60,6 @@
_IMPORTS = set(['import_name', 'import_from'])
-
class DocstringMixin(object):
__slots__ = ()
@@ -133,7 +132,6 @@ def get_start_pos_of_prefix(self):
return previous_leaf.end_pos
-
class _LeafWithoutNewlines(PythonLeaf):
"""
Simply here to optimize performance.
@@ -166,6 +164,10 @@ class EndMarker(_LeafWithoutNewlines):
__slots__ = ()
type = 'endmarker'
+ @utf8_repr
+ def __repr__(self):
+ return "<%s: prefix=%s>" % (type(self).__name__, repr(self.prefix))
+
class Newline(PythonLeaf):
"""Contains NEWLINE and ENDMARKER tokens."""
@@ -235,7 +237,6 @@ def get_definition(self, import_name_always=False):
return None
-
class Literal(PythonLeaf):
__slots__ = ()
@@ -262,6 +263,33 @@ def _get_payload(self):
return match.group(2)[:-len(match.group(1))]
+class FStringString(Leaf):
+ """
+ f-strings contain f-string expressions and normal python strings. These are
+ the string parts of f-strings.
+ """
+ type = 'fstring_string'
+ __slots__ = ()
+
+
+class FStringStart(Leaf):
+ """
+ f-strings contain f-string expressions and normal python strings. These are
+ the string parts of f-strings.
+ """
+ type = 'fstring_start'
+ __slots__ = ()
+
+
+class FStringEnd(Leaf):
+ """
+ f-strings contain f-string expressions and normal python strings. These are
+ the string parts of f-strings.
+ """
+ type = 'fstring_end'
+ __slots__ = ()
+
+
class _StringComparisonMixin(object):
def __eq__(self, other):
"""
@@ -626,6 +654,7 @@ def annotation(self):
except IndexError:
return None
+
class Lambda(Function):
"""
Lambdas are basically trimmed functions, so give it the same interface.
diff --git a/pythonFiles/parso/tree.py b/pythonFiles/parso/tree.py
index 72a14945b0f6..5316795be57c 100644
--- a/pythonFiles/parso/tree.py
+++ b/pythonFiles/parso/tree.py
@@ -55,7 +55,6 @@ def get_previous_sibling(self):
Returns the node immediately preceding this node in this parent's
children list. If this node does not have a previous sibling, it is
None.
- None.
"""
# Can't use index(); we need to test by identity
for i, child in enumerate(self.parent.children):
@@ -339,7 +338,7 @@ def __repr__(self):
class ErrorNode(BaseNode):
"""
- A node that containes valid nodes/leaves that we're follow by a token that
+ A node that contains valid nodes/leaves that we're follow by a token that
was invalid. This basically means that the leaf after this node is where
Python would mark a syntax error.
"""
diff --git a/pythonFiles/refactor.py b/pythonFiles/refactor.py
index dd4b23ee7727..b782eee26ffb 100644
--- a/pythonFiles/refactor.py
+++ b/pythonFiles/refactor.py
@@ -2,9 +2,11 @@
# 1. Working directory.
# 2. Rope folder
+import difflib
import io
-import sys
import json
+import os
+import sys
import traceback
try:
@@ -55,6 +57,27 @@ def __init__(self, filePath, fileMode=ChangeType.EDIT, diff=""):
self.diff = diff
self.fileMode = fileMode
+def get_diff(changeset):
+ """This is a copy of the code form the ChangeSet.get_description method found in Rope."""
+ new = changeset.new_contents
+ old = changeset.old_contents
+ if old is None:
+ if changeset.resource.exists():
+ old = changeset.resource.read()
+ else:
+ old = ''
+
+ # Ensure code has a trailing empty lines, before generating a diff.
+ # https://github.com/Microsoft/vscode-python/issues/695.
+ old_lines = old.splitlines(True)
+ if not old_lines[-1].endswith('\n'):
+ old_lines[-1] = old_lines[-1] + os.linesep
+ new = new + os.linesep
+
+ result = difflib.unified_diff(
+ old_lines, new.splitlines(True),
+ 'a/' + changeset.resource.path, 'b/' + changeset.resource.path)
+ return ''.join(list(result))
class BaseRefactoring(object):
"""
@@ -117,7 +140,7 @@ def onRefactor(self):
for item in changes.changes:
if isinstance(item, rope.base.change.ChangeContents):
self.changes.append(
- Change(item.resource.real_path, ChangeType.EDIT, item.get_description()))
+ Change(item.resource.real_path, ChangeType.EDIT, get_diff(item)))
else:
raise Exception('Unknown Change')
@@ -141,7 +164,7 @@ def onRefactor(self):
for item in changes.changes:
if isinstance(item, rope.base.change.ChangeContents):
self.changes.append(
- Change(item.resource.real_path, ChangeType.EDIT, item.get_description()))
+ Change(item.resource.real_path, ChangeType.EDIT, get_diff(item)))
else:
raise Exception('Unknown Change')
@@ -160,7 +183,7 @@ def onRefactor(self):
for item in changes.changes:
if isinstance(item, rope.base.change.ChangeContents):
self.changes.append(
- Change(item.resource.real_path, ChangeType.EDIT, item.get_description()))
+ Change(item.resource.real_path, ChangeType.EDIT, get_diff(item)))
else:
raise Exception('Unknown Change')
diff --git a/requirements.txt b/requirements.txt
index 752eee82422f..cb71d94eb4e0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,12 +1,15 @@
-autopep8==1.2.1
-yapf==0.6.2
-pylint==1.8.2
-pep8==1.7.0
-prospector==0.11.7
-flake8==2.6.0
-pydocstyle==1.0.0
+# Install flake8 first, as both flake8 and autopep8 require pycodestyle,
+# but flake8 has a tighter pinning.
+flake8
+autopep8
+black ; python_version>='3.6'
+yapf
+pylint<2.0.0
+pep8
+prospector
+pydocstyle
nose
pytest
-fabric
-numba
rope
+flask
+django
diff --git a/src/client/activation/activationService.ts b/src/client/activation/activationService.ts
new file mode 100644
index 000000000000..73af6ba7cd0b
--- /dev/null
+++ b/src/client/activation/activationService.ts
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { ConfigurationChangeEvent, Disposable, OutputChannel, Uri } from 'vscode';
+import { IApplicationShell, ICommandManager, IWorkspaceService } from '../common/application/types';
+import { isLanguageServerTest, STANDARD_OUTPUT_CHANNEL } from '../common/constants';
+import '../common/extensions';
+import { IConfigurationService, IDisposableRegistry, IOutputChannel, IPythonSettings } from '../common/types';
+import { IServiceContainer } from '../ioc/types';
+import { ExtensionActivators, IExtensionActivationService, IExtensionActivator } from './types';
+
+const jediEnabledSetting: keyof IPythonSettings = 'jediEnabled';
+
+type ActivatorInfo = { jedi: boolean; activator: IExtensionActivator };
+
+@injectable()
+export class ExtensionActivationService implements IExtensionActivationService, Disposable {
+ private currentActivator?: ActivatorInfo;
+ private readonly workspaceService: IWorkspaceService;
+ private readonly output: OutputChannel;
+ private readonly appShell: IApplicationShell;
+ constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
+ this.workspaceService = this.serviceContainer.get(IWorkspaceService);
+ this.output = this.serviceContainer.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
+ this.appShell = this.serviceContainer.get(IApplicationShell);
+
+ const disposables = serviceContainer.get(IDisposableRegistry);
+ disposables.push(this);
+ disposables.push(this.workspaceService.onDidChangeConfiguration(this.onDidChangeConfiguration.bind(this)));
+ }
+ public async activate(): Promise {
+ if (this.currentActivator) {
+ return;
+ }
+
+ const jedi = this.useJedi();
+
+ const engineName = jedi ? 'Jedi Python language engine' : 'Microsoft Python language server';
+ this.output.appendLine(`Starting ${engineName}.`);
+ const activatorName = jedi ? ExtensionActivators.Jedi : ExtensionActivators.DotNet;
+ const activator = this.serviceContainer.get(IExtensionActivator, activatorName);
+ this.currentActivator = { jedi, activator };
+
+ await activator.activate();
+ }
+ public dispose() {
+ if (this.currentActivator) {
+ this.currentActivator.activator.deactivate().ignoreErrors();
+ }
+ }
+ private async onDidChangeConfiguration(event: ConfigurationChangeEvent) {
+ const workspacesUris: (Uri | undefined)[] = this.workspaceService.hasWorkspaceFolders ? this.workspaceService.workspaceFolders!.map(workspace => workspace.uri) : [undefined];
+ if (workspacesUris.findIndex(uri => event.affectsConfiguration(`python.${jediEnabledSetting}`, uri)) === -1) {
+ return;
+ }
+ const jedi = this.useJedi();
+ if (this.currentActivator && this.currentActivator.jedi === jedi) {
+ return;
+ }
+
+ const item = await this.appShell.showInformationMessage('Please reload the window switching between language engines.', 'Reload');
+ if (item === 'Reload') {
+ this.serviceContainer.get(ICommandManager).executeCommand('workbench.action.reloadWindow');
+ }
+ }
+ private useJedi(): boolean {
+ const workspacesUris: (Uri | undefined)[] = this.workspaceService.hasWorkspaceFolders ? this.workspaceService.workspaceFolders!.map(item => item.uri) : [undefined];
+ const configuraionService = this.serviceContainer.get(IConfigurationService);
+ const jediEnabledForAnyWorkspace = workspacesUris.filter(uri => configuraionService.getSettings(uri).jediEnabled).length > 0;
+ return !isLanguageServerTest() && jediEnabledForAnyWorkspace;
+ }
+}
diff --git a/src/client/activation/downloader.ts b/src/client/activation/downloader.ts
new file mode 100644
index 000000000000..0bb6b9dbcf20
--- /dev/null
+++ b/src/client/activation/downloader.ts
@@ -0,0 +1,157 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import * as fileSystem from 'fs';
+import * as path from 'path';
+import * as request from 'request';
+import * as requestProgress from 'request-progress';
+import { OutputChannel, ProgressLocation, window } from 'vscode';
+import { STANDARD_OUTPUT_CHANNEL } from '../common/constants';
+import { createDeferred } from '../common/helpers';
+import { IFileSystem, IPlatformService } from '../common/platform/types';
+import { IExtensionContext, IOutputChannel } from '../common/types';
+import { IServiceContainer } from '../ioc/types';
+import { PlatformData, PlatformName } from './platformData';
+
+// tslint:disable-next-line:no-require-imports no-var-requires
+const StreamZip = require('node-stream-zip');
+
+const downloadUriPrefix = 'https://pvsc.blob.core.windows.net/python-language-server';
+const downloadBaseFileName = 'Python-Language-Server';
+const downloadVersion = '0.1.18204.3';
+const downloadFileExtension = '.nupkg';
+
+export const DownloadLinks = {
+ [PlatformName.Windows32Bit]: `${downloadUriPrefix}/${downloadBaseFileName}-${PlatformName.Windows32Bit}.${downloadVersion}${downloadFileExtension}`,
+ [PlatformName.Windows64Bit]: `${downloadUriPrefix}/${downloadBaseFileName}-${PlatformName.Windows64Bit}.${downloadVersion}${downloadFileExtension}`,
+ [PlatformName.Linux64Bit]: `${downloadUriPrefix}/${downloadBaseFileName}-${PlatformName.Linux64Bit}.${downloadVersion}${downloadFileExtension}`,
+ [PlatformName.Mac64Bit]: `${downloadUriPrefix}/${downloadBaseFileName}-${PlatformName.Mac64Bit}.${downloadVersion}${downloadFileExtension}`
+};
+
+export class LanguageServerDownloader {
+ private readonly output: OutputChannel;
+ private readonly platform: IPlatformService;
+ private readonly platformData: PlatformData;
+ private readonly fs: IFileSystem;
+
+ constructor(private readonly services: IServiceContainer, private engineFolder: string) {
+ this.output = this.services.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
+ this.fs = this.services.get(IFileSystem);
+ this.platform = this.services.get(IPlatformService);
+ this.platformData = new PlatformData(this.platform, this.fs);
+ }
+
+ public async getDownloadUri() {
+ const platformString = await this.platformData.getPlatformName();
+ return DownloadLinks[platformString];
+ }
+
+ public async downloadLanguageServer(context: IExtensionContext): Promise {
+ const downloadUri = await this.getDownloadUri();
+
+ let localTempFilePath = '';
+ try {
+ localTempFilePath = await this.downloadFile(downloadUri, 'Downloading Microsoft Python Language Server... ');
+ await this.unpackArchive(context.extensionPath, localTempFilePath);
+ } catch (err) {
+ this.output.appendLine('failed.');
+ this.output.appendLine(err);
+ throw new Error(err);
+ } finally {
+ if (localTempFilePath.length > 0) {
+ await this.fs.deleteFile(localTempFilePath);
+ }
+ }
+ }
+
+ private async downloadFile(uri: string, title: string): Promise {
+ this.output.append(`Downloading ${uri}... `);
+ const tempFile = await this.fs.createTemporaryFile(downloadFileExtension);
+
+ const deferred = createDeferred();
+ const fileStream = fileSystem.createWriteStream(tempFile.filePath);
+ fileStream.on('finish', () => {
+ fileStream.close();
+ }).on('error', (err) => {
+ tempFile.dispose();
+ deferred.reject(err);
+ });
+
+ await window.withProgress({
+ location: ProgressLocation.Window
+ }, (progress) => {
+
+ requestProgress(request(uri))
+ .on('progress', (state) => {
+ // https://www.npmjs.com/package/request-progress
+ const received = Math.round(state.size.transferred / 1024);
+ const total = Math.round(state.size.total / 1024);
+ const percentage = Math.round(100 * state.percent);
+ progress.report({
+ message: `${title}${received} of ${total} KB (${percentage}%)`
+ });
+ })
+ .on('error', (err) => {
+ deferred.reject(err);
+ })
+ .on('end', () => {
+ this.output.append('complete.');
+ deferred.resolve();
+ })
+ .pipe(fileStream);
+ return deferred.promise;
+ });
+
+ return tempFile.filePath;
+ }
+
+ private async unpackArchive(extensionPath: string, tempFilePath: string): Promise {
+ this.output.append('Unpacking archive... ');
+
+ const installFolder = path.join(extensionPath, this.engineFolder);
+ const deferred = createDeferred();
+
+ const title = 'Extracting files... ';
+ await window.withProgress({
+ location: ProgressLocation.Window,
+ title
+ }, (progress) => {
+ const zip = new StreamZip({
+ file: tempFilePath,
+ storeEntries: true
+ });
+
+ let totalFiles = 0;
+ let extractedFiles = 0;
+ zip.on('ready', async () => {
+ totalFiles = zip.entriesCount;
+ if (!await this.fs.directoryExists(installFolder)) {
+ await this.fs.createDirectory(installFolder);
+ }
+ zip.extract(null, installFolder, (err, count) => {
+ if (err) {
+ deferred.reject(err);
+ } else {
+ deferred.resolve();
+ }
+ zip.close();
+ });
+ }).on('extract', (entry, file) => {
+ extractedFiles += 1;
+ progress.report({ message: `${title}${Math.round(100 * extractedFiles / totalFiles)}%` });
+ }).on('error', e => {
+ deferred.reject(e);
+ });
+ return deferred.promise;
+ });
+
+ // Set file to executable
+ if (!this.platform.isWindows) {
+ const executablePath = path.join(installFolder, this.platformData.getEngineExecutableName());
+ fileSystem.chmodSync(executablePath, '0764'); // -rwxrw-r--
+ }
+ this.output.appendLine('done.');
+ }
+}
diff --git a/src/client/activation/hashVerifier.ts b/src/client/activation/hashVerifier.ts
new file mode 100644
index 000000000000..61d1177966f9
--- /dev/null
+++ b/src/client/activation/hashVerifier.ts
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { createHash } from 'crypto';
+import * as fs from 'fs';
+import { createDeferred } from '../common/helpers';
+
+export class HashVerifier {
+ public async verifyHash(filePath: string, platformString: string, expectedDigest: string): Promise {
+ const readStream = fs.createReadStream(filePath);
+ const deferred = createDeferred();
+ const hash = createHash('sha512');
+ hash.setEncoding('hex');
+ readStream
+ .on('end', () => {
+ hash.end();
+ deferred.resolve();
+ })
+ .on('error', (err) => {
+ deferred.reject(`Unable to calculate file hash. Error ${err}`);
+ });
+
+ readStream.pipe(hash);
+ await deferred.promise;
+ const actual = hash.read() as string;
+ return expectedDigest === platformString ? true : actual.toLowerCase() === expectedDigest.toLowerCase();
+ }
+}
diff --git a/src/client/activation/interpreterDataService.ts b/src/client/activation/interpreterDataService.ts
new file mode 100644
index 000000000000..f923758b36bf
--- /dev/null
+++ b/src/client/activation/interpreterDataService.ts
@@ -0,0 +1,146 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { createHash } from 'crypto';
+import * as fs from 'fs';
+import * as path from 'path';
+import { ExtensionContext, Uri } from 'vscode';
+import { IApplicationShell } from '../common/application/types';
+import '../common/extensions';
+import { createDeferred } from '../common/helpers';
+import { IPlatformService } from '../common/platform/types';
+import { IPythonExecutionFactory, IPythonExecutionService } from '../common/process/types';
+import { IServiceContainer } from '../ioc/types';
+
+const DataVersion = 1;
+
+export class InterpreterData {
+ constructor(
+ public readonly dataVersion: number,
+ // tslint:disable-next-line:no-shadowed-variable
+ public readonly path: string,
+ public readonly version: string,
+ public readonly prefix: string,
+ public readonly searchPaths: string,
+ public readonly hash: string
+ ) { }
+}
+
+export class InterpreterDataService {
+ constructor(
+ private readonly context: ExtensionContext,
+ private readonly serviceContainer: IServiceContainer) { }
+
+ public async getInterpreterData(resource?: Uri): Promise {
+ const executionFactory = this.serviceContainer.get(IPythonExecutionFactory);
+ const execService = await executionFactory.create({ resource });
+
+ const interpreterPath = await execService.getExecutablePath();
+ if (interpreterPath.length === 0) {
+ return;
+ }
+
+ const cacheKey = `InterpreterData-${interpreterPath}`;
+ let interpreterData = this.context.globalState.get(cacheKey) as InterpreterData;
+ let interpreterChanged = false;
+ if (interpreterData) {
+ // Check if interpreter executable changed
+ if (interpreterData.dataVersion !== DataVersion) {
+ interpreterChanged = true;
+ } else {
+ const currentHash = await this.getInterpreterHash(interpreterPath);
+ interpreterChanged = currentHash !== interpreterData.hash;
+ }
+ }
+
+ if (interpreterChanged || !interpreterData) {
+ interpreterData = await this.getInterpreterDataFromPython(execService, interpreterPath);
+ this.context.globalState.update(interpreterPath, interpreterData);
+ } else {
+ // Make sure we verify that search paths did not change. This must be done
+ // completely async so we don't delay Python language server startup.
+ this.verifySearchPaths(interpreterData.searchPaths, interpreterPath, execService);
+ }
+ return interpreterData;
+ }
+
+ public getInterpreterHash(interpreterPath: string): Promise {
+ const platform = this.serviceContainer.get(IPlatformService);
+ const pythonExecutable = path.join(path.dirname(interpreterPath), platform.isWindows ? 'python.exe' : 'python');
+ // Hash mod time and creation time
+ const deferred = createDeferred();
+ fs.lstat(pythonExecutable, (err, stats) => {
+ if (err) {
+ deferred.resolve('');
+ } else {
+ const actual = createHash('sha512').update(`${stats.ctime}-${stats.mtime}`).digest('hex');
+ deferred.resolve(actual);
+ }
+ });
+ return deferred.promise;
+ }
+
+ private async getInterpreterDataFromPython(execService: IPythonExecutionService, interpreterPath: string): Promise {
+ const result = await execService.exec(['-c', 'import sys; print(sys.version_info); print(sys.prefix)'], {});
+ // 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) <>
+ // [MSC v.1500 32 bit (Intel)]
+ // C:\Python27
+ if (!result.stdout) {
+ throw Error('Unable to determine Python interpreter version and system prefix.');
+ }
+ const output = result.stdout.splitLines({ removeEmptyEntries: true, trim: true });
+ if (!output || output.length < 2) {
+ throw Error('Unable to parse version and and system prefix from the Python interpreter output.');
+ }
+ const majorMatches = output[0].match(/major=(\d*?),/);
+ const minorMatches = output[0].match(/minor=(\d*?),/);
+ if (!majorMatches || majorMatches.length < 2 || !minorMatches || minorMatches.length < 2) {
+ throw Error('Unable to parse interpreter version.');
+ }
+ const prefix = output[output.length - 1];
+ const hash = await this.getInterpreterHash(interpreterPath);
+ const searchPaths = await this.getSearchPaths(execService);
+ return new InterpreterData(DataVersion, interpreterPath, `${majorMatches[1]}.${minorMatches[1]}`, prefix, searchPaths, hash);
+ }
+
+ private async getSearchPaths(execService: IPythonExecutionService): Promise {
+ const result = await execService.exec(['-c', 'import sys; print(sys.path);'], {});
+ if (!result.stdout) {
+ throw Error('Unable to determine Python interpreter search paths.');
+ }
+ // tslint:disable-next-line:no-unnecessary-local-variable
+ const paths = result.stdout.split(',')
+ .filter(p => this.isValidPath(p))
+ .map(p => this.pathCleanup(p));
+ return paths.join(';'); // PTVS uses ; on all platforms
+ }
+
+ private pathCleanup(s: string): string {
+ s = s.trim();
+ if (s[0] === '\'') {
+ s = s.substr(1);
+ }
+ if (s[s.length - 1] === ']') {
+ s = s.substr(0, s.length - 1);
+ }
+ if (s[s.length - 1] === '\'') {
+ s = s.substr(0, s.length - 1);
+ }
+ return s;
+ }
+
+ private isValidPath(s: string): boolean {
+ return s.length > 0 && s[0] !== '[';
+ }
+
+ private verifySearchPaths(currentPaths: string, interpreterPath: string, execService: IPythonExecutionService): void {
+ this.getSearchPaths(execService)
+ .then(async paths => {
+ if (paths !== currentPaths) {
+ this.context.globalState.update(interpreterPath, undefined);
+ const appShell = this.serviceContainer.get(IApplicationShell);
+ await appShell.showWarningMessage('Search paths have changed for this Python interpreter. Please reload the extension to ensure that the IntelliSense works correctly.');
+ }
+ }).ignoreErrors();
+ }
+}
diff --git a/src/client/activation/jedi.ts b/src/client/activation/jedi.ts
new file mode 100644
index 000000000000..86629009162a
--- /dev/null
+++ b/src/client/activation/jedi.ts
@@ -0,0 +1,74 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { inject, injectable } from 'inversify';
+import { DocumentFilter, languages } from 'vscode';
+import { PYTHON } from '../common/constants';
+import { IConfigurationService, IExtensionContext, ILogger } from '../common/types';
+import { IShebangCodeLensProvider } from '../interpreter/contracts';
+import { IServiceContainer, IServiceManager } from '../ioc/types';
+import { JediFactory } from '../languageServices/jediProxyFactory';
+import { PythonCompletionItemProvider } from '../providers/completionProvider';
+import { PythonDefinitionProvider } from '../providers/definitionProvider';
+import { PythonHoverProvider } from '../providers/hoverProvider';
+import { activateGoToObjectDefinitionProvider } from '../providers/objectDefinitionProvider';
+import { PythonReferenceProvider } from '../providers/referenceProvider';
+import { PythonRenameProvider } from '../providers/renameProvider';
+import { PythonSignatureProvider } from '../providers/signatureProvider';
+import { PythonSymbolProvider } from '../providers/symbolProvider';
+import { IUnitTestManagementService } from '../unittests/types';
+import { WorkspaceSymbols } from '../workspaceSymbols/main';
+import { IExtensionActivator } from './types';
+
+@injectable()
+export class JediExtensionActivator implements IExtensionActivator {
+ private readonly context: IExtensionContext;
+ private jediFactory?: JediFactory;
+ private readonly documentSelector: DocumentFilter[];
+ constructor(@inject(IServiceManager) private serviceManager: IServiceManager) {
+ this.context = this.serviceManager.get(IExtensionContext);
+ this.documentSelector = PYTHON;
+ }
+
+ public async activate(): Promise {
+ const context = this.context;
+
+ const jediFactory = this.jediFactory = new JediFactory(context.asAbsolutePath('.'), this.serviceManager);
+ context.subscriptions.push(jediFactory);
+ context.subscriptions.push(...activateGoToObjectDefinitionProvider(jediFactory));
+
+ context.subscriptions.push(jediFactory);
+ context.subscriptions.push(languages.registerRenameProvider(this.documentSelector, new PythonRenameProvider(this.serviceManager)));
+ const definitionProvider = new PythonDefinitionProvider(jediFactory);
+
+ context.subscriptions.push(languages.registerDefinitionProvider(this.documentSelector, definitionProvider));
+ context.subscriptions.push(languages.registerHoverProvider(this.documentSelector, new PythonHoverProvider(jediFactory)));
+ context.subscriptions.push(languages.registerReferenceProvider(this.documentSelector, new PythonReferenceProvider(jediFactory)));
+ context.subscriptions.push(languages.registerCompletionItemProvider(this.documentSelector, new PythonCompletionItemProvider(jediFactory, this.serviceManager), '.'));
+ context.subscriptions.push(languages.registerCodeLensProvider(this.documentSelector, this.serviceManager.get(IShebangCodeLensProvider)));
+
+ const serviceContainer = this.serviceManager.get(IServiceContainer);
+ context.subscriptions.push(new WorkspaceSymbols(serviceContainer));
+
+ const symbolProvider = new PythonSymbolProvider(serviceContainer, jediFactory);
+ context.subscriptions.push(languages.registerDocumentSymbolProvider(this.documentSelector, symbolProvider));
+
+ const pythonSettings = this.serviceManager.get(IConfigurationService).getSettings();
+ if (pythonSettings.devOptions.indexOf('DISABLE_SIGNATURE') === -1) {
+ context.subscriptions.push(languages.registerSignatureHelpProvider(this.documentSelector, new PythonSignatureProvider(jediFactory), '(', ','));
+ }
+
+ const testManagementService = this.serviceManager.get(IUnitTestManagementService);
+ testManagementService.activate()
+ .then(() => testManagementService.activateCodeLenses(symbolProvider))
+ .catch(ex => this.serviceManager.get(ILogger).logError('Failed to activate Unit Tests', ex));
+
+ return true;
+ }
+
+ public async deactivate(): Promise {
+ if (this.jediFactory) {
+ this.jediFactory.dispose();
+ }
+ }
+}
diff --git a/src/client/activation/languageServer.ts b/src/client/activation/languageServer.ts
new file mode 100644
index 000000000000..8c416206a7b1
--- /dev/null
+++ b/src/client/activation/languageServer.ts
@@ -0,0 +1,345 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { inject, injectable } from 'inversify';
+import * as path from 'path';
+import { CancellationToken, CompletionContext, OutputChannel, Position,
+ TextDocument, Uri } from 'vscode';
+import { Disposable, LanguageClient, LanguageClientOptions,
+ ProvideCompletionItemsSignature, ServerOptions } from 'vscode-languageclient';
+import { IApplicationShell, ICommandManager, IWorkspaceService } from '../common/application/types';
+import { PythonSettings } from '../common/configSettings';
+import { isTestExecution, STANDARD_OUTPUT_CHANNEL } from '../common/constants';
+import { createDeferred, Deferred } from '../common/helpers';
+import { IFileSystem, IPlatformService } from '../common/platform/types';
+import { StopWatch } from '../common/stopWatch';
+import { BANNER_NAME_LS_SURVEY, IConfigurationService, IExtensionContext, ILogger,
+ IOutputChannel, IPythonExtensionBanner, IPythonSettings } from '../common/types';
+import { IServiceContainer } from '../ioc/types';
+import {
+ PYTHON_LANGUAGE_SERVER_DOWNLOADED,
+ PYTHON_LANGUAGE_SERVER_ENABLED,
+ PYTHON_LANGUAGE_SERVER_ERROR
+} from '../telemetry/constants';
+import { getTelemetryReporter } from '../telemetry/telemetry';
+import { IUnitTestManagementService } from '../unittests/types';
+import { LanguageServerDownloader } from './downloader';
+import { InterpreterData, InterpreterDataService } from './interpreterDataService';
+import { PlatformData } from './platformData';
+import { ProgressReporting } from './progress';
+import { IExtensionActivator } from './types';
+
+const PYTHON = 'python';
+const dotNetCommand = 'dotnet';
+const languageClientName = 'Python Tools';
+const languageServerFolder = 'languageServer';
+const loadExtensionCommand = 'python._loadLanguageServerExtension';
+
+@injectable()
+export class LanguageServerExtensionActivator implements IExtensionActivator {
+ private readonly configuration: IConfigurationService;
+ private readonly appShell: IApplicationShell;
+ private readonly output: OutputChannel;
+ private readonly fs: IFileSystem;
+ private readonly sw = new StopWatch();
+ private readonly platformData: PlatformData;
+ private readonly startupCompleted: Deferred;
+ private readonly disposables: Disposable[] = [];
+ private readonly context: IExtensionContext;
+ private readonly workspace: IWorkspaceService;
+ private readonly root: Uri | undefined;
+
+ private languageClient: LanguageClient | undefined;
+ private interpreterHash: string = '';
+ private excludedFiles: string[] = [];
+ private typeshedPaths: string[] = [];
+ private loadExtensionArgs: {} | undefined;
+ private surveyBanner: IPythonExtensionBanner;
+ // tslint:disable-next-line:no-unused-variable
+ private progressReporting: ProgressReporting | undefined;
+
+ constructor(@inject(IServiceContainer) private readonly services: IServiceContainer) {
+ this.context = this.services.get(IExtensionContext);
+ this.configuration = this.services.get(IConfigurationService);
+ this.appShell = this.services.get(IApplicationShell);
+ this.output = this.services.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
+ this.fs = this.services.get(IFileSystem);
+ this.platformData = new PlatformData(services.get(IPlatformService), this.fs);
+ this.workspace = this.services.get(IWorkspaceService);
+
+ // Currently only a single root. Multi-root support is future.
+ this.root = this.workspace && this.workspace.hasWorkspaceFolders
+ ? this.workspace.workspaceFolders![0]!.uri : undefined;
+
+ this.startupCompleted = createDeferred();
+ const commandManager = this.services.get(ICommandManager);
+
+ this.disposables.push(commandManager.registerCommand(loadExtensionCommand,
+ async (args) => {
+ if (this.languageClient) {
+ await this.startupCompleted.promise;
+ this.languageClient.sendRequest('python/loadExtension', args);
+ } else {
+ this.loadExtensionArgs = args;
+ }
+ }
+ ));
+
+ this.surveyBanner = services.get(IPythonExtensionBanner, BANNER_NAME_LS_SURVEY);
+
+ (this.configuration.getSettings() as PythonSettings).addListener('change', this.onSettingsChanged);
+ }
+
+ public async activate(): Promise {
+ this.sw.reset();
+ const clientOptions = await this.getAnalysisOptions();
+ if (!clientOptions) {
+ return false;
+ }
+
+ const testManagementService = this.services.get(IUnitTestManagementService);
+ testManagementService.activate()
+ .catch(ex => this.services.get(ILogger).logError('Failed to activate Unit Tests', ex));
+
+ return this.startLanguageServer(clientOptions);
+ }
+
+ public async deactivate(): Promise {
+ if (this.languageClient) {
+ // Do not await on this
+ this.languageClient.stop();
+ }
+ for (const d of this.disposables) {
+ d.dispose();
+ }
+ (this.configuration.getSettings() as PythonSettings).removeListener('change', this.onSettingsChanged);
+ }
+
+ private async startLanguageServer(clientOptions: LanguageClientOptions): Promise {
+ // Determine if we are running MSIL/Universal via dotnet or self-contained app.
+
+ const reporter = getTelemetryReporter();
+ reporter.sendTelemetryEvent(PYTHON_LANGUAGE_SERVER_ENABLED);
+
+ const settings = this.configuration.getSettings();
+ if (!settings.downloadLanguageServer) {
+ // Depends on .NET Runtime or SDK. Typically development-only case.
+ this.languageClient = this.createSimpleLanguageClient(clientOptions);
+ await this.startLanguageClient();
+ return true;
+ }
+
+ const mscorlib = path.join(this.context.extensionPath, languageServerFolder, 'mscorlib.dll');
+ if (!await this.fs.fileExists(mscorlib)) {
+ const downloader = new LanguageServerDownloader(this.services, languageServerFolder);
+ await downloader.downloadLanguageServer(this.context);
+ reporter.sendTelemetryEvent(PYTHON_LANGUAGE_SERVER_DOWNLOADED);
+ }
+
+ const serverModule = path.join(this.context.extensionPath, languageServerFolder, this.platformData.getEngineExecutableName());
+ this.languageClient = this.createSelfContainedLanguageClient(serverModule, clientOptions);
+ try {
+ await this.startLanguageClient();
+ return true;
+ } catch (ex) {
+ this.appShell.showErrorMessage(`Language server failed to start. Error ${ex}`);
+ reporter.sendTelemetryEvent(PYTHON_LANGUAGE_SERVER_ERROR, { error: 'Failed to start (platform)' });
+ return false;
+ }
+ }
+
+ private async startLanguageClient(): Promise {
+ this.context.subscriptions.push(this.languageClient!.start());
+ await this.serverReady();
+ this.progressReporting = new ProgressReporting(this.languageClient!);
+ }
+
+ private async serverReady(): Promise {
+ while (!this.languageClient!.initializeResult) {
+ await new Promise(resolve => setTimeout(resolve, 100));
+ }
+ if (this.loadExtensionArgs) {
+ this.languageClient!.sendRequest('python/loadExtension', this.loadExtensionArgs);
+ }
+
+ this.startupCompleted.resolve();
+ }
+
+ private createSimpleLanguageClient(clientOptions: LanguageClientOptions): LanguageClient {
+ const commandOptions = { stdio: 'pipe' };
+ const serverModule = path.join(this.context.extensionPath, languageServerFolder, this.platformData.getEngineDllName());
+ const serverOptions: ServerOptions = {
+ run: { command: dotNetCommand, args: [serverModule], options: commandOptions },
+ debug: { command: dotNetCommand, args: [serverModule, '--debug'], options: commandOptions }
+ };
+ return new LanguageClient(PYTHON, languageClientName, serverOptions, clientOptions);
+ }
+
+ private createSelfContainedLanguageClient(serverModule: string, clientOptions: LanguageClientOptions): LanguageClient {
+ const options = { stdio: 'pipe' };
+ const serverOptions: ServerOptions = {
+ run: { command: serverModule, rgs: [], options: options },
+ debug: { command: serverModule, args: ['--debug'], options }
+ };
+ return new LanguageClient(PYTHON, languageClientName, serverOptions, clientOptions);
+ }
+
+ private async getAnalysisOptions(): Promise {
+ // tslint:disable-next-line:no-any
+ const properties = new Map();
+ let interpreterData: InterpreterData | undefined;
+ let pythonPath = '';
+
+ try {
+ const interpreterDataService = new InterpreterDataService(this.context, this.services);
+ interpreterData = await interpreterDataService.getInterpreterData();
+ } catch (ex) {
+ this.appShell.showWarningMessage('Unable to determine path to the Python interpreter. IntelliSense will be limited.');
+ }
+
+ this.interpreterHash = interpreterData ? interpreterData.hash : '';
+ if (interpreterData) {
+ pythonPath = path.dirname(interpreterData.path);
+ // tslint:disable-next-line:no-string-literal
+ properties['InterpreterPath'] = interpreterData.path;
+ // tslint:disable-next-line:no-string-literal
+ properties['Version'] = interpreterData.version;
+ // tslint:disable-next-line:no-string-literal
+ properties['PrefixPath'] = interpreterData.prefix;
+ }
+
+ // tslint:disable-next-line:no-string-literal
+ properties['DatabasePath'] = path.join(this.context.extensionPath, languageServerFolder);
+
+ let searchPaths = interpreterData ? interpreterData.searchPaths.split(path.delimiter) : [];
+ const settings = this.configuration.getSettings();
+ if (settings.autoComplete) {
+ const extraPaths = settings.autoComplete.extraPaths;
+ if (extraPaths && extraPaths.length > 0) {
+ searchPaths.push(...extraPaths);
+ }
+ }
+
+ // Make sure paths do not contain multiple slashes so file URIs
+ // in VS Code (Node.js) and in the language server (.NET) match.
+ // Note: for the language server paths separator is always ;
+ searchPaths.push(pythonPath);
+ searchPaths = searchPaths.map(p => path.normalize(p));
+
+ const selector = [{ language: PYTHON, scheme: 'file' }];
+ this.excludedFiles = this.getExcludedFiles();
+ this.typeshedPaths = this.getTypeshedPaths(settings);
+
+ const traceLogging = (settings.analysis && settings.analysis.traceLogging) ? settings.analysis.traceLogging : false;
+
+ // Options to control the language client
+ return {
+ // Register the server for Python documents
+ documentSelector: selector,
+ synchronize: {
+ configurationSection: PYTHON
+ },
+ outputChannel: this.output,
+ initializationOptions: {
+ interpreter: {
+ properties
+ },
+ displayOptions: {
+ preferredFormat: 'markdown',
+ trimDocumentationLines: false,
+ maxDocumentationLineLength: 0,
+ trimDocumentationText: false,
+ maxDocumentationTextLength: 0
+ },
+ searchPaths,
+ typeStubSearchPaths: this.typeshedPaths,
+ excludeFiles: this.excludedFiles,
+ testEnvironment: isTestExecution(),
+ analysisUpdates: true,
+ traceLogging
+ },
+ middleware: {
+ provideCompletionItem: (document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature) => {
+ if (this.surveyBanner) {
+ this.surveyBanner.showBanner().ignoreErrors();
+ }
+ return next(document, position, context, token);
+ }
+ }
+ };
+ }
+
+ private getExcludedFiles(): string[] {
+ const list: string[] = ['**/Lib/**', '**/site-packages/**'];
+ this.getVsCodeExcludeSection('search.exclude', list);
+ this.getVsCodeExcludeSection('files.exclude', list);
+ this.getVsCodeExcludeSection('files.watcherExclude', list);
+ this.getPythonExcludeSection('linting.ignorePatterns', list);
+ this.getPythonExcludeSection('workspaceSymbols.exclusionPattern', list);
+ return list;
+ }
+
+ private getVsCodeExcludeSection(setting: string, list: string[]): void {
+ const states = this.workspace.getConfiguration(setting, this.root);
+ if (states) {
+ Object.keys(states)
+ .filter(k => (k.indexOf('*') >= 0 || k.indexOf('/') >= 0) && states[k])
+ .forEach(p => list.push(p));
+ }
+ }
+
+ private getPythonExcludeSection(setting: string, list: string[]): void {
+ const pythonSettings = this.configuration.getSettings(this.root);
+ const paths = pythonSettings && pythonSettings.linting ? pythonSettings.linting.ignorePatterns : undefined;
+ if (paths && Array.isArray(paths)) {
+ paths
+ .filter(p => p && p.length > 0)
+ .forEach(p => list.push(p));
+ }
+ }
+
+ private getTypeshedPaths(settings: IPythonSettings): string[] {
+ return settings.analysis.typeshedPaths && settings.analysis.typeshedPaths.length > 0
+ ? settings.analysis.typeshedPaths
+ : [path.join(this.context.extensionPath, 'typeshed')];
+ }
+
+ private async onSettingsChanged(): Promise {
+ const ids = new InterpreterDataService(this.context, this.services);
+ const idata = await ids.getInterpreterData();
+ if (!idata || idata.hash !== this.interpreterHash) {
+ this.interpreterHash = idata ? idata.hash : '';
+ await this.restartLanguageServer();
+ return;
+ }
+
+ const excludedFiles = this.getExcludedFiles();
+ await this.restartLanguageServerIfArrayChanged(this.excludedFiles, excludedFiles);
+
+ const settings = this.configuration.getSettings();
+ const typeshedPaths = this.getTypeshedPaths(settings);
+ await this.restartLanguageServerIfArrayChanged(this.typeshedPaths, typeshedPaths);
+ }
+
+ private async restartLanguageServerIfArrayChanged(oldArray: string[], newArray: string[]): Promise {
+ if (newArray.length !== oldArray.length) {
+ await this.restartLanguageServer();
+ return;
+ }
+
+ for (let i = 0; i < oldArray.length; i += 1) {
+ if (oldArray[i] !== newArray[i]) {
+ await this.restartLanguageServer();
+ return;
+ }
+ }
+ }
+
+ private async restartLanguageServer(): Promise {
+ if (!this.context) {
+ return;
+ }
+ await this.deactivate();
+ await this.activate();
+ }
+}
diff --git a/src/client/activation/languageServerHashes.ts b/src/client/activation/languageServerHashes.ts
new file mode 100644
index 000000000000..d8d856064363
--- /dev/null
+++ b/src/client/activation/languageServerHashes.ts
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+// This file will be replaced by a generated one during the release build
+// with actual hashes of the uploaded packages.
+// Values are for test purposes only
+export const language_server_win_x86_sha512 = 'win-x86';
+export const language_server_win_x64_sha512 = 'win-x64';
+export const language_server_osx_x64_sha512 = 'osx-x64';
+export const language_server_linux_x64_sha512 = 'linux-x64';
diff --git a/src/client/activation/platformData.ts b/src/client/activation/platformData.ts
new file mode 100644
index 000000000000..39cce79cc82f
--- /dev/null
+++ b/src/client/activation/platformData.ts
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { IFileSystem, IPlatformService } from '../common/platform/types';
+import {
+ language_server_linux_x64_sha512,
+ language_server_osx_x64_sha512,
+ language_server_win_x64_sha512,
+ language_server_win_x86_sha512
+} from './languageServerHashes';
+
+export enum PlatformName {
+ Windows32Bit = 'win-x86',
+ Windows64Bit = 'win-x64',
+ Mac64Bit = 'osx-x64',
+ Linux64Bit = 'linux-x64'
+}
+
+export enum PlatformLSExecutables {
+ Windows = 'Microsoft.Python.LanguageServer.exe',
+ MacOS = 'Microsoft.Python.LanguageServer',
+ Linux = 'Microsoft.Python.LanguageServer'
+}
+
+export class PlatformData {
+ constructor(private platform: IPlatformService, fs: IFileSystem) { }
+ public async getPlatformName(): Promise {
+ if (this.platform.isWindows) {
+ return this.platform.is64bit ? PlatformName.Windows64Bit : PlatformName.Windows32Bit;
+ }
+ if (this.platform.isMac) {
+ return PlatformName.Mac64Bit;
+ }
+ if (this.platform.isLinux) {
+ if (!this.platform.is64bit) {
+ throw new Error('Microsoft Python Language Server does not support 32-bit Linux.');
+ }
+ return PlatformName.Linux64Bit;
+ }
+ throw new Error('Unknown OS platform.');
+ }
+
+ public getEngineDllName(): string {
+ return 'Microsoft.Python.LanguageServer.dll';
+ }
+
+ public getEngineExecutableName(): string {
+ if (this.platform.isWindows) {
+ return PlatformLSExecutables.Windows;
+ } else if (this.platform.isLinux) {
+ return PlatformLSExecutables.Linux;
+ } else if (this.platform.isMac) {
+ return PlatformLSExecutables.MacOS;
+ } else {
+ return 'unknown-platform';
+ }
+ }
+
+ public async getExpectedHash(): Promise {
+ if (this.platform.isWindows) {
+ return this.platform.is64bit ? language_server_win_x64_sha512 : language_server_win_x86_sha512;
+ }
+ if (this.platform.isMac) {
+ return language_server_osx_x64_sha512;
+ }
+ if (this.platform.isLinux && this.platform.is64bit) {
+ return language_server_linux_x64_sha512;
+ }
+ throw new Error('Unknown platform.');
+ }
+}
diff --git a/src/client/activation/progress.ts b/src/client/activation/progress.ts
new file mode 100644
index 000000000000..a9c7fa916fcc
--- /dev/null
+++ b/src/client/activation/progress.ts
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { Progress, ProgressLocation, window } from 'vscode';
+import { Disposable, LanguageClient } from 'vscode-languageclient';
+import { createDeferred, Deferred } from '../common/helpers';
+
+export class ProgressReporting {
+ private statusBarMessage: Disposable | undefined;
+ private progress: Progress<{ message?: string; increment?: number }> | undefined;
+ private progressDeferred: Deferred | undefined;
+
+ constructor(private readonly languageClient: LanguageClient) {
+ this.languageClient.onNotification('python/setStatusBarMessage', (m: string) => {
+ if (this.statusBarMessage) {
+ this.statusBarMessage.dispose();
+ }
+ this.statusBarMessage = window.setStatusBarMessage(m);
+ });
+
+ this.languageClient.onNotification('python/beginProgress', async _ => {
+ this.progressDeferred = createDeferred();
+ window.withProgress({
+ location: ProgressLocation.Window,
+ title: ''
+ }, progress => {
+ this.progress = progress;
+ return this.progressDeferred!.promise;
+ });
+ });
+
+ this.languageClient.onNotification('python/reportProgress', (m: string) => {
+ if (!this.progress) {
+ return;
+ }
+ this.progress.report({ message: m });
+ });
+
+ this.languageClient.onNotification('python/endProgress', _ => {
+ if (this.progressDeferred) {
+ this.progressDeferred.resolve();
+ this.progressDeferred = undefined;
+ }
+ });
+ }
+}
diff --git a/src/client/activation/serviceRegistry.ts b/src/client/activation/serviceRegistry.ts
new file mode 100644
index 000000000000..23dffa6cd365
--- /dev/null
+++ b/src/client/activation/serviceRegistry.ts
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { BANNER_NAME_LS_SURVEY, BANNER_NAME_PROPOSE_LS, IPythonExtensionBanner } from '../common/types';
+import { IServiceManager } from '../ioc/types';
+import { LanguageServerSurveyBanner } from '../languageServices/languageServerSurveyBanner';
+import { ProposeLanguageServerBanner } from '../languageServices/proposeLanguageServerBanner';
+import { ExtensionActivationService } from './activationService';
+import { JediExtensionActivator } from './jedi';
+import { LanguageServerExtensionActivator } from './languageServer';
+import { ExtensionActivators, IExtensionActivationService, IExtensionActivator } from './types';
+
+export function registerTypes(serviceManager: IServiceManager) {
+ serviceManager.addSingleton(IExtensionActivationService, ExtensionActivationService);
+ serviceManager.add(IExtensionActivator, JediExtensionActivator, ExtensionActivators.Jedi);
+ serviceManager.add(IExtensionActivator, LanguageServerExtensionActivator, ExtensionActivators.DotNet);
+ serviceManager.addSingleton(IPythonExtensionBanner, LanguageServerSurveyBanner, BANNER_NAME_LS_SURVEY);
+ serviceManager.addSingleton(IPythonExtensionBanner, ProposeLanguageServerBanner, BANNER_NAME_PROPOSE_LS);
+}
diff --git a/src/client/activation/types.ts b/src/client/activation/types.ts
new file mode 100644
index 000000000000..714f51378251
--- /dev/null
+++ b/src/client/activation/types.ts
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+export const IExtensionActivationService = Symbol('IExtensionActivationService');
+export interface IExtensionActivationService {
+ activate(): Promise;
+}
+
+export enum ExtensionActivators {
+ Jedi = 'Jedi',
+ DotNet = 'DotNet'
+}
+
+export const IExtensionActivator = Symbol('IExtensionActivator');
+export interface IExtensionActivator {
+ activate(): Promise;
+ deactivate(): Promise;
+}
diff --git a/src/client/application/diagnostics/applicationDiagnostics.ts b/src/client/application/diagnostics/applicationDiagnostics.ts
new file mode 100644
index 000000000000..5956cf5d6e5e
--- /dev/null
+++ b/src/client/application/diagnostics/applicationDiagnostics.ts
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { DiagnosticSeverity } from 'vscode';
+import { STANDARD_OUTPUT_CHANNEL } from '../../common/constants';
+import { ILogger, IOutputChannel } from '../../common/types';
+import { IServiceContainer } from '../../ioc/types';
+import { IApplicationDiagnostics } from '../types';
+import { EnvironmentPathVariableDiagnosticsServiceId } from './checks/envPathVariable';
+import { IDiagnostic, IDiagnosticsService } from './types';
+
+@injectable()
+export class ApplicationDiagnostics implements IApplicationDiagnostics {
+ constructor(@inject(IServiceContainer) private readonly serviceContainer: IServiceContainer) { }
+ public async performPreStartupHealthCheck(): Promise {
+ const envHealthCheck = this.serviceContainer.get(IDiagnosticsService, EnvironmentPathVariableDiagnosticsServiceId);
+ const diagnostics = await envHealthCheck.diagnose();
+ this.log(diagnostics);
+ if (diagnostics.length > 0) {
+ await envHealthCheck.handle(diagnostics);
+ }
+ }
+ private log(diagnostics: IDiagnostic[]): void {
+ const logger = this.serviceContainer.get(ILogger);
+ const outputChannel = this.serviceContainer.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
+ diagnostics.forEach(item => {
+ const message = `Diagnostic Code: ${item.code}, Message: ${item.message}`;
+ switch (item.severity) {
+ case DiagnosticSeverity.Error: {
+ logger.logError(message);
+ outputChannel.appendLine(message);
+ break;
+ }
+ case DiagnosticSeverity.Warning: {
+ logger.logWarning(message);
+ outputChannel.appendLine(message);
+ break;
+ }
+ default: {
+ logger.logInformation(message);
+ }
+ }
+ });
+ }
+}
diff --git a/src/client/application/diagnostics/base.ts b/src/client/application/diagnostics/base.ts
new file mode 100644
index 000000000000..bafb8e84561c
--- /dev/null
+++ b/src/client/application/diagnostics/base.ts
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { injectable, unmanaged } from 'inversify';
+import { DiagnosticSeverity } from 'vscode';
+import { IServiceContainer } from '../../ioc/types';
+import { DiagnosticScope, IDiagnostic, IDiagnosticFilterService, IDiagnosticsService } from './types';
+
+@injectable()
+export abstract class BaseDiagnostic implements IDiagnostic {
+ constructor(public readonly code: string, public readonly message: string,
+ public readonly severity: DiagnosticSeverity, public readonly scope: DiagnosticScope) { }
+}
+
+@injectable()
+export abstract class BaseDiagnosticsService implements IDiagnosticsService {
+ protected readonly filterService: IDiagnosticFilterService;
+ constructor(@unmanaged() private readonly supportedDiagnosticCodes: string[],
+ @unmanaged() protected serviceContainer: IServiceContainer) {
+ this.filterService = serviceContainer.get(IDiagnosticFilterService);
+ }
+ public abstract diagnose(): Promise;
+ public abstract handle(diagnostics: IDiagnostic[]): Promise;
+ public async canHandle(diagnostic: IDiagnostic): Promise {
+ return this.supportedDiagnosticCodes.filter(item => item === diagnostic.code).length > 0;
+ }
+}
diff --git a/src/client/application/diagnostics/checks/envPathVariable.ts b/src/client/application/diagnostics/checks/envPathVariable.ts
new file mode 100644
index 000000000000..bccb3a29c042
--- /dev/null
+++ b/src/client/application/diagnostics/checks/envPathVariable.ts
@@ -0,0 +1,84 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { DiagnosticSeverity } from 'vscode';
+import { IApplicationEnvironment } from '../../../common/application/types';
+import '../../../common/extensions';
+import { IPlatformService } from '../../../common/platform/types';
+import { ICurrentProcess, IPathUtils } from '../../../common/types';
+import { IServiceContainer } from '../../../ioc/types';
+import { BaseDiagnostic, BaseDiagnosticsService } from '../base';
+import { IDiagnosticsCommandFactory } from '../commands/types';
+import { DiagnosticCodes } from '../constants';
+import { DiagnosticCommandPromptHandlerServiceId, MessageCommandPrompt } from '../promptHandler';
+import { DiagnosticScope, IDiagnostic, IDiagnosticHandlerService } from '../types';
+
+const InvalidEnvPathVariableMessage = 'The environment variable \'{0}\' seems to have some paths containing the \'"\' character.' +
+ ' The existence of such a character is known to have caused the {1} extension to not load. If the extension fails to load please modify your paths to remove this \'"\' character.';
+
+export class InvalidEnvironmentPathVariableDiagnostic extends BaseDiagnostic {
+ constructor(message) {
+ super(DiagnosticCodes.InvalidEnvironmentPathVariableDiagnostic,
+ message, DiagnosticSeverity.Warning, DiagnosticScope.Global);
+ }
+}
+
+export const EnvironmentPathVariableDiagnosticsServiceId = 'EnvironmentPathVariableDiagnosticsServiceId';
+
+@injectable()
+export class EnvironmentPathVariableDiagnosticsService extends BaseDiagnosticsService {
+ protected readonly messageService: IDiagnosticHandlerService;
+ private readonly platform: IPlatformService;
+ constructor(@inject(IServiceContainer) serviceContainer: IServiceContainer) {
+ super([DiagnosticCodes.InvalidEnvironmentPathVariableDiagnostic], serviceContainer);
+ this.platform = this.serviceContainer.get(IPlatformService);
+ this.messageService = serviceContainer.get>(IDiagnosticHandlerService, DiagnosticCommandPromptHandlerServiceId);
+ }
+ public async diagnose(): Promise {
+ if (this.platform.isWindows &&
+ this.doesPathVariableHaveInvalidEntries()) {
+ const env = this.serviceContainer.get(IApplicationEnvironment);
+ const message = InvalidEnvPathVariableMessage
+ .format(this.platform.pathVariableName, env.extensionName);
+ return [new InvalidEnvironmentPathVariableDiagnostic(message)];
+ } else {
+ return [];
+ }
+ }
+ public async handle(diagnostics: IDiagnostic[]): Promise {
+ // This class can only handle one type of diagnostic, hence just use first item in list.
+ if (diagnostics.length === 0 || !this.canHandle(diagnostics[0])) {
+ return;
+ }
+ const diagnostic = diagnostics[0];
+ if (await this.filterService.shouldIgnoreDiagnostic(diagnostic.code)) {
+ return;
+ }
+ const commandFactory = this.serviceContainer.get(IDiagnosticsCommandFactory);
+ const options = [
+ {
+ prompt: 'Ignore'
+ },
+ {
+ prompt: 'Always Ignore',
+ command: commandFactory.createCommand(diagnostic, { type: 'ignore', options: DiagnosticScope.Global })
+ },
+ {
+ prompt: 'More Info',
+ command: commandFactory.createCommand(diagnostic, { type: 'launch', options: 'https://aka.ms/Niq35h' })
+ }
+ ];
+
+ await this.messageService.handle(diagnostic, { commandPrompts: options });
+ }
+ private doesPathVariableHaveInvalidEntries() {
+ const currentProc = this.serviceContainer.get(ICurrentProcess);
+ const pathValue = currentProc.env[this.platform.pathVariableName];
+ const pathSeparator = this.serviceContainer.get(IPathUtils).delimiter;
+ const paths = pathValue.split(pathSeparator);
+ return paths.filter(item => item.indexOf('"') >= 0).length > 0;
+ }
+}
diff --git a/src/client/application/diagnostics/commands/base.ts b/src/client/application/diagnostics/commands/base.ts
new file mode 100644
index 000000000000..8bbb4cc5f1e4
--- /dev/null
+++ b/src/client/application/diagnostics/commands/base.ts
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { IDiagnostic, IDiagnosticCommand } from '../types';
+
+export abstract class BaseDiagnosticCommand implements IDiagnosticCommand {
+ constructor(public readonly diagnostic: IDiagnostic) {
+ }
+ public abstract invoke(): Promise;
+}
diff --git a/src/client/application/diagnostics/commands/factory.ts b/src/client/application/diagnostics/commands/factory.ts
new file mode 100644
index 000000000000..47d2e63aa0d8
--- /dev/null
+++ b/src/client/application/diagnostics/commands/factory.ts
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { IServiceContainer } from '../../../ioc/types';
+import { IDiagnostic, IDiagnosticCommand } from '../types';
+import { IgnoreDiagnosticCommand } from './ignore';
+import { LaunchBrowserCommand } from './launchBrowser';
+import { CommandOptions, IDiagnosticsCommandFactory } from './types';
+
+@injectable()
+export class DiagnosticsCommandFactory implements IDiagnosticsCommandFactory {
+ constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) { }
+ public createCommand(diagnostic: IDiagnostic, options: CommandOptions): IDiagnosticCommand {
+ const commandType = options.type;
+ switch (options.type) {
+ case 'ignore': {
+ return new IgnoreDiagnosticCommand(diagnostic, this.serviceContainer, options.options);
+ }
+ case 'launch': {
+ return new LaunchBrowserCommand(diagnostic, this.serviceContainer, options.options);
+ }
+ default: {
+ throw new Error(`Unknown Diagnostic command commandType '${commandType}'`);
+ }
+ }
+ }
+}
diff --git a/src/client/application/diagnostics/commands/ignore.ts b/src/client/application/diagnostics/commands/ignore.ts
new file mode 100644
index 000000000000..18a47bba07ab
--- /dev/null
+++ b/src/client/application/diagnostics/commands/ignore.ts
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { IServiceContainer } from '../../../ioc/types';
+import { DiagnosticScope, IDiagnostic, IDiagnosticFilterService } from '../types';
+import { BaseDiagnosticCommand } from './base';
+
+export class IgnoreDiagnosticCommand extends BaseDiagnosticCommand {
+ constructor(diagnostic: IDiagnostic, private serviceContainer: IServiceContainer, private readonly scope: DiagnosticScope) {
+ super(diagnostic);
+ }
+ public invoke(): Promise {
+ const filter = this.serviceContainer.get(IDiagnosticFilterService);
+ return filter.ignoreDiagnostic(this.diagnostic.code, this.scope);
+ }
+}
diff --git a/src/client/application/diagnostics/commands/launchBrowser.ts b/src/client/application/diagnostics/commands/launchBrowser.ts
new file mode 100644
index 000000000000..55a78a3c0971
--- /dev/null
+++ b/src/client/application/diagnostics/commands/launchBrowser.ts
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { IBrowserService } from '../../../common/types';
+import { IServiceContainer } from '../../../ioc/types';
+import { IDiagnostic } from '../types';
+import { BaseDiagnosticCommand } from './base';
+
+export class LaunchBrowserCommand extends BaseDiagnosticCommand {
+ constructor(diagnostic: IDiagnostic, private serviceContainer: IServiceContainer, private url: string) {
+ super(diagnostic);
+ }
+ public async invoke(): Promise {
+ const browser = this.serviceContainer.get(IBrowserService);
+ return browser.launch(this.url);
+ }
+}
diff --git a/src/client/application/diagnostics/commands/types.ts b/src/client/application/diagnostics/commands/types.ts
new file mode 100644
index 000000000000..b6f95e2bc769
--- /dev/null
+++ b/src/client/application/diagnostics/commands/types.ts
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { DiagnosticScope, IDiagnostic, IDiagnosticCommand } from '../types';
+
+export type CommandOption = { type: Type; options: Option };
+export type LaunchBrowserOption = CommandOption<'launch', string>;
+export type IgnoreDiagnostOption = CommandOption<'ignore', DiagnosticScope>;
+export type CommandOptions = LaunchBrowserOption | IgnoreDiagnostOption;
+
+export const IDiagnosticsCommandFactory = Symbol('IDiagnosticsCommandFactory');
+
+export interface IDiagnosticsCommandFactory {
+ createCommand(diagnostic: IDiagnostic, options: CommandOptions): IDiagnosticCommand;
+}
diff --git a/src/client/application/diagnostics/constants.ts b/src/client/application/diagnostics/constants.ts
new file mode 100644
index 000000000000..88431d4a855b
--- /dev/null
+++ b/src/client/application/diagnostics/constants.ts
@@ -0,0 +1,8 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+export enum DiagnosticCodes {
+ InvalidEnvironmentPathVariableDiagnostic = 'InvalidEnvironmentPathVariableDiagnostic'
+}
diff --git a/src/client/application/diagnostics/filter.ts b/src/client/application/diagnostics/filter.ts
new file mode 100644
index 000000000000..908c02c61136
--- /dev/null
+++ b/src/client/application/diagnostics/filter.ts
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { IPersistentStateFactory } from '../../common/types';
+import { IServiceContainer } from '../../ioc/types';
+import { DiagnosticScope, IDiagnosticFilterService } from './types';
+
+export enum FilterKeys {
+ GlobalDiagnosticFilter = 'GLOBAL_DIAGNOSTICS_FILTER',
+ WorkspaceDiagnosticFilter = 'WORKSPACE_DIAGNOSTICS_FILTER'
+}
+
+@injectable()
+export class DiagnosticFilterService implements IDiagnosticFilterService {
+ constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
+ }
+ public async shouldIgnoreDiagnostic(code: string): Promise {
+ const factory = this.serviceContainer.get(IPersistentStateFactory);
+ const globalState = factory.createGlobalPersistentState(FilterKeys.GlobalDiagnosticFilter, []);
+ const workspaceState = factory.createWorkspacePersistentState(FilterKeys.WorkspaceDiagnosticFilter, []);
+ return globalState.value.indexOf(code) >= 0 ||
+ workspaceState.value.indexOf(code) >= 0;
+ }
+ public async ignoreDiagnostic(code: string, scope: DiagnosticScope): Promise {
+ const factory = this.serviceContainer.get(IPersistentStateFactory);
+ const state = scope === DiagnosticScope.Global ?
+ factory.createGlobalPersistentState(FilterKeys.GlobalDiagnosticFilter, []) :
+ factory.createWorkspacePersistentState(FilterKeys.WorkspaceDiagnosticFilter, []);
+
+ const currentValue = state.value.slice();
+ await state.updateValue(currentValue.concat(code));
+ }
+}
diff --git a/src/client/application/diagnostics/promptHandler.ts b/src/client/application/diagnostics/promptHandler.ts
new file mode 100644
index 000000000000..939f7074ec49
--- /dev/null
+++ b/src/client/application/diagnostics/promptHandler.ts
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { inject, injectable } from 'inversify';
+import { DiagnosticSeverity } from 'vscode';
+import { IApplicationShell } from '../../common/application/types';
+import { IServiceContainer } from '../../ioc/types';
+import { IDiagnostic, IDiagnosticCommand, IDiagnosticHandlerService } from './types';
+
+export type MessageCommandPrompt = {
+ commandPrompts: {
+ prompt: string;
+ command?: IDiagnosticCommand;
+ }[];
+ message?: string;
+};
+
+export const DiagnosticCommandPromptHandlerServiceId = 'DiagnosticCommandPromptHandlerServiceId';
+
+@injectable()
+export class DiagnosticCommandPromptHandlerService implements IDiagnosticHandlerService {
+ private readonly appShell: IApplicationShell;
+ constructor(@inject(IServiceContainer) serviceContainer: IServiceContainer) {
+ this.appShell = serviceContainer.get(IApplicationShell);
+ }
+ public async handle(diagnostic: IDiagnostic, options: MessageCommandPrompt = { commandPrompts: [] }): Promise {
+ const prompts = options.commandPrompts.map(option => option.prompt);
+ const response = await this.displayMessage(options.message ? options.message : diagnostic.message, diagnostic.severity, prompts);
+ if (!response) {
+ return;
+ }
+ const selectedOption = options.commandPrompts.find(option => option.prompt === response);
+ if (selectedOption && selectedOption.command) {
+ await selectedOption.command.invoke();
+ }
+ }
+ private async displayMessage(message: string, severity: DiagnosticSeverity, prompts: string[]): Promise {
+ switch (severity) {
+ case DiagnosticSeverity.Error: {
+ return this.appShell.showErrorMessage(message, ...prompts);
+ }
+ case DiagnosticSeverity.Warning: {
+ return this.appShell.showWarningMessage(message, ...prompts);
+ }
+ default: {
+ return this.appShell.showInformationMessage(message, ...prompts);
+ }
+ }
+ }
+}
diff --git a/src/client/application/diagnostics/serviceRegistry.ts b/src/client/application/diagnostics/serviceRegistry.ts
new file mode 100644
index 000000000000..6554a6ddf37b
--- /dev/null
+++ b/src/client/application/diagnostics/serviceRegistry.ts
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { IServiceManager } from '../../ioc/types';
+import { EnvironmentPathVariableDiagnosticsService, EnvironmentPathVariableDiagnosticsServiceId } from './checks/envPathVariable';
+import { DiagnosticsCommandFactory } from './commands/factory';
+import { IDiagnosticsCommandFactory } from './commands/types';
+import { DiagnosticFilterService } from './filter';
+import { DiagnosticCommandPromptHandlerService, DiagnosticCommandPromptHandlerServiceId, MessageCommandPrompt } from './promptHandler';
+import { IDiagnosticFilterService, IDiagnosticHandlerService, IDiagnosticsService } from './types';
+
+export function registerTypes(serviceManager: IServiceManager) {
+ serviceManager.addSingleton(IDiagnosticFilterService, DiagnosticFilterService);
+ serviceManager.addSingleton>(IDiagnosticHandlerService, DiagnosticCommandPromptHandlerService, DiagnosticCommandPromptHandlerServiceId);
+ serviceManager.addSingleton(IDiagnosticsService, EnvironmentPathVariableDiagnosticsService, EnvironmentPathVariableDiagnosticsServiceId);
+ serviceManager.addSingleton(IDiagnosticsCommandFactory, DiagnosticsCommandFactory);
+}
diff --git a/src/client/application/diagnostics/types.ts b/src/client/application/diagnostics/types.ts
new file mode 100644
index 000000000000..41f5940c8c63
--- /dev/null
+++ b/src/client/application/diagnostics/types.ts
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { DiagnosticSeverity } from 'vscode';
+
+export enum DiagnosticScope {
+ Global = 'Global',
+ WorkspaceFolder = 'WorkspaceFolder'
+}
+
+export interface IDiagnostic {
+ readonly code: string;
+ readonly message: string;
+ readonly severity: DiagnosticSeverity;
+ readonly scope: DiagnosticScope;
+}
+
+export const IDiagnosticsService = Symbol('IDiagnosticsService');
+
+export interface IDiagnosticsService {
+ diagnose(): Promise;
+ canHandle(diagnostic: IDiagnostic): Promise;
+ handle(diagnostics: IDiagnostic[]): Promise;
+}
+
+export const IDiagnosticFilterService = Symbol('IDiagnosticFilterService');
+
+export interface IDiagnosticFilterService {
+ shouldIgnoreDiagnostic(code: string): Promise;
+ ignoreDiagnostic(code: string, scope: DiagnosticScope): Promise;
+}
+
+export const IDiagnosticHandlerService = Symbol('IDiagnosticHandlerService');
+
+export interface IDiagnosticHandlerService {
+ handle(diagnostic: IDiagnostic, options?: T): Promise;
+}
+
+export interface IDiagnosticCommand {
+ readonly diagnostic: IDiagnostic;
+ invoke(): Promise;
+}
diff --git a/src/client/application/serviceRegistry.ts b/src/client/application/serviceRegistry.ts
new file mode 100644
index 000000000000..7e4b561b4995
--- /dev/null
+++ b/src/client/application/serviceRegistry.ts
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { IServiceManager } from '../ioc/types';
+import { ApplicationDiagnostics } from './diagnostics/applicationDiagnostics';
+import { registerTypes as diagnosticsRegisterTypes } from './diagnostics/serviceRegistry';
+import { IApplicationDiagnostics } from './types';
+
+export function registerTypes(serviceManager: IServiceManager) {
+ serviceManager.addSingleton(IApplicationDiagnostics, ApplicationDiagnostics);
+ diagnosticsRegisterTypes(serviceManager);
+}
diff --git a/src/client/application/types.ts b/src/client/application/types.ts
new file mode 100644
index 000000000000..7ceaf387f94d
--- /dev/null
+++ b/src/client/application/types.ts
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+export const IApplicationDiagnostics = Symbol('IApplicationDiagnostics');
+
+export interface IApplicationDiagnostics {
+ /**
+ * Perform pre-extension activation health checks.
+ * E.g. validate user environment, etc.
+ * @returns {Promise}
+ * @memberof IApplicationDiagnostics
+ */
+ performPreStartupHealthCheck(): Promise;
+}
diff --git a/src/client/common/application/applicationEnvironment.ts b/src/client/common/application/applicationEnvironment.ts
new file mode 100644
index 000000000000..a26eb2eede00
--- /dev/null
+++ b/src/client/common/application/applicationEnvironment.ts
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { injectable } from 'inversify';
+import * as path from 'path';
+import * as vscode from 'vscode';
+import { EXTENSION_ROOT_DIR } from '../constants';
+import { IApplicationEnvironment } from './types';
+
+@injectable()
+export class ApplicationEnvironment implements IApplicationEnvironment {
+ public get appName(): string {
+ return vscode.env.appName;
+ }
+ public get appRoot(): string {
+ return vscode.env.appRoot;
+ }
+ public get language(): string {
+ return vscode.env.language;
+ }
+ public get sessionId(): string {
+ return vscode.env.sessionId;
+ }
+ public get machineId(): string {
+ return vscode.env.machineId;
+ }
+ public get extensionName(): string {
+ // tslint:disable-next-line:non-literal-require
+ return require(path.join(EXTENSION_ROOT_DIR, 'package.json')).displayName;
+ }
+}
diff --git a/src/client/common/application/applicationShell.ts b/src/client/common/application/applicationShell.ts
index ac3330651b55..e956becd2204 100644
--- a/src/client/common/application/applicationShell.ts
+++ b/src/client/common/application/applicationShell.ts
@@ -6,50 +6,49 @@
const opn = require('opn');
import { injectable } from 'inversify';
-import * as vscode from 'vscode';
-import { Disposable, StatusBarAlignment, StatusBarItem, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
+import { CancellationToken, Disposable, InputBoxOptions, MessageItem, MessageOptions, OpenDialogOptions, QuickPickItem, QuickPickOptions, SaveDialogOptions, StatusBarAlignment, StatusBarItem, Uri, window, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { IApplicationShell } from './types';
@injectable()
export class ApplicationShell implements IApplicationShell {
public showInformationMessage(message: string, ...items: string[]): Thenable;
- public showInformationMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
- public showInformationMessage(message: string, ...items: T[]): Thenable;
- public showInformationMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ public showInformationMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
+ public showInformationMessage(message: string, ...items: T[]): Thenable;
+ public showInformationMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
public showInformationMessage(message: string, options?: any, ...items: any[]): Thenable {
- return vscode.window.showInformationMessage(message, options, ...items);
+ return window.showInformationMessage(message, options, ...items);
}
public showWarningMessage(message: string, ...items: string[]): Thenable;
- public showWarningMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
- public showWarningMessage(message: string, ...items: T[]): Thenable;
- public showWarningMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ public showWarningMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
+ public showWarningMessage(message: string, ...items: T[]): Thenable;
+ public showWarningMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
public showWarningMessage(message: any, options?: any, ...items: any[]) {
- return vscode.window.showWarningMessage(message, options, ...items);
+ return window.showWarningMessage(message, options, ...items);
}
public showErrorMessage(message: string, ...items: string[]): Thenable;
- public showErrorMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
- public showErrorMessage(message: string, ...items: T[]): Thenable;
- public showErrorMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ public showErrorMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
+ public showErrorMessage(message: string, ...items: T[]): Thenable;
+ public showErrorMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
public showErrorMessage(message: any, options?: any, ...items: any[]) {
- return vscode.window.showErrorMessage(message, options, ...items);
+ return window.showErrorMessage(message, options, ...items);
}
- public showQuickPick(items: string[] | Thenable, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable;
- public showQuickPick(items: T[] | Thenable, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable;
- public showQuickPick(items: any, options?: any, token?: any) {
- return vscode.window.showQuickPick(items, options, token);
+ public showQuickPick(items: string[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable;
+ public showQuickPick(items: T[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable;
+ public showQuickPick(items: any, options?: any, token?: any): Thenable {
+ return window.showQuickPick(items, options, token);
}
- public showOpenDialog(options: vscode.OpenDialogOptions): Thenable {
- return vscode.window.showOpenDialog(options);
+ public showOpenDialog(options: OpenDialogOptions): Thenable {
+ return window.showOpenDialog(options);
}
- public showSaveDialog(options: vscode.SaveDialogOptions): Thenable {
- return vscode.window.showSaveDialog(options);
+ public showSaveDialog(options: SaveDialogOptions): Thenable {
+ return window.showSaveDialog(options);
}
- public showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken): Thenable {
- return vscode.window.showInputBox(options, token);
+ public showInputBox(options?: InputBoxOptions, token?: CancellationToken): Thenable {
+ return window.showInputBox(options, token);
}
public openUrl(url: string): void {
opn(url);
@@ -59,14 +58,14 @@ export class ApplicationShell implements IApplicationShell {
public setStatusBarMessage(text: string, hideWhenDone: Thenable): Disposable;
public setStatusBarMessage(text: string): Disposable;
public setStatusBarMessage(text: string, arg?: any): Disposable {
- return vscode.window.setStatusBarMessage(text, arg);
+ return window.setStatusBarMessage(text, arg);
}
public createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem {
- return vscode.window.createStatusBarItem(alignment, priority);
+ return window.createStatusBarItem(alignment, priority);
}
public showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions): Thenable {
- return vscode.window.showWorkspaceFolderPick(options);
+ return window.showWorkspaceFolderPick(options);
}
}
diff --git a/src/client/common/application/debugService.ts b/src/client/common/application/debugService.ts
new file mode 100644
index 000000000000..33d8cad5e1c7
--- /dev/null
+++ b/src/client/common/application/debugService.ts
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+'use strict';
+
+import { injectable } from 'inversify';
+import { debug, DebugConfiguration, DebugSession, Event, WorkspaceFolder } from 'vscode';
+import { IDebugService } from './types';
+
+@injectable()
+export class DebugService implements IDebugService {
+ public get onDidStartDebugSession(): Event {
+ return debug.onDidStartDebugSession;
+ }
+ public get onDidTerminateDebugSession(): Event {
+ return debug.onDidTerminateDebugSession;
+ }
+ public startDebugging(folder: WorkspaceFolder | undefined, nameOrConfiguration: string | DebugConfiguration): Thenable {
+ return debug.startDebugging(folder, nameOrConfiguration);
+ }
+}
diff --git a/src/client/common/application/types.ts b/src/client/common/application/types.ts
index 1808e7c220aa..3943d9cb7504 100644
--- a/src/client/common/application/types.ts
+++ b/src/client/common/application/types.ts
@@ -4,12 +4,13 @@
// tslint:disable:no-any unified-signatures
-import * as vscode from 'vscode';
-import { CancellationToken, ConfigurationChangeEvent, Disposable, Event, FileSystemWatcher, GlobPattern, TextDocument, TextDocumentShowOptions, WorkspaceConfiguration, WorkspaceFolderPickOptions } from 'vscode';
-import { TextEditor, TextEditorEdit, TextEditorOptionsChangeEvent, TextEditorSelectionChangeEvent, TextEditorViewColumnChangeEvent } from 'vscode';
-import { StatusBarAlignment, StatusBarItem } from 'vscode';
-import { Uri, ViewColumn, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode';
-import { Terminal, TerminalOptions } from 'vscode';
+import {
+ CancellationToken, ConfigurationChangeEvent, DebugConfiguration, DebugSession, Disposable, Event, FileSystemWatcher, GlobPattern, InputBoxOptions, MessageItem,
+ MessageOptions, OpenDialogOptions, QuickPickItem, QuickPickOptions, SaveDialogOptions,
+ StatusBarAlignment, StatusBarItem, Terminal, TerminalOptions, TextDocument, TextDocumentShowOptions, TextEditor,
+ TextEditorEdit, TextEditorOptionsChangeEvent, TextEditorSelectionChangeEvent, TextEditorViewColumnChangeEvent, Uri, ViewColumn, WorkspaceConfiguration, WorkspaceFolder,
+ WorkspaceFolderPickOptions, WorkspaceFoldersChangeEvent
+} from 'vscode';
export const IApplicationShell = Symbol('IApplicationShell');
export interface IApplicationShell {
@@ -24,7 +25,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showInformationMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
+ showInformationMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
/**
* Show an information message.
@@ -35,7 +36,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showInformationMessage(message: string, ...items: T[]): Thenable;
+ showInformationMessage(message: string, ...items: T[]): Thenable;
/**
* Show an information message.
@@ -47,7 +48,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showInformationMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ showInformationMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
/**
* Show a warning message.
@@ -70,7 +71,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showWarningMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
+ showWarningMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
/**
* Show a warning message.
@@ -81,7 +82,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showWarningMessage(message: string, ...items: T[]): Thenable;
+ showWarningMessage(message: string, ...items: T[]): Thenable;
/**
* Show a warning message.
@@ -93,7 +94,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showWarningMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ showWarningMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
/**
* Show an error message.
@@ -116,7 +117,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showErrorMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable;
+ showErrorMessage(message: string, options: MessageOptions, ...items: string[]): Thenable;
/**
* Show an error message.
@@ -127,7 +128,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showErrorMessage(message: string, ...items: T[]): Thenable;
+ showErrorMessage(message: string, ...items: T[]): Thenable;
/**
* Show an error message.
@@ -139,7 +140,7 @@ export interface IApplicationShell {
* @param items A set of items that will be rendered as actions in the message.
* @return A thenable that resolves to the selected item or `undefined` when being dismissed.
*/
- showErrorMessage(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable;
+ showErrorMessage(message: string, options: MessageOptions, ...items: T[]): Thenable;
/**
* Shows a selection list.
@@ -149,7 +150,7 @@ export interface IApplicationShell {
* @param token A token that can be used to signal cancellation.
* @return A promise that resolves to the selection or `undefined`.
*/
- showQuickPick(items: string[] | Thenable, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable;
+ showQuickPick(items: string[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable;
/**
* Shows a selection list.
@@ -159,7 +160,7 @@ export interface IApplicationShell {
* @param token A token that can be used to signal cancellation.
* @return A promise that resolves to the selected item or `undefined`.
*/
- showQuickPick(items: T[] | Thenable, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable;
+ showQuickPick(items: T[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable;
/**
* Shows a file open dialog to the user which allows to select a file
@@ -168,7 +169,7 @@ export interface IApplicationShell {
* @param options Options that control the dialog.
* @returns A promise that resolves to the selected resources or `undefined`.
*/
- showOpenDialog(options: vscode.OpenDialogOptions): Thenable