diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000000..a483485a030b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6322 @@ +{ + "name": "python", + "version": "2018.1.0-alpha", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/chai": { + "version": "https://registry.npmjs.org/@types/chai/-/chai-4.0.6.tgz", + "integrity": "sha1-nLWn+33YO+DPyq/b2VorXdNRdi8=", + "dev": true + }, + "@types/chai-as-promised": { + "version": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.0.tgz", + "integrity": "sha1-AQsEzeeOrPtucr/ds+WP4jwueLk=", + "dev": true, + "requires": { + "@types/chai": "https://registry.npmjs.org/@types/chai/-/chai-4.0.6.tgz" + } + }, + "@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": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz" + } + }, + "@types/del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/del/-/del-3.0.0.tgz", + "integrity": "sha512-18mSs54BvzV8+TTQxt0ancig6tsuPZySnhp3cQkWFFDmDMavU4pmWwR+bHHqRBWODYqpzIzVkqKLuk/fP6yypQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.34" + } + }, + "@types/event-stream": { + "version": "3.3.33", + "resolved": "https://registry.npmjs.org/@types/event-stream/-/event-stream-3.3.33.tgz", + "integrity": "sha512-Wqfgz7PzIquugISKAlj1nKD4f1QtmjYzWqrpdYp3B64TkS6GlWp0Aj+3ldXvTQUx1/XuMkw29uC9QViTpVPD6w==", + "dev": true, + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==", + "dev": true + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.5.tgz", + "integrity": "sha1-iqYDPA6HxlOwmmcRaGkWhktI7J4=", + "dev": true, + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "@types/get-port": { + "version": "https://registry.npmjs.org/@types/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-+eChFEPMITNkcBherj37pEldKbw=", + "dev": true + }, + "@types/glob": { + "version": "5.0.34", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.34.tgz", + "integrity": "sha512-sUvpieq+HsWTLdkeOI8Mi8u22Ag3AoGuM3sv+XMP1bKtbaIAHpEA2f52K2mz6vK5PVhTa3bFyRZLZMqTxOo2Cw==", + "dev": true, + "requires": { + "@types/events": "1.1.0", + "@types/minimatch": "3.0.2", + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "@types/iconv-lite": { + "version": "https://registry.npmjs.org/@types/iconv-lite/-/iconv-lite-0.0.1.tgz", + "integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=", + "dev": true, + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "@types/istanbul": { + "version": "0.4.29", + "resolved": "https://registry.npmjs.org/@types/istanbul/-/istanbul-0.4.29.tgz", + "integrity": "sha1-KcjLt0esVygJZVRdxYUUug27ma8=", + "dev": true + }, + "@types/lodash": { + "version": "4.14.87", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.87.tgz", + "integrity": "sha512-AqRC+aEF4N0LuNHtcjKtvF9OTfqZI0iaBoe3dA6m/W+/YZJBZjBmW/QIZ8fBeXC6cnytSY9tBoFBqZ9uSCeVsw==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.2.tgz", + "integrity": "sha512-tctoxbfuMCxeI2CAsnwoZQfaBA+T7gPzDzDuiiFnyCSSyGYEB92cmRTh6E3tdR1hWsprbJ9IdbvX3PzLmJU/GA==", + "dev": true + }, + "@types/mocha": { + "version": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", + "integrity": "sha1-HUp5jlPzUhL9WtTQQFBiAXHNW14=", + "dev": true + }, + "@types/node": { + "version": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz", + "integrity": "sha1-5/chrigncuEroleZaMANnM5CLF0=", + "dev": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.4.0.tgz", + "integrity": "sha1-82WFNa9/H1AqzW2n2vQF/+sffuQ=", + "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": "https://registry.npmjs.org/@types/sinon/-/sinon-2.3.7.tgz", + "integrity": "sha1-6Swv7TKX6uB4140doDKyZ4i0r4Y=", + "dev": true + }, + "@types/uuid": { + "version": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.3.tgz", + "integrity": "sha1-EhrOJl9Vac5A9PbQ/3ijOMcyp1Q=", + "dev": true, + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "@types/winreg": { + "version": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", + "integrity": "sha1-kdZxDlNtNFucmwF8V0z2qNpkxRg=", + "dev": true + }, + "@types/xml2js": { + "version": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.2.tgz", + "integrity": "sha1-pLhLOHn/1HEJU/2Syr/emopOhFY=", + "dev": true, + "requires": { + "@types/node": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz" + } + }, + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, + "requires": { + "jsonparse": "1.2.0", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + } + }, + "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 + }, + "ajv": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", + "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "dev": true, + "requires": { + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "fast-deep-equal": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "fast-json-stable-stringify": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz" + } + }, + "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": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "longest": "1.0.1", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "dev": true, + "requires": { + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" + } + }, + "applicationinsights": { + "version": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.15.6.tgz", + "integrity": "sha1-IBoGgsBwT+S92aktCyy+NNKuWXI=" + }, + "arch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz", + "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk=" + }, + "archy": { + "version": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "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": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" + } + }, + "arr-flatten": { + "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "dev": true + }, + "array-differ": { + "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "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": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", + "dev": true + }, + "array-union": { + "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + } + }, + "array-uniq": { + "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assertion-error": { + "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "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": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "azure-storage": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.7.0.tgz", + "integrity": "sha1-EGw18LpsVR+Si9OUwCbkTQQB/88=", + "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.81.0", + "underscore": "1.8.3", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "validator": "3.35.0", + "xml2js": "0.2.7", + "xmlbuilder": "0.4.3" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "extend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", + "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "1.0.0", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "0.12.0", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "extend": "3.0.1", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "har-validator": "4.2.1", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "tunnel-agent": "0.6.0", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + }, + "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.2", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.2.tgz", + "integrity": "sha1-c1/6o5oc/4/7lZjwIjq9sDqfsuo=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "xml2js": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.7.tgz", + "integrity": "sha1-GDhRi7AXQcrgh4urSRXklMMjBq8=", + "dev": true, + "requires": { + "sax": "0.5.2" + } + }, + "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": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "js-tokens": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" + } + }, + "balanced-match": { + "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + } + }, + "beeper": { + "version": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "binary-extensions": { + "version": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "block-stream": { + "version": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + }, + "boom": { + "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + } + }, + "brace-expansion": { + "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "concat-map": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + }, + "braces": { + "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "preserve": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" + } + }, + "browser-stdout": { + "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "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-crc32": { + "version": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "builtin-modules": { + "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "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": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "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": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "check-error": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "deep-eql": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "get-func-name": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "pathval": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz" + } + }, + "chai-as-promised": { + "version": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha1-CGRdgl3rhpbuYXJdv1kMAS6wDKA=", + "dev": true, + "requires": { + "check-error": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + } + }, + "chalk": { + "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + } + }, + "check-error": { + "version": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "async-each": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "is-binary-path": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" + } + }, + "ci-info": { + "version": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz", + "integrity": "sha1-A1YSWdtI0EdMi9yQ9bR7Botrv7Q=", + "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 + }, + "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": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-buffer": { + "version": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "requires": { + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + } + }, + "co": { + "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "codecov": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.0.0.tgz", + "integrity": "sha1-wnO4xPEpRXI+jcnSWAPYk0Pl8o4=", + "dev": true, + "requires": { + "argv": "0.0.2", + "request": "2.81.0", + "urlgrey": "0.4.4" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "0.12.0", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "har-validator": "4.2.1", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "tunnel-agent": "0.6.0", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "color-convert": { + "version": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", + "dev": true, + "requires": { + "color-name": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + } + }, + "color-name": { + "version": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + } + }, + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "commandpost": { + "version": "https://registry.npmjs.org/commandpost/-/commandpost-1.2.1.tgz", + "integrity": "sha1-LpxMdQi53HBK/vqpHKuS7mBUzGg=", + "dev": true + }, + "concat-map": { + "version": "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": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "proto-list": "1.2.4" + } + }, + "convert-source-map": { + "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "core-util-is": { + "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + } + }, + "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" + } + }, + "dashdash": { + "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "dateformat": { + "version": "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": "https://registry.npmjs.org/debounce-hashed/-/debounce-hashed-0.1.2.tgz", + "integrity": "sha1-oN/jB8Gn2zD2kRyM+8DvhB831K8=", + "dev": true + }, + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + }, + "decache": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/decache/-/decache-4.3.0.tgz", + "integrity": "sha1-o5XkBwlWmKyKbe8B8qaky3Y49jU=", + "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 + }, + "deep-assign": { + "version": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", + "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", + "dev": true, + "requires": { + "is-obj": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz" + } + }, + "deep-eql": { + "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", + "dev": true, + "requires": { + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz" + } + }, + "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": "0.2.10", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=", + "dev": true + }, + "defaults": { + "version": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz" + } + }, + "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.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deprecated": { + "version": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz" + } + }, + "detect-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-2.0.0.tgz", + "integrity": "sha1-cg/1Hk2Xt2iE9r9XKSNIsT396Tk=", + "dev": true, + "requires": { + "get-stdin": "3.0.2", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "repeating": "1.1.3" + }, + "dependencies": { + "get-stdin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-3.0.2.tgz", + "integrity": "sha1-wc7SS5A5s43thb3xYeV3E7bdSr4=", + "dev": true + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + } + } + }, + "diff": { + "version": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "diff-match-patch": { + "version": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", + "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=" + }, + "doctrine": { + "version": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "requires": { + "esutils": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "dependencies": { + "esutils": { + "version": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "dev": true + } + } + }, + "duplexer": { + "version": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + } + }, + "duplexify": { + "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha1-ThUWvmiDi8kKSZlPCzmm5ZYL780=", + "dev": true, + "requires": { + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "stream-shift": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz" + }, + "dependencies": { + "end-of-stream": { + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + } + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "once": { + "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "ecc-jsbn": { + "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + } + }, + "editorconfig": { + "version": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz", + "integrity": "sha1-tt1KC2ueds5I4Ga9wVOBrruIBP0=", + "dev": true, + "requires": { + "@types/commander": "2.12.2", + "@types/semver": "https://registry.npmjs.org/@types/semver/-/semver-5.4.0.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + }, + "dependencies": { + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "dev": true + }, + "lru-cache": { + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "dev": true, + "requires": { + "pseudomap": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "yallist": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" + } + } + } + }, + "end-of-stream": { + "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + } + }, + "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" + } + }, + "escape-string-regexp": { + "version": "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": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "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": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-stream": { + "version": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "from": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "map-stream": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "pause-stream": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "split": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "stream-combiner": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + } + }, + "expand-brackets": { + "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" + } + }, + "expand-range": { + "version": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" + } + }, + "expand-tilde": { + "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + } + }, + "extend": { + "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + } + }, + "extglob": { + "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" + } + }, + "extsprintf": { + "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "time-stamp": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz" + } + }, + "fast-deep-equal": { + "version": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "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": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" + } + }, + "filename-regex": { + "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "randomatic": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "repeat-element": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "repeat-string": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + } + }, + "find-index": { + "version": "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": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + } + }, + "findup-sync": { + "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "resolve-dir": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz" + } + }, + "fined": { + "version": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "is-plain-object": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "object.defaults": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "object.pick": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "parse-filepath": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz" + }, + "dependencies": { + "expand-tilde": { + "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz" + } + } + } + }, + "first-chunk-stream": { + "version": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + } + }, + "forever-agent": { + "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + } + }, + "formatio": { + "version": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "dev": true, + "requires": { + "samsam": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz" + } + }, + "from": { + "version": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "fs-exists-sync": { + "version": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs-extra": { + "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "jsonfile": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "universalify": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz" + } + }, + "fs.realpath": { + "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "rimraf": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz" + } + }, + "fuzzy": { + "version": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz", + "integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg=" + }, + "gaze": { + "version": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" + } + }, + "generate-function": { + "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + } + }, + "get-func-name": { + "version": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-port": { + "version": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" + }, + "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 + }, + "getpass": { + "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" + }, + "dependencies": { + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" + } + } + } + }, + "glob-base": { + "version": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + } + }, + "glob-parent": { + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + } + }, + "glob-stream": { + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "glob2base": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz" + }, + "dependencies": { + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + } + }, + "glob-watcher": { + "version": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz" + } + }, + "glob2base": { + "version": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz" + } + }, + "global-modules": { + "version": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz" + } + }, + "global-prefix": { + "version": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "ini": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "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 + } + } + }, + "globule": { + "version": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "lodash": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + }, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" + } + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + } + } + }, + "glogg": { + "version": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" + } + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "growl": { + "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "gulp": { + "version": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "deprecated": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "interpret": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "liftoff": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "orchestrator": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "pretty-hrtime": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "tildify": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "v8flags": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz" + }, + "dependencies": { + "semver": { + "version": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + } + } + }, + "gulp-chmod": { + "version": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", + "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", + "dev": true, + "requires": { + "deep-assign": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", + "stat-mode": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + } + }, + "gulp-debounced-watch": { + "version": "https://registry.npmjs.org/gulp-debounced-watch/-/gulp-debounced-watch-1.0.4.tgz", + "integrity": "sha1-WkfU4kzkY2XOguysMqKjA+QysSo=", + "dev": true, + "requires": { + "debounce-hashed": "https://registry.npmjs.org/debounce-hashed/-/debounce-hashed-0.1.2.tgz", + "gulp-watch": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-4.3.11.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" + } + }, + "gulp-filter": { + "version": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", + "integrity": "sha1-XYf2YuMX5YOe92UOYg5skAj/ktA=", + "dev": true, + "requires": { + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "multimatch": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "streamfilter": "1.0.6" + } + }, + "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": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "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": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "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": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "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": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + } + } + }, + "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" + } + }, + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "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": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + }, + "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": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", + "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", + "dev": true, + "requires": { + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" + }, + "dependencies": { + "clone": { + "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + } + } + }, + "gulp-json-editor": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.2.1.tgz", + "integrity": "sha1-fE3XR36NBtxdxJwLgedFzbBPl7s=", + "dev": true, + "requires": { + "deepmerge": "0.2.10", + "detect-indent": "2.0.0", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "js-beautify": "1.5.10", + "through2": "0.5.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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "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" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-remote-src": { + "version": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", + "integrity": "sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE=", + "dev": true, + "requires": { + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "node.extend": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz" + }, + "dependencies": { + "clone-stats": { + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "request": { + "version": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", + "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" + } + } + } + }, + "gulp-sourcemaps": { + "version": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + }, + "dependencies": { + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + } + } + }, + "gulp-symdest": { + "version": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", + "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=", + "dev": true, + "requires": { + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "queue": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz" + }, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "glob-parent": { + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + } + }, + "glob-stream": { + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "to-absolute-glob": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + } + }, + "is-extglob": { + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + } + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "ordered-read-streams": { + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "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": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + } + }, + "unique-stream": { + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + }, + "vinyl-fs": { + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "gulp-sourcemaps": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "is-valid-glob": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "lodash.isequal": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "strip-bom-stream": "1.0.0", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "vali-date": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + } + } + } + }, + "gulp-typescript": { + "version": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.3.tgz", + "integrity": "sha1-MtUquXuXxM4HDAQZ2wjqOvUU1yA=", + "dev": true, + "requires": { + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz" + }, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "glob-parent": { + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + } + }, + "glob-stream": { + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "to-absolute-glob": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + } + }, + "is-extglob": { + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + } + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "ordered-read-streams": { + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "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": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + } + }, + "unique-stream": { + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + }, + "vinyl-fs": { + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "gulp-sourcemaps": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "is-valid-glob": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "lodash.isequal": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "strip-bom-stream": "1.0.0", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "vali-date": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + } + } + } + }, + "gulp-untar": { + "version": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.6.tgz", + "integrity": "sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA=", + "dev": true, + "requires": { + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "streamifier": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", + "tar": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz" + } + }, + "gulp-util": { + "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "beeper": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dateformat": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" + } + }, + "gulp-vinyl-zip": { + "version": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", + "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=", + "dev": true, + "requires": { + "event-stream": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "queue": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "vinyl-fs": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "yauzl": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "yazl": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz" + }, + "dependencies": { + "clone": { + "version": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "glob-parent": { + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + } + }, + "glob-stream": { + "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "micromatch": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "ordered-read-streams": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "to-absolute-glob": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "unique-stream": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + } + }, + "is-extglob": { + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + } + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "ordered-read-streams": { + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + } + }, + "queue": { + "version": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", + "integrity": "sha1-Wpcz2ai4vRs26TS8nFWribKOKcc=", + "dev": true, + "requires": { + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "replace-ext": { + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "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": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + } + }, + "unique-stream": { + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "clone-buffer": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "cloneable-readable": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz" + } + }, + "vinyl-fs": { + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "gulp-sourcemaps": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "is-valid-glob": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "lazystream": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "lodash.isequal": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "merge-stream": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "strip-bom-stream": "1.0.0", + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "through2-filter": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "vali-date": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + }, + "dependencies": { + "clone": { + "version": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-stats": { + "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "replace-ext": { + "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + } + } + } + } + }, + "gulp-watch": { + "version": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-4.3.11.tgz", + "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", + "dev": true, + "requires": { + "anymatch": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "chokidar": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "glob-parent": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "gulp-util": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "slash": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "vinyl-file": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz" + }, + "dependencies": { + "glob-parent": { + "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "path-dirname": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" + } + }, + "is-extglob": { + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + } + }, + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + } + } + }, + "gulplog": { + "version": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz" + } + }, + "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": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "is-my-json-valid": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "dependencies": { + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "dev": true + } + } + }, + "has-ansi": { + "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + } + }, + "has-flag": { + "version": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-gulplog": { + "version": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz" + } + }, + "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": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "hawk": { + "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + } + }, + "he": { + "version": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hoek": { + "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "http-signature": { + "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" + } + }, + "husky": { + "version": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", + "integrity": "sha1-xp7XTi0neXaaF7qDmbVM4LY8EsM=", + "dev": true, + "requires": { + "is-ci": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", + "strip-indent": "2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "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": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + }, + "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": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + }, + "inherits": { + "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=", + "dev": true + }, + "interpret": { + "version": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "inversify": { + "version": "https://registry.npmjs.org/inversify/-/inversify-4.5.2.tgz", + "integrity": "sha1-8keP0UDzmINrLh/ug583WI8eaps=" + }, + "is": { + "version": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=", + "dev": true + }, + "is-absolute": { + "version": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "is-windows": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz" + } + }, + "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": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz" + } + }, + "is-buffer": { + "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", + "dev": true + }, + "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": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + } + }, + "is-ci": { + "version": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true, + "requires": { + "ci-info": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz" + } + }, + "is-dotfile": { + "version": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" + } + }, + "is-extendable": { + "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "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": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" + } + }, + "is-my-json-valid": { + "version": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha1-WoRnd+LCYg0eaRBOXToDsfYIjxE=", + "dev": true, + "requires": { + "generate-function": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "generate-object-property": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "jsonpointer": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "is-number": { + "version": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + } + }, + "is-obj": { + "version": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "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.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "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-object": { + "version": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "dev": true, + "requires": { + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + }, + "dependencies": { + "isobject": { + "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-relative": { + "version": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz" + } + }, + "is-stream": { + "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz" + } + }, + "is-utf8": { + "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-windows": { + "version": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "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": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "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.10.0", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "nopt": "3.0.6", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "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": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "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 + }, + "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" + } + } + } + }, + "jade": { + "version": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + }, + "dependencies": { + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "js-beautify": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.5.10.tgz", + "integrity": "sha1-TZU3FwJpk0SlFsomv1nwonu3Vxk=", + "dev": true, + "requires": { + "config-chain": "1.1.11", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "nopt": "3.0.6" + } + }, + "js-tokens": { + "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "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": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": 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": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + } + }, + "json-stringify-safe": { + "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" + } + }, + "jsonify": { + "version": "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 + }, + "jsonpointer": { + "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "kind-of": { + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + } + }, + "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": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "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": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "findup-sync": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "fined": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "flagged-respawn": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "lodash.isplainobject": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "lodash.isstring": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "lodash.mapvalues": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "rechoir": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" + } + }, + "line-by-line": { + "version": "https://registry.npmjs.org/line-by-line/-/line-by-line-0.1.5.tgz", + "integrity": "sha1-GcRbWfCoBjLDC1xDpkf+Faq5BcI=" + }, + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "parse-json": "2.2.0", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "strip-bom": "2.0.0" + }, + "dependencies": { + "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": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + } + } + }, + "lodash": { + "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "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": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "lodash.pairs": "3.0.1" + } + }, + "lodash._basecopy": { + "version": "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": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + } + }, + "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": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "lodash.istypedarray": "3.0.6", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + } + }, + "lodash._basetostring": { + "version": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "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": "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": "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": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "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": "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": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" + } + }, + "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": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + } + }, + "lodash.isarguments": { + "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "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.isplainobject": { + "version": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "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": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "lodash.isarguments": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "lodash.isarray": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" + } + }, + "lodash.mapvalues": { + "version": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "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": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + } + }, + "lodash.restparam": { + "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "lodash._basetostring": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "lodash._basevalues": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "lodash._isiterateecall": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "lodash.keys": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "lodash.restparam": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "lodash.templatesettings": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz" + } + }, + "lodash.templatesettings": { + "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.escape": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz" + } + }, + "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": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", + "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" + } + }, + "lru-cache": { + "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-cache": { + "version": "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": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "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": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + }, + "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": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "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" + }, + "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 + } + } + }, + "merge-stream": { + "version": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "micromatch": { + "version": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "array-unique": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "braces": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "expand-brackets": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "extglob": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "filename-regex": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "normalize-path": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "object.omit": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "parse-glob": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "regex-cache": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz" + } + }, + "mime-db": { + "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz" + } + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz" + } + }, + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + }, + "dependencies": { + "minimist": { + "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "growl": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "jade": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "to-iso-string": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz" + }, + "dependencies": { + "escape-string-regexp": { + "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz" + } + }, + "minimatch": { + "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "sigmund": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz" + } + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + } + } + }, + "ms": { + "version": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "multimatch": { + "version": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "array-union": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "arrify": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + } + }, + "multipipe": { + "version": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz" + } + }, + "named-js-regexp": { + "version": "https://registry.npmjs.org/named-js-regexp/-/named-js-regexp-1.3.3.tgz", + "integrity": "sha1-ousWVcdMuCITpPyCd337Z7iV2Mg=" + }, + "native-promise-only": { + "version": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "dev": true + }, + "natives": { + "version": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "node.extend": { + "version": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", + "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", + "dev": true, + "requires": { + "is": "https://registry.npmjs.org/is/-/is-3.2.1.tgz" + } + }, + "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.5.0", + "is-builtin-module": "1.0.0", + "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" + } + }, + "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": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object.defaults": { + "version": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "array-slice": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "for-own": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + }, + "dependencies": { + "for-own": { + "version": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + } + }, + "isobject": { + "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "is-extendable": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + } + }, + "object.pick": { + "version": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + }, + "dependencies": { + "isobject": { + "version": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "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": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "sequencify": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "stream-consume": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz" + } + }, + "ordered-read-streams": { + "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "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 + }, + "parse-filepath": { + "version": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "map-cache": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "path-root": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz" + } + }, + "parse-glob": { + "version": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "is-dotfile": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "is-extglob": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "is-glob": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + } + }, + "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": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-dirname": { + "version": "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": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + } + }, + "path-is-absolute": { + "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "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-parse": { + "version": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-root": { + "version": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz" + } + }, + "path-root-regex": { + "version": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-to-regexp": { + "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + } + }, + "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": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + } + }, + "pathval": { + "version": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pause-stream": { + "version": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + } + }, + "pend": { + "version": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + }, + "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 + }, + "preserve": { + "version": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "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": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "punycode": { + "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "querystringify": { + "version": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true + }, + "queue": { + "version": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz", + "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=", + "dev": true, + "requires": { + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + }, + "randomatic": { + "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "dev": true, + "requires": { + "is-number": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + }, + "dependencies": { + "is-number": { + "version": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + }, + "dependencies": { + "kind-of": { + "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + } + } + } + }, + "kind-of": { + "version": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + } + } + } + }, + "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": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "readdirp": { + "version": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "set-immediate-shim": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "rechoir": { + "version": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz" + } + }, + "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": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz", + "integrity": "sha1-tPg3BEFqytiZiMmxVjXUfgO5NEo=" + }, + "regex-cache": { + "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "dev": true, + "requires": { + "is-equal-shallow": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" + } + }, + "relative": { + "version": "https://registry.npmjs.org/relative/-/relative-3.0.2.tgz", + "integrity": "sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8=", + "dev": true, + "requires": { + "isobject": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + } + }, + "remap-istanbul": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.9.5.tgz", + "integrity": "sha1-oYYXsfMe7Fp9vud1OCmLd1YGqqg=", + "dev": true, + "requires": { + "amdefine": "1.0.1", + "gulp-util": "3.0.7", + "istanbul": "0.4.5", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "through2": "2.0.1" + }, + "dependencies": { + "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": "3.0.7", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", + "dev": true, + "requires": { + "array-differ": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "array-uniq": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "beeper": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "dateformat": "1.0.12", + "fancy-log": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "gulplog": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "has-gulplog": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "lodash._reescape": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "lodash._reevaluate": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "lodash._reinterpolate": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "lodash.template": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "minimist": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "multipipe": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "through2": "2.0.1", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "1.0.0", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "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": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + } + }, + "remove-trailing-separator": { + "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "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": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "dev": true, + "requires": { + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "performance-now": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "aws-sign2": { + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "boom": { + "version": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" + } + }, + "caseless": { + "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "cryptiles": { + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz" + }, + "dependencies": { + "boom": { + "version": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" + } + } + } + }, + "form-data": { + "version": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "dev": true, + "requires": { + "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz" + } + }, + "har-validator": { + "version": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.1", + "har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" + } + }, + "hawk": { + "version": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "sntp": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz" + } + }, + "hoek": { + "version": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=", + "dev": true + }, + "http-signature": { + "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz" + } + }, + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "dev": true + }, + "sntp": { + "version": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha1-LGzsFP7cIiJznK+bXD2F0cxaLMg=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz" + } + }, + "tunnel-agent": { + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "requires-port": { + "version": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=", + "dev": true, + "requires": { + "path-parse": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" + } + }, + "resolve-dir": { + "version": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "global-modules": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz" + } + }, + "retyped-diff-match-patch-tsd-ambient": { + "version": "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": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "dev": true, + "requires": { + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" + }, + "dependencies": { + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + } + } + }, + "rxjs": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.3.tgz", + "integrity": "sha512-VWockSz7xmDveeZ7wv8RvdipGGZ1NmL/m4jnpvN9BH4x1fW/TPoD23yXh+qDkbWSlajXVVfLIbGmyxa94Ls84w==", + "requires": { + "symbol-observable": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz" + } + }, + "safe-buffer": { + "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "dev": true + }, + "samsam": { + "version": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha1-jR2TUOJWItow3j5EumkrUiGrfFA=", + "dev": true + }, + "sax": { + "version": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + }, + "semver": { + "version": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" + }, + "sequencify": { + "version": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-immediate-shim": { + "version": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "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": "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": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", + "integrity": "sha1-Ah/WS1TLd9nS+w1Dze3652KcOjY=", + "dev": true, + "requires": { + "diff": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "formatio": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "lolex": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "native-promise-only": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "path-to-regexp": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "samsam": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "text-encoding": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "type-detect": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz" + }, + "dependencies": { + "diff": { + "version": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", + "dev": true + } + } + }, + "slash": { + "version": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sntp": { + "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + } + }, + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", + "integrity": "sha1-IBinrSvfj68mkeX92rJr7VorrKs=", + "dev": true, + "requires": { + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + }, + "dependencies": { + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + } + } + }, + "sparkles": { + "version": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "split": { + "version": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + } + }, + "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": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stat-mode": { + "version": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "stream-combiner": { + "version": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" + } + }, + "stream-consume": { + "version": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-shift": { + "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamfilter": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.6.tgz", + "integrity": "sha512-JM3zxd/lvOuo+EZJlZNYdQucfybA+Jr6jRtZwWlMAq1dAV0LIjZrqSNBBK62qCtflJ8rL/+cAnxy69CPhkTJNA==", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "1.0.0", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "streamifier": { + "version": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", + "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", + "dev": true + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + } + }, + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "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.3.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "1.0.0", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "1.0.3", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + }, + "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": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + } + } + }, + "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" + } + }, + "sudo-prompt": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.0.0.tgz", + "integrity": "sha512-/GT0xH/265PMi6HlZ8ki/AhTKnHN4JBnr1ISELqT0BqzcBvqaXPVhG/yUx1nG+ICCE5CXtF+awBwVMCn72dR0A==" + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-observable": { + "version": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz", + "integrity": "sha1-XGj9jVQRXZ37cqhHIFSSIujbmzI=" + }, + "tar": { + "version": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "fstream": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + }, + "text-encoding": { + "version": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, + "through": { + "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + }, + "dependencies": { + "isarray": { + "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "process-nextick-args": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "util-deprecate": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + }, + "string_decoder": { + "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + } + } + } + }, + "through2-filter": { + "version": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "tildify": { + "version": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + } + }, + "time-stamp": { + "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tmp": { + "version": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", + "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", + "requires": { + "os-tmpdir": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + } + }, + "to-absolute-glob": { + "version": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + } + }, + "to-iso-string": { + "version": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + }, + "tough-cookie": { + "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + } + }, + "tree-kill": { + "version": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha1-WEZ4Yje0I5AU8F2xVrZDIS1MbzY=" + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tslib": { + "version": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", + "integrity": "sha1-3GBOutZLy/aW1hPabJVKoOfqHrY=", + "dev": true + }, + "tslint": { + "version": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", + "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "dev": true, + "requires": { + "babel-code-frame": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "builtin-modules": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "chalk": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolve": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "tslib": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", + "tsutils": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz" + }, + "dependencies": { + "ansi-styles": { + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "dev": true, + "requires": { + "color-convert": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz" + } + }, + "chalk": { + "version": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "dev": true, + "requires": { + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz" + } + }, + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha1-D1lGxCftnsDZGka7ne9T5UZQ5VU=", + "dev": true + }, + "diff": { + "version": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha1-sdhVB9rzlkgo3lSzfQ1zumfdpWw=", + "dev": true + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" + } + } + } + }, + "tslint-eslint-rules": { + "version": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz", + "integrity": "sha1-fDDniC8mvCdr/5HSOEl1xp2viLo=", + "dev": true, + "requires": { + "doctrine": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "tslib": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz", + "tsutils": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz" + }, + "dependencies": { + "tsutils": { + "version": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", + "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", + "dev": true + } + } + }, + "tslint-microsoft-contrib": { + "version": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.1.tgz", + "integrity": "sha1-Mo7pwo0HzfeTKTIEyW4v+rkiGZQ=", + "dev": true, + "requires": { + "tsutils": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz" + }, + "dependencies": { + "tsutils": { + "version": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", + "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", + "dev": true + } + } + }, + "tsutils": { + "version": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz", + "integrity": "sha1-D1K2qrvEIW5yeWtm2wKMbPFz4UQ=", + "dev": true, + "requires": { + "tslib": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz" + } + }, + "tunnel-agent": { + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "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": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", + "integrity": "sha1-1w5byB223io4G8rKDG4MvcdjXeI=", + "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": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "postinstall-build": "5.0.1" + } + }, + "typescript": { + "version": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "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": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-6.1.0.tgz", + "integrity": "sha1-RCWsK6uKrqmgQlHAePR6t6AgLxM=", + "dev": true, + "requires": { + "commandpost": "https://registry.npmjs.org/commandpost/-/commandpost-1.2.1.tgz", + "editorconfig": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz" + } + }, + "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": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "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": "https://registry.npmjs.org/uint64be/-/uint64be-1.0.1.tgz", + "integrity": "sha1-H3FUIC8qG4rzU4cd2mUb80zpPpU=" + }, + "unc-path-regex": { + "version": "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 + }, + "unique-stream": { + "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "universalify": { + "version": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "untildify": { + "version": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", + "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" + }, + "url-parse": { + "version": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha1-OhnoqqbQI93SfcxEy0/I9/7COYY=", + "dev": true, + "requires": { + "querystringify": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "requires-port": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + } + }, + "urlgrey": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", + "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", + "dev": true + }, + "user-home": { + "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "dev": true + }, + "v8flags": { + "version": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" + } + }, + "vali-date": { + "version": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "validator": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-3.35.0.tgz", + "integrity": "sha1-PwcklALB/I/Ak8MsbkPXKnnModw=", + "dev": true + }, + "verror": { + "version": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + }, + "vinyl-file": { + "version": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "dev": true, + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "pify": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "strip-bom-stream": "2.0.0", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz" + }, + "dependencies": { + "strip-bom": { + "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "replace-ext": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz" + } + } + } + }, + "vinyl-fs": { + "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "glob-stream": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "glob-watcher": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "strip-bom": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" + }, + "dependencies": { + "clone": { + "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz" + } + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + } + } + }, + "vinyl-source-stream": { + "version": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", + "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", + "dev": true, + "requires": { + "through2": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "vinyl": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz" + }, + "dependencies": { + "clone": { + "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "isarray": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + } + }, + "through2": { + "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "vinyl": { + "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "clone-stats": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz" + } + } + } + }, + "vscode": { + "version": "https://registry.npmjs.org/vscode/-/vscode-1.1.9.tgz", + "integrity": "sha1-F87oj+YozQtTzNZ9PGeDyGY3sHQ=", + "dev": true, + "requires": { + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "gulp-chmod": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", + "gulp-filter": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", + "gulp-gunzip": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", + "gulp-remote-src": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", + "gulp-symdest": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz", + "gulp-untar": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.6.tgz", + "gulp-vinyl-zip": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz", + "mocha": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", + "request": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "semver": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "source-map-support": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", + "url-parse": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "vinyl-source-stream": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz" + }, + "dependencies": { + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "dev": true + }, + "debug": { + "version": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "dev": true, + "requires": { + "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + } + }, + "diff": { + "version": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=", + "dev": true + }, + "glob": { + "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "minimatch": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "once": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "path-is-absolute": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + } + }, + "growl": { + "version": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=", + "dev": true + }, + "mocha": { + "version": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", + "integrity": "sha1-Cu5alc9ppGGIIPXlH6MXFxF9rxs=", + "dev": true, + "requires": { + "browser-stdout": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "debug": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "diff": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "glob": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "growl": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "he": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz" + } + }, + "ms": { + "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", + "dev": true, + "requires": { + "has-flag": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz" + } + } + } + }, + "vscode-debugadapter": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.25.0.tgz", + "integrity": "sha512-tsOtNNKKTbnQanARdkFfUxI8qKVKba+QHOKWC1reDDeeyvzoNKkLMGkL/xsiKn5vQDeaP3zFBcLY8Ysak9GrvQ==", + "requires": { + "vscode-debugprotocol": "1.25.0" + } + }, + "vscode-debugadapter-testsupport": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.25.0.tgz", + "integrity": "sha512-6E2N7CoH7B0KEDvI9mFVFt4H+dRFDhtj3PmLVjNojfZ1VZZS2yfhE0XO0E5Axdhef3zTpUU6WZoeOOMVFGZGIg==", + "dev": true, + "requires": { + "vscode-debugprotocol": "1.25.0" + } + }, + "vscode-debugprotocol": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz", + "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" + }, + "vscode-extension-telemetry": { + "version": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.5.tgz", + "integrity": "sha1-IeKrtMvOMybkad27MiEjs3AvP4U=", + "requires": { + "applicationinsights": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.15.6.tgz", + "winreg": "https://registry.npmjs.org/winreg/-/winreg-0.0.13.tgz" + }, + "dependencies": { + "winreg": { + "version": "https://registry.npmjs.org/winreg/-/winreg-0.0.13.tgz", + "integrity": "sha1-dr/gLh3QycgnX7n98XqfNoRuNIM=" + } + } + }, + "vscode-jsonrpc": { + "version": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz", + "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=" + }, + "vscode-languageclient": { + "version": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.0.tgz", + "integrity": "sha1-NtAswYaoNlpEZ3GaKQ+yAKmuSQo=", + "requires": { + "vscode-languageserver-protocol": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz" + } + }, + "vscode-languageserver": { + "version": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.5.0.tgz", + "integrity": "sha1-0oCZvG3dqMHdFrcH5FThsd2uDbo=", + "requires": { + "vscode-languageserver-protocol": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz", + "vscode-uri": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz" + } + }, + "vscode-languageserver-protocol": { + "version": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz", + "integrity": "sha1-Bnxcvidwl5U5jRGWksl+u6FFIgk=", + "requires": { + "vscode-jsonrpc": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz", + "vscode-languageserver-types": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz" + } + }, + "vscode-languageserver-types": { + "version": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz", + "integrity": "sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=" + }, + "vscode-uri": { + "version": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz", + "integrity": "sha1-Eahr7+rDxKo+wIYjZRo8gabQu8g=" + }, + "which": { + "version": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + } + }, + "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": "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": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml2js": { + "version": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", + "requires": { + "sax": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "xmlbuilder": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz" + } + }, + "xmlbuilder": { + "version": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", + "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=" + }, + "xtend": { + "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "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": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "dev": true, + "requires": { + "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "fd-slicer": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz" + } + }, + "yazl": { + "version": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz", + "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=", + "dev": true, + "requires": { + "buffer-crc32": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" + } + } + } +} diff --git a/package.json b/package.json index 7e2a1c39ff43..49ec028f55ab 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,9 @@ "onCommand:python.buildWorkspaceSymbols", "onCommand:python.updateSparkLibrary", "onCommand:python.startREPL", - "onCommand:python.goToPythonObject" + "onCommand:python.goToPythonObject", + "onCommand:python.setLinter", + "onCommand:python.enableLinting" ], "main": "./out/client/extension", "contributes": { @@ -213,6 +215,16 @@ "command": "python.goToPythonObject", "title": "%python.command.python.goToPythonObject.title%", "category": "Python" + }, + { + "command": "python.setLinter", + "title": "%python.command.python.setLinter.title%", + "category": "Python" + }, + { + "command": "python.enableLinting", + "title": "%python.command.python.enableLinting.title%", + "category": "Python" } ], "menus": { @@ -949,12 +961,6 @@ "description": "Whether to lint Python files.", "scope": "resource" }, - "python.linting.enabledWithoutWorkspace": { - "type": "boolean", - "default": true, - "description": "Whether to lint Python files when no workspace is opened.", - "scope": "resource" - }, "python.linting.prospectorEnabled": { "type": "boolean", "default": false, @@ -1003,6 +1009,12 @@ "description": "Controls the maximum number of problems produced by the server.", "scope": "resource" }, + "python.linting.pylintUseMinimalCheckers": { + "type": "boolean", + "default": true, + "description": "Whether to run Pylint with minimal set of rules.", + "scope": "resource" + }, "python.linting.pylintCategorySeverity.convention": { "type": "string", "default": "Information", diff --git a/package.nls.json b/package.nls.json index c6af56214f8d..3313f7c1c07b 100644 --- a/package.nls.json +++ b/package.nls.json @@ -23,6 +23,8 @@ "python.command.jupyter.gotToPreviousCell.title": "Go to Previous Cell", "python.command.jupyter.gotToNextCell.title": "Go to Next Cell", "python.command.python.goToPythonObject.title": "Go to Python Object", + "python.command.python.setLinter.title": "Select Linter", + "python.command.python.enableLinting.title": "Enable Linting", "python.snippet.launch.standard.label": "Python", "python.snippet.launch.standard.description": "Debug a Python program with standard output", "python.snippet.launch.pyspark.label": "Python: PySpark", diff --git a/package.nls.ru.json b/package.nls.ru.json index e0e22abbc06d..fccc142b15ae 100644 --- a/package.nls.ru.json +++ b/package.nls.ru.json @@ -23,6 +23,8 @@ "python.command.jupyter.gotToPreviousCell.title": "Перейти к предыдущей ячейке", "python.command.jupyter.gotToNextCell.title": "Перейти к следующей ячейке", "python.command.python.goToPythonObject.title": "Перейти к объекту Python", + "python.command.python.setLinter.title": "Выбрать анализатор кода", + "python.command.python.enableLinting.title": "Включить анализатор кода", "python.snippet.launch.standard.label": "Python", "python.snippet.launch.standard.description": "Отладить программу Python со стандартным выводом", "python.snippet.launch.pyspark.label": "Python: PySpark", diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts index bc5de07e17f4..fe35fc91ce7c 100644 --- a/src/client/common/configSettings.ts +++ b/src/client/common/configSettings.ts @@ -4,7 +4,7 @@ import * as child_process from 'child_process'; import { EventEmitter } from 'events'; import * as path from 'path'; import * as vscode from 'vscode'; -import { Uri } from 'vscode'; +import { ConfigurationTarget, Uri } from 'vscode'; import { IAutoCompeteSettings, IFormattingSettings, @@ -61,12 +61,9 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { } // tslint:disable-next-line:function-name public static getInstance(resource?: Uri): PythonSettings { - const workspaceFolder = resource ? vscode.workspace.getWorkspaceFolder(resource) : undefined; - let workspaceFolderUri: Uri | undefined = workspaceFolder ? workspaceFolder.uri : undefined; - if (!workspaceFolderUri && Array.isArray(vscode.workspace.workspaceFolders) && vscode.workspace.workspaceFolders.length > 0) { - workspaceFolderUri = vscode.workspace.workspaceFolders[0].uri; - } + const workspaceFolderUri = PythonSettings.getSettingsUriAndTarget(resource).uri; const workspaceFolderKey = workspaceFolderUri ? workspaceFolderUri.fsPath : ''; + if (!PythonSettings.pythonSettings.has(workspaceFolderKey)) { const settings = new PythonSettings(workspaceFolderUri); PythonSettings.pythonSettings.set(workspaceFolderKey, settings); @@ -74,6 +71,19 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { // tslint:disable-next-line:no-non-null-assertion return PythonSettings.pythonSettings.get(workspaceFolderKey)!; } + + public static getSettingsUriAndTarget(resource?: Uri): { uri: Uri | undefined, target: ConfigurationTarget } { + const workspaceFolder = resource ? vscode.workspace.getWorkspaceFolder(resource) : undefined; + let workspaceFolderUri: Uri | undefined = workspaceFolder ? workspaceFolder.uri : undefined; + + if (!workspaceFolderUri && Array.isArray(vscode.workspace.workspaceFolders) && vscode.workspace.workspaceFolders.length > 0) { + workspaceFolderUri = vscode.workspace.workspaceFolders[0].uri; + } + + const target = workspaceFolderUri ? ConfigurationTarget.WorkspaceFolder : ConfigurationTarget.Global; + return { uri: workspaceFolderUri, target }; + } + // tslint:disable-next-line:function-name public static dispose() { if (!isTestExecution()) { @@ -138,7 +148,6 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { // Support for travis. this.linting = this.linting ? this.linting : { enabled: false, - enabledWithoutWorkspace: false, ignorePatterns: [], flake8Args: [], flake8Enabled: false, flake8Path: 'flake', lintOnSave: false, maxNumberOfProblems: 100, @@ -167,7 +176,8 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { mypyCategorySeverity: { error: vscode.DiagnosticSeverity.Error, note: vscode.DiagnosticSeverity.Hint - } + }, + pylintUseMinimalCheckers: false }; this.linting.pylintPath = getAbsolutePath(systemVariables.resolveAny(this.linting.pylintPath), workspaceRoot); this.linting.flake8Path = getAbsolutePath(systemVariables.resolveAny(this.linting.flake8Path), workspaceRoot); diff --git a/src/client/common/configuration/service.ts b/src/client/common/configuration/service.ts index 8ee86ce0de6f..effbba72efed 100644 --- a/src/client/common/configuration/service.ts +++ b/src/client/common/configuration/service.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { injectable } from 'inversify'; -import { Uri } from 'vscode'; +import { ConfigurationTarget, Uri, workspace, WorkspaceConfiguration } from 'vscode'; import { PythonSettings } from '../configSettings'; import { IConfigurationService, IPythonSettings } from '../types'; @@ -11,4 +11,48 @@ export class ConfigurationService implements IConfigurationService { public getSettings(resource?: Uri): IPythonSettings { return PythonSettings.getInstance(resource); } + public async updateSettingAsync(setting: string, value?: {}, resource?: Uri, configTarget?: ConfigurationTarget): Promise { + const settingsInfo = PythonSettings.getSettingsUriAndTarget(resource); + + const pythonConfig = workspace.getConfiguration('python', settingsInfo.uri); + const currentValue = pythonConfig.inspect(setting); + + if (currentValue !== undefined && + ((settingsInfo.target === ConfigurationTarget.Global && currentValue.globalValue === value) || + (settingsInfo.target === ConfigurationTarget.Workspace && currentValue.workspaceValue === value) || + (settingsInfo.target === ConfigurationTarget.WorkspaceFolder && currentValue.workspaceFolderValue === value))) { + return; + } + + await pythonConfig.update(setting, value, settingsInfo.target); + await this.verifySetting(pythonConfig, settingsInfo.target, setting, value); + } + + public isTestExecution(): boolean { + return process.env.VSC_PYTHON_CI_TEST === '1'; + } + + private async verifySetting(pythonConfig: WorkspaceConfiguration, target: ConfigurationTarget, settingName: string, value?: {}): Promise { + if (this.isTestExecution()) { + let retries = 0; + do { + const setting = pythonConfig.inspect(settingName); + if (!setting && value === undefined) { + break; // Both are unset + } + if (setting && value !== undefined) { + // Both specified + const actual = target === ConfigurationTarget.Global + ? setting.globalValue + : target === ConfigurationTarget.Workspace ? setting.workspaceValue : setting.workspaceFolderValue; + if (actual === value) { + break; + } + } + // Wait for settings to get refreshed. + await new Promise((resolve, reject) => setTimeout(resolve, 250)); + retries += 1; + } while (retries < 20); + } + } } diff --git a/src/client/common/constants.ts b/src/client/common/constants.ts index cde72d22fd21..2f2d7f2c960f 100644 --- a/src/client/common/constants.ts +++ b/src/client/common/constants.ts @@ -3,6 +3,7 @@ export const PythonLanguage = { language: 'python' }; export namespace Commands { export const Set_Interpreter = 'python.setInterpreter'; + export const Set_ShebangInterpreter = 'python.setShebangInterpreter'; export const Exec_In_Terminal = 'python.execInTerminal'; export const Exec_Selection_In_Terminal = 'python.execSelectionInTerminal'; export const Exec_Selection_In_Django_Shell = 'python.execSelectionInDjangoShell'; @@ -27,6 +28,8 @@ export namespace Commands { export const Update_SparkLibrary = 'python.updateSparkLibrary'; export const Build_Workspace_Symbols = 'python.buildWorkspaceSymbols'; export const Start_REPL = 'python.startREPL'; + export const Set_Linter = 'python.setLinter'; + export const Enable_Linter = 'python.enableLinting'; } export namespace Octicons { export const Test_Pass = '$(check)'; diff --git a/src/client/common/errors/moduleNotInstalledError.ts b/src/client/common/errors/moduleNotInstalledError.ts index 60ec06781e76..944f6dfc3e5d 100644 --- a/src/client/common/errors/moduleNotInstalledError.ts +++ b/src/client/common/errors/moduleNotInstalledError.ts @@ -3,6 +3,6 @@ export class ModuleNotInstalledError extends Error { constructor(moduleName: string) { - super(`Module '${moduleName} not installed.`); + super(`Module '${moduleName}' not installed.`); } } diff --git a/src/client/common/installer/installer.ts b/src/client/common/installer/installer.ts index 28a553b6afb8..0409af1fa737 100644 --- a/src/client/common/installer/installer.ts +++ b/src/client/common/installer/installer.ts @@ -5,7 +5,7 @@ import { ConfigurationTarget, QuickPickItem, Uri, window, workspace } from 'vsco import * as vscode from 'vscode'; import { IFormatterHelper } from '../../formatters/types'; import { IServiceContainer } from '../../ioc/types'; -import { ILinterHelper } from '../../linters/types'; +import { ILinterManager } from '../../linters/types'; import { ITestsHelper } from '../../unittests/common/types'; import { PythonSettings } from '../configSettings'; import { STANDARD_OUTPUT_CHANNEL } from '../constants'; @@ -34,17 +34,6 @@ ProductNames.set(Product.pytest, 'pytest'); ProductNames.set(Product.yapf, 'yapf'); ProductNames.set(Product.rope, 'rope'); -export const SettingToDisableProduct = new Map(); -SettingToDisableProduct.set(Product.flake8, 'linting.flake8Enabled'); -SettingToDisableProduct.set(Product.mypy, 'linting.mypyEnabled'); -SettingToDisableProduct.set(Product.nosetest, 'unitTest.nosetestsEnabled'); -SettingToDisableProduct.set(Product.pep8, 'linting.pep8Enabled'); -SettingToDisableProduct.set(Product.pylama, 'linting.pylamaEnabled'); -SettingToDisableProduct.set(Product.prospector, 'linting.prospectorEnabled'); -SettingToDisableProduct.set(Product.pydocstyle, 'linting.pydocstyleEnabled'); -SettingToDisableProduct.set(Product.pylint, 'linting.pylintEnabled'); -SettingToDisableProduct.set(Product.pytest, 'unitTest.pyTestEnabled'); - // tslint:disable-next-line:variable-name const ProductInstallationPrompt = new Map(); ProductInstallationPrompt.set(Product.ctags, 'Install CTags to enable Python workspace symbols'); @@ -92,15 +81,7 @@ export class Installer implements IInstaller { const productTypeName = ProductTypeNames.get(productType)!; const productName = ProductNames.get(product)!; - if (!this.shouldDisplayPrompt(product)) { - const message = `${productTypeName} '${productName}' not installed.`; - this.outputChannel.appendLine(message); - return InstallerResponse.Ignore; - } - const installOption = ProductInstallationPrompt.has(product) ? ProductInstallationPrompt.get(product)! : `Install ${productName}`; - const disableOption = `Disable ${productTypeName}`; - const dontShowAgain = 'Don\'t show this prompt again'; const alternateFormatter = product === Product.autopep8 ? 'yapf' : 'autopep8'; const useOtherFormatter = `Use '${alternateFormatter}' formatter`; const options: string[] = []; @@ -108,9 +89,6 @@ export class Installer implements IInstaller { if (productType === ProductType.Formatter) { options.push(...[useOtherFormatter]); } - if (SettingToDisableProduct.has(product)) { - options.push(...[disableOption, dontShowAgain]); - } const item = await window.showErrorMessage(`${productTypeName} ${productName} is not installed`, ...options); if (!item) { return InstallerResponse.Ignore; @@ -119,24 +97,10 @@ export class Installer implements IInstaller { case installOption: { return this.install(product, resource); } - case disableOption: { - if (ProductTypes.has(product) && ProductTypes.get(product)! === ProductType.Linter) { - return this.disableLinter(product, resource).then(() => InstallerResponse.Disabled); - } else { - const settingToDisable = SettingToDisableProduct.get(product)!; - return this.updateSetting(settingToDisable, false, resource).then(() => InstallerResponse.Disabled); - } - } case useOtherFormatter: { return this.updateSetting('formatting.provider', alternateFormatter, resource) .then(() => InstallerResponse.Installed); } - case dontShowAgain: { - const pythonConfig = workspace.getConfiguration('python'); - const features = pythonConfig.get('disablePromptForFeatures', [] as string[]); - features.push(productName); - return pythonConfig.update('disablePromptForFeatures', features, true).then(() => InstallerResponse.Ignore); - } default: { throw new Error('Invalid selection'); } @@ -210,24 +174,6 @@ export class Installer implements IInstaller { .catch(() => false); } } - public async disableLinter(product: Product, resource?: Uri) { - if (resource && workspace.getWorkspaceFolder(resource)) { - const settingToDisable = SettingToDisableProduct.get(product)!; - const pythonConfig = workspace.getConfiguration('python', resource); - const isMultiroot = Array.isArray(workspace.workspaceFolders) && workspace.workspaceFolders.length > 1; - const configTarget = isMultiroot ? ConfigurationTarget.WorkspaceFolder : ConfigurationTarget.Workspace; - return pythonConfig.update(settingToDisable, false, configTarget); - } else { - const pythonConfig = workspace.getConfiguration('python'); - return pythonConfig.update('linting.enabledWithoutWorkspace', false, true); - } - } - private shouldDisplayPrompt(product: Product) { - const productName = ProductNames.get(product)!; - const pythonConfig = workspace.getConfiguration('python'); - const disablePromptForFeatures = pythonConfig.get('disablePromptForFeatures', [] as string[]); - return disablePromptForFeatures.indexOf(productName) === -1; - } private installCTags() { if (this.serviceContainer.get(IPlatformService).isWindows) { this.outputChannel.appendLine('Install Universal Ctags Win32 to enable support for Workspace Symbols'); @@ -302,9 +248,8 @@ export class Installer implements IInstaller { } case ProductType.RefactoringLibrary: return this.translateProductToModuleName(product, ModuleNamePurpose.run); case ProductType.Linter: { - const linterHelper = this.serviceContainer.get(ILinterHelper); - const settingsPropNames = linterHelper.getSettingsPropertyNames(product); - return settings.linting[settingsPropNames.pathName] as string; + const linterManager = this.serviceContainer.get(ILinterManager); + return linterManager.getLinterInfo(product).pathName(resource); } default: { throw new Error(`Unrecognized Product '${product}'`); diff --git a/src/client/common/installer/pipInstaller.ts b/src/client/common/installer/pipInstaller.ts index fe522521a491..7e49e7afa217 100644 --- a/src/client/common/installer/pipInstaller.ts +++ b/src/client/common/installer/pipInstaller.ts @@ -11,7 +11,6 @@ import { IModuleInstaller } from './types'; @injectable() export class PipInstaller extends ModuleInstaller implements IModuleInstaller { - private isCondaAvailable: boolean | undefined; public get displayName() { return 'Pip'; } @@ -19,10 +18,7 @@ export class PipInstaller extends ModuleInstaller implements IModuleInstaller { super(serviceContainer); } public isSupported(resource?: Uri): Promise { - const pythonExecutionFactory = this.serviceContainer.get(IPythonExecutionFactory); - return pythonExecutionFactory.create(resource) - .then(proc => proc.isModuleInstalled('pip')) - .catch(() => false); + return this.isPipAvailable(resource); } protected async getExecutionInfo(moduleName: string, resource?: Uri): Promise { const proxyArgs = []; @@ -37,7 +33,7 @@ export class PipInstaller extends ModuleInstaller implements IModuleInstaller { moduleName: 'pip' }; } - private isPipAvailable(resource?: Uri) { + private isPipAvailable(resource?: Uri): Promise { const pythonExecutionFactory = this.serviceContainer.get(IPythonExecutionFactory); return pythonExecutionFactory.create(resource) .then(proc => proc.isModuleInstalled('pip')) diff --git a/src/client/common/installer/productInstaller.ts b/src/client/common/installer/productInstaller.ts new file mode 100644 index 000000000000..3991a882a4ff --- /dev/null +++ b/src/client/common/installer/productInstaller.ts @@ -0,0 +1,330 @@ +import { inject, injectable, named } from 'inversify'; +import * as os from 'os'; +import * as path from 'path'; +import { OutputChannel, QuickPickItem, Uri, window } from 'vscode'; +import * as vscode from 'vscode'; +import { IFormatterHelper } from '../../formatters/types'; +import { IServiceContainer } from '../../ioc/types'; +import { ILinterManager } from '../../linters/types'; +import { ITestsHelper } from '../../unittests/common/types'; +import { IApplicationShell } from '../application/types'; +import { STANDARD_OUTPUT_CHANNEL } from '../constants'; +import { IPlatformService } from '../platform/types'; +import { IProcessService, IPythonExecutionFactory } from '../process/types'; +import { ITerminalServiceFactory } from '../terminal/types'; +import { IConfigurationService, IInstaller, ILogger, InstallerResponse, IOutputChannel, ModuleNamePurpose, Product } from '../types'; +import { IModuleInstaller } from './types'; + +export { Product } from '../types'; + +const CTagsInsllationScript = os.platform() === 'darwin' ? 'brew install ctags' : 'sudo apt-get install exuberant-ctags'; + +// tslint:disable-next-line:variable-name +const ProductNames = new Map(); +ProductNames.set(Product.autopep8, 'autopep8'); +ProductNames.set(Product.flake8, 'flake8'); +ProductNames.set(Product.mypy, 'mypy'); +ProductNames.set(Product.nosetest, 'nosetest'); +ProductNames.set(Product.pep8, 'pep8'); +ProductNames.set(Product.pylama, 'pylama'); +ProductNames.set(Product.prospector, 'prospector'); +ProductNames.set(Product.pydocstyle, 'pydocstyle'); +ProductNames.set(Product.pylint, 'pylint'); +ProductNames.set(Product.pytest, 'pytest'); +ProductNames.set(Product.yapf, 'yapf'); +ProductNames.set(Product.rope, 'rope'); + +enum ProductType { + Linter, + Formatter, + TestFramework, + RefactoringLibrary, + WorkspaceSymbols +} + +// tslint:disable-next-line:max-classes-per-file +abstract class BaseInstaller { + protected appShell: IApplicationShell; + protected configService: IConfigurationService; + + constructor(protected serviceContainer: IServiceContainer, protected outputChannel: OutputChannel) { + this.appShell = serviceContainer.get(IApplicationShell); + this.configService = serviceContainer.get(IConfigurationService); + } + + public abstract promptToInstall(product: Product, resource?: Uri): Promise; + + public async install(product: Product, resource?: Uri): Promise { + if (product === Product.unittest) { + return InstallerResponse.Installed; + } + + const installer = await this.getInstallationChannel(product, resource); + if (!installer) { + return InstallerResponse.Ignore; + } + + const moduleName = translateProductToModule(product, ModuleNamePurpose.install); + const logger = this.serviceContainer.get(ILogger); + await installer.installModule(moduleName) + .catch(logger.logError.bind(logger, `Error in installing the module '${moduleName}'`)); + + return this.isInstalled(product) + .then(isInstalled => isInstalled ? InstallerResponse.Installed : InstallerResponse.Ignore); + } + + public async isInstalled(product: Product, resource?: Uri): Promise { + let moduleName: string | undefined; + try { + moduleName = translateProductToModule(product, ModuleNamePurpose.run); + // tslint:disable-next-line:no-empty + } catch { } + + // User may have customized the module name or provided the fully qualifieid path. + const executableName = this.getExecutableNameFromSettings(product, resource); + + const isModule = typeof moduleName === 'string' && moduleName.length > 0 && path.basename(executableName) === executableName; + // Prospector is an exception, it can be installed as a module, but not run as one. + if (product !== Product.prospector && isModule) { + const pythonProcess = await this.serviceContainer.get(IPythonExecutionFactory).create(resource); + return pythonProcess.isModuleInstalled(executableName); + } else { + const process = this.serviceContainer.get(IProcessService); + const prospectorPath = this.configService.getSettings(resource).linting.prospectorPath; + return process.exec(prospectorPath, ['--version'], { mergeStdOutErr: true }) + .then(() => true) + .catch(() => false); + } + } + + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + throw new Error('getExecutableNameFromSettings is not supported on this object'); + } + + private async getInstallationChannel(product: Product, resource?: Uri): Promise { + const productName = ProductNames.get(product)!; + const channels = await this.getInstallationChannels(resource); + if (channels.length === 0) { + window.showInformationMessage(`No installers available to install ${productName}.`); + return; + } + if (channels.length === 1) { + return channels[0]; + } + const placeHolder = `Select an option to install ${productName}`; + const options = channels.map(installer => { + return { + label: `Install using ${installer.displayName}`, + description: '', + installer + } as QuickPickItem & { installer: IModuleInstaller }; + }); + const selection = await window.showQuickPick(options, { matchOnDescription: true, matchOnDetail: true, placeHolder }); + return selection ? selection.installer : undefined; + } + + private async getInstallationChannels(resource?: Uri): Promise { + const installers = this.serviceContainer.getAll(IModuleInstaller); + const supportedInstallers = await Promise.all(installers.map(async installer => installer.isSupported(resource).then(supported => supported ? installer : undefined))); + return supportedInstallers.filter(installer => installer !== undefined).map(installer => installer!); + } +} + +class CTagsInstaller extends BaseInstaller { + constructor(serviceContainer: IServiceContainer, outputChannel: OutputChannel) { + super(serviceContainer, outputChannel); + } + + public async promptToInstall(product: Product, resource?: Uri): Promise { + const item = await this.appShell.showErrorMessage('Install CTags to enable Python workspace symbols?', 'Yes', 'No'); + return item === 'Yes' ? this.install(product, resource) : InstallerResponse.Ignore; + } + + public async install(product: Product, resource?: Uri): Promise { + if (this.serviceContainer.get(IPlatformService).isWindows) { + this.outputChannel.appendLine('Install Universal Ctags Win32 to enable support for Workspace Symbols'); + this.outputChannel.appendLine('Download the CTags binary from the Universal CTags site.'); + this.outputChannel.appendLine('Option 1: Extract ctags.exe from the downloaded zip to any folder within your PATH so that Visual Studio Code can run it.'); + this.outputChannel.appendLine('Option 2: Extract to any folder and add the path to this folder to the command setting.'); + this.outputChannel.appendLine('Option 3: Extract to any folder and define that path in the python.workspaceSymbols.ctagsPath setting of your user settings file (settings.json).'); + this.outputChannel.show(); + } else { + const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(); + const logger = this.serviceContainer.get(ILogger); + terminalService.sendCommand(CTagsInsllationScript, []) + .catch(logger.logError.bind(logger, `Failed to install ctags. Script sent '${CTagsInsllationScript}'.`)); + } + return InstallerResponse.Ignore; + } + + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + const settings = this.configService.getSettings(resource); + return settings.workspaceSymbols.ctagsPath; + } +} + +class FormatterInstaller extends BaseInstaller { + public async promptToInstall(product: Product, resource?: Uri): Promise { + const productName = ProductNames.get(product)!; + + const installThis = `Install ${productName}`; + const alternateFormatter = product === Product.autopep8 ? 'yapf' : 'autopep8'; + const useOtherFormatter = `Use '${alternateFormatter}' formatter`; + const item = await this.appShell.showErrorMessage(`Formatter ${productName} is not installed.`, installThis, useOtherFormatter); + + if (item === installThis) { + return this.install(product, resource); + } + if (item === useOtherFormatter) { + await this.configService.updateSettingAsync('formatting.provider', alternateFormatter, resource); + return InstallerResponse.Installed; + } + return InstallerResponse.Ignore; + } + + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + const settings = this.configService.getSettings(resource); + const formatHelper = this.serviceContainer.get(IFormatterHelper); + const settingsPropNames = formatHelper.getSettingsPropertyNames(product); + return settings.formatting[settingsPropNames.pathName] as string; + } +} + +// tslint:disable-next-line:max-classes-per-file +class LinterInstaller extends BaseInstaller { + public async promptToInstall(product: Product, resource?: Uri): Promise { + const productName = ProductNames.get(product)!; + const install = 'Install'; + const disable = 'Disable linting'; + + const response = await this.appShell + .showErrorMessage(`Linter ${productName} is not installed.`, install, disable); + if (response === install) { + return this.install(product, resource); + } + const lm = this.serviceContainer.get(ILinterManager); + if (response === disable) { + await lm.enableLintingAsync(false); + } else { + lm.disableSessionLinting(); + } + return InstallerResponse.Ignore; + } + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + const linterManager = this.serviceContainer.get(ILinterManager); + return linterManager.getLinterInfo(product).pathName(resource); + } +} + +// tslint:disable-next-line:max-classes-per-file +class TestFrameworkInstaller extends BaseInstaller { + public async promptToInstall(product: Product, resource?: Uri): Promise { + const productName = ProductNames.get(product)!; + const item = await this.appShell.showErrorMessage(`Test framework ${productName} is not installed. Install?`, 'Yes', 'No'); + return item === 'Yes' ? this.install(product, resource) : InstallerResponse.Ignore; + } + + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + const testHelper = this.serviceContainer.get(ITestsHelper); + const settingsPropNames = testHelper.getSettingsPropertyNames(product); + if (!settingsPropNames.pathName) { + // E.g. in the case of UnitTests we don't allow customizing the paths. + return translateProductToModule(product, ModuleNamePurpose.run); + } + const settings = this.configService.getSettings(resource); + return settings.unitTest[settingsPropNames.pathName] as string; + } +} + +// tslint:disable-next-line:max-classes-per-file +class RefactoringLibraryInstaller extends BaseInstaller { + public async promptToInstall(product: Product, resource?: Uri): Promise { + const productName = ProductNames.get(product)!; + const item = await this.appShell.showErrorMessage(`Refactoring library ${productName} is not installed. Install?`, 'Yes', 'No'); + return item === 'Yes' ? this.install(product, resource) : InstallerResponse.Ignore; + } + protected getExecutableNameFromSettings(product: Product, resource?: Uri): string { + return translateProductToModule(product, ModuleNamePurpose.run); + } +} + +// tslint:disable-next-line:max-classes-per-file +@injectable() +export class ProductInstaller implements IInstaller { + private ProductTypes = new Map(); + + constructor( @inject(IServiceContainer) private serviceContainer: IServiceContainer, + @inject(IOutputChannel) @named(STANDARD_OUTPUT_CHANNEL) private outputChannel: vscode.OutputChannel) { + this.ProductTypes.set(Product.flake8, ProductType.Linter); + this.ProductTypes.set(Product.mypy, ProductType.Linter); + this.ProductTypes.set(Product.pep8, ProductType.Linter); + this.ProductTypes.set(Product.prospector, ProductType.Linter); + this.ProductTypes.set(Product.pydocstyle, ProductType.Linter); + this.ProductTypes.set(Product.pylama, ProductType.Linter); + this.ProductTypes.set(Product.pylint, ProductType.Linter); + this.ProductTypes.set(Product.ctags, ProductType.WorkspaceSymbols); + this.ProductTypes.set(Product.nosetest, ProductType.TestFramework); + this.ProductTypes.set(Product.pytest, ProductType.TestFramework); + this.ProductTypes.set(Product.unittest, ProductType.TestFramework); + this.ProductTypes.set(Product.autopep8, ProductType.Formatter); + this.ProductTypes.set(Product.yapf, ProductType.Formatter); + this.ProductTypes.set(Product.rope, ProductType.RefactoringLibrary); + } + + // tslint:disable-next-line:no-empty + public dispose() { } + public async promptToInstall(product: Product, resource?: Uri): Promise { + return this.createInstaller(product).promptToInstall(product, resource); + } + public async install(product: Product, resource?: Uri): Promise { + return this.createInstaller(product).install(product, resource); + } + public async isInstalled(product: Product, resource?: Uri): Promise { + return this.createInstaller(product).isInstalled(product, resource); + } + public translateProductToModuleName(product: Product, purpose: ModuleNamePurpose): string { + return translateProductToModule(product, purpose); + } + + private createInstaller(product: Product): BaseInstaller { + const productType = this.ProductTypes.get(product)!; + switch (productType) { + case ProductType.Formatter: + return new FormatterInstaller(this.serviceContainer, this.outputChannel); + case ProductType.Linter: + return new LinterInstaller(this.serviceContainer, this.outputChannel); + case ProductType.WorkspaceSymbols: + return new CTagsInstaller(this.serviceContainer, this.outputChannel); + case ProductType.TestFramework: + return new TestFrameworkInstaller(this.serviceContainer, this.outputChannel); + case ProductType.RefactoringLibrary: + return new RefactoringLibraryInstaller(this.serviceContainer, this.outputChannel); + default: + break; + } + throw new Error(`Unknown product ${product}`); + } +} + +function translateProductToModule(product: Product, purpose: ModuleNamePurpose): string { + switch (product) { + case Product.mypy: return 'mypy'; + case Product.nosetest: { + return purpose === ModuleNamePurpose.install ? 'nose' : 'nosetests'; + } + case Product.pylama: return 'pylama'; + case Product.prospector: return 'prospector'; + case Product.pylint: return 'pylint'; + case Product.pytest: return 'pytest'; + case Product.autopep8: return 'autopep8'; + case Product.pep8: return 'pep8'; + case Product.pydocstyle: return 'pydocstyle'; + case Product.yapf: return 'yapf'; + case Product.flake8: return 'flake8'; + case Product.unittest: return 'unittest'; + case Product.rope: return 'rope'; + default: { + throw new Error(`Product ${product} cannot be installed as a Python Module.`); + } + } +} diff --git a/src/client/common/installer/serviceRegistry.ts b/src/client/common/installer/serviceRegistry.ts index d89a81c7ad3f..c53d457a3829 100644 --- a/src/client/common/installer/serviceRegistry.ts +++ b/src/client/common/installer/serviceRegistry.ts @@ -3,11 +3,9 @@ 'use strict'; import { IServiceManager } from '../../ioc/types'; -import { IInstaller } from '../types'; import { CondaInstaller } from './condaInstaller'; -import { Installer } from './installer'; import { PipInstaller } from './pipInstaller'; -import { IModuleInstaller, IPythonInstallation } from './types'; +import { IModuleInstaller } from './types'; export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IModuleInstaller, CondaInstaller); diff --git a/src/client/common/process/pythonExecutionFactory.ts b/src/client/common/process/pythonExecutionFactory.ts index 34f21731db44..32ab2566c132 100644 --- a/src/client/common/process/pythonExecutionFactory.ts +++ b/src/client/common/process/pythonExecutionFactory.ts @@ -3,20 +3,21 @@ import { inject, injectable } from 'inversify'; import { Uri } from 'vscode'; -import { PythonSettings } from '../configSettings'; +import { IServiceContainer } from '../../ioc/types'; import { IEnvironmentVariablesProvider } from '../variables/types'; import { PythonExecutionService } from './pythonProcess'; -import { IProcessService, IPythonExecutionFactory, IPythonExecutionService } from './types'; +import { IPythonExecutionFactory, IPythonExecutionService } from './types'; @injectable() export class PythonExecutionFactory implements IPythonExecutionFactory { - constructor( @inject(IProcessService) private procService: IProcessService, - @inject(IEnvironmentVariablesProvider) private envVarsService: IEnvironmentVariablesProvider) { } + private envVarsService: IEnvironmentVariablesProvider; + constructor( @inject(IServiceContainer) private serviceContainer: IServiceContainer) { + this.envVarsService = serviceContainer.get(IEnvironmentVariablesProvider); + } public async create(resource?: Uri): Promise { - const settings = PythonSettings.getInstance(resource); return this.envVarsService.getEnvironmentVariables(resource) .then(customEnvVars => { - return new PythonExecutionService(this.procService, settings.pythonPath, customEnvVars); + return new PythonExecutionService(this.serviceContainer, customEnvVars); }); } } diff --git a/src/client/common/process/pythonProcess.ts b/src/client/common/process/pythonProcess.ts index ed8b68c2765f..92d0f8fecdc7 100644 --- a/src/client/common/process/pythonProcess.ts +++ b/src/client/common/process/pythonProcess.ts @@ -2,14 +2,23 @@ // Licensed under the MIT License. import { injectable } from 'inversify'; +import { IServiceContainer } from '../../ioc/types'; import { ErrorUtils } from '../errors/errorUtils'; import { ModuleNotInstalledError } from '../errors/moduleNotInstalledError'; +import { IConfigurationService } from '../types'; import { EnvironmentVariables } from '../variables/types'; import { ExecutionResult, IProcessService, IPythonExecutionService, ObservableExecutionResult, SpawnOptions } from './types'; @injectable() export class PythonExecutionService implements IPythonExecutionService { - constructor(private procService: IProcessService, private pythonPath: string, private envVars: EnvironmentVariables | undefined) { } + private procService: IProcessService; + private configService: IConfigurationService; + + constructor(serviceContainer: IServiceContainer, private envVars: EnvironmentVariables | undefined) { + this.procService = serviceContainer.get(IProcessService); + this.configService = serviceContainer.get(IConfigurationService); + } + public async getVersion(): Promise { return this.procService.exec(this.pythonPath, ['--version'], { env: this.envVars, mergeStdOutErr: true }) .then(output => output.stdout.trim()); @@ -61,4 +70,7 @@ export class PythonExecutionService implements IPythonExecutionService { return result; } + private get pythonPath(): string { + return this.configService.getSettings().pythonPath; + } } diff --git a/src/client/common/serviceRegistry.ts b/src/client/common/serviceRegistry.ts index 43d1735ebb16..b800774eeed4 100644 --- a/src/client/common/serviceRegistry.ts +++ b/src/client/common/serviceRegistry.ts @@ -9,7 +9,7 @@ import { TerminalManager } from './application/terminalManager'; import { IApplicationShell, ICommandManager, IDocumentManager, ITerminalManager, IWorkspaceService } from './application/types'; import { WorkspaceService } from './application/workspace'; import { ConfigurationService } from './configuration/service'; -import { Installer } from './installer/installer'; +import { ProductInstaller } from './installer/productInstaller'; import { Logger } from './logger'; import { PersistentStateFactory } from './persistentState'; import { IS_64_BIT, IS_WINDOWS } from './platform/constants'; @@ -32,7 +32,7 @@ export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IPathUtils, PathUtils); serviceManager.addSingleton(IApplicationShell, ApplicationShell); serviceManager.addSingleton(ICurrentProcess, CurrentProcess); - serviceManager.addSingleton(IInstaller, Installer); + serviceManager.addSingleton(IInstaller, ProductInstaller); serviceManager.addSingleton(ICommandManager, CommandManager); serviceManager.addSingleton(IConfigurationService, ConfigurationService); serviceManager.addSingleton(IWorkspaceService, WorkspaceService); diff --git a/src/client/common/types.ts b/src/client/common/types.ts index 7faa2567acc7..1a65a0661d05 100644 --- a/src/client/common/types.ts +++ b/src/client/common/types.ts @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { DiagnosticSeverity, Uri } from 'vscode'; +import { ConfigurationTarget, DiagnosticSeverity, Uri } from 'vscode'; import { EnvironmentVariables } from './variables/types'; export const IOutputChannel = Symbol('IOutputChannel'); export const IDocumentSymbolProvider = Symbol('IDocumentSymbolProvider'); @@ -73,7 +73,6 @@ export interface IInstaller { promptToInstall(product: Product, resource?: Uri): Promise; install(product: Product, resource?: Uri): Promise; isInstalled(product: Product, resource?: Uri): Promise; - disableLinter(product: Product, resource?: Uri): Promise; translateProductToModuleName(product: Product, purpose: ModuleNamePurpose): string; } @@ -147,7 +146,6 @@ export interface IMypyCategorySeverity { } export interface ILintingSettings { enabled: boolean; - enabledWithoutWorkspace: boolean; ignorePatterns: string[]; prospectorEnabled: boolean; prospectorArgs: string[]; @@ -176,6 +174,7 @@ export interface ILintingSettings { mypyEnabled: boolean; mypyArgs: string[]; mypyPath: string; + pylintUseMinimalCheckers: boolean; } export interface IFormattingSettings { provider: string; @@ -206,4 +205,6 @@ export const IConfigurationService = Symbol('IConfigurationService'); export interface IConfigurationService { getSettings(resource?: Uri): IPythonSettings; + isTestExecution(): boolean; + updateSettingAsync(setting: string, value?: {}, resource?: Uri, configTarget?: ConfigurationTarget): Promise; } diff --git a/src/client/extension.ts b/src/client/extension.ts index deeebe91610a..c4e42c7c2f9f 100644 --- a/src/client/extension.ts +++ b/src/client/extension.ts @@ -7,8 +7,8 @@ if ((Reflect as any).metadata === undefined) { } import { Container } from 'inversify'; import * as os from 'os'; -import { Disposable, Memento, OutputChannel, window } from 'vscode'; import * as vscode from 'vscode'; +import { Disposable, Memento, OutputChannel, window } from 'vscode'; import { BannerService } from './banner'; import { PythonSettings } from './common/configSettings'; import * as settings from './common/configSettings'; @@ -25,7 +25,7 @@ import { GLOBAL_MEMENTO, IDisposableRegistry, ILogger, IMemento, IOutputChannel, import { registerTypes as variableRegisterTypes } from './common/variables/serviceRegistry'; import { SimpleConfigurationProvider } from './debugger'; import { registerTypes as formattersRegisterTypes } from './formatters/serviceRegistry'; -import { SetInterpreterProvider } from './interpreter/configuration/setInterpreterProvider'; +import { InterpreterSelector } from './interpreter/configuration/interpreterSelector'; import { ICondaService, IInterpreterService, IInterpreterVersionService } from './interpreter/contracts'; import { ShebangCodeLensProvider } from './interpreter/display/shebangCodeLensProvider'; import { registerTypes as interpretersRegisterTypes } from './interpreter/serviceRegistry'; @@ -39,7 +39,7 @@ import { PythonCompletionItemProvider } from './providers/completionProvider'; import { PythonDefinitionProvider } from './providers/definitionProvider'; import { PythonFormattingEditProvider } from './providers/formatProvider'; import { PythonHoverProvider } from './providers/hoverProvider'; -import { LintProvider } from './providers/lintProvider'; +import { LinterProvider } from './providers/linterProvider'; import { activateGoToObjectDefinitionProvider } from './providers/objectDefinitionProvider'; import { PythonReferenceProvider } from './providers/referenceProvider'; import { PythonRenameProvider } from './providers/renameProvider'; @@ -111,7 +111,7 @@ export async function activate(context: vscode.ExtensionContext) { const processService = serviceContainer.get(IProcessService); const interpreterVersionService = serviceContainer.get(IInterpreterVersionService); - context.subscriptions.push(new SetInterpreterProvider(interpreterManager, interpreterVersionService, processService)); + context.subscriptions.push(new InterpreterSelector(interpreterManager, interpreterVersionService, processService)); context.subscriptions.push(activateUpdateSparkLibraryProvider()); activateSimplePythonRefactorProvider(context, standardOutputChannel, serviceContainer); const jediFactory = new JediFactory(context.asAbsolutePath('.'), serviceContainer); @@ -146,7 +146,7 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.languages.registerDefinitionProvider(PYTHON, definitionProvider)); context.subscriptions.push(vscode.languages.registerHoverProvider(PYTHON, new PythonHoverProvider(jediFactory))); context.subscriptions.push(vscode.languages.registerReferenceProvider(PYTHON, new PythonReferenceProvider(jediFactory))); - context.subscriptions.push(vscode.languages.registerCompletionItemProvider(PYTHON, new PythonCompletionItemProvider(jediFactory), '.')); + context.subscriptions.push(vscode.languages.registerCompletionItemProvider(PYTHON, new PythonCompletionItemProvider(jediFactory, serviceContainer), '.')); context.subscriptions.push(vscode.languages.registerCodeLensProvider(PYTHON, new ShebangCodeLensProvider(processService))); const symbolProvider = new PythonSymbolProvider(jediFactory); @@ -161,7 +161,7 @@ export async function activate(context: vscode.ExtensionContext) { } // tslint:disable-next-line:promise-function-async - const linterProvider = new LintProvider(context, standardOutputChannel, (a, b) => Promise.resolve(false), serviceContainer); + const linterProvider = new LinterProvider(context, standardOutputChannel, (a, b) => Promise.resolve(false), serviceContainer); context.subscriptions.push(linterProvider); const jupyterExtInstalled = vscode.extensions.getExtension('donjayamanne.jupyter'); if (jupyterExtInstalled) { diff --git a/src/client/formatters/autoPep8Formatter.ts b/src/client/formatters/autoPep8Formatter.ts index 11f217641e01..6be2f961acf1 100644 --- a/src/client/formatters/autoPep8Formatter.ts +++ b/src/client/formatters/autoPep8Formatter.ts @@ -1,6 +1,6 @@ import * as vscode from 'vscode'; import { PythonSettings } from '../common/configSettings'; -import { Product } from '../common/installer/installer'; +import { Product } from '../common/installer/productInstaller'; import { IServiceContainer } from '../ioc/types'; import { sendTelemetryWhenDone } from '../telemetry'; import { FORMAT } from '../telemetry/constants'; diff --git a/src/client/interpreter/configuration/setInterpreterProvider.ts b/src/client/interpreter/configuration/interpreterSelector.ts similarity index 91% rename from src/client/interpreter/configuration/setInterpreterProvider.ts rename to src/client/interpreter/configuration/interpreterSelector.ts index 22a2da9aabbc..220f916af4a2 100644 --- a/src/client/interpreter/configuration/setInterpreterProvider.ts +++ b/src/client/interpreter/configuration/interpreterSelector.ts @@ -1,25 +1,25 @@ import * as path from 'path'; import { commands, ConfigurationTarget, Disposable, QuickPickItem, QuickPickOptions, Uri, window, workspace } from 'vscode'; import * as settings from '../../common/configSettings'; +import { Commands } from '../../common/constants'; import { IProcessService } from '../../common/process/types'; import { IInterpreterService, IInterpreterVersionService, PythonInterpreter, WorkspacePythonPath } from '../contracts'; import { ShebangCodeLensProvider } from '../display/shebangCodeLensProvider'; import { PythonPathUpdaterService } from './pythonPathUpdaterService'; import { PythonPathUpdaterServiceFactory } from './pythonPathUpdaterServiceFactory'; -// tslint:disable-next-line:interface-name -interface PythonPathQuickPickItem extends QuickPickItem { +interface IInterpreterQuickPickItem extends QuickPickItem { path: string; } -export class SetInterpreterProvider implements Disposable { +export class InterpreterSelector implements Disposable { private disposables: Disposable[] = []; private pythonPathUpdaterService: PythonPathUpdaterService; constructor(private interpreterManager: IInterpreterService, interpreterVersionService: IInterpreterVersionService, private processService: IProcessService) { - this.disposables.push(commands.registerCommand('python.setInterpreter', this.setInterpreter.bind(this))); - this.disposables.push(commands.registerCommand('python.setShebangInterpreter', this.setShebangInterpreter.bind(this))); + this.disposables.push(commands.registerCommand(Commands.Set_Interpreter, this.setInterpreter.bind(this))); + this.disposables.push(commands.registerCommand(Commands.Set_ShebangInterpreter, this.setShebangInterpreter.bind(this))); this.pythonPathUpdaterService = new PythonPathUpdaterService(new PythonPathUpdaterServiceFactory(), interpreterVersionService); } public dispose() { @@ -38,7 +38,7 @@ export class SetInterpreterProvider implements Disposable { const workspaceFolder = await (window as any).showWorkspaceFolderPick({ placeHolder: 'Select a workspace' }); return workspaceFolder ? { folderUri: workspaceFolder.uri, configTarget: ConfigurationTarget.WorkspaceFolder } : undefined; } - private async suggestionToQuickPickItem(suggestion: PythonInterpreter, workspaceUri?: Uri): Promise { + private async suggestionToQuickPickItem(suggestion: PythonInterpreter, workspaceUri?: Uri): Promise { let detail = suggestion.path; if (workspaceUri && suggestion.path.startsWith(workspaceUri.fsPath)) { detail = `.${path.sep}${path.relative(workspaceUri.fsPath, suggestion.path)}`; diff --git a/src/client/linters/baseLinter.ts b/src/client/linters/baseLinter.ts index 7f491efa8ab8..2c90e5c42731 100644 --- a/src/client/linters/baseLinter.ts +++ b/src/client/linters/baseLinter.ts @@ -1,14 +1,14 @@ import * as path from 'path'; -import { CancellationToken, OutputChannel, TextDocument, Uri } from 'vscode'; import * as vscode from 'vscode'; -import { PythonSettings } from '../common/configSettings'; +import { CancellationToken, OutputChannel, TextDocument, Uri } from 'vscode'; import '../common/extensions'; import { IPythonToolExecutionService } from '../common/process/types'; -import { IPythonSettings } from '../common/types'; -import { ExecutionInfo, IInstaller, ILogger, Product } from '../common/types'; +import { ExecutionInfo, ILogger, Product } from '../common/types'; +import { IConfigurationService, IPythonSettings } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import { ErrorHandler } from './errorHandlers/main'; -import { ILinterHelper, LinterId } from './types'; +import { ErrorHandler } from './errorHandlers/errorHandler'; +import { ILinter, ILinterInfo, ILinterManager, ILintMessage, LintMessageSeverity } from './types'; + // tslint:disable-next-line:no-require-imports no-var-requires const namedRegexp = require('named-js-regexp'); @@ -22,22 +22,6 @@ export interface IRegexGroup { type: string; } -export interface ILintMessage { - line: number; - column: number; - code: string; - message: string; - type: string; - severity?: LintMessageSeverity; - provider: string; -} -export enum LintMessageSeverity { - Hint, - Error, - Warning, - Information -} - export function matchNamedRegEx(data, regex): IRegexGroup | undefined { const compiledRegexp = namedRegexp(regex, 'g'); const rawMatch = compiledRegexp.exec(data); @@ -47,49 +31,50 @@ export function matchNamedRegEx(data, regex): IRegexGroup | undefined { return undefined; } -export abstract class BaseLinter { - public Id: LinterId; + +export abstract class BaseLinter implements ILinter { + protected readonly configService: IConfigurationService; + private errorHandler: ErrorHandler; private _pythonSettings: IPythonSettings; + private _info: ILinterInfo; + protected get pythonSettings(): IPythonSettings { return this._pythonSettings; } - constructor(public product: Product, protected outputChannel: OutputChannel, - protected readonly installer: IInstaller, - protected helper: ILinterHelper, protected logger: ILogger, protected serviceContainer: IServiceContainer, + + constructor(product: Product, + protected readonly outputChannel: OutputChannel, + protected readonly serviceContainer: IServiceContainer, protected readonly columnOffset = 0) { - this.Id = this.helper.translateToId(product); - this.errorHandler = new ErrorHandler(product, installer, helper, logger, outputChannel, serviceContainer); - } - public isEnabled(resource: Uri) { - this._pythonSettings = PythonSettings.getInstance(resource); - const names = this.helper.getSettingsPropertyNames(this.product); - return this._pythonSettings.linting[names.enabledName] as boolean; + this._info = serviceContainer.get(ILinterManager).getLinterInfo(product); + this.errorHandler = new ErrorHandler(this.info.product, outputChannel, serviceContainer); + this.configService = serviceContainer.get(IConfigurationService); } - public linterArgs(resource: Uri) { - this._pythonSettings = PythonSettings.getInstance(resource); - const names = this.helper.getSettingsPropertyNames(this.product); - return this._pythonSettings.linting[names.argsName] as string[]; + + public get info(): ILinterInfo { + return this._info; } + public isLinterExecutableSpecified(resource: Uri) { - this._pythonSettings = PythonSettings.getInstance(resource); - const names = this.helper.getSettingsPropertyNames(this.product); - const executablePath = this._pythonSettings.linting[names.pathName] as string; + const executablePath = this.info.pathName(resource); return path.basename(executablePath).length > 0 && path.basename(executablePath) !== executablePath; } public async lint(document: vscode.TextDocument, cancellation: vscode.CancellationToken): Promise { - if (!this.isEnabled(document.uri)) { - return []; - } - this._pythonSettings = PythonSettings.getInstance(document.uri); + this._pythonSettings = this.configService.getSettings(document.uri); return this.runLinter(document, cancellation); } + protected getWorkspaceRootPath(document: vscode.TextDocument): string { const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri); const workspaceRootPath = (workspaceFolder && typeof workspaceFolder.uri.fsPath === 'string') ? workspaceFolder.uri.fsPath : undefined; return typeof workspaceRootPath === 'string' ? workspaceRootPath : __dirname; } + protected get logger(): ILogger { + return this.serviceContainer.get(ILogger); + } protected abstract runLinter(document: vscode.TextDocument, cancellation: vscode.CancellationToken): Promise; + // tslint:disable-next-line:no-any protected parseMessagesSeverity(error: string, categorySeverity: any): LintMessageSeverity { if (categorySeverity[error]) { @@ -111,11 +96,14 @@ export abstract class BaseLinter { } } } - return LintMessageSeverity.Information; } + protected async run(args: string[], document: vscode.TextDocument, cancellation: vscode.CancellationToken, regEx: string = REGEX): Promise { - const executionInfo = this.helper.getExecutionInfo(this.product, args, document.uri); + if (!this.info.isEnabled(document.uri)) { + return []; + } + const executionInfo = this.info.getExecutionInfo(args, document.uri); const cwd = this.getWorkspaceRootPath(document); const pythonToolsExecutionService = this.serviceContainer.get(IPythonToolExecutionService); try { @@ -127,10 +115,12 @@ export abstract class BaseLinter { return []; } } + protected async parseMessages(output: string, document: TextDocument, token: CancellationToken, regEx: string) { const outputLines = output.splitLines({ removeEmptyEntries: false, trim: false }); return this.parseLines(outputLines, regEx); } + protected handleError(error: Error, resource: Uri, execInfo: ExecutionInfo) { this.errorHandler.handleError(error, resource, execInfo) .catch(this.logger.logError.bind(this, 'Error in errorHandler.handleError')); @@ -153,9 +143,10 @@ export abstract class BaseLinter { column: isNaN(match.column) || match.column === 0 ? 0 : match.column - this.columnOffset, line: match.line, type: match.type, - provider: this.Id + provider: this.info.id }; } + private parseLines(outputLines: string[], regEx: string): ILintMessage[] { return outputLines .filter((value, index) => index <= this.pythonSettings.linting.maxNumberOfProblems) @@ -166,15 +157,16 @@ export abstract class BaseLinter { return msg; } } catch (ex) { - this.logger.logError(`Linter '${this.Id}' failed to parse the line '${line}.`, ex); + this.logger.logError(`Linter '${this.info.id}' failed to parse the line '${line}.`, ex); } return; }) .filter(item => item !== undefined) .map(item => item!); } + private displayLinterResultHeader(data: string) { - this.outputChannel.append(`${'#'.repeat(10)}Linting Output - ${this.Id}${'#'.repeat(10)}\n`); + this.outputChannel.append(`${'#'.repeat(10)}Linting Output - ${this.info.id}${'#'.repeat(10)}\n`); this.outputChannel.append(data); } } diff --git a/src/client/linters/errorHandlers/baseErrorHandler.ts b/src/client/linters/errorHandlers/baseErrorHandler.ts index eace0002477b..994b6c0f0160 100644 --- a/src/client/linters/errorHandlers/baseErrorHandler.ts +++ b/src/client/linters/errorHandlers/baseErrorHandler.ts @@ -4,14 +4,17 @@ import { OutputChannel, Uri } from 'vscode'; import { ExecutionInfo, IInstaller, ILogger, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; -import { IErrorHandler, ILinterHelper } from '../types'; +import { IErrorHandler } from '../types'; export abstract class BaseErrorHandler implements IErrorHandler { + protected logger: ILogger; + protected installer: IInstaller; + private handler: IErrorHandler; - constructor(protected product: Product, protected installer: IInstaller, - protected helper: ILinterHelper, protected logger: ILogger, - protected outputChannel: OutputChannel, protected serviceContainer: IServiceContainer) { + constructor(protected product: Product, protected outputChannel: OutputChannel, protected serviceContainer: IServiceContainer) { + this.logger = this.serviceContainer.get(ILogger); + this.installer = this.serviceContainer.get(IInstaller); } protected get nextHandler() { return this.handler; diff --git a/src/client/linters/errorHandlers/main.ts b/src/client/linters/errorHandlers/errorHandler.ts similarity index 58% rename from src/client/linters/errorHandlers/main.ts rename to src/client/linters/errorHandlers/errorHandler.ts index abf41ba1e1cd..5c2311bd8176 100644 --- a/src/client/linters/errorHandlers/main.ts +++ b/src/client/linters/errorHandlers/errorHandler.ts @@ -1,19 +1,17 @@ import { OutputChannel, Uri } from 'vscode'; import { ExecutionInfo, IInstaller, ILogger, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; -import { IErrorHandler, ILinterHelper } from '../types'; +import { IErrorHandler, ILinterInfo } from '../types'; import { BaseErrorHandler } from './baseErrorHandler'; -import { ModuleNotInstalledErrorHandler } from './notInstalled'; +import { NotInstalledErrorHandler } from './notInstalled'; import { StandardErrorHandler } from './standard'; export class ErrorHandler implements IErrorHandler { private handler: BaseErrorHandler; - constructor(product: Product, installer: IInstaller, - helper: ILinterHelper, logger: ILogger, - outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + constructor(product: Product, outputChannel: OutputChannel, serviceContainer: IServiceContainer) { // Create chain of handlers. - const standardErrorHandler = new StandardErrorHandler(product, installer, helper, logger, outputChannel, serviceContainer); - this.handler = new ModuleNotInstalledErrorHandler(product, installer, helper, logger, outputChannel, serviceContainer); + const standardErrorHandler = new StandardErrorHandler(product, outputChannel, serviceContainer); + this.handler = new NotInstalledErrorHandler(product, outputChannel, serviceContainer); this.handler.setNextHandler(standardErrorHandler); } diff --git a/src/client/linters/errorHandlers/notInstalled.ts b/src/client/linters/errorHandlers/notInstalled.ts index 50f8686a4fc3..3ffd90363c58 100644 --- a/src/client/linters/errorHandlers/notInstalled.ts +++ b/src/client/linters/errorHandlers/notInstalled.ts @@ -1,22 +1,16 @@ import { OutputChannel, Uri } from 'vscode'; import { isNotInstalledError } from '../../common/helpers'; import { IPythonExecutionFactory } from '../../common/process/types'; -import { ExecutionInfo, IInstaller, ILogger, Product } from '../../common/types'; +import { ExecutionInfo, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; -import { ILinterHelper } from '../types'; +import { ILinterManager } from '../types'; import { BaseErrorHandler } from './baseErrorHandler'; -export class ModuleNotInstalledErrorHandler extends BaseErrorHandler { - constructor(product: Product, installer: IInstaller, - helper: ILinterHelper, logger: ILogger, - outputChannel: OutputChannel, serviceContainer: IServiceContainer) { - super(product, installer, helper, logger, outputChannel, serviceContainer); +export class NotInstalledErrorHandler extends BaseErrorHandler { + constructor(product: Product, outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(product, outputChannel, serviceContainer); } public async handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise { - if (!isNotInstalledError(error) || !execInfo.moduleName) { - return this.nextHandler ? await this.nextHandler.handleError(error, resource, execInfo) : false; - } - const pythonExecutionService = await this.serviceContainer.get(IPythonExecutionFactory).create(resource); const isModuleInstalled = await pythonExecutionService.isModuleInstalled(execInfo.moduleName!); if (isModuleInstalled) { @@ -26,8 +20,9 @@ export class ModuleNotInstalledErrorHandler extends BaseErrorHandler { this.installer.promptToInstall(this.product, resource) .catch(this.logger.logError.bind(this, 'NotInstalledErrorHandler.promptToInstall')); - const id = this.helper.translateToId(execInfo.product!); - const customError = `Linting with ${id} failed.\nYou could either install the '${id}' linter or turn it off in setings.json via "python.linting.${id}Enabled = false".`; + const linterManager = this.serviceContainer.get(ILinterManager); + const info = linterManager.getLinterInfo(execInfo.product!); + const customError = `Linter '${info.id}' is not installed. Please install it or select another linter".`; this.outputChannel.appendLine(`\n${customError}\n${error}`); this.logger.logWarning(customError, error); return true; diff --git a/src/client/linters/errorHandlers/standard.ts b/src/client/linters/errorHandlers/standard.ts index 15907311137c..3db392bd0c3a 100644 --- a/src/client/linters/errorHandlers/standard.ts +++ b/src/client/linters/errorHandlers/standard.ts @@ -1,44 +1,31 @@ import { OutputChannel, Uri, window } from 'vscode'; -import { ExecutionInfo, IInstaller, ILogger, Product } from '../../common/types'; +import { ExecutionInfo, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; -import { ILinterHelper, LinterId } from '../types'; +import { ILinterManager, LinterId } from '../types'; import { BaseErrorHandler } from './baseErrorHandler'; export class StandardErrorHandler extends BaseErrorHandler { - constructor(product: Product, installer: IInstaller, - helper: ILinterHelper, logger: ILogger, - outputChannel: OutputChannel, serviceContainer: IServiceContainer) { - super(product, installer, helper, logger, outputChannel, serviceContainer); + constructor(product: Product, outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(product, outputChannel, serviceContainer); } public async handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise { if (typeof error === 'string' && (error as string).indexOf('OSError: [Errno 2] No such file or directory: \'/') > 0) { return this.nextHandler ? this.nextHandler.handleError(error, resource, execInfo) : Promise.resolve(false); } - const linterId = this.helper.translateToId(execInfo.product!); - this.logger.logError(`There was an error in running the linter ${linterId}`, error); - this.outputChannel.appendLine(`Linting with ${linterId} failed.`); + const linterManager = this.serviceContainer.get(ILinterManager); + const info = linterManager.getLinterInfo(execInfo.product!); + + this.logger.logError(`There was an error in running the linter ${info.id}`, error); + this.outputChannel.appendLine(`Linting with ${info.id} failed.`); this.outputChannel.appendLine(error.toString()); - this.displayLinterError(linterId, resource); + this.displayLinterError(info.id, resource); return true; } private async displayLinterError(linterId: LinterId, resource: Uri) { const message = `There was an error in running the linter '${linterId}'`; - const item = await window.showErrorMessage(message, 'Disable linter', 'View Errors'); - switch (item) { - case 'Disable linter': { - this.installer.disableLinter(this.product, resource) - .catch(this.logger.logError.bind(this, 'StandardErrorHandler.displayLinterError')); - break; - } - case 'View Errors': { - this.outputChannel.show(); - break; - } - default: { - // Ignore this selection (e.g. user hit cancel). - } - } + await window.showErrorMessage(message, 'View Errors'); + this.outputChannel.show(); } } diff --git a/src/client/linters/flake8.ts b/src/client/linters/flake8.ts index 1edd736872d8..efc00becf9a9 100644 --- a/src/client/linters/flake8.ts +++ b/src/client/linters/flake8.ts @@ -1,18 +1,18 @@ import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage } from './types'; const COLUMN_OFF_SET = 1; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.flake8, outputChannel, installer, helper, logger, serviceContainer, COLUMN_OFF_SET); +export class Flake8 extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.flake8, outputChannel, serviceContainer, COLUMN_OFF_SET); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { const messages = await this.run(['--format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s', document.uri.fsPath], document, cancellation); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.flake8CategorySeverity); diff --git a/src/client/linters/helper.ts b/src/client/linters/helper.ts deleted file mode 100644 index f0692400cdc9..000000000000 --- a/src/client/linters/helper.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { injectable } from 'inversify'; -import * as path from 'path'; -import { Uri } from 'vscode'; -import { PythonSettings } from '../common/configSettings'; -import { ILintingSettings } from '../common/types'; -import { ExecutionInfo, Product } from '../common/types'; -import { ILinterHelper, LinterId, LinterSettingsPropertyNames } from './types'; - -@injectable() -export class LinterHelper implements ILinterHelper { - private linterIdMapping: Map; - constructor() { - this.linterIdMapping = new Map(); - - this.linterIdMapping.set(Product.flake8, 'flake8'); - this.linterIdMapping.set(Product.mypy, 'mypy'); - this.linterIdMapping.set(Product.pep8, 'pep8'); - this.linterIdMapping.set(Product.prospector, 'prospector'); - this.linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); - this.linterIdMapping.set(Product.pylama, 'pylama'); - this.linterIdMapping.set(Product.pylint, 'pylint'); - } - public getExecutionInfo(linter: Product, customArgs: string[], resource?: Uri): ExecutionInfo { - const settings = PythonSettings.getInstance(resource); - const names = this.getSettingsPropertyNames(linter); - - const execPath = settings.linting[names.pathName] as string; - let args: string[] = Array.isArray(settings.linting[names.argsName]) ? settings.linting[names.argsName] as string[] : []; - args = args.concat(customArgs); - - let moduleName: string | undefined; - - // If path information is not available, then treat it as a module, - // Except for prospector as that needs to be run as an executable (its a python package). - if (path.basename(execPath) === execPath && linter !== Product.prospector) { - moduleName = execPath; - } - - return { execPath, moduleName, args, product: linter }; - } - public translateToId(linter: Product): LinterId { - if (this.linterIdMapping.has(linter)) { - return this.linterIdMapping.get(linter)!; - } - throw new Error('Invalid linter'); - } - public getSettingsPropertyNames(linter: Product): LinterSettingsPropertyNames { - const id = this.translateToId(linter); - return { - argsName: `${id}Args` as keyof ILintingSettings, - pathName: `${id}Path` as keyof ILintingSettings, - enabledName: `${id}Enabled` as keyof ILintingSettings - }; - } -} diff --git a/src/client/linters/linterCommands.ts b/src/client/linters/linterCommands.ts new file mode 100644 index 000000000000..613ea5a42c54 --- /dev/null +++ b/src/client/linters/linterCommands.ts @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as vscode from 'vscode'; +import { IApplicationShell, ICommandManager } from '../common/application/types'; +import { Commands } from '../common/constants'; +import { IServiceContainer } from '../ioc/types'; +import { ILinterManager } from './types'; + +export class LinterCommands implements vscode.Disposable { + private disposables: vscode.Disposable[] = []; + private linterManager: ILinterManager; + private appShell: IApplicationShell; + + constructor(private serviceContainer: IServiceContainer) { + this.linterManager = this.serviceContainer.get(ILinterManager); + this.appShell = this.serviceContainer.get(IApplicationShell); + + const commandManager = this.serviceContainer.get(ICommandManager); + commandManager.registerCommand(Commands.Set_Linter, this.setLinterAsync.bind(this)); + commandManager.registerCommand(Commands.Enable_Linter, this.enableLintingAsync.bind(this)); + } + public dispose() { + this.disposables.forEach(disposable => disposable.dispose()); + } + + public async setLinterAsync(): Promise { + const linters = this.linterManager.getAllLinterInfos(); + const suggestions = linters.map(x => x.id).sort(); + const activeLinters = this.linterManager.getActiveLinters(this.settingsUri); + + let current: string; + switch (activeLinters.length) { + case 0: + current = 'none'; + break; + case 1: + current = activeLinters[0].id; + break; + default: + current = 'multiple selected'; + break; + } + + const quickPickOptions: vscode.QuickPickOptions = { + matchOnDetail: true, + matchOnDescription: true, + placeHolder: `current: ${current}` + }; + + const selection = await this.appShell.showQuickPick(suggestions, quickPickOptions); + if (selection !== undefined) { + const index = linters.findIndex(x => x.id === selection); + if (activeLinters.length > 1) { + const response = await this.appShell.showWarningMessage(`Multiple linters are enabled in settings. Replace with '${selection}'?`, 'Yes', 'No'); + if (response !== 'Yes') { + return; + } + } + await this.linterManager.setActiveLintersAsync([linters[index].product], this.settingsUri); + } + } + + public async enableLintingAsync(): Promise { + const options = ['on', 'off']; + const current = this.linterManager.isLintingEnabled(this.settingsUri) ? options[0] : options[1]; + + const quickPickOptions: vscode.QuickPickOptions = { + matchOnDetail: true, + matchOnDescription: true, + placeHolder: `current: ${current}` + }; + + const selection = await this.appShell.showQuickPick(options, quickPickOptions); + if (selection !== undefined) { + const enable = selection === options[0]; + await this.linterManager.enableLintingAsync(enable, this.settingsUri); + } + } + + private get settingsUri(): vscode.Uri | undefined { + return vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : undefined; + } +} diff --git a/src/client/linters/linterInfo.ts b/src/client/linters/linterInfo.ts new file mode 100644 index 000000000000..f6af6a7cc0eb --- /dev/null +++ b/src/client/linters/linterInfo.ts @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as path from 'path'; +import { Uri } from 'vscode'; +import { ExecutionInfo, IConfigurationService, Product } from '../common/types'; +import { ILinterInfo, LinterId } from './types'; + +export class LinterInfo implements ILinterInfo { + private _id: LinterId; + private _product: Product; + + constructor(product: Product, id: LinterId, private configService: IConfigurationService) { + this._product = product; + this._id = id; + } + + public get id(): LinterId { + return this._id; + } + public get product(): Product { + return this._product; + } + + public get pathSettingName(): string { + return `${this.id}Path`; + } + public get argsSettingName(): string { + return `${this.id}Args`; + } + public get enabledSettingName(): string { + return `${this.id}Enabled`; + } + + public async enableAsync(enabled: boolean, resource?: Uri): Promise { + return this.configService.updateSettingAsync(`linting.${this.enabledSettingName}`, enabled, resource); + } + public isEnabled(resource?: Uri): boolean { + const settings = this.configService.getSettings(resource); + return settings.linting[this.enabledSettingName] as boolean; + } + + public pathName(resource?: Uri): string { + const settings = this.configService.getSettings(resource); + return settings.linting[this.pathSettingName] as string; + } + public linterArgs(resource?: Uri): string[] { + const settings = this.configService.getSettings(resource); + const args = settings.linting[this.argsSettingName]; + return Array.isArray(args) ? args as string[] : []; + } + public getExecutionInfo(customArgs: string[], resource?: Uri): ExecutionInfo { + const execPath = this.pathName(resource); + const args = this.linterArgs(resource).concat(customArgs); + let moduleName: string | undefined; + + // If path information is not available, then treat it as a module, + // Except for prospector as that needs to be run as an executable (its a python package). + if (path.basename(execPath) === execPath) { + moduleName = execPath; + } + + return { execPath, moduleName, args, product: this.product }; + } +} diff --git a/src/client/linters/linterManager.ts b/src/client/linters/linterManager.ts new file mode 100644 index 000000000000..2a809762ecd3 --- /dev/null +++ b/src/client/linters/linterManager.ts @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { inject, injectable } from 'inversify'; +import { CancellationToken, OutputChannel, TextDocument, Uri } from 'vscode'; +import { IConfigurationService, ILogger, Product } from '../common/types'; +import { IServiceContainer } from '../ioc/types'; +import { Flake8 } from './flake8'; +import { LinterInfo } from './linterInfo'; +import { MyPy } from './mypy'; +import { Pep8 } from './pep8'; +import { Prospector } from './prospector'; +import { PyDocStyle } from './pydocstyle'; +import { PyLama } from './pylama'; +import { Pylint } from './pylint'; +import { ILinter, ILinterInfo, ILinterManager, ILintMessage } from './types'; + +class DisabledLinter implements ILinter { + constructor(private configService: IConfigurationService) { } + public get info() { + return new LinterInfo(Product.pylint, 'pylint', this.configService); + } + public async lint(document: TextDocument, cancellation: CancellationToken): Promise { + return []; + } +} + +@injectable() +export class LinterManager implements ILinterManager { + private lintingEnabledSettingName = 'enabled'; + private linters: ILinterInfo[]; + private configService: IConfigurationService; + private disabledForCurrentSession = false; + + constructor( @inject(IServiceContainer) serviceContainer: IServiceContainer) { + this.configService = serviceContainer.get(IConfigurationService); + this.linters = [ + new LinterInfo(Product.flake8, 'flake8', this.configService), + new LinterInfo(Product.pylint, 'pylint', this.configService), + new LinterInfo(Product.mypy, 'mypy', this.configService), + new LinterInfo(Product.pep8, 'pep8', this.configService), + new LinterInfo(Product.prospector, 'prospector', this.configService), + new LinterInfo(Product.pydocstyle, 'pydocstyle', this.configService), + new LinterInfo(Product.pylama, 'pylama', this.configService) + ]; + } + + public getAllLinterInfos(): ILinterInfo[] { + return this.linters; + } + + public getLinterInfo(product: Product): ILinterInfo { + const x = this.linters.findIndex((value, index, obj) => value.product === product); + if (x >= 0) { + return this.linters[x]; + } + throw new Error('Invalid linter'); + } + + public isLintingEnabled(resource?: Uri): boolean { + if (this.disabledForCurrentSession) { + return false; + } + const settings = this.configService.getSettings(resource); + return (settings.linting[this.lintingEnabledSettingName] as boolean) && this.getActiveLinters(resource).length > 0; + } + + public async enableLintingAsync(enable: boolean, resource?: Uri): Promise { + if (enable) { + this.disabledForCurrentSession = false; + } + + await this.configService.updateSettingAsync(`linting.${this.lintingEnabledSettingName}`, enable, resource); + + // If nothing is enabled, fix it up to PyLint (default). + if (enable && this.getActiveLinters(resource).length === 0) { + await this.setActiveLintersAsync([Product.pylint], resource); + } + } + + public disableSessionLinting(): void { + this.disabledForCurrentSession = true; + } + + public getActiveLinters(resource?: Uri): ILinterInfo[] { + return this.linters.filter(x => x.isEnabled(resource)); + } + + public async setActiveLintersAsync(products: Product[], resource?: Uri): Promise { + const active = this.getActiveLinters(resource); + for (const x of active) { + await x.enableAsync(false, resource); + } + if (products.length > 0) { + const toActivate = this.linters.filter(x => products.findIndex(p => x.product === p) >= 0); + for (const x of toActivate) { + await x.enableAsync(true, resource); + } + await this.enableLintingAsync(true, resource); + } + } + + public createLinter(product: Product, outputChannel: OutputChannel, serviceContainer: IServiceContainer, resource?: Uri): ILinter { + if (!this.isLintingEnabled(resource)) { + return new DisabledLinter(this.configService); + } + const error = 'Linter manager: Unknown linter'; + switch (product) { + case Product.flake8: + return new Flake8(outputChannel, serviceContainer); + case Product.pylint: + return new Pylint(outputChannel, serviceContainer); + case Product.mypy: + return new MyPy(outputChannel, serviceContainer); + case Product.prospector: + return new Prospector(outputChannel, serviceContainer); + case Product.pylama: + return new PyLama(outputChannel, serviceContainer); + case Product.pydocstyle: + return new PyDocStyle(outputChannel, serviceContainer); + case Product.pep8: + return new Pep8(outputChannel, serviceContainer); + default: + serviceContainer.get(ILogger).logError(error); + break; + } + throw new Error(error); + } +} diff --git a/src/client/linters/mypy.ts b/src/client/linters/mypy.ts index 53d32f25f3e9..15c8046a08d3 100644 --- a/src/client/linters/mypy.ts +++ b/src/client/linters/mypy.ts @@ -1,18 +1,18 @@ import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage } from './types'; const REGEX = '(?.py):(?\\d+): (?\\w+): (?.*)\\r?(\\n|$)'; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.mypy, outputChannel, installer, helper, logger, serviceContainer); +export class MyPy extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.mypy, outputChannel, serviceContainer); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { const messages = await this.run([document.uri.fsPath], document, cancellation, REGEX); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.mypyCategorySeverity); diff --git a/src/client/linters/pep8Linter.ts b/src/client/linters/pep8.ts similarity index 53% rename from src/client/linters/pep8Linter.ts rename to src/client/linters/pep8.ts index 921452436711..24bcaa9abeb2 100644 --- a/src/client/linters/pep8Linter.ts +++ b/src/client/linters/pep8.ts @@ -1,18 +1,18 @@ import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage } from './types'; const COLUMN_OFF_SET = 1; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.pep8, outputChannel, installer, helper, logger, serviceContainer, COLUMN_OFF_SET); +export class Pep8 extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.pep8, outputChannel, serviceContainer, COLUMN_OFF_SET); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { const messages = await this.run(['--format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s', document.uri.fsPath], document, cancellation); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pep8CategorySeverity); diff --git a/src/client/linters/prospector.ts b/src/client/linters/prospector.ts index bfa2267d78e3..930fa91c458a 100644 --- a/src/client/linters/prospector.ts +++ b/src/client/linters/prospector.ts @@ -1,9 +1,9 @@ import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage } from './types'; interface IProspectorResponse { messages: IProspectorMessage[]; @@ -22,12 +22,12 @@ interface IProspectorLocation { module: 'beforeFormat'; } -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.prospector, outputChannel, installer, helper, logger, serviceContainer); +export class Prospector extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.prospector, outputChannel, serviceContainer); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { return await this.run(['--absolute-paths', '--output-format=json', document.uri.fsPath], document, cancellation); } protected async parseMessages(output: string, document: TextDocument, token: CancellationToken, regEx: string) { @@ -35,7 +35,7 @@ export class Linter extends baseLinter.BaseLinter { try { parsedData = JSON.parse(output); } catch (ex) { - this.outputChannel.appendLine(`${'#'.repeat(10)}Linting Output - ${this.Id}${'#'.repeat(10)}`); + this.outputChannel.appendLine(`${'#'.repeat(10)}Linting Output - ${this.info.id}${'#'.repeat(10)}`); this.outputChannel.append(output); this.logger.logError('Failed to parse Prospector output', ex); return []; @@ -52,7 +52,7 @@ export class Linter extends baseLinter.BaseLinter { column: msg.location.character, line: lineNumber, type: msg.code, - provider: `${this.Id} - ${msg.source}` + provider: `${this.info.id} - ${msg.source}` }; }); } diff --git a/src/client/linters/pydocstyle.ts b/src/client/linters/pydocstyle.ts index 09116b8aa2b5..f0b05bb16726 100644 --- a/src/client/linters/pydocstyle.ts +++ b/src/client/linters/pydocstyle.ts @@ -1,23 +1,22 @@ import * as path from 'path'; import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; import { IS_WINDOWS } from './../common/utils'; -import * as baseLinter from './baseLinter'; -import { ILintMessage } from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage, LintMessageSeverity } from './types'; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.pydocstyle, outputChannel, installer, helper, logger, serviceContainer); +export class PyDocStyle extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.pydocstyle, outputChannel, serviceContainer); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { const messages = await this.run([document.uri.fsPath], document, cancellation); // All messages in pep8 are treated as warnings for now. messages.forEach(msg => { - msg.severity = baseLinter.LintMessageSeverity.Warning; + msg.severity = LintMessageSeverity.Warning; }); return messages; @@ -68,7 +67,7 @@ export class Linter extends baseLinter.BaseLinter { column: sourceStart, line: lineNumber, type: '', - provider: this.Id + provider: this.info.id } as ILintMessage; } catch (ex) { this.logger.logError(`Failed to parse pydocstyle line '${line}'`, ex); diff --git a/src/client/linters/pylama.ts b/src/client/linters/pylama.ts index 55524f3d161b..ab29fd9c55ec 100644 --- a/src/client/linters/pylama.ts +++ b/src/client/linters/pylama.ts @@ -1,23 +1,23 @@ import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage, LintMessageSeverity } from './types'; const REGEX = '(?.py):(?\\d+):(?\\d+): \\[(?\\w+)\\] (?\\w\\d+):? (?.*)\\r?(\\n|$)'; const COLUMN_OFF_SET = 1; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.pylama, outputChannel, installer, helper, logger, serviceContainer, COLUMN_OFF_SET); +export class PyLama extends BaseLinter { + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.pylama, outputChannel, serviceContainer, COLUMN_OFF_SET); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { const messages = await this.run(['--format=parsable', document.uri.fsPath], document, cancellation, REGEX); // All messages in pylama are treated as warnings for now. messages.forEach(msg => { - msg.severity = baseLinter.LintMessageSeverity.Warning; + msg.severity = LintMessageSeverity.Warning; }); return messages; diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts index 099315a5e460..c650714e45dd 100644 --- a/src/client/linters/pylint.ts +++ b/src/client/linters/pylint.ts @@ -1,21 +1,107 @@ + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as path from 'path'; import { OutputChannel } from 'vscode'; import { CancellationToken, TextDocument } from 'vscode'; -import { IInstaller, ILogger, Product } from '../common/types'; +import { IFileSystem, IPlatformService } from '../common/platform/types'; +import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as baseLinter from './baseLinter'; -import { ILinterHelper } from './types'; +import { BaseLinter } from './baseLinter'; +import { ILintMessage } from './types'; + +export class Pylint extends BaseLinter { + private fileSystem: IFileSystem; + private platformService: IPlatformService; -export class Linter extends baseLinter.BaseLinter { - constructor(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer) { - super(Product.pylint, outputChannel, installer, helper, logger, serviceContainer); + constructor(outputChannel: OutputChannel, serviceContainer: IServiceContainer) { + super(Product.pylint, outputChannel, serviceContainer); + this.fileSystem = serviceContainer.get(IFileSystem); + this.platformService = serviceContainer.get(IPlatformService); } - protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { - const messages = await this.run(['--msg-template=\'{line},{column},{category},{msg_id}:{msg}\'', '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); + protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { + let minArgs: string[] = []; + // Only use minimal checkers if + // a) there are no custom arguments and + // b) there is no pylintrc file + const uri = document.uri; + const settings = this.configService.getSettings(uri); + if (settings.linting.pylintUseMinimalCheckers + && this.info.linterArgs(uri).length === 0 + && !await Pylint.hasConfigurationFile(this.fileSystem, uri.fsPath, this.platformService)) { + minArgs = [ + '--disable=all', + '--enable=F,E,unreachable,duplicate-key,unnecessary-semicolon,global-variable-not-assigned,unused-variable,unused-wildcard-import,binary-op-exception,bad-format-string,anomalous-backslash-in-string,bad-open-mode' + ]; + } + const args = [ + '--msg-template=\'{line},{column},{category},{msg_id}:{msg}\'', + '--reports=n', + '--output-format=text', + uri.fsPath + ]; + const messages = await this.run(minArgs.concat(args), document, cancellation); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pylintCategorySeverity); }); return messages; } + + // tslint:disable-next-line:member-ordering + public static async hasConfigurationFile(fs: IFileSystem, filePath: string, platformService: IPlatformService): Promise { + // https://pylint.readthedocs.io/en/latest/user_guide/run.html + // https://github.com/PyCQA/pylint/blob/975e08148c0faa79958b459303c47be1a2e1500a/pylint/config.py + // 1. pylintrc in the current working directory + // 2. .pylintrc in the current working directory + // 3. If the current working directory is in a Python module, Pylint searches + // up the hierarchy of Python modules until it finds a pylintrc file. + // This allows you to specify coding standards on a module by module basis. + // A directory is judged to be a Python module if it contains an __init__.py file. + // 4. The file named by environment variable PYLINTRC + // 5. if you have a home directory which isn’t /root: + // a) .pylintrc in your home directory + // b) .config/pylintrc in your home directory + // 6. /etc/pylintrc + if (process.env.PYLINTRC) { + return true; + } + + let dir = path.dirname(filePath); + const pylintrc = 'pylintrc'; + const dotPylintrc = '.pylintrc'; + if (await fs.fileExistsAsync(path.join(dir, pylintrc)) || await fs.fileExistsAsync(path.join(dir, dotPylintrc))) { + return true; + } + + let current = dir; + let above = path.dirname(dir); + do { + if (!await fs.fileExistsAsync(path.join(current, '__init__.py'))) { + break; + } + if (await fs.fileExistsAsync(path.join(current, pylintrc)) || await fs.fileExistsAsync(path.join(current, dotPylintrc))) { + return true; + } + current = above; + above = path.dirname(above); + } while (current !== above); + + dir = path.resolve('~'); + if (await fs.fileExistsAsync(path.join(dir, dotPylintrc))) { + return true; + } + if (await fs.fileExistsAsync(path.join(dir, '.config', pylintrc))) { + return true; + } + + if (!platformService.isWindows) { + if (await fs.fileExistsAsync(path.join('/etc', pylintrc))) { + return true; + } + } + return false; + } } diff --git a/src/client/linters/serviceRegistry.ts b/src/client/linters/serviceRegistry.ts index 8ca230d32e9b..963b1b06d76a 100644 --- a/src/client/linters/serviceRegistry.ts +++ b/src/client/linters/serviceRegistry.ts @@ -2,9 +2,9 @@ // Licensed under the MIT License. import { IServiceManager } from '../ioc/types'; -import { LinterHelper } from './helper'; -import { ILinterHelper } from './types'; +import { LinterManager } from './linterManager'; +import { ILinterManager } from './types'; export function registerTypes(serviceManager: IServiceManager) { - serviceManager.addSingleton(ILinterHelper, LinterHelper); + serviceManager.addSingleton(ILinterManager, LinterManager); } diff --git a/src/client/linters/types.ts b/src/client/linters/types.ts index e8a1155f3cef..2c9ef1e8562f 100644 --- a/src/client/linters/types.ts +++ b/src/client/linters/types.ts @@ -1,25 +1,58 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { Uri } from 'vscode'; -import { ExecutionInfo, ILintingSettings, Product } from '../common/types'; +import * as vscode from 'vscode'; +import { ExecutionInfo, Product } from '../common/types'; +import { IServiceContainer } from '../ioc/types'; export interface IErrorHandler { - handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise; + handleError(error: Error, resource: vscode.Uri, execInfo: ExecutionInfo): Promise; } -export const ILinterHelper = Symbol('ILinterHelper'); - export type LinterId = 'flake8' | 'mypy' | 'pep8' | 'prospector' | 'pydocstyle' | 'pylama' | 'pylint'; -export type LinterSettingsPropertyNames = { - enabledName: keyof ILintingSettings; - argsName: keyof ILintingSettings; - pathName: keyof ILintingSettings; -}; +export interface ILinterInfo { + readonly id: LinterId; + readonly product: Product; + readonly pathSettingName: string; + readonly argsSettingName: string; + readonly enabledSettingName: string; + enableAsync(flag: boolean, resource?: vscode.Uri): Promise; + isEnabled(resource?: vscode.Uri): boolean; + pathName(resource?: vscode.Uri): string; + linterArgs(resource?: vscode.Uri): string[]; + getExecutionInfo(customArgs: string[], resource?: vscode.Uri): ExecutionInfo; +} + +export interface ILinter { + readonly info: ILinterInfo; + lint(document: vscode.TextDocument, cancellation: vscode.CancellationToken): Promise; +} -export interface ILinterHelper { - getExecutionInfo(linter: Product, customArgs: string[], resource?: Uri): ExecutionInfo; - translateToId(linter: Product): LinterId; - getSettingsPropertyNames(linter: Product): LinterSettingsPropertyNames; +export const ILinterManager = Symbol('ILinterManager'); +export interface ILinterManager { + getAllLinterInfos(): ILinterInfo[]; + getLinterInfo(product: Product): ILinterInfo; + getActiveLinters(resource?: vscode.Uri): ILinterInfo[]; + isLintingEnabled(resource?: vscode.Uri): boolean; + enableLintingAsync(enable: boolean, resource?: vscode.Uri): Promise; + disableSessionLinting(): void; + setActiveLintersAsync(products: Product[], resource?: vscode.Uri): Promise; + createLinter(product: Product, outputChannel: vscode.OutputChannel, serviceContainer: IServiceContainer, resource?: vscode.Uri): ILinter; +} + +export interface ILintMessage { + line: number; + column: number; + code: string; + message: string; + type: string; + severity?: LintMessageSeverity; + provider: string; +} +export enum LintMessageSeverity { + Hint, + Error, + Warning, + Information } diff --git a/src/client/providers/completionProvider.ts b/src/client/providers/completionProvider.ts index 7f02343f60d6..ba18829db73d 100644 --- a/src/client/providers/completionProvider.ts +++ b/src/client/providers/completionProvider.ts @@ -1,7 +1,8 @@ 'use strict'; import * as vscode from 'vscode'; -import { isTestExecution } from '../common/configSettings'; +import { IConfigurationService } from '../common/types'; +import { IServiceContainer } from '../ioc/types'; import { JediFactory } from '../languageServices/jediProxyFactory'; import { captureTelemetry } from '../telemetry'; import { COMPLETION } from '../telemetry/constants'; @@ -9,16 +10,18 @@ import { CompletionSource } from './completionSource'; export class PythonCompletionItemProvider implements vscode.CompletionItemProvider { private completionSource: CompletionSource; + private configService: IConfigurationService; - constructor(jediFactory: JediFactory) { + constructor(jediFactory: JediFactory, serviceContainer: IServiceContainer) { this.completionSource = new CompletionSource(jediFactory); + this.configService = serviceContainer.get(IConfigurationService); } @captureTelemetry(COMPLETION) public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { const items = await this.completionSource.getVsCodeCompletionItems(document, position, token); - if (isTestExecution()) { + if (this.configService.isTestExecution()) { for (let i = 0; i < Math.min(3, items.length); i += 1) { items[i] = await this.resolveCompletionItem(items[i], token); } diff --git a/src/client/providers/lintProvider.ts b/src/client/providers/linterProvider.ts similarity index 70% rename from src/client/providers/lintProvider.ts rename to src/client/providers/linterProvider.ts index 452bee68cdb3..522f383cb5d5 100644 --- a/src/client/providers/lintProvider.ts +++ b/src/client/providers/linterProvider.ts @@ -5,31 +5,24 @@ import { ConfigurationTarget, Uri, workspace } from 'vscode'; import { ConfigSettingMonitor } from '../common/configSettingMonitor'; import { PythonSettings } from '../common/configSettings'; import { LinterErrors, PythonLanguage } from '../common/constants'; -import { IInstaller, ILogger } from '../common/types'; import { IServiceContainer } from '../ioc/types'; -import * as linter from '../linters/baseLinter'; -import { ILinterHelper } from '../linters/types'; +import { ILinterInfo, ILinterManager, ILintMessage, LintMessageSeverity } from '../linters/types'; import { sendTelemetryWhenDone } from '../telemetry'; import { LINTING } from '../telemetry/constants'; import { StopWatch } from '../telemetry/stopWatch'; -import * as flake8 from './../linters/flake8'; -import * as mypy from './../linters/mypy'; -import * as pep8 from './../linters/pep8Linter'; -import * as prospector from './../linters/prospector'; -import * as pydocstyle from './../linters/pydocstyle'; -import * as pylama from './../linters/pylama'; -import * as pylint from './../linters/pylint'; +import { LinterTrigger, LintingTelemetry } from '../telemetry/types'; + // tslint:disable-next-line:no-require-imports no-var-requires const Minimatch = require('minimatch').Minimatch; const uriSchemesToIgnore = ['git', 'showModifications', 'svn']; -const lintSeverityToVSSeverity = new Map(); -lintSeverityToVSSeverity.set(linter.LintMessageSeverity.Error, vscode.DiagnosticSeverity.Error); -lintSeverityToVSSeverity.set(linter.LintMessageSeverity.Hint, vscode.DiagnosticSeverity.Hint); -lintSeverityToVSSeverity.set(linter.LintMessageSeverity.Information, vscode.DiagnosticSeverity.Information); -lintSeverityToVSSeverity.set(linter.LintMessageSeverity.Warning, vscode.DiagnosticSeverity.Warning); +const lintSeverityToVSSeverity = new Map(); +lintSeverityToVSSeverity.set(LintMessageSeverity.Error, vscode.DiagnosticSeverity.Error); +lintSeverityToVSSeverity.set(LintMessageSeverity.Hint, vscode.DiagnosticSeverity.Hint); +lintSeverityToVSSeverity.set(LintMessageSeverity.Information, vscode.DiagnosticSeverity.Information); +lintSeverityToVSSeverity.set(LintMessageSeverity.Warning, vscode.DiagnosticSeverity.Warning); -function createDiagnostics(message: linter.ILintMessage, document: vscode.TextDocument): vscode.Diagnostic { +function createDiagnostics(message: ILintMessage, document: vscode.TextDocument): vscode.Diagnostic { const position = new vscode.Position(message.line - 1, message.column); const range = new vscode.Range(position, position); @@ -45,16 +38,21 @@ interface DocumentHasJupyterCodeCells { // tslint:disable-next-line:callable-types (doc: vscode.TextDocument, token: vscode.CancellationToken): Promise; } -export class LintProvider implements vscode.Disposable { +export class LinterProvider implements vscode.Disposable { + private linterManager: ILinterManager; private diagnosticCollection: vscode.DiagnosticCollection; - private linters: linter.BaseLinter[] = []; private pendingLintings = new Map(); private outputChannel: vscode.OutputChannel; private context: vscode.ExtensionContext; private disposables: vscode.Disposable[]; private configMonitor: ConfigSettingMonitor; - public constructor(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel, - public documentHasJupyterCodeCells: DocumentHasJupyterCodeCells, private serviceContainer: IServiceContainer) { + public constructor( + context: vscode.ExtensionContext, + outputChannel: vscode.OutputChannel, + public documentHasJupyterCodeCells: DocumentHasJupyterCodeCells, + private serviceContainer: IServiceContainer) { + + this.linterManager = serviceContainer.get(ILinterManager); this.outputChannel = outputChannel; this.context = context; this.disposables = []; @@ -73,18 +71,6 @@ export class LintProvider implements vscode.Disposable { private initialize() { this.diagnosticCollection = vscode.languages.createDiagnosticCollection('python'); - const helper = this.serviceContainer.get(ILinterHelper); - const installer = this.serviceContainer.get(IInstaller); - const logger = this.serviceContainer.get(ILogger); - - this.linters.push(new prospector.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new pylint.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new pep8.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new pylama.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new flake8.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new pydocstyle.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - this.linters.push(new mypy.Linter(this.outputChannel, installer, helper, logger, this.serviceContainer)); - let disposable = vscode.workspace.onDidSaveTextDocument((e) => { const settings = PythonSettings.getInstance(e.uri); if (e.languageId !== 'python' || !settings.linting.enabled || !settings.linting.lintOnSave) { @@ -124,9 +110,9 @@ export class LintProvider implements vscode.Disposable { } private lintOpenPythonFiles() { - workspace.textDocuments.forEach(document => { + workspace.textDocuments.forEach(async document => { if (document.languageId === PythonLanguage.language) { - this.onLintDocument(document, 'auto'); + await this.onLintDocument(document, 'auto'); } }); } @@ -136,17 +122,17 @@ export class LintProvider implements vscode.Disposable { return; } // Look for python files that belong to the specified workspace folder. - workspace.textDocuments.forEach(document => { + workspace.textDocuments.forEach(async document => { const wkspaceFolder = workspace.getWorkspaceFolder(document.uri); if (wkspaceFolder && wkspaceFolder.uri.fsPath === wkspaceOrFolder.fsPath) { - this.onLintDocument(document, 'auto'); + await this.onLintDocument(document, 'auto'); } }); } // tslint:disable-next-line:member-ordering no-any private lastTimeout: any; - private lintDocument(document: vscode.TextDocument, delay: number, trigger: 'auto' | 'save'): void { + private lintDocument(document: vscode.TextDocument, delay: number, trigger: LinterTrigger): void { // Since this is a hack, lets wait for 2 seconds before linting. // Give user to continue typing before we waste CPU time. if (this.lastTimeout) { @@ -154,19 +140,22 @@ export class LintProvider implements vscode.Disposable { this.lastTimeout = 0; } - this.lastTimeout = setTimeout(() => { - this.onLintDocument(document, trigger); + this.lastTimeout = setTimeout(async () => { + await this.onLintDocument(document, trigger); }, delay); } - private onLintDocument(document: vscode.TextDocument, trigger: 'auto' | 'save'): void { + private async onLintDocument(document: vscode.TextDocument, trigger: LinterTrigger): Promise { // Check if we need to lint this document const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri); const workspaceRootPath = (workspaceFolder && typeof workspaceFolder.uri.fsPath === 'string') ? workspaceFolder.uri.fsPath : undefined; const relativeFileName = typeof workspaceRootPath === 'string' ? path.relative(workspaceRootPath, document.fileName) : document.fileName; const settings = PythonSettings.getInstance(document.uri); - if (document.languageId !== PythonLanguage.language || !settings.linting.enabled) { + if (document.languageId !== PythonLanguage.language) { return; } + if (!this.linterManager.isLintingEnabled()) { + this.diagnosticCollection.set(document.uri, []); + } const ignoreMinmatches = settings.linting.ignorePatterns.map(pattern => { return new Minimatch(pattern); }); @@ -188,17 +177,13 @@ export class LintProvider implements vscode.Disposable { this.pendingLintings.set(document.uri.fsPath, cancelToken); this.outputChannel.clear(); - const promises: Promise[] = this.linters - .filter(item => item.isEnabled(document.uri)) - .map(item => { - if (typeof workspaceRootPath !== 'string' && !settings.linting.enabledWithoutWorkspace) { - return Promise.resolve([]); - } + + const promises: Promise[] = this.linterManager.getActiveLinters(document.uri) + .map(info => { const stopWatch = new StopWatch(); - const promise = item.lint(document, cancelToken.token); - const hasCustomArgs = item.linterArgs(document.uri).length > 0; - const executableSpecified = item.isLinterExecutableSpecified(document.uri); - sendTelemetryWhenDone(LINTING, promise, stopWatch, { tool: item.Id, hasCustomArgs, trigger, executableSpecified }); + const linter = this.linterManager.createLinter(info.product, this.outputChannel, this.serviceContainer); + const promise = linter.lint(document, cancelToken.token); + this.sendLinterRunTelemetry(info, document.uri, promise, stopWatch, trigger); return promise; }); this.documentHasJupyterCodeCells(document, cancelToken.token) @@ -239,4 +224,15 @@ export class LintProvider implements vscode.Disposable { }) .catch(ex => console.error('Python Extension: documentHasJupyterCodeCells', ex)); } + + private sendLinterRunTelemetry(info: ILinterInfo, resource: Uri, promise: Promise, stopWatch: StopWatch, trigger: LinterTrigger): void { + const linterExecutablePathName = info.pathName(resource); + const properties: LintingTelemetry = { + tool: info.id, + hasCustomArgs: info.linterArgs(resource).length > 0, + trigger, + executableSpecified: linterExecutablePathName.length > 0 + }; + sendTelemetryWhenDone(LINTING, promise, stopWatch, properties); + } } diff --git a/src/client/telemetry/types.ts b/src/client/telemetry/types.ts index 3ee528928624..36514f41b3b0 100644 --- a/src/client/telemetry/types.ts +++ b/src/client/telemetry/types.ts @@ -1,3 +1,5 @@ +import { LinterId } from '../linters/types'; + // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. @@ -9,10 +11,13 @@ export type FormatTelemetry = { hasCustomArgs: boolean; formatSelection: boolean; }; + +export type LinterTrigger = 'auto' | 'save'; + export type LintingTelemetry = { - tool: 'flake8' | 'mypy' | 'pep8' | 'prospector' | 'pydocstyle' | 'pylama' | 'pylint'; + tool: LinterId; hasCustomArgs: boolean; - trigger: 'save' | 'auto'; + trigger: LinterTrigger; executableSpecified: boolean; }; export type PythonInterpreterTelemetry = { diff --git a/src/test/.vscode/settings.json b/src/test/.vscode/settings.json index 12cde5b9dc53..dcfb904cf4f1 100644 --- a/src/test/.vscode/settings.json +++ b/src/test/.vscode/settings.json @@ -1,5 +1,5 @@ { - "python.linting.pylintEnabled": false, + "python.linting.pylintEnabled": true, "python.linting.flake8Enabled": false, "python.workspaceSymbols.enabled": false, "python.unitTest.nosetestArgs": [], diff --git a/src/test/common.ts b/src/test/common.ts index 3c59c4235d8f..e399012adf2c 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -15,7 +15,7 @@ export type PythonSettingKeys = 'workspaceSymbols.enabled' | 'pythonPath' | 'unitTest.nosetestArgs' | 'unitTest.pyTestArgs' | 'unitTest.unittestArgs' | 'formatting.provider' | 'sortImports.args' | 'unitTest.nosetestsEnabled' | 'unitTest.pyTestEnabled' | 'unitTest.unittestEnabled' | - 'linting.enabledWithoutWorkspace' | 'envFile'; + 'envFile'; export async function updateSetting(setting: PythonSettingKeys, value: {} | undefined, resource: Uri | undefined, configTarget: ConfigurationTarget) { const settings = workspace.getConfiguration('python', resource); diff --git a/src/test/common/installer.multiroot.test.ts b/src/test/common/installer.multiroot.test.ts deleted file mode 100644 index 9425800988e8..000000000000 --- a/src/test/common/installer.multiroot.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import { ConfigurationTarget, Uri, workspace } from 'vscode'; -import { IInstaller, Product } from '../../client/common/types'; -import { rootWorkspaceUri } from '../common'; -import { updateSetting } from '../common'; -import { UnitTestIocContainer } from '../unittests/serviceRegistry'; -import { closeActiveWindows, initializeTest, IS_MULTI_ROOT_TEST } from './../initialize'; - -// tslint:disable-next-line:no-suspicious-comment -// TODO: Need to mock the command runner, to check what commands are being sent. -// Instead of altering the environment. - -suite('Installer', () => { - let ioc: UnitTestIocContainer; - const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test')); - suiteSetup(async function () { - if (!IS_MULTI_ROOT_TEST) { - // tslint:disable-next-line:no-invalid-this - this.skip(); - } - await initializeTest(); - }); - setup(async () => { - await initializeTest(); - await resetSettings(); - initializeDI(); - }); - suiteTeardown(async () => { - await closeActiveWindows(); - await resetSettings(); - }); - teardown(async () => { - ioc.dispose(); - closeActiveWindows(); - }); - - function initializeDI() { - ioc = new UnitTestIocContainer(); - ioc.registerCommonTypes(); - ioc.registerUnitTestTypes(); - ioc.registerVariableTypes(); - } - - async function resetSettings() { - await updateSetting('linting.enabledWithoutWorkspace', true, undefined, ConfigurationTarget.Global); - await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); - if (IS_MULTI_ROOT_TEST) { - await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.WorkspaceFolder); - } - } - - test('Disable linting of files contained in a multi-root workspace', async function () { - if (!IS_MULTI_ROOT_TEST) { - // tslint:disable-next-line:no-invalid-this - this.skip(); - } - const installer = ioc.serviceContainer.get(IInstaller); - await installer.disableLinter(Product.pylint, workspaceUri); - const pythonWConfig = workspace.getConfiguration('python', workspaceUri); - const value = pythonWConfig.inspect('linting.pylintEnabled'); - // tslint:disable-next-line:no-non-null-assertion - assert.equal(value!.workspaceValue, true, 'Workspace setting has been disabled'); - // tslint:disable-next-line:no-non-null-assertion - assert.equal(value!.workspaceFolderValue, false, 'Workspace folder setting not disabled'); - }); -}); diff --git a/src/test/common/installer.test.ts b/src/test/common/installer.test.ts index bc5f3933981b..4574a4925c42 100644 --- a/src/test/common/installer.test.ts +++ b/src/test/common/installer.test.ts @@ -1,16 +1,18 @@ -import * as assert from 'assert'; import * as path from 'path'; -import { ConfigurationTarget, Uri, workspace } from 'vscode'; +import * as TypeMoq from 'typemoq'; +import { ConfigurationTarget, Uri } from 'vscode'; +import { IApplicationShell } from '../../client/common/application/types'; +import { ConfigurationService } from '../../client/common/configuration/service'; import { EnumEx } from '../../client/common/enumUtils'; import { createDeferred } from '../../client/common/helpers'; -import { Installer } from '../../client/common/installer/installer'; +import { ProductInstaller } from '../../client/common/installer/productInstaller'; import { IModuleInstaller } from '../../client/common/installer/types'; import { Logger } from '../../client/common/logger'; import { PersistentStateFactory } from '../../client/common/persistentState'; import { PathUtils } from '../../client/common/platform/pathUtils'; import { CurrentProcess } from '../../client/common/process/currentProcess'; import { IProcessService } from '../../client/common/process/types'; -import { ICurrentProcess, IInstaller, ILogger, IPathUtils, IPersistentStateFactory, IsWindows, ModuleNamePurpose, Product } from '../../client/common/types'; +import { IConfigurationService, ICurrentProcess, IInstaller, ILogger, IPathUtils, IPersistentStateFactory, IsWindows, ModuleNamePurpose, Product } from '../../client/common/types'; import { updateSetting } from '../common'; import { rootWorkspaceUri } from '../common'; import { MockModuleInstaller } from '../mocks/moduleInstaller'; @@ -47,20 +49,22 @@ suite('Installer', () => { ioc.serviceManager.addSingleton(IPersistentStateFactory, PersistentStateFactory); ioc.serviceManager.addSingleton(ILogger, Logger); - ioc.serviceManager.addSingleton(IInstaller, Installer); + ioc.serviceManager.addSingleton(IInstaller, ProductInstaller); ioc.serviceManager.addSingleton(IPathUtils, PathUtils); ioc.serviceManager.addSingleton(ICurrentProcess, CurrentProcess); + ioc.serviceManager.addSingletonInstance(IApplicationShell, TypeMoq.Mock.ofType().object); + ioc.serviceManager.addSingleton(IConfigurationService, ConfigurationService); + ioc.registerMockProcessTypes(); ioc.serviceManager.addSingletonInstance(IsWindows, false); } async function resetSettings() { - await updateSetting('linting.enabledWithoutWorkspace', true, undefined, ConfigurationTarget.Global); await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); } async function testCheckingIfProductIsInstalled(product: Product) { - const installer = ioc.serviceContainer.get(IInstaller); + const installer = ioc.serviceContainer.get(IInstaller); const processService = ioc.serviceContainer.get(IProcessService); const checkInstalledDef = createDeferred(); processService.onExec((file, args, options, callback) => { @@ -88,7 +92,7 @@ suite('Installer', () => { }); async function testInstallingProduct(product: Product) { - const installer = ioc.serviceContainer.get(IInstaller); + const installer = ioc.serviceContainer.get(IInstaller); const checkInstalledDef = createDeferred(); const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); const moduleInstallerOne = moduleInstallers.find(item => item.displayName === 'two')!; @@ -112,30 +116,4 @@ suite('Installer', () => { await testInstallingProduct(prod.value); }); }); - - test('Disable linting of files not contained in a workspace', async () => { - const installer = ioc.serviceContainer.get(IInstaller); - await installer.disableLinter(Product.pylint, undefined); - // tslint:disable-next-line:no-any - const pythonConfig = workspace.getConfiguration('python', null as any as Uri); - assert.equal(pythonConfig.get('linting.enabledWithoutWorkspace'), false, 'Incorrect setting'); - }); - - test('Disable linting of files contained in a single workspace', async function () { - if (IS_MULTI_ROOT_TEST) { - // tslint:disable-next-line:no-invalid-this - this.skip(); - } - const installer = ioc.serviceContainer.get(IInstaller); - await installer.disableLinter(Product.pylint, workspaceUri); - const pythonConfig = workspace.getConfiguration('python', workspaceUri); - assert.equal(pythonConfig.get('linting.pylintEnabled'), false, 'Incorrect setting'); - }); - - test('Disable linting of files contained in a any kind of workspace', async () => { - const installer = ioc.serviceContainer.get(IInstaller); - await installer.disableLinter(Product.pylint, workspaceUri); - const pythonConfig = workspace.getConfiguration('python', workspaceUri); - assert.equal(pythonConfig.get('linting.pylintEnabled'), false, 'Incorrect setting'); - }); }); diff --git a/src/test/common/moduleInstaller.test.ts b/src/test/common/moduleInstaller.test.ts index bb7a5d9df28e..64c73b823b22 100644 --- a/src/test/common/moduleInstaller.test.ts +++ b/src/test/common/moduleInstaller.test.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as TypeMoq from 'typemoq'; import { ConfigurationTarget, Uri } from 'vscode'; import { PythonSettings } from '../../client/common/configSettings'; +import { ConfigurationService } from '../../client/common/configuration/service'; import { CondaInstaller } from '../../client/common/installer/condaInstaller'; import { Installer } from '../../client/common/installer/installer'; import { PipInstaller } from '../../client/common/installer/pipInstaller'; @@ -16,9 +17,9 @@ import { Architecture, IFileSystem, IPlatformService } from '../../client/common import { CurrentProcess } from '../../client/common/process/currentProcess'; import { IProcessService, IPythonExecutionFactory } from '../../client/common/process/types'; import { ITerminalService, ITerminalServiceFactory } from '../../client/common/terminal/types'; -import { ICurrentProcess, IInstaller, ILogger, IPathUtils, IPersistentStateFactory, IsWindows } from '../../client/common/types'; +import { IConfigurationService, ICurrentProcess, IInstaller, ILogger, IPathUtils, IPersistentStateFactory, IsWindows } from '../../client/common/types'; import { ICondaService, IInterpreterLocatorService, IInterpreterService, INTERPRETER_LOCATOR_SERVICE, InterpreterType, PythonInterpreter } from '../../client/interpreter/contracts'; -import { rootWorkspaceUri, updateSetting } from '../common'; +import { rootWorkspaceUri } from '../common'; import { MockModuleInstaller } from '../mocks/moduleInstaller'; import { MockProcessService } from '../mocks/proc'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -30,12 +31,13 @@ suite('Module Installer', () => { let mockTerminalService: TypeMoq.IMock; let condaService: TypeMoq.IMock; let interpreterService: TypeMoq.IMock; + const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test')); suiteSetup(initializeTest); setup(async () => { + initializeDI(); await initializeTest(); await resetSettings(); - initializeDI(); }); suiteTeardown(async () => { await closeActiveWindows(); @@ -72,13 +74,14 @@ suite('Module Installer', () => { ioc.serviceManager.addSingleton(ICurrentProcess, CurrentProcess); ioc.serviceManager.addSingleton(IFileSystem, FileSystem); ioc.serviceManager.addSingleton(IPlatformService, PlatformService); + ioc.serviceManager.addSingleton(IConfigurationService, ConfigurationService); ioc.registerMockProcessTypes(); ioc.serviceManager.addSingletonInstance(IsWindows, false); } - async function resetSettings() { - await updateSetting('linting.enabledWithoutWorkspace', true, undefined, ConfigurationTarget.Global); - await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); + async function resetSettings(): Promise { + const configService = ioc.serviceManager.get(IConfigurationService); + await configService.updateSettingAsync('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); } async function getCurrentPythonPath(): Promise { const pythonPath = PythonSettings.getInstance(workspaceUri).pythonPath; @@ -172,7 +175,7 @@ suite('Module Installer', () => { let argsSent: string[] = []; mockTerminalService - .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) + .setup(async t => await t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) .returns((cmd: string, args: string[]) => { argsSent = args; return Promise.resolve(void 0); }); await pipInstaller.installModule(moduleName); diff --git a/src/test/common/process/pythonProc.simple.multiroot.test.ts b/src/test/common/process/pythonProc.simple.multiroot.test.ts index bd5ca67feb44..490a941a3655 100644 --- a/src/test/common/process/pythonProc.simple.multiroot.test.ts +++ b/src/test/common/process/pythonProc.simple.multiroot.test.ts @@ -9,15 +9,18 @@ import { EOL } from 'os'; import * as path from 'path'; import { ConfigurationTarget, Disposable, Uri } from 'vscode'; import { PythonSettings } from '../../../client/common/configSettings'; +import { ConfigurationService } from '../../../client/common/configuration/service'; import { PathUtils } from '../../../client/common/platform/pathUtils'; import { CurrentProcess } from '../../../client/common/process/currentProcess'; import { registerTypes as processRegisterTypes } from '../../../client/common/process/serviceRegistry'; import { IPythonExecutionFactory, StdErrError } from '../../../client/common/process/types'; -import { ICurrentProcess, IDisposableRegistry, IPathUtils, IsWindows } from '../../../client/common/types'; +import { IConfigurationService, ICurrentProcess, IDisposableRegistry, IPathUtils, IsWindows } from '../../../client/common/types'; import { IS_WINDOWS } from '../../../client/common/utils'; import { registerTypes as variablesRegisterTypes } from '../../../client/common/variables/serviceRegistry'; +import { ServiceContainer } from '../../../client/ioc/container'; import { ServiceManager } from '../../../client/ioc/serviceManager'; -import { clearPythonPathInWorkspaceFolder, updateSetting } from '../../common'; +import { IServiceContainer } from '../../../client/ioc/types'; +import { clearPythonPathInWorkspaceFolder } from '../../common'; import { closeActiveWindows, initialize, initializeTest, IS_MULTI_ROOT_TEST } from './../../initialize'; use(chaiAsPromised); @@ -29,25 +32,38 @@ const workspace4PyFile = Uri.file(path.join(workspace4Path.fsPath, 'one.py')); // tslint:disable-next-line:max-func-body-length suite('PythonExecutableService', () => { let cont: Container; - let serviceManager: ServiceManager; + let serviceContainer: IServiceContainer; + let configService: IConfigurationService; + let pythonExecFactory: IPythonExecutionFactory; + suiteSetup(async function () { if (!IS_MULTI_ROOT_TEST) { // tslint:disable-next-line:no-invalid-this this.skip(); } await clearPythonPathInWorkspaceFolder(workspace4Path); - await updateSetting('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); + + await (new ConfigurationService()).updateSettingAsync('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); await initialize(); }); setup(() => { cont = new Container(); - serviceManager = new ServiceManager(cont); + serviceContainer = new ServiceContainer(cont); + const serviceManager = new ServiceManager(cont); + + serviceManager.addSingletonInstance(IServiceContainer, serviceContainer); serviceManager.addSingletonInstance(IDisposableRegistry, []); serviceManager.addSingletonInstance(IsWindows, IS_WINDOWS); serviceManager.addSingleton(IPathUtils, PathUtils); serviceManager.addSingleton(ICurrentProcess, CurrentProcess); + serviceManager.addSingleton(IConfigurationService, ConfigurationService); + processRegisterTypes(serviceManager); variablesRegisterTypes(serviceManager); + + configService = serviceManager.get(IConfigurationService); + pythonExecFactory = serviceContainer.get(IPythonExecutionFactory); + return initializeTest(); }); suiteTeardown(closeActiveWindows); @@ -56,13 +72,13 @@ suite('PythonExecutableService', () => { cont.unload(); await closeActiveWindows(); await clearPythonPathInWorkspaceFolder(workspace4Path); - await updateSetting('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); + await configService.updateSettingAsync('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); await initializeTest(); }); test('Importing without a valid PYTHONPATH should fail', async () => { - await updateSetting('envFile', 'someInvalidFile.env', workspace4PyFile, ConfigurationTarget.WorkspaceFolder); - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); + await configService.updateSettingAsync('envFile', 'someInvalidFile.env', workspace4PyFile, ConfigurationTarget.WorkspaceFolder); + pythonExecFactory = serviceContainer.get(IPythonExecutionFactory); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const promise = pythonExecService.exec([workspace4PyFile.fsPath], { cwd: path.dirname(workspace4PyFile.fsPath), throwOnStdErr: true }); @@ -70,8 +86,7 @@ suite('PythonExecutableService', () => { }); test('Importing with a valid PYTHONPATH from .env file should succeed', async () => { - await updateSetting('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); + await configService.updateSettingAsync('envFile', undefined, workspace4PyFile, ConfigurationTarget.WorkspaceFolder); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const promise = pythonExecService.exec([workspace4PyFile.fsPath], { cwd: path.dirname(workspace4PyFile.fsPath), throwOnStdErr: true }); @@ -79,7 +94,6 @@ suite('PythonExecutableService', () => { }); test('Known modules such as \'os\' and \'sys\' should be deemed \'installed\'', async () => { - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const osModuleIsInstalled = pythonExecService.isModuleInstalled('os'); const sysModuleIsInstalled = pythonExecService.isModuleInstalled('sys'); @@ -88,7 +102,6 @@ suite('PythonExecutableService', () => { }); test('Unknown modules such as \'xyzabc123\' be deemed \'not installed\'', async () => { - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const randomModuleName = `xyz123${new Date().getSeconds()}`; const randomModuleIsInstalled = pythonExecService.isModuleInstalled(randomModuleName); @@ -103,7 +116,6 @@ suite('PythonExecutableService', () => { resolve(out.trim()); }); }); - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const version = await pythonExecService.getVersion(); expect(version).to.equal(expectedVersion, 'Versions are not the same'); @@ -116,7 +128,6 @@ suite('PythonExecutableService', () => { resolve(stdout.trim()); }); }); - const pythonExecFactory = serviceManager.get(IPythonExecutionFactory); const pythonExecService = await pythonExecFactory.create(workspace4PyFile); const executablePath = await pythonExecService.getExecutablePath(); expect(executablePath).to.equal(expectedExecutablePath, 'Executable paths are not the same'); diff --git a/src/test/format/extension.format.test.ts b/src/test/format/extension.format.test.ts index 2c00fa8c6dd6..a078a4c92d98 100644 --- a/src/test/format/extension.format.test.ts +++ b/src/test/format/extension.format.test.ts @@ -95,7 +95,7 @@ suite('Formatting', () => { }); assert.equal(textEditor.document.getText(), formattedContents, 'Formatted text is not the same'); } - test('AutoPep8', () => testFormatting(new AutoPep8Formatter(ioc.serviceContainer), formattedAutoPep8, autoPep8FileToFormat, 'autopep8.output')); + test('AutoPep8', async () => await testFormatting(new AutoPep8Formatter(ioc.serviceContainer), formattedAutoPep8, autoPep8FileToFormat, 'autopep8.output')); - test('Yapf', () => testFormatting(new YapfFormatter(ioc.serviceContainer), formattedYapf, yapfFileToFormat, 'yapf.output')); + test('Yapf', async () => await testFormatting(new YapfFormatter(ioc.serviceContainer), formattedYapf, yapfFileToFormat, 'yapf.output')); }); diff --git a/src/test/linters/lint.commands.test.ts b/src/test/linters/lint.commands.test.ts new file mode 100644 index 000000000000..d46d65e6dbfc --- /dev/null +++ b/src/test/linters/lint.commands.test.ts @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as assert from 'assert'; +import { Container } from 'inversify'; +import * as TypeMoq from 'typemoq'; +import { QuickPickOptions } from 'vscode'; +import { IApplicationShell, ICommandManager } from '../../client/common/application/types'; +import { ConfigurationService } from '../../client/common/configuration/service'; +import { IConfigurationService, Product } from '../../client/common/types'; +import { ServiceContainer } from '../../client/ioc/container'; +import { ServiceManager } from '../../client/ioc/serviceManager'; +import { IServiceContainer } from '../../client/ioc/types'; +import { LinterCommands } from '../../client/linters/linterCommands'; +import { LinterManager } from '../../client/linters/linterManager'; +import { ILinterManager } from '../../client/linters/types'; +import { closeActiveWindows, initialize, initializeTest } from '../initialize'; + +// tslint:disable-next-line:max-func-body-length +suite('Linting - Linter Selector', () => { + let serviceContainer: IServiceContainer; + let appShell: TypeMoq.IMock; + let commands: LinterCommands; + let lm: ILinterManager; + + suiteSetup(initialize); + setup(async () => { + await initializeTest(); + initializeServices(); + }); + suiteTeardown(closeActiveWindows); + teardown(async () => await closeActiveWindows()); + + function initializeServices() { + const cont = new Container(); + const serviceManager = new ServiceManager(cont); + serviceContainer = new ServiceContainer(cont); + + appShell = TypeMoq.Mock.ofType(); + serviceManager.addSingleton(IConfigurationService, ConfigurationService); + + const commandManager = TypeMoq.Mock.ofType(); + serviceManager.addSingletonInstance(ICommandManager, commandManager.object); + serviceManager.addSingletonInstance(IApplicationShell, appShell.object); + + lm = new LinterManager(serviceContainer); + serviceManager.addSingletonInstance(ILinterManager, lm); + + commands = new LinterCommands(serviceContainer); + } + + test('Enable linting', async () => { + await enableDisableLinterAsync(true); + }); + + test('Disable linting', async () => { + await enableDisableLinterAsync(false); + }); + + test('Single linter active', async () => { + await selectLinterAsync([Product.pylama]); + }); + + test('Multiple linters active', async () => { + await selectLinterAsync([Product.flake8, Product.pydocstyle]); + }); + + test('No linters active', async () => { + await selectLinterAsync([Product.flake8]); + }); + + async function enableDisableLinterAsync(enable: boolean): Promise { + let suggestions: string[] = []; + let options: QuickPickOptions; + + await lm.enableLintingAsync(!enable); + appShell.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .callback((s, o) => { + suggestions = s as string[]; + options = o as QuickPickOptions; + }) + .returns((s) => enable + ? new Promise((resolve, reject) => { return resolve('on'); }) + : new Promise((resolve, reject) => { return resolve('off'); }) + ); + const current = enable ? 'off' : 'on'; + await commands.enableLintingAsync(); + assert.notEqual(suggestions.length, 0, 'showQuickPick was not called'); + assert.notEqual(options!, undefined, 'showQuickPick was not called'); + + assert.equal(suggestions.length, 2, 'Wrong number of suggestions'); + assert.equal(suggestions[0], 'on', 'Wrong first suggestions'); + assert.equal(suggestions[1], 'off', 'Wrong second suggestions'); + + assert.equal(options!.matchOnDescription, true, 'Quick pick options are incorrect'); + assert.equal(options!.matchOnDetail, true, 'Quick pick options are incorrect'); + assert.equal(options!.placeHolder, `current: ${current}`, 'Quick pick current option is incorrect'); + assert.equal(lm.isLintingEnabled(undefined), enable, 'Linting selector did not change linting on/off flag'); + } + + async function selectLinterAsync(products: Product[]): Promise { + let suggestions: string[] = []; + let options: QuickPickOptions; + let warning: string; + + appShell.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .callback((s, o) => { + suggestions = s as string[]; + options = o as QuickPickOptions; + }) + .returns(s => new Promise((resolve, reject) => resolve('pylint'))); + appShell.setup(x => x.showWarningMessage(TypeMoq.It.isAnyString(), TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .callback((s, o) => { + warning = s; + }) + .returns(s => new Promise((resolve, reject) => resolve('Yes'))); + + const linters = lm.getAllLinterInfos(); + await lm.setActiveLintersAsync(products); + + let current: string; + let activeLinters = lm.getActiveLinters(); + switch (activeLinters.length) { + case 0: + current = 'none'; + break; + case 1: + current = activeLinters[0].id; + break; + default: + current = 'multiple selected'; + break; + } + + await commands.setLinterAsync(); + + assert.notEqual(suggestions.length, 0, 'showQuickPick was not called'); + assert.notEqual(options!, undefined, 'showQuickPick was not called'); + + assert.equal(suggestions.length, linters.length, 'Wrong number of suggestions'); + assert.deepEqual(suggestions, linters.map(x => x.id).sort(), 'Wrong linters order in suggestions'); + + assert.equal(options!.matchOnDescription, true, 'Quick pick options are incorrect'); + assert.equal(options!.matchOnDetail, true, 'Quick pick options are incorrect'); + assert.equal(options!.placeHolder, `current: ${current}`, 'Quick pick current option is incorrect'); + + activeLinters = lm.getActiveLinters(); + assert.equal(activeLinters.length, 1, 'Linting selector did not change active linter'); + assert.equal(activeLinters[0].product, Product.pylint, 'Linting selector did not change to pylint'); + + if (products.length > 1) { + assert.notEqual(warning!, undefined, 'Warning was not shown when overwriting multiple linters'); + } + } +}); diff --git a/src/test/linters/lint.helper.test.ts b/src/test/linters/lint.helper.test.ts deleted file mode 100644 index 93e523f46cb6..000000000000 --- a/src/test/linters/lint.helper.test.ts +++ /dev/null @@ -1,98 +0,0 @@ -import * as assert from 'assert'; -import { PythonSettings } from '../../client/common/configSettings'; -import { EnumEx } from '../../client/common/enumUtils'; -import { ILintingSettings, Product } from '../../client/common/types'; -import { LinterHelper } from '../../client/linters/helper'; -import { LinterId } from '../../client/linters/types'; -import { initialize } from '../initialize'; - -// tslint:disable-next-line:max-func-body-length -suite('Linting - Helper', () => { - const linterHelper = new LinterHelper(); - suiteSetup(initialize); - - test('Ensure product is set in Execution Info', async () => { - [Product.flake8, Product.mypy, Product.pep8, - Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { - const info = linterHelper.getExecutionInfo(linter, []); - assert.equal(info.product, linter, `Incorrect products for ${linterHelper.translateToId(linter)}`); - }); - }); - - test('Ensure executable is set in Execution Info', async () => { - const settings = PythonSettings.getInstance(); - - [Product.flake8, Product.mypy, Product.pep8, - Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { - const info = linterHelper.getExecutionInfo(linter, []); - const names = linterHelper.getSettingsPropertyNames(linter); - const execPath = settings.linting[names.pathName] as string; - - assert.equal(info.execPath, execPath, `Incorrect executable paths for product ${linterHelper.translateToId(linter)}`); - }); - }); - - test('Ensure arguments are set in Execution Info', async () => { - const settings = PythonSettings.getInstance(); - const customArgs = ['1', '2', '3']; - - [Product.flake8, Product.mypy, Product.pep8, - Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { - const names = linterHelper.getSettingsPropertyNames(linter); - const args: string[] = Array.isArray(settings.linting[names.argsName]) ? settings.linting[names.argsName] as string[] : []; - const expectedArgs = args.concat(customArgs).join(','); - - assert.equal(expectedArgs.endsWith(customArgs.join(',')), true, `Incorrect custom arguments for product ${linterHelper.translateToId(linter)}`); - - }); - }); - - test('Ensure correct setting names are returned', async () => { - [Product.flake8, Product.mypy, Product.pep8, - Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { - const translatedId = linterHelper.translateToId(linter)!; - const settings = { - argsName: `${translatedId}Args` as keyof ILintingSettings, - pathName: `${translatedId}Path` as keyof ILintingSettings, - enabledName: `${translatedId}Enabled` as keyof ILintingSettings - }; - - assert.deepEqual(linterHelper.getSettingsPropertyNames(linter), settings, `Incorrect settings for product ${linterHelper.translateToId(linter)}`); - }); - }); - - test('Ensure translation of ids works', async () => { - const linterIdMapping = new Map(); - linterIdMapping.set(Product.flake8, 'flake8'); - linterIdMapping.set(Product.mypy, 'mypy'); - linterIdMapping.set(Product.pep8, 'pep8'); - linterIdMapping.set(Product.prospector, 'prospector'); - linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); - linterIdMapping.set(Product.pylama, 'pylama'); - linterIdMapping.set(Product.pylint, 'pylint'); - - [Product.flake8, Product.mypy, Product.pep8, - Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { - const translatedId = linterHelper.translateToId(linter); - assert.equal(translatedId, linterIdMapping.get(linter)!, `Incorrect translation for product ${linterHelper.translateToId(linter)}`); - }); - }); - - EnumEx.getValues(Product).forEach(product => { - const linterIdMapping = new Map(); - linterIdMapping.set(Product.flake8, 'flake8'); - linterIdMapping.set(Product.mypy, 'mypy'); - linterIdMapping.set(Product.pep8, 'pep8'); - linterIdMapping.set(Product.prospector, 'prospector'); - linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); - linterIdMapping.set(Product.pylama, 'pylama'); - linterIdMapping.set(Product.pylint, 'pylint'); - if (linterIdMapping.has(product)) { - return; - } - - test(`Ensure translation of ids throws exceptions for unknown linters (${product})`, async () => { - assert.throws(() => linterHelper.translateToId(product)); - }); - }); -}); diff --git a/src/test/linters/lint.manager.test.ts b/src/test/linters/lint.manager.test.ts new file mode 100644 index 000000000000..26eb0c39a7b2 --- /dev/null +++ b/src/test/linters/lint.manager.test.ts @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as assert from 'assert'; +import { Container } from 'inversify'; +import { ConfigurationService } from '../../client/common/configuration/service'; +import { EnumEx } from '../../client/common/enumUtils'; +import { IConfigurationService, ILintingSettings, IPythonSettings, Product } from '../../client/common/types'; +import { ServiceContainer } from '../../client/ioc/container'; +import { ServiceManager } from '../../client/ioc/serviceManager'; +import { LinterManager } from '../../client/linters/linterManager'; +import { ILinterManager, LinterId } from '../../client/linters/types'; +import { initialize } from '../initialize'; + +// tslint:disable-next-line:max-func-body-length +suite('Linting - Manager', () => { + let lm: ILinterManager; + let configService: IConfigurationService; + let settings: IPythonSettings; + + suiteSetup(initialize); + setup(async () => { + const cont = new Container(); + const serviceManager = new ServiceManager(cont); + const serviceContainer = new ServiceContainer(cont); + + serviceManager.addSingleton(IConfigurationService, ConfigurationService); + configService = serviceManager.get(IConfigurationService); + + settings = configService.getSettings(); + lm = new LinterManager(serviceContainer); + + await lm.setActiveLintersAsync([Product.pylint]); + await lm.enableLintingAsync(true); + }); + + test('Ensure product is set in Execution Info', async () => { + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(product => { + const execInfo = lm.getLinterInfo(product).getExecutionInfo([]); + assert.equal(execInfo.product, product, `Incorrect information for ${product}`); + }); + }); + + test('Ensure executable is set in Execution Info', async () => { + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(product => { + const info = lm.getLinterInfo(product); + const execInfo = info.getExecutionInfo([]); + const execPath = settings.linting[info.pathSettingName] as string; + assert.equal(execInfo.execPath, execPath, `Incorrect executable paths for product ${info.id}`); + }); + }); + + test('Ensure correct setting names are returned', async () => { + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(product => { + const linter = lm.getLinterInfo(product); + const expected = { + argsName: `${linter.id}Args` as keyof ILintingSettings, + pathName: `${linter.id}Path` as keyof ILintingSettings, + enabledName: `${linter.id}Enabled` as keyof ILintingSettings + }; + + assert.equal(linter.argsSettingName, expected.argsName, `Incorrect args settings for product ${linter.id}`); + assert.equal(linter.pathSettingName, expected.pathName, `Incorrect path settings for product ${linter.id}`); + assert.equal(linter.enabledSettingName, expected.enabledName, `Incorrect enabled settings for product ${linter.id}`); + }); + }); + + test('Ensure linter id match product', async () => { + const ids = ['flake8', 'mypy', 'pep8', 'prospector', 'pydocstyle', 'pylama', 'pylint']; + const products = [Product.flake8, Product.mypy, Product.pep8, Product.prospector, Product.pydocstyle, Product.pylama, Product.pylint]; + for (let i = 0; i < products.length; i += 1) { + const linter = lm.getLinterInfo(products[i]); + assert.equal(linter.id, ids[i], `Id ${ids[i]} does not match product ${products[i]}`); + } + }); + + test('Enable/disable linting', async () => { + await lm.enableLintingAsync(false); + assert.equal(lm.isLintingEnabled(), false, 'Linting not disabled'); + await lm.enableLintingAsync(true); + assert.equal(lm.isLintingEnabled(), true, 'Linting not enabled'); + }); + + test('Set single linter', async () => { + for (const linter of lm.getAllLinterInfos()) { + await lm.setActiveLintersAsync([linter.product]); + const selected = lm.getActiveLinters(); + assert.notEqual(selected.length, 0, 'Current linter is undefined'); + assert.equal(linter!.id, selected![0].id, `Selected linter ${selected} does not match requested ${linter.id}`); + } + }); + + test('Set multiple linters', async () => { + await lm.setActiveLintersAsync([Product.flake8, Product.pydocstyle]); + const selected = lm.getActiveLinters(); + assert.equal(selected.length, 2, 'Selected linters lengths does not match'); + assert.equal(Product.flake8, selected[0].product, `Selected linter ${selected[0].id} does not match requested 'flake8'`); + assert.equal(Product.pydocstyle, selected[1].product, `Selected linter ${selected[1].id} does not match requested 'pydocstyle'`); + }); + + test('Try setting unsupported linter', async () => { + const before = lm.getActiveLinters(); + assert.notEqual(before, undefined, 'Current/before linter is undefined'); + + await lm.setActiveLintersAsync([Product.nosetest]); + const after = lm.getActiveLinters(); + assert.notEqual(after, undefined, 'Current/after linter is undefined'); + + assert.equal(after![0].id, before![0].id, 'Should not be able to set unsupported linter'); + }); + + EnumEx.getValues(Product).forEach(product => { + const linterIdMapping = new Map(); + linterIdMapping.set(Product.flake8, 'flake8'); + linterIdMapping.set(Product.mypy, 'mypy'); + linterIdMapping.set(Product.pep8, 'pep8'); + linterIdMapping.set(Product.prospector, 'prospector'); + linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); + linterIdMapping.set(Product.pylama, 'pylama'); + linterIdMapping.set(Product.pylint, 'pylint'); + if (linterIdMapping.has(product)) { + return; + } + + test(`Ensure translation of ids throws exceptions for unknown linters (${product})`, async () => { + assert.throws(() => lm.getLinterInfo(product)); + }); + }); +}); diff --git a/src/test/linters/lint.multiroot.test.ts b/src/test/linters/lint.multiroot.test.ts index b06e4ec14544..038c2efa82c4 100644 --- a/src/test/linters/lint.multiroot.test.ts +++ b/src/test/linters/lint.multiroot.test.ts @@ -1,19 +1,20 @@ import * as assert from 'assert'; import * as path from 'path'; -import { CancellationTokenSource, ConfigurationTarget, OutputChannel, Uri, window, workspace } from 'vscode'; +import { CancellationTokenSource, ConfigurationTarget, OutputChannel, Uri, workspace } from 'vscode'; import { PythonSettings } from '../../client/common/configSettings'; -import { IInstaller, ILogger, IOutputChannel, Product } from '../../client/common/types'; -import * as baseLinter from '../../client/linters/baseLinter'; -import * as flake8 from '../../client/linters/flake8'; -import * as pyLint from '../../client/linters/pylint'; -import { ILinterHelper } from '../../client/linters/types'; +import { IConfigurationService, IOutputChannel, Product } from '../../client/common/types'; +import { ILinter, ILinterManager } from '../../client/linters/types'; import { TEST_OUTPUT_CHANNEL } from '../../client/unittests/common/constants'; import { closeActiveWindows, initialize, initializeTest, IS_MULTI_ROOT_TEST } from '../initialize'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; const multirootPath = path.join(__dirname, '..', '..', '..', 'src', 'testMultiRootWkspc'); +// tslint:disable-next-line:max-func-body-length suite('Multiroot Linting', () => { + const pylintSetting = 'linting.pylintEnabled'; + const flake8Setting = 'linting.flake8Enabled'; + let ioc: UnitTestIocContainer; suiteSetup(function () { if (!IS_MULTI_ROOT_TEST) { @@ -39,72 +40,55 @@ suite('Multiroot Linting', () => { ioc.registerProcessTypes(); ioc.registerLinterTypes(); ioc.registerVariableTypes(); + ioc.registerPlatformTypes(); } - function createLinter(linter: Product) { + async function createLinter(product: Product, resource?: Uri): Promise { const mockOutputChannel = ioc.serviceContainer.get(IOutputChannel, TEST_OUTPUT_CHANNEL); - const installer = ioc.serviceContainer.get(IInstaller); - const logger = ioc.serviceContainer.get(ILogger); - const linterHelper = ioc.serviceContainer.get(ILinterHelper); - switch (linter) { - case Product.pylint: { - return new pyLint.Linter(mockOutputChannel, installer, linterHelper, logger, ioc.serviceContainer); - } - case Product.flake8: { - return new flake8.Linter(mockOutputChannel, installer, linterHelper, logger, ioc.serviceContainer); - } - default: { - throw new Error('Not implemented for the unit tests'); - } - } + const lm = ioc.serviceContainer.get(ILinterManager); + await lm.setActiveLintersAsync([product], resource); + return lm.createLinter(product, mockOutputChannel, ioc.serviceContainer); } - async function testLinterInWorkspaceFolder(linter: baseLinter.BaseLinter, workspaceFolderRelativePath: string, mustHaveErrors: boolean) { + async function testLinterInWorkspaceFolder(product: Product, workspaceFolderRelativePath: string, mustHaveErrors: boolean): Promise { const fileToLint = path.join(multirootPath, workspaceFolderRelativePath, 'file.py'); const cancelToken = new CancellationTokenSource(); const document = await workspace.openTextDocument(fileToLint); + + const linter = await createLinter(product); const messages = await linter.lint(document, cancelToken.token); + const errorMessage = mustHaveErrors ? 'No errors returned by linter' : 'Errors returned by linter'; assert.equal(messages.length > 0, mustHaveErrors, errorMessage); } - async function enableDisableSetting(workspaceFolder, configTarget: ConfigurationTarget, setting: string, value: boolean) { - const folderUri = Uri.file(workspaceFolder); - const settings = workspace.getConfiguration('python.linting', folderUri); - await settings.update(setting, value, configTarget); + async function enableDisableSetting(workspaceFolder, configTarget: ConfigurationTarget, setting: string, value: boolean): Promise { + const config = ioc.serviceContainer.get(IConfigurationService); + await config.updateSettingAsync(setting, value, Uri.file(workspaceFolder), configTarget); } test('Enabling Pylint in root and also in Workspace, should return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'pylintEnabled', true); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'pylintEnabled', true); - await testLinterInWorkspaceFolder(createLinter(Product.pylint), 'workspace1', true); + await runTest(Product.pylint, true, true, pylintSetting); }); - test('Enabling Pylint in root and disabling in Workspace, should not return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'pylintEnabled', true); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'pylintEnabled', false); - await testLinterInWorkspaceFolder(createLinter(Product.pylint), 'workspace1', false); + await runTest(Product.pylint, true, false, pylintSetting); }); - test('Disabling Pylint in root and enabling in Workspace, should return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'pylintEnabled', false); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'pylintEnabled', true); - await testLinterInWorkspaceFolder(createLinter(Product.pylint), 'workspace1', true); + await runTest(Product.pylint, false, true, pylintSetting); }); test('Enabling Flake8 in root and also in Workspace, should return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'flake8Enabled', true); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'flake8Enabled', true); - await testLinterInWorkspaceFolder(createLinter(Product.flake8), 'workspace1', true); + await runTest(Product.flake8, true, true, flake8Setting); }); - test('Enabling Flake8 in root and disabling in Workspace, should not return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'flake8Enabled', true); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'flake8Enabled', false); - await testLinterInWorkspaceFolder(createLinter(Product.flake8), 'workspace1', false); + await runTest(Product.flake8, true, false, flake8Setting); }); - test('Disabling Flake8 in root and enabling in Workspace, should return errors', async () => { - await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, 'flake8Enabled', false); - await enableDisableSetting(path.join(multirootPath, 'workspace1'), ConfigurationTarget.WorkspaceFolder, 'flake8Enabled', true); - await testLinterInWorkspaceFolder(createLinter(Product.flake8), 'workspace1', true); + await runTest(Product.flake8, false, true, flake8Setting); }); + + async function runTest(product: Product, global: boolean, wks: boolean, setting: string): Promise { + const expected = wks ? wks : global; + await enableDisableSetting(multirootPath, ConfigurationTarget.Global, setting, global); + await enableDisableSetting(multirootPath, ConfigurationTarget.Workspace, setting, wks); + await testLinterInWorkspaceFolder(product, 'workspace1', expected); + } }); diff --git a/src/test/linters/lint.test.ts b/src/test/linters/lint.test.ts index 4717a84a61f9..571cc1cd5a7a 100644 --- a/src/test/linters/lint.test.ts +++ b/src/test/linters/lint.test.ts @@ -1,21 +1,14 @@ import * as assert from 'assert'; import * as fs from 'fs-extra'; import * as path from 'path'; -import { OutputChannel, Uri } from 'vscode'; +import { Uri } from 'vscode'; import * as vscode from 'vscode'; import { STANDARD_OUTPUT_CHANNEL } from '../../client/common/constants'; -import { Installer, Product, SettingToDisableProduct } from '../../client/common/installer/installer'; -import { IInstaller, ILogger, IOutputChannel } from '../../client/common/types'; -import { IServiceContainer } from '../../client/ioc/types'; -import { BaseLinter } from '../../client/linters/baseLinter'; -import * as baseLinter from '../../client/linters/baseLinter'; -import * as flake8 from '../../client/linters/flake8'; -import * as pep8 from '../../client/linters/pep8Linter'; -import * as prospector from '../../client/linters/prospector'; -import * as pydocstyle from '../../client/linters/pydocstyle'; -import * as pyLint from '../../client/linters/pylint'; -import { ILinterHelper } from '../../client/linters/types'; -import { deleteFile, PythonSettingKeys, rootWorkspaceUri, updateSetting } from '../common'; +import { Product } from '../../client/common/installer/productInstaller'; +import { IConfigurationService, IOutputChannel } from '../../client/common/types'; +import { LinterManager } from '../../client/linters/linterManager'; +import { ILinterManager, ILintMessage, LintMessageSeverity } from '../../client/linters/types'; +import { deleteFile, PythonSettingKeys, rootWorkspaceUri } from '../common'; import { closeActiveWindows, initialize, initializeTest, IS_MULTI_ROOT_TEST } from '../initialize'; import { MockOutputChannel } from '../mockClasses'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; @@ -28,79 +21,82 @@ const pydocstyleConfigPath27 = path.join(pythoFilesPath, 'pydocstyleconfig27'); const pylintConfigPath = path.join(pythoFilesPath, 'pylintconfig'); const fileToLint = path.join(pythoFilesPath, 'file.py'); -const pylintMessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 24, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 30, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 34, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 40, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 44, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 55, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 59, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 62, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling undefined-variable (E0602)', provider: '', type: '' }, - { line: 70, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 84, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 87, column: 0, severity: baseLinter.LintMessageSeverity.Hint, code: 'C0304', message: 'Final newline missing', provider: '', type: '' }, - { line: 11, column: 20, severity: baseLinter.LintMessageSeverity.Warning, code: 'W0613', message: 'Unused argument \'arg\'', provider: '', type: '' }, - { line: 26, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blop\' member', provider: '', type: '' }, - { line: 36, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 46, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 61, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 72, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 75, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 77, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 83, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' } +const pylintMessagesToBeReturned: ILintMessage[] = [ + { line: 24, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 30, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 34, column: 0, severity: LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, + { line: 40, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 44, column: 0, severity: LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, + { line: 55, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 59, column: 0, severity: LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, + { line: 62, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling undefined-variable (E0602)', provider: '', type: '' }, + { line: 70, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 84, column: 0, severity: LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, + { line: 87, column: 0, severity: LintMessageSeverity.Hint, code: 'C0304', message: 'Final newline missing', provider: '', type: '' }, + { line: 11, column: 20, severity: LintMessageSeverity.Warning, code: 'W0613', message: 'Unused argument \'arg\'', provider: '', type: '' }, + { line: 26, column: 14, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blop\' member', provider: '', type: '' }, + { line: 36, column: 14, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 46, column: 18, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 61, column: 18, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 72, column: 18, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 75, column: 18, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 77, column: 14, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, + { line: 83, column: 14, severity: LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' } ]; -const flake8MessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 5, column: 1, severity: baseLinter.LintMessageSeverity.Error, code: 'E302', message: 'expected 2 blank lines, found 1', provider: '', type: '' }, - { line: 19, column: 15, severity: baseLinter.LintMessageSeverity.Error, code: 'E127', message: 'continuation line over-indented for visual indent', provider: '', type: '' }, - { line: 24, column: 23, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 62, column: 30, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 70, column: 22, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 80, column: 5, severity: baseLinter.LintMessageSeverity.Error, code: 'E303', message: 'too many blank lines (2)', provider: '', type: '' }, - { line: 87, column: 24, severity: baseLinter.LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } +const flake8MessagesToBeReturned: ILintMessage[] = [ + { line: 5, column: 1, severity: LintMessageSeverity.Error, code: 'E302', message: 'expected 2 blank lines, found 1', provider: '', type: '' }, + { line: 19, column: 15, severity: LintMessageSeverity.Error, code: 'E127', message: 'continuation line over-indented for visual indent', provider: '', type: '' }, + { line: 24, column: 23, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 62, column: 30, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 70, column: 22, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 80, column: 5, severity: LintMessageSeverity.Error, code: 'E303', message: 'too many blank lines (2)', provider: '', type: '' }, + { line: 87, column: 24, severity: LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } ]; -const pep8MessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 5, column: 1, severity: baseLinter.LintMessageSeverity.Error, code: 'E302', message: 'expected 2 blank lines, found 1', provider: '', type: '' }, - { line: 19, column: 15, severity: baseLinter.LintMessageSeverity.Error, code: 'E127', message: 'continuation line over-indented for visual indent', provider: '', type: '' }, - { line: 24, column: 23, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 62, column: 30, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 70, column: 22, severity: baseLinter.LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, - { line: 80, column: 5, severity: baseLinter.LintMessageSeverity.Error, code: 'E303', message: 'too many blank lines (2)', provider: '', type: '' }, - { line: 87, column: 24, severity: baseLinter.LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } +const pep8MessagesToBeReturned: ILintMessage[] = [ + { line: 5, column: 1, severity: LintMessageSeverity.Error, code: 'E302', message: 'expected 2 blank lines, found 1', provider: '', type: '' }, + { line: 19, column: 15, severity: LintMessageSeverity.Error, code: 'E127', message: 'continuation line over-indented for visual indent', provider: '', type: '' }, + { line: 24, column: 23, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 62, column: 30, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 70, column: 22, severity: LintMessageSeverity.Error, code: 'E261', message: 'at least two spaces before inline comment', provider: '', type: '' }, + { line: 80, column: 5, severity: LintMessageSeverity.Error, code: 'E303', message: 'too many blank lines (2)', provider: '', type: '' }, + { line: 87, column: 24, severity: LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } ]; -const pydocstyleMessagseToBeReturned: baseLinter.ILintMessage[] = [ - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'e\')', column: 0, line: 1, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'t\')', column: 0, line: 5, type: '', provider: 'pydocstyle' }, - { code: 'D102', severity: baseLinter.LintMessageSeverity.Information, message: 'Missing docstring in public method', column: 4, line: 8, type: '', provider: 'pydocstyle' }, - { code: 'D401', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should be in imperative mood (\'thi\', not \'this\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'This\', not \'this\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'e\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'And\', not \'and\')', column: 4, line: 15, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'t\')', column: 4, line: 15, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 21, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 21, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 28, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 28, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 38, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 38, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 53, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 53, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 68, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 68, type: '', provider: 'pydocstyle' }, - { code: 'D403', severity: baseLinter.LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 80, type: '', provider: 'pydocstyle' }, - { code: 'D400', severity: baseLinter.LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 80, type: '', provider: 'pydocstyle' } +const pydocstyleMessagseToBeReturned: ILintMessage[] = [ + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'e\')', column: 0, line: 1, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'t\')', column: 0, line: 5, type: '', provider: 'pydocstyle' }, + { code: 'D102', severity: LintMessageSeverity.Information, message: 'Missing docstring in public method', column: 4, line: 8, type: '', provider: 'pydocstyle' }, + { code: 'D401', severity: LintMessageSeverity.Information, message: 'First line should be in imperative mood (\'thi\', not \'this\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'This\', not \'this\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'e\')', column: 4, line: 11, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'And\', not \'and\')', column: 4, line: 15, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'t\')', column: 4, line: 15, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 21, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 21, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 28, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 28, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 38, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 38, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 53, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 53, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 68, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 68, type: '', provider: 'pydocstyle' }, + { code: 'D403', severity: LintMessageSeverity.Information, message: 'First word of the first line should be properly capitalized (\'Test\', not \'test\')', column: 4, line: 80, type: '', provider: 'pydocstyle' }, + { code: 'D400', severity: LintMessageSeverity.Information, message: 'First line should end with a period (not \'g\')', column: 4, line: 80, type: '', provider: 'pydocstyle' } ]; -const filteredFlake8MessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 87, column: 24, severity: baseLinter.LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } +const filteredFlake8MessagesToBeReturned: ILintMessage[] = [ + { line: 87, column: 24, severity: LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } ]; -const filteredPep88MessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 87, column: 24, severity: baseLinter.LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } +const filteredPep88MessagesToBeReturned: ILintMessage[] = [ + { line: 87, column: 24, severity: LintMessageSeverity.Warning, code: 'W292', message: 'no newline at end of file', provider: '', type: '' } ]; // tslint:disable-next-line:max-func-body-length suite('Linting', () => { let ioc: UnitTestIocContainer; + let linterManager: ILinterManager; + let configService: IConfigurationService; + suiteSetup(initialize); setup(async () => { initializeDI(); @@ -122,78 +118,44 @@ suite('Linting', () => { ioc.registerProcessTypes(); ioc.registerLinterTypes(); ioc.registerVariableTypes(); + ioc.registerPlatformTypes(); + + linterManager = new LinterManager(ioc.serviceContainer); + configService = ioc.serviceContainer.get(IConfigurationService); } - type LinterCtor = { new(outputChannel: OutputChannel, installer: IInstaller, helper: ILinterHelper, logger: ILogger, serviceContainer: IServiceContainer): BaseLinter }; - function createLinter(linter: Product) { - const mockOutputChannel = ioc.serviceManager.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL); - const installer = ioc.serviceContainer.get(IInstaller); - const logger = ioc.serviceContainer.get(ILogger); - const linterHelper = ioc.serviceContainer.get(ILinterHelper); + async function resetSettings() { + // Don't run these updates in parallel, as they are updating the same file. + const target = IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace; - let linterCtor: LinterCtor; - switch (linter) { - case Product.pylint: { - linterCtor = pyLint.Linter; - break; - } - case Product.flake8: { - linterCtor = flake8.Linter; - break; - } - case Product.pep8: { - linterCtor = pep8.Linter; - break; - } - case Product.prospector: { - linterCtor = prospector.Linter; - break; - } - case Product.pydocstyle: { - linterCtor = pydocstyle.Linter; - break; - } - default: { - throw new Error('Not implemented for the unit tests'); - } - } + await configService.updateSettingAsync('linting.enabled', true, rootWorkspaceUri, target); + await configService.updateSettingAsync('linting.lintOnSave', false, rootWorkspaceUri, target); + await configService.updateSettingAsync('linting.pylintUseMinimalCheckers', false, workspaceUri); - if (linterCtor) { - return new linterCtor(mockOutputChannel, installer, linterHelper, logger, ioc.serviceContainer); - } + linterManager.getAllLinterInfos().forEach(async (x) => { + await configService.updateSettingAsync(makeSettingKey(x.product), false, rootWorkspaceUri, target); + }); } - async function resetSettings() { - // Don't run these updates in parallel, as they are updating the same file. - await updateSetting('linting.enabled', true, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - if (IS_MULTI_ROOT_TEST) { - await updateSetting('linting.enabled', true, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - } - await updateSetting('linting.lintOnSave', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.pylintEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.flake8Enabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.pep8Enabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.prospectorEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.mypyEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.pydocstyleEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - await updateSetting('linting.pylamaEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.Workspace); - if (IS_MULTI_ROOT_TEST) { - await updateSetting('linting.lintOnSave', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.pylintEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.flake8Enabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.pep8Enabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.prospectorEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.mypyEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.pydocstyleEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - await updateSetting('linting.pylamaEnabled', false, rootWorkspaceUri, vscode.ConfigurationTarget.WorkspaceFolder); - } + function makeSettingKey(product: Product): PythonSettingKeys { + return `linting.${linterManager.getLinterInfo(product).enabledSettingName}` as PythonSettingKeys; } - async function testEnablingDisablingOfLinter(product: Product, setting: PythonSettingKeys, enabled: boolean) { - const linter = createLinter(product)!; + + async function testEnablingDisablingOfLinter(product: Product, enabled: boolean, file?: string) { + const setting = makeSettingKey(product); const output = ioc.serviceContainer.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL); - await updateSetting(setting, enabled, rootWorkspaceUri, IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace); - const document = await vscode.workspace.openTextDocument(fileToLint); + + await configService.updateSettingAsync(setting, enabled, rootWorkspaceUri, + IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace); + + file = file ? file : fileToLint; + const document = await vscode.workspace.openTextDocument(file); const cancelToken = new vscode.CancellationTokenSource(); + + await linterManager.setActiveLintersAsync([product]); + await linterManager.enableLintingAsync(enabled); + const linter = linterManager.createLinter(product, output, ioc.serviceContainer); + const messages = await linter.lint(document, cancelToken.token); if (enabled) { assert.notEqual(messages.length, 0, `No linter errors when linter is enabled, Output - ${output.output}`); @@ -201,43 +163,48 @@ suite('Linting', () => { assert.equal(messages.length, 0, `Errors returned when linter is disabled, Output - ${output.output}`); } } + test('Disable Pylint and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pylint, 'linting.pylintEnabled', false); + await testEnablingDisablingOfLinter(Product.pylint, false); }); test('Enable Pylint and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pylint, 'linting.pylintEnabled', true); + await testEnablingDisablingOfLinter(Product.pylint, true); }); test('Disable Pep8 and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pep8, 'linting.pep8Enabled', false); + await testEnablingDisablingOfLinter(Product.pep8, false); }); test('Enable Pep8 and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pep8, 'linting.pep8Enabled', true); + await testEnablingDisablingOfLinter(Product.pep8, true); }); test('Disable Flake8 and test linter', async () => { - await testEnablingDisablingOfLinter(Product.flake8, 'linting.flake8Enabled', false); + await testEnablingDisablingOfLinter(Product.flake8, false); }); test('Enable Flake8 and test linter', async () => { - await testEnablingDisablingOfLinter(Product.flake8, 'linting.flake8Enabled', true); + await testEnablingDisablingOfLinter(Product.flake8, true); }); test('Disable Prospector and test linter', async () => { - await testEnablingDisablingOfLinter(Product.prospector, 'linting.prospectorEnabled', false); + await testEnablingDisablingOfLinter(Product.prospector, false); }); + // test('Enable Prospector and test linter', async () => { + // Fails on Travis. Can be run locally though. + // await testEnablingDisablingOfLinter(Product.prospector, true); + // }); test('Disable Pydocstyle and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pydocstyle, 'linting.pydocstyleEnabled', false); + await testEnablingDisablingOfLinter(Product.pydocstyle, false); }); test('Enable Pydocstyle and test linter', async () => { - await testEnablingDisablingOfLinter(Product.pydocstyle, 'linting.pydocstyleEnabled', true); + await testEnablingDisablingOfLinter(Product.pydocstyle, true); }); // tslint:disable-next-line:no-any - async function testLinterMessages(product: Product, pythonFile: string, messagesToBeReceived: baseLinter.ILintMessage[]): Promise { - const linter = createLinter(product)!; + async function testLinterMessages(product: Product, pythonFile: string, messagesToBeReceived: ILintMessage[]): Promise { const outputChannel = ioc.serviceContainer.get(IOutputChannel, STANDARD_OUTPUT_CHANNEL); const cancelToken = new vscode.CancellationTokenSource(); - const settingToEnable = SettingToDisableProduct.get(linter.product); - // tslint:disable-next-line:no-any prefer-type-cast - await updateSetting(settingToEnable as any, true, rootWorkspaceUri, IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace); const document = await vscode.workspace.openTextDocument(pythonFile); + + await linterManager.setActiveLintersAsync([product], document.uri); + const linter = linterManager.createLinter(product, outputChannel, ioc.serviceContainer); + const messages = await linter.lint(document, cancelToken.token); if (messagesToBeReceived.length === 0) { assert.equal(messages.length, 0, `No errors in linter, Output - ${outputChannel.output}`); @@ -272,7 +239,15 @@ suite('Linting', () => { await testLinterMessages(Product.pep8, path.join(pep8ConfigPath, 'file.py'), filteredPep88MessagesToBeReturned); }); test('Pydocstyle with config in root', async () => { + await configService.updateSettingAsync('linting.pylintUseMinimalCheckers', false, workspaceUri); await fs.copy(path.join(pydocstyleConfigPath27, '.pydocstyle'), path.join(workspaceUri.fsPath, '.pydocstyle')); await testLinterMessages(Product.pydocstyle, path.join(pydocstyleConfigPath27, 'file.py'), []); }); + test('PyLint minimal checkers', async () => { + const file = path.join(pythoFilesPath, 'minCheck.py'); + await configService.updateSettingAsync('linting.pylintUseMinimalCheckers', true, workspaceUri); + await testEnablingDisablingOfLinter(Product.pylint, false, file); + await configService.updateSettingAsync('linting.pylintUseMinimalCheckers', false, workspaceUri); + await testEnablingDisablingOfLinter(Product.pylint, true, file); + }); }); diff --git a/src/test/linters/pylint.test.ts b/src/test/linters/pylint.test.ts new file mode 100644 index 000000000000..cc527e320478 --- /dev/null +++ b/src/test/linters/pylint.test.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { expect } from 'chai'; +import * as path from 'path'; +import * as TypeMoq from 'typemoq'; +import { IFileSystem, IPlatformService } from '../../client/common/platform/types'; +import { Pylint } from '../../client/linters/pylint'; + +suite('Linting - Pylintrc search', () => { + const basePath = '/user/a/b/c/d'; + const file = path.join(basePath, 'file.py'); + const pylintrc = 'pylintrc'; + const dotPylintrc = '.pylintrc'; + + let fileSystem: TypeMoq.IMock; + let platformService: TypeMoq.IMock; + + setup(() => { + fileSystem = TypeMoq.Mock.ofType(); + platformService = TypeMoq.Mock.ofType(); + }); + + test('pylintrc in the file folder', async () => { + fileSystem.setup(x => x.fileExistsAsync(path.join(basePath, pylintrc))).returns(() => Promise.resolve(true)); + let result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${pylintrc}' not detected in the file folder.`); + + fileSystem.setup(x => x.fileExistsAsync(path.join(basePath, dotPylintrc))).returns(() => Promise.resolve(true)); + result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${dotPylintrc}' not detected in the file folder.`); + }); + test('pylintrc up the module tree', async () => { + const module1 = path.join('/user/a/b/c/d', '__init__.py'); + const module2 = path.join('/user/a/b/c', '__init__.py'); + const module3 = path.join('/user/a/b', '__init__.py'); + const rc = path.join('/user/a/b/c', pylintrc); + + fileSystem.setup(x => x.fileExistsAsync(module1)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(module2)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(module3)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(rc)).returns(() => Promise.resolve(true)); + + const result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${pylintrc}' not detected in the module tree.`); + }); + test('.pylintrc up the module tree', async () => { + // Don't use path.join since it will use / on Travis and Mac + const module1 = path.join('/user/a/b/c/d', '__init__.py'); + const module2 = path.join('/user/a/b/c', '__init__.py'); + const module3 = path.join('/user/a/b', '__init__.py'); + const rc = path.join('/user/a/b/c', pylintrc); + + fileSystem.setup(x => x.fileExistsAsync(module1)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(module2)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(module3)).returns(() => Promise.resolve(true)); + fileSystem.setup(x => x.fileExistsAsync(rc)).returns(() => Promise.resolve(true)); + + const result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${dotPylintrc}' not detected in the module tree.`); + }); + test('.pylintrc up the ~ folder', async () => { + const home = path.resolve('~'); + const rc = path.join(home, dotPylintrc); + fileSystem.setup(x => x.fileExistsAsync(rc)).returns(() => Promise.resolve(true)); + + const result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${dotPylintrc}' not detected in the ~ folder.`); + }); + test('pylintrc up the ~/.config folder', async () => { + const home = path.resolve('~'); + const rc = path.join(home, '.config', pylintrc); + fileSystem.setup(x => x.fileExistsAsync(rc)).returns(() => Promise.resolve(true)); + + const result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${pylintrc}' not detected in the ~/.config folder.`); + }); + test('pylintrc in the /etc folder', async () => { + platformService.setup(x => x.isWindows).returns(() => false); + const rc = path.join('/etc', pylintrc); + fileSystem.setup(x => x.fileExistsAsync(rc)).returns(() => Promise.resolve(true)); + + const result = await Pylint.hasConfigurationFile(fileSystem.object, file, platformService.object); + expect(result).to.be.equal(true, `'${pylintrc}' not detected in the /etc folder.`); + }); +}); diff --git a/src/test/pythonFiles/linting/minCheck.py b/src/test/pythonFiles/linting/minCheck.py new file mode 100644 index 000000000000..d93fa56f7e8a --- /dev/null +++ b/src/test/pythonFiles/linting/minCheck.py @@ -0,0 +1 @@ +filter(lambda x: x == 1, [1, 1, 2]) diff --git a/src/test/pythonFiles/linting/pydocstyleconfig27/.pydocstyle b/src/test/pythonFiles/linting/pydocstyleconfig27/.pydocstyle index ad9ca74f73c6..19020834ad32 100644 --- a/src/test/pythonFiles/linting/pydocstyleconfig27/.pydocstyle +++ b/src/test/pythonFiles/linting/pydocstyleconfig27/.pydocstyle @@ -1,2 +1,2 @@ [pydocstyle] -ignore=D400,D401,D402,D403,D203,D102 +ignore=D400,D401,D402,D403,D404,D203,D102,D107 diff --git a/src/test/terminals/codeExecution/codeExecutionManager.test.ts b/src/test/terminals/codeExecution/codeExecutionManager.test.ts index 7e8c81e2eafd..8dec4d7f5025 100644 --- a/src/test/terminals/codeExecution/codeExecutionManager.test.ts +++ b/src/test/terminals/codeExecution/codeExecutionManager.test.ts @@ -69,7 +69,7 @@ suite('Terminal - Code Execution Manager', () => { serviceContainer.setup(s => s.get(TypeMoq.It.isValue(ICodeExecutionHelper))).returns(() => helper.object); await commandHandler!(); - helper.verify(h => h.getFileToExecute(), TypeMoq.Times.once()); + helper.verify(async h => await h.getFileToExecute(), TypeMoq.Times.once()); }); test('Ensure executeFileInterTerminal will use provided file', async () => { @@ -96,8 +96,8 @@ suite('Terminal - Code Execution Manager', () => { const fileToExecute = Uri.file('x'); await commandHandler!(fileToExecute); - helper.verify(h => h.getFileToExecute(), TypeMoq.Times.never()); - executionService.verify(e => e.executeFile(TypeMoq.It.isValue(fileToExecute)), TypeMoq.Times.once()); + helper.verify(async h => await h.getFileToExecute(), TypeMoq.Times.never()); + executionService.verify(async e => await e.executeFile(TypeMoq.It.isValue(fileToExecute)), TypeMoq.Times.once()); }); test('Ensure executeFileInterTerminal will use active file', async () => { @@ -119,12 +119,12 @@ suite('Terminal - Code Execution Manager', () => { const fileToExecute = Uri.file('x'); const helper = TypeMoq.Mock.ofType(); serviceContainer.setup(s => s.get(TypeMoq.It.isValue(ICodeExecutionHelper))).returns(() => helper.object); - helper.setup(h => h.getFileToExecute).returns(() => () => Promise.resolve(fileToExecute)); + helper.setup(async h => await h.getFileToExecute()).returns(() => Promise.resolve(fileToExecute)); const executionService = TypeMoq.Mock.ofType(); serviceContainer.setup(s => s.get(TypeMoq.It.isValue(ICodeExecutionService), TypeMoq.It.isValue('standard'))).returns(() => executionService.object); await commandHandler!(fileToExecute); - executionService.verify(e => e.executeFile(TypeMoq.It.isValue(fileToExecute)), TypeMoq.Times.once()); + executionService.verify(async e => await e.executeFile(TypeMoq.It.isValue(fileToExecute)), TypeMoq.Times.once()); }); async function testExecutionOfSelectionWithoutAnyActiveDocument(commandId: string, executionSericeId: string) { @@ -150,7 +150,7 @@ suite('Terminal - Code Execution Manager', () => { documentManager.setup(d => d.activeTextEditor).returns(() => undefined); await commandHandler!(); - executionService.verify(e => e.execute(TypeMoq.It.isAny()), TypeMoq.Times.never()); + executionService.verify(async e => await e.execute(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure executeSelectionInTerminal will do nothing if theres no active document', async () => { @@ -186,7 +186,7 @@ suite('Terminal - Code Execution Manager', () => { documentManager.setup(d => d.activeTextEditor).returns(() => { return {} as any; }); await commandHandler!(); - executionService.verify(e => e.execute(TypeMoq.It.isAny()), TypeMoq.Times.never()); + executionService.verify(async e => await e.execute(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure executeSelectionInTerminal will do nothing if no text is selected', async () => { @@ -228,7 +228,7 @@ suite('Terminal - Code Execution Manager', () => { documentManager.setup(d => d.activeTextEditor).returns(() => activeEditor.object); await commandHandler!(); - executionService.verify(e => e.execute(TypeMoq.It.isValue(textSelected), TypeMoq.It.isValue(activeDocumentUri)), TypeMoq.Times.once()); + executionService.verify(async e => await e.execute(TypeMoq.It.isValue(textSelected), TypeMoq.It.isValue(activeDocumentUri)), TypeMoq.Times.once()); } test('Ensure executeSelectionInTerminal will normalize selected text and send it to the terminal', async () => { await testExecutionOfSelectionIsSentToTerminal(Commands.Exec_Selection_In_Terminal, 'standard'); diff --git a/src/test/terminals/codeExecution/terminalCodeExec.test.ts b/src/test/terminals/codeExecution/terminalCodeExec.test.ts index c6bf45d2277b..90c92560ee20 100644 --- a/src/test/terminals/codeExecution/terminalCodeExec.test.ts +++ b/src/test/terminals/codeExecution/terminalCodeExec.test.ts @@ -95,7 +95,7 @@ suite('Terminal Code Execution', () => { terminalFactory.setup(f => f.getTerminalService(TypeMoq.It.isAny(), TypeMoq.It.isValue(expectedTerminalTitle))).returns(() => terminalService.object); }); - async function ensureTerminalIsCreatedUponInvokingInitializeRepl(isWindows: boolean, isOsx: boolean, isLinux: boolean) { + async function ensureTerminalIsCreatedUponInvokingInitializeRepl(isWindows: boolean, isOsx: boolean, isLinux: boolean): Promise { platform.setup(p => p.isWindows).returns(() => isWindows); platform.setup(p => p.isMac).returns(() => isOsx); platform.setup(p => p.isLinux).returns(() => isLinux); @@ -124,7 +124,7 @@ suite('Terminal Code Execution', () => { terminalFactory.setup(f => f.getTerminalService(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => terminalService.object); }); - async function ensureWeSetCurrentDirectoryBeforeExecutingAFile(isWindows: boolean) { + async function ensureWeSetCurrentDirectoryBeforeExecutingAFile(isWindows: boolean): Promise { const file = Uri.file(path.join('c', 'path', 'to', 'file', 'one.py')); terminalSettings.setup(t => t.executeInFileDir).returns(() => true); workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); @@ -135,7 +135,7 @@ suite('Terminal Code Execution', () => { await executor.executeFile(file); - terminalService.verify(t => t.sendText(TypeMoq.It.isValue(`cd ${path.dirname(file.path)}`)), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendText(TypeMoq.It.isValue(`cd ${path.dirname(file.fsPath)}`)), TypeMoq.Times.once()); } test('Ensure we set current directory before executing file (non windows)', async () => { await ensureWeSetCurrentDirectoryBeforeExecutingAFile(false); @@ -144,7 +144,7 @@ suite('Terminal Code Execution', () => { await ensureWeSetCurrentDirectoryBeforeExecutingAFile(true); }); - async function ensureWeWetCurrentDirectoryAndQuoteBeforeExecutingFile(isWindows: boolean) { + async function ensureWeWetCurrentDirectoryAndQuoteBeforeExecutingFile(isWindows: boolean): Promise { const file = Uri.file(path.join('c', 'path', 'to', 'file with spaces in path', 'one.py')); terminalSettings.setup(t => t.executeInFileDir).returns(() => true); workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); @@ -154,7 +154,7 @@ suite('Terminal Code Execution', () => { terminalSettings.setup(t => t.launchArgs).returns(() => []); await executor.executeFile(file); - terminalService.verify(t => t.sendText(TypeMoq.It.isValue(`cd "${path.dirname(file.path)}"`)), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendText(TypeMoq.It.isValue(`cd "${path.dirname(file.fsPath)}"`)), TypeMoq.Times.once()); } test('Ensure we set current directory (and quote it when containing spaces) before executing file (non windows)', async () => { @@ -165,7 +165,7 @@ suite('Terminal Code Execution', () => { await ensureWeWetCurrentDirectoryAndQuoteBeforeExecutingFile(true); }); - async function ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileInSameDirectory(isWindows: boolean) { + async function ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileInSameDirectory(isWindows: boolean): Promise { const file = Uri.file(path.join('c', 'path', 'to', 'file with spaces in path', 'one.py')); terminalSettings.setup(t => t.executeInFileDir).returns(() => true); workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => workspaceFolder.object); @@ -176,7 +176,7 @@ suite('Terminal Code Execution', () => { await executor.executeFile(file); - terminalService.verify(t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure we do not set current directory before executing file if in the same directory (non windows)', async () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileInSameDirectory(false); @@ -185,7 +185,7 @@ suite('Terminal Code Execution', () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileInSameDirectory(true); }); - async function ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileNotInSameDirectory(isWindows: boolean) { + async function ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileNotInSameDirectory(isWindows: boolean): Promise { const file = Uri.file(path.join('c', 'path', 'to', 'file with spaces in path', 'one.py')); terminalSettings.setup(t => t.executeInFileDir).returns(() => true); workspace.setup(w => w.getWorkspaceFolder(TypeMoq.It.isAny())).returns(() => undefined); @@ -195,7 +195,7 @@ suite('Terminal Code Execution', () => { await executor.executeFile(file); - terminalService.verify(t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); } test('Ensure we do not set current directory before executing file if file is not in a workspace (non windows)', async () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileNotInSameDirectory(false); @@ -204,7 +204,7 @@ suite('Terminal Code Execution', () => { await ensureWeDoNotSetCurrentDirectoryBeforeExecutingFileNotInSameDirectory(true); }); - async function testFileExecution(isWindows: boolean, pythonPath: string, terminalArgs: string[], file: Uri) { + async function testFileExecution(isWindows: boolean, pythonPath: string, terminalArgs: string[], file: Uri): Promise { platform.setup(p => p.isWindows).returns(() => isWindows); settings.setup(s => s.pythonPath).returns(() => pythonPath); terminalSettings.setup(t => t.launchArgs).returns(() => terminalArgs); @@ -214,7 +214,7 @@ suite('Terminal Code Execution', () => { await executor.executeFile(file); const expectedPythonPath = isWindows ? pythonPath.replace(/\\/g, '/') : pythonPath; const expectedArgs = terminalArgs.concat(file.fsPath.indexOf(' ') > 0 ? `"${file.fsPath}"` : file.fsPath); - terminalService.verify(t => t.sendCommand(TypeMoq.It.isValue(expectedPythonPath), TypeMoq.It.isValue(expectedArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(expectedPythonPath), TypeMoq.It.isValue(expectedArgs)), TypeMoq.Times.once()); } test('Ensure python file execution script is sent to terminal on windows', async () => { @@ -249,35 +249,35 @@ suite('Terminal Code Execution', () => { expect(replCommandArgs.args).to.be.deep.equal(expectedTerminalArgs, 'Incorrect arguments'); } - test('Ensure fully qualified python path is escaped when building repl args on Windows', async () => { + test('Ensure fully qualified python path is escaped when building repl args on Windows', () => { const pythonPath = 'c:\\program files\\python\\python.exe'; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(true, pythonPath, 'c:/program files/python/python.exe', terminalArgs); }); - test('Ensure fully qualified python path is returned as is, when building repl args on Windows', async () => { + test('Ensure fully qualified python path is returned as is, when building repl args on Windows', () => { const pythonPath = 'c:/program files/python/python.exe'; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(true, pythonPath, pythonPath, terminalArgs); }); - test('Ensure python path is returned as is, when building repl args on Windows', async () => { + test('Ensure python path is returned as is, when building repl args on Windows', () => { const pythonPath = 'python'; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(true, pythonPath, pythonPath, terminalArgs); }); - test('Ensure fully qualified python path is returned as is, on non Windows', async () => { + test('Ensure fully qualified python path is returned as is, on non Windows', () => { const pythonPath = 'usr/bin/python'; const terminalArgs = ['-a', 'b', 'c']; testReplCommandArguments(false, pythonPath, pythonPath, terminalArgs); }); - test('Ensure python path is returned as is, on non Windows', async () => { + test('Ensure python path is returned as is, on non Windows', () => { const pythonPath = 'python'; const terminalArgs = ['-a', 'b', 'c']; @@ -290,8 +290,8 @@ suite('Terminal Code Execution', () => { // tslint:disable-next-line:no-any await executor.execute(undefined as any as string); - terminalService.verify(t => t.sendCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never()); - terminalService.verify(t => t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny()), TypeMoq.Times.never()); + terminalService.verify(async t => await t.sendText(TypeMoq.It.isAny()), TypeMoq.Times.never()); }); test('Ensure repl is initialized once before sending text to the repl', async () => { @@ -307,7 +307,7 @@ suite('Terminal Code Execution', () => { await executor.execute('cmd3'); const expectedTerminalArgs = isDjangoRepl ? terminalArgs.concat(['manage.py', 'shell']) : terminalArgs; - terminalService.verify(t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); }); test('Ensure repl is re-initialized when temrinal is closed', async () => { @@ -333,15 +333,15 @@ suite('Terminal Code Execution', () => { const expectedTerminalArgs = isDjangoRepl ? terminalArgs.concat(['manage.py', 'shell']) : terminalArgs; expect(closeTerminalCallback).not.to.be.an('undefined', 'Callback not initialized'); - terminalService.verify(t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.once()); closeTerminalCallback!.call(terminalService.object); await executor.execute('cmd4'); - terminalService.verify(t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(2)); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(2)); closeTerminalCallback!.call(terminalService.object); await executor.execute('cmd5'); - terminalService.verify(t => t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(3)); + terminalService.verify(async t => await t.sendCommand(TypeMoq.It.isValue(pythonPath), TypeMoq.It.isValue(expectedTerminalArgs)), TypeMoq.Times.exactly(3)); }); test('Ensure code is sent to terminal', async () => { @@ -352,10 +352,10 @@ suite('Terminal Code Execution', () => { terminalSettings.setup(t => t.launchArgs).returns(() => terminalArgs); await executor.execute('cmd1'); - terminalService.verify(t => t.sendText('cmd1'), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendText('cmd1'), TypeMoq.Times.once()); await executor.execute('cmd2'); - terminalService.verify(t => t.sendText('cmd2'), TypeMoq.Times.once()); + terminalService.verify(async t => await t.sendText('cmd2'), TypeMoq.Times.once()); }); }); });