├── .gitignore
├── .jshintrc
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── img
├── config.gif
├── example.gif
└── install.gif
├── lib
├── cache.js
├── cache.js.map
├── config.js
├── config.js.map
├── init.js
├── init.js.map
├── linter.js
├── linter.js.map
├── logger.js
├── logger.js.map
├── parser.js
├── parser.js.map
├── runner.js
├── runner.js.map
├── util.js
└── util.js.map
├── package.json
├── src
├── cache.ts
├── config.ts
├── init.ts
├── linter.ts
├── logger.ts
├── parser.ts
├── runner.ts
└── util.ts
├── test.py
├── tsconfig.json
└── typings.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | node_modules
4 | typings
5 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": true,
3 | "moz": true
4 | }
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | #### 3.1.2
2 | * (#37) Fix issue: Cannot read property 'getPath' of undefined
3 |
4 | #### 3.1.1
5 | * Update release notes and readme file
6 |
7 | #### 3.1.0
8 | * (#31) Execution finished with error because of pylama exit code change
9 |
10 | #### 3.0.5
11 | * (#28) Add cache functionality
12 | * (#25) Remove underline options from plugin configuration
13 | * (#27) Documentation update
14 | * (#26) Regenerate new plugin exaples
15 |
16 | #### 3.0.4
17 | * Rewrite whole plugin to typescript
18 | * (#23) Remove logic responsible by disabling console
19 | * (#22) Add link to lint errors
20 | * (#17) Change "Lint trigger" option names
21 | * Fix few deployment issues
22 | * Add colorLink option
23 |
24 | #### 2.1.7
25 | * Fix error if file is in edition without project
26 |
27 | #### 2.1.6
28 | * Add option to run only single lint instance
29 | * Fix error with blocked lint operation
30 | * Change way how results are returned to linter
31 |
32 | #### 2.1.5
33 | * Fix error with lint plugins order
34 | * Fix error related to messages without error code
35 |
36 | #### 2.1.4
37 | * Reduce plugin dependencies
38 | * Reduce plugin startup
39 |
40 | #### 2.1.3
41 | * Fix error message
42 | * Set whole line for errors with position 0
43 | * Set items order in settings window
44 | * Speed up startup
45 |
46 | #### 2.1.2
47 | * Update package documentation
48 |
49 | #### 2.1.1
50 | * Update package description
51 |
52 | #### 2.1.0
53 | * Move documentation to separate project
54 | * Add trigger options: after save, after change, after save and change
55 | * Add option to define underscore type and size
56 |
57 | #### 2.0.0
58 | * First release
59 | * Fix error with unknown line number
60 | * Update documentation
61 |
62 | #### 1.0.0
63 | * Create plugin
64 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Pawel Chomicki
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # linter-python package
2 |
3 | Plugin to lint python files. Whole logic based on pylama and pylama-pylint applications.
4 |
5 | 
6 |
7 | ## Requirements
8 |
9 | * python >= 2.7
10 | * pylama >= 7.3.3
11 | * pylama-pylint (optional)
12 |
13 | ## Atom linters
14 |
15 | * [Atom Linters](http://atomlinter.github.io/)
16 |
17 | #### Linters for python
18 |
19 | * [linter-python](https://atom.io/packages/linter-python)
20 | * [linter-pep8](https://atom.io/packages/linter-pep8)
21 | * [linter-pydocstyle](https://atom.io/packages/linter-pydocstyle)
22 | * [linter-flake8](https://atom.io/packages/linter-flake8)
23 | * [linter-pylama](https://atom.io/packages/linter-pylama)
24 |
25 | ## Plugin installation
26 |
27 | #### Atom plugin installation
28 |
29 | 
30 |
31 | * Go to Settings -> Install
32 | * Type "linter-python"
33 | * Press "Install"
34 |
35 | #### Pylama installation
36 |
37 | ```
38 | pip install pylama pylama-pylint
39 | ```
40 |
41 | If pip is something new for you please look [here](https://pip.pypa.io/en/stable/installing/) for more detail.
42 |
43 | ## Plugin configuration
44 |
45 | #### Basic plugin configuration
46 |
47 | 
48 |
49 | * Go to Settings -> Packages
50 | * Type "linter-python" and go to plugin settings
51 | * Set path to pylama binary e.g. /usr/bin/pylama
52 | * Select needed pylama options
53 |
54 | #### Options added in 3.0.4 version
55 |
56 | 
57 |
58 | * Atom API was used to select error
59 | * URL to error description
60 |
61 | #### Plugin configuration vs. performance
62 |
63 | Please be informed that plugin has to create temporary files to lint file in the fly. In case of any performance issues please try
64 | to change trigger option to "File saved". For such option temporary files are not needed.
65 |
66 | ## Pylama related topics
67 |
68 | #### Pylama results depend on plugin order
69 |
70 | It was discovered that pylama plugin order may change lint results. Issue is under investigated and will be reported
71 | to pylama project as soon as I get time to create test scenarios.
72 |
73 | Tests show that the most trusted configuration is: mccabe,pyflakes,pylint,pep8,pep257
74 |
75 | #### Pyflakes plugin may change pylama result
76 |
77 | New issue was created in pylama project. Pylama results are not constant when pyflakes plugin is enabled. Issue is visible with Python 3.5.1
78 |
79 | Issue details are available [here](https://github.com/klen/pylama/issues/67).
80 |
81 | ## Lint errors
82 |
83 | Starting from plugin version 3.0.0 lint output provides link to error description available on GitHub [project](https://github.com/pchomik/linter-python-doc/blob/master/errors/).
84 |
85 | Thanks to @linickx who created all pages. Please provide more pull requests if you like to create single place for all python defined errors.
86 |
87 | ## Contribution
88 |
89 | Pull requests, issues, issue investigation, reviews are more than welcome.
90 |
91 | ## Contributors
92 |
93 | * @linickx
94 | * @Arcanemagus
95 | * @Zebradil
96 |
97 | ## License
98 |
99 | Package license is available [here](https://raw.githubusercontent.com/pchomik/linter-python/master/LICENSE.md)
100 |
101 | ## Contact
102 |
103 | Please create issue in case of any question or feature request.
104 |
105 | ## Changelog
106 |
107 | This section contains changes from last 3 releases.
108 |
109 | Full list of changes is available [here](https://raw.githubusercontent.com/pchomik/linter-python/master/CHANGELOG.md)
110 |
111 | #### 3.1.2
112 | * (#37) Fix issue: Cannot read property 'getPath' of undefined
113 |
114 | #### 3.1.1
115 | * Update release notes and readme file
116 |
117 | #### 3.1.0
118 | * (#31) Execution finished with error because of pylama exit code change
119 |
120 | #### 3.0.5
121 | * (#28) Add cache functionality
122 | * (#25) Remove underline options from plugin configuration
123 | * (#27) Documentation update
124 | * (#26) Regenerate new plugin exaples
125 |
--------------------------------------------------------------------------------
/img/config.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pchomik/linter-python/15b0e636b0f26a4bff5e14c443ae9f7d26c10080/img/config.gif
--------------------------------------------------------------------------------
/img/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pchomik/linter-python/15b0e636b0f26a4bff5e14c443ae9f7d26c10080/img/example.gif
--------------------------------------------------------------------------------
/img/install.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pchomik/linter-python/15b0e636b0f26a4bff5e14c443ae9f7d26c10080/img/install.gif
--------------------------------------------------------------------------------
/lib/cache.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var logger_1 = require('./logger');
3 | var logger = logger_1.Logger.getInstance();
4 | var Cache = (function () {
5 | function Cache() {
6 | this.messages = {};
7 | if (Cache._instance) {
8 | throw new Error("Error: Instantiation failed: Use Logger.getInstance() instead of new.");
9 | }
10 | Cache._instance = this;
11 | }
12 | Cache.getInstance = function () {
13 | return Cache._instance;
14 | };
15 | Cache.prototype.store = function (messages) {
16 | logger.log(">>> NEW MESSAGES STORED IN CACHE <<<");
17 | this.messages[this.filePointer] = messages;
18 | };
19 | Cache.prototype.get = function () {
20 | logger.log(">>> MESSAGES RETURNED FROM CACHE <<<");
21 | if (!this.messages[this.filePointer]) {
22 | return [];
23 | }
24 | else {
25 | return this.messages[this.filePointer];
26 | }
27 | };
28 | Cache.prototype.set = function (filePath) {
29 | this.filePointer = filePath;
30 | logger.log(">>> CACHE SET FOR " + this.filePointer + " <<<");
31 | };
32 | Cache._instance = new Cache();
33 | return Cache;
34 | }());
35 | exports.Cache = Cache;
36 | //# sourceMappingURL=cache.js.map
--------------------------------------------------------------------------------
/lib/cache.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":";AAAA,uBAAuB,UAAU,CAAC,CAAA;AAGlC,IAAM,MAAM,GAAU,eAAM,CAAC,WAAW,EAAE,CAAC;AAG3C;IAMI;QAHQ,aAAQ,GAAO,EAAE,CAAC;QAItB,EAAE,CAAA,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC7F,CAAC;QACD,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IAC3B,CAAC;IAEa,iBAAW,GAAzB;QAEI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;IAC3B,CAAC;IAEM,qBAAK,GAAZ,UAAa,QAAQ;QACjB,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,QAAQ,CAAC;IAC/C,CAAC;IAEM,mBAAG,GAAV;QACI,MAAM,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACnD,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,CAAC,EAAE,CAAC;QACd,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,CAAC;IACL,CAAC;IAEM,mBAAG,GAAV,UAAW,QAAQ;QACf,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,uBAAqB,IAAI,CAAC,WAAW,SAAM,CAAC,CAAC;IAC5D,CAAC;IAlCc,eAAS,GAAS,IAAI,KAAK,EAAE,CAAC;IAmCjD,YAAC;AAAD,CAAC,AApCD,IAoCC;AApCY,aAAK,QAoCjB,CAAA"}
--------------------------------------------------------------------------------
/lib/config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /** Module to define plugin configuration and react on change. */
3 | var logger_1 = require('./logger');
4 | var CompositeDisposable = require('atom').CompositeDisposable;
5 | var logger = logger_1.Logger.getInstance();
6 | /** Plugin runtime configuration. What is really set by the user when Atom is working */
7 | var PluginRuntimeConfig = (function () {
8 | function PluginRuntimeConfig() {
9 | this.pylamaArgs = [];
10 | this.executablePath = '';
11 | this.enableDebug = false;
12 | this.lintOnChange = false;
13 | this.lintOnSave = false;
14 | this.lintOnFly = false;
15 | this.optionsFileSet = false;
16 | this.underlineType = 'Whole line';
17 | this.underlineSize = 2;
18 | this.limitToSingleInstance = true;
19 | this.linkColor = "";
20 | this.initialConfg = this.initialConfg.bind(this);
21 | this.updateConfig = this.updateConfig.bind(this);
22 | this.subs = new CompositeDisposable();
23 | this.subs.add(atom.config.observe('linter-python.executablePath', {}, this.updateConfig));
24 | this.subs.add(atom.config.observe('linter-python.withPep8', {}, this.updateConfig));
25 | this.subs.add(atom.config.observe('linter-python.withPep257', {}, this.updateConfig));
26 | this.subs.add(atom.config.observe('linter-python.withMcCabe', {}, this.updateConfig));
27 | this.subs.add(atom.config.observe('linter-python.withPylint', {}, this.updateConfig));
28 | this.subs.add(atom.config.observe('linter-python.withPyflakes', {}, this.updateConfig));
29 | this.subs.add(atom.config.observe('linter-python.ignoreCodes', {}, this.updateConfig));
30 | this.subs.add(atom.config.observe('linter-python.skipFiles', {}, this.updateConfig));
31 | this.subs.add(atom.config.observe('linter-python.force', {}, this.updateConfig));
32 | this.subs.add(atom.config.observe('linter-python.optionsFile', {}, this.updateConfig));
33 | this.subs.add(atom.config.observe('linter-python.enableDebug', {}, this.updateConfig));
34 | this.subs.add(atom.config.observe('linter-python.lintTrigger', {}, this.updateConfig));
35 | this.subs.add(atom.config.observe('linter-python.underlineSize', {}, this.updateConfig));
36 | this.subs.add(atom.config.observe('linter-python.underlineType', {}, this.updateConfig));
37 | this.subs.add(atom.config.observe('linter-python.limitToSingleInstance', {}, this.updateConfig));
38 | this.subs.add(atom.config.observe('linter-python.linkColor', {}, this.updateConfig));
39 | }
40 | /** Set default cofiguration values */
41 | PluginRuntimeConfig.prototype.initialConfg = function () {
42 | var linters = [];
43 | this.pylamaArgs = [];
44 | this.optionsFileSet = false;
45 | this.executablePath = this.readConfigValue('executablePath');
46 | this.limitToSingleInstance = this.readConfigValue('limitToSingleInstance');
47 | this.linkColor = this.readConfigValue('linkColor');
48 | this.underlineType = this.readConfigValue('underlineType');
49 | if (this.underlineType == 'Only place with error') {
50 | this.underlineSize = this.readConfigValue('underlineSize');
51 | }
52 | var enabledDebug = this.readConfigValue('enableDebug');
53 | if (enabledDebug) {
54 | logger.enableLogger();
55 | }
56 | else {
57 | logger.disableLogger();
58 | }
59 | var withMcCabe = this.readConfigValue('withMcCabe');
60 | if (withMcCabe) {
61 | linters.push('mccabe');
62 | }
63 | var withPyflakes = this.readConfigValue('withPyflakes');
64 | if (withPyflakes) {
65 | linters.push('pyflakes');
66 | }
67 | var withPylint = this.readConfigValue('withPylint');
68 | if (withPylint) {
69 | linters.push('pylint');
70 | }
71 | var withPep8 = this.readConfigValue('withPep8');
72 | if (withPep8) {
73 | linters.push('pep8');
74 | }
75 | var withPep257 = this.readConfigValue('withPep257');
76 | if (withPep257) {
77 | linters.push('pep257');
78 | }
79 | if (linters.length > 0) {
80 | this.pylamaArgs.push('-l');
81 | this.pylamaArgs.push(linters.join());
82 | }
83 | var skipFiles = this.readConfigValue('skipFiles');
84 | if (skipFiles.length > 0) {
85 | this.pylamaArgs.push('--skip');
86 | this.pylamaArgs.push(skipFiles);
87 | }
88 | var ignoreCodes = this.readConfigValue('ignoreCodes');
89 | if (ignoreCodes.length > 0) {
90 | this.pylamaArgs.push('-i');
91 | this.pylamaArgs.push(ignoreCodes);
92 | }
93 | var optionsFile = this.readConfigValue('optionsFile');
94 | if (optionsFile.length > 0) {
95 | this.optionsFileSet = true;
96 | this.pylamaArgs.push('-o');
97 | this.pylamaArgs.push(optionsFile);
98 | }
99 | var force = this.readConfigValue('force');
100 | if (force) {
101 | this.pylamaArgs.push('-F');
102 | }
103 | var lintTrigger = this.readConfigValue('lintTrigger');
104 | if (lintTrigger == 'File saved') {
105 | this.lintOnSave = true;
106 | this.lintOnFly = false;
107 | }
108 | else if (lintTrigger == 'File modified') {
109 | this.lintOnSave = false;
110 | this.lintOnFly = true;
111 | }
112 | else if (lintTrigger == 'File saved or modified') {
113 | this.lintOnSave = true;
114 | this.lintOnFly = true;
115 | }
116 | };
117 | /** Method to simplify variable reading */
118 | PluginRuntimeConfig.prototype.readConfigValue = function (value) {
119 | try {
120 | return atom.config.get("linter-python." + value);
121 | }
122 | catch (err) {
123 | console.log(err);
124 | return '';
125 | }
126 | };
127 | /** Method to update configuration after value changing */
128 | PluginRuntimeConfig.prototype.updateConfig = function (value) {
129 | this.initialConfg();
130 | };
131 | PluginRuntimeConfig.prototype.logCurrentState = function () {
132 | logger.log(">>> PLUGIN INITIAL CONFIGURATION <<<");
133 | logger.log("> pylamaArgs = " + this.pylamaArgs);
134 | logger.log("> executablePath = " + this.executablePath);
135 | logger.log("> enableDebug = " + this.enableDebug);
136 | logger.log("> lintOnChange = " + this.lintOnChange);
137 | logger.log("> linkOnFly = " + this.lintOnFly);
138 | logger.log("> lintOnSave = " + this.lintOnSave);
139 | logger.log("> optionsFileSet = " + this.optionsFileSet);
140 | logger.log("> underlineType = " + this.underlineType);
141 | logger.log("> underlineSize = " + this.underlineSize);
142 | logger.log("> limitToSingleInstance = " + this.limitToSingleInstance);
143 | logger.log("> linkColor = " + this.linkColor);
144 | logger.log('>>> END <<<');
145 | };
146 | return PluginRuntimeConfig;
147 | }());
148 | exports.PluginRuntimeConfig = PluginRuntimeConfig;
149 | //# sourceMappingURL=config.js.map
--------------------------------------------------------------------------------
/lib/config.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/lib/init.js:
--------------------------------------------------------------------------------
1 | /** Plugin initialization needed by Atom editor and linter plugin. */
2 | "use strict";
3 | var linter_1 = require('./linter');
4 | var logger_1 = require('./logger');
5 | var logger = logger_1.Logger.getInstance();
6 | module.exports = {
7 | activate: function (state) {
8 | require('atom-package-deps').install('linter-python');
9 | logger.log(">>> PACKAGE \"python-linter\" ACTIVATED <<<");
10 | },
11 | deactivate: function () {
12 | logger.log(">>> PACKAGE \"python-linter\" DEACTIVATED <<<");
13 | },
14 | provideLinter: function () {
15 | var linter = new linter_1.PluginLinter();
16 | var provider = {
17 | name: 'Python Linter',
18 | grammarScopes: ['source.python'],
19 | scope: 'file',
20 | lintOnFly: true,
21 | lint: linter.lint,
22 | };
23 | return provider;
24 | }
25 | };
26 | //# sourceMappingURL=init.js.map
--------------------------------------------------------------------------------
/lib/init.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,qEAAqE;;AAIrE,uBAA6B,UAAU,CAAC,CAAA;AACxC,uBAAuB,UAAU,CAAC,CAAA;AAElC,IAAM,MAAM,GAAU,eAAM,CAAC,WAAW,EAAE,CAAC;AAE3C,iBAAS;IACL,QAAQ,YAAC,KAAK;QACV,OAAO,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC9D,CAAC;IAED,UAAU;QACN,MAAM,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAChE,CAAC;IAED,aAAa;QACT,IAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAC;QAClC,IAAM,QAAQ,GAAG;YACb,IAAI,EAAE,eAAe;YACrB,aAAa,EAAE,CAAC,eAAe,CAAC;YAChC,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,MAAM,CAAC,IAAI;SACpB,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC;IACpB,CAAC;CACJ,CAAA"}
--------------------------------------------------------------------------------
/lib/linter.js:
--------------------------------------------------------------------------------
1 | /** Main body to handle whole process. */
2 | "use strict";
3 | var runner_1 = require('./runner');
4 | var config_1 = require('./config');
5 | var parser_1 = require('./parser');
6 | var logger_1 = require('./logger');
7 | var cache_1 = require('./cache');
8 | var util_1 = require('./util');
9 | var fs = require('fs');
10 | var os = require('os');
11 | var temp = require('temp');
12 | var path = require('path');
13 | var logger = logger_1.Logger.getInstance();
14 | var cache = cache_1.Cache.getInstance();
15 | var PluginLinter = (function () {
16 | function PluginLinter() {
17 | this.runtimeConfig = new config_1.PluginRuntimeConfig();
18 | this.runtimeConfig.initialConfg();
19 | this.runtimeConfig.logCurrentState();
20 | this.runner = new runner_1.ProcessRunner();
21 | this.tempFileHandler = new util_1.TempFileHandler();
22 | this.running = false;
23 | this.tempFile = null;
24 | this.lint = this.lint.bind(this);
25 | }
26 | PluginLinter.prototype.lint = function () {
27 | var textEditor = atom.workspace.getActiveTextEditor();
28 | if (!atom.workspace.isTextEditor(textEditor)) {
29 | return Promise.resolve(cache.get());
30 | }
31 | var filePath = textEditor.getPath();
32 | if (!filePath) {
33 | return Promise.resolve(cache.get());
34 | }
35 | var projectDir = this.calculateProjectDir(filePath);
36 | var cmd = this.runtimeConfig.executablePath;
37 | var args = [];
38 | cache.set(filePath);
39 | if (this.running == true && this.runtimeConfig.limitToSingleInstance == true) {
40 | logger.log(">>> EXECUTION SKIPPED <<<");
41 | return Promise.resolve(cache.get());
42 | }
43 | logger.log(">>> INPUT FOR LINTING <<<");
44 | logger.log("> filePath = " + filePath);
45 | logger.log("> projectDir = " + projectDir);
46 | logger.log("> cmd = " + cmd);
47 | logger.log("> args = []");
48 | logger.log('>>> END <<<');
49 | if (!util_1.canExecute(cmd)) {
50 | atom.notifications.addError("Provided path doesn't exist.\n\n" + cmd + "\n\nPlease fix pylama path or install latest version.");
51 | return Promise.resolve(cache.get());
52 | }
53 | if (this.isForLintOnFly(textEditor)) {
54 | this.tempFile = this.tempFileHandler.create(textEditor.getText());
55 | var parser = new parser_1.OnFlyParameterParser();
56 | var result = parser.parse(projectDir, this.tempFile.path, this.runtimeConfig);
57 | args = result.args;
58 | projectDir = result.projectDir;
59 | }
60 | else if (this.isForLintOnSave(textEditor)) {
61 | var parser = new parser_1.SaveParameterParser();
62 | var result = parser.parse(projectDir, filePath, this.runtimeConfig);
63 | args = result.args;
64 | projectDir = result.projectDir;
65 | }
66 | else {
67 | return Promise.resolve(cache.get());
68 | }
69 | logger.log(">>> NEW ARGS <<<");
70 | logger.log("> " + args);
71 | logger.log('>>> END <<<');
72 | return this.runner.run(textEditor, this.runtimeConfig, projectDir, cmd, args, this.running, this.tempFile);
73 | };
74 | PluginLinter.prototype.calculateProjectDir = function (filePath) {
75 | var projectDir = atom.project.relativizePath(filePath)[0];
76 | if (projectDir) {
77 | return projectDir;
78 | }
79 | var fileDir = path.dirname(filePath);
80 | if (fileDir) {
81 | return fileDir;
82 | }
83 | return os.tmpdir();
84 | };
85 | PluginLinter.prototype.isForLintOnFly = function (textEditor) {
86 | if (this.runtimeConfig.lintOnFly && textEditor.isModified()) {
87 | return true;
88 | }
89 | else {
90 | return false;
91 | }
92 | };
93 | PluginLinter.prototype.isForLintOnSave = function (textEditor) {
94 | if (this.runtimeConfig.lintOnSave && !textEditor.isModified()) {
95 | return true;
96 | }
97 | else {
98 | return false;
99 | }
100 | };
101 | return PluginLinter;
102 | }());
103 | exports.PluginLinter = PluginLinter;
104 | //# sourceMappingURL=linter.js.map
--------------------------------------------------------------------------------
/lib/linter.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"linter.js","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/lib/logger.js:
--------------------------------------------------------------------------------
1 | /** Module to log debug prints if debug prints are enabled */
2 | "use strict";
3 | var Logger = (function () {
4 | function Logger() {
5 | this._enabled = false;
6 | if (Logger._instance) {
7 | throw new Error("Error: Instantiation failed: Use Logger.getInstance() instead of new.");
8 | }
9 | Logger._instance = this;
10 | }
11 | Logger.getInstance = function () {
12 | return Logger._instance;
13 | };
14 | Logger.prototype.enableLogger = function () {
15 | if (!this._enabled) {
16 | this._enabled = true;
17 | console.log(">>> DEBUG ENABLED <<<");
18 | }
19 | };
20 | Logger.prototype.disableLogger = function () {
21 | if (this._enabled) {
22 | this._enabled = false;
23 | console.log(">>> DEBUG DISABLED <<<");
24 | }
25 | };
26 | Logger.prototype.log = function (message) {
27 | if (this._enabled) {
28 | console.log(message);
29 | }
30 | };
31 | Logger._instance = new Logger();
32 | return Logger;
33 | }());
34 | exports.Logger = Logger;
35 | //# sourceMappingURL=logger.js.map
--------------------------------------------------------------------------------
/lib/logger.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,6DAA6D;;AAE7D;IAMI;QAFQ,aAAQ,GAAW,KAAK,CAAC;QAG7B,EAAE,CAAA,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEa,kBAAW,GAAzB;QAEI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IAC5B,CAAC;IAEM,6BAAY,GAAnB;QACI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACzC,CAAC;IACL,CAAC;IAEM,8BAAa,GAApB;QACI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IAEM,oBAAG,GAAV,UAAW,OAAO;QACd,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IAlCc,gBAAS,GAAU,IAAI,MAAM,EAAE,CAAC;IAmCnD,aAAC;AAAD,CAAC,AArCD,IAqCC;AArCY,cAAM,SAqClB,CAAA"}
--------------------------------------------------------------------------------
/lib/parser.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /** Module responsible to read, parse message returned by pylama application.
3 | This module should return also link to github page where all errors
4 | are available.*/
5 | var logger_1 = require('./logger');
6 | var util_1 = require('./util');
7 | var docUrl = 'https://github.com/pchomik/linter-python-doc/blob/master/errors/';
8 | var genericRegexp = /(.*):(\d+):(\d+):\s(.\d+)\s*(.*)\[(.*)\]$/; // file:row:col:error:message:tool
9 | var pyflakesRegexp = /(.*):(\d+):(\d+):\s*(.*)\[(.*)\]$/; // file:row:col:message:tool
10 | var logger = logger_1.Logger.getInstance();
11 | var path = require('path');
12 | var atomLinter = require('atom-linter');
13 | var MessageParser = (function () {
14 | function MessageParser() {
15 | }
16 | MessageParser.prototype.parseLines = function (data) {
17 | var results = [];
18 | var lines = data.split('\n');
19 | for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
20 | var line = lines_1[_i];
21 | var found = line.match(genericRegexp);
22 | if (found) {
23 | results.push({
24 | 'fileName': found[1],
25 | 'row': Number(found[2]),
26 | 'col': Number(found[3]),
27 | 'error': found[4],
28 | 'message': found[5],
29 | 'tool': found[6]
30 | });
31 | }
32 | else {
33 | found = line.match(pyflakesRegexp);
34 | if (found) {
35 | results.push({
36 | 'fileName': found[1],
37 | 'row': Number(found[2]),
38 | 'col': Number(found[3]),
39 | 'error': '',
40 | 'message': found[4],
41 | 'tool': found[5]
42 | });
43 | }
44 | }
45 | }
46 | return results;
47 | };
48 | MessageParser.prototype.buildMessage = function (textEditor, result, config) {
49 | var line = textEditor.getBuffer().lineForRow(result.row - 1);
50 | var filePath = textEditor.getPath();
51 | var resultType = 'Warning';
52 | if (result.error.indexOf('E') > -1 || result.error.indexOf('F') > -1) {
53 | resultType = 'Error';
54 | }
55 | var text = this.buildErrorText(result, config);
56 | var range = atomLinter.rangeFromLineNumber(textEditor, result.row - 1, result.col - 1);
57 | var message = {
58 | type: resultType,
59 | html: text,
60 | filePath: filePath,
61 | range: range,
62 | };
63 | logger.log(">>> NEW MESSAGE <<");
64 | logger.log("> type = " + message.type);
65 | logger.log("> html = " + message.html);
66 | logger.log("> filePath = " + message.filePath);
67 | logger.log("> range = " + message.range);
68 | logger.log(">>> END <<<");
69 | return message;
70 | };
71 | MessageParser.prototype.buildErrorText = function (result, config) {
72 | if (!result.tool) {
73 | return result.error + " " + result.message;
74 | }
75 | else if (result.tool == 'mccabe') {
76 | return result.error + " " + result.message + " [" + result.tool + "]";
77 | }
78 | else {
79 | return "" + result.error + " " + result.message + " [" + result.tool + "]";
80 | }
81 | };
82 | return MessageParser;
83 | }());
84 | exports.MessageParser = MessageParser;
85 | var SaveParameterParser = (function () {
86 | function SaveParameterParser() {
87 | }
88 | SaveParameterParser.prototype.parse = function (projectDir, filePath, config) {
89 | return {
90 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-f', 'pep8', filePath]),
91 | 'projectDir': projectDir
92 | };
93 | };
94 | return SaveParameterParser;
95 | }());
96 | exports.SaveParameterParser = SaveParameterParser;
97 | var OnFlyParameterParser = (function () {
98 | function OnFlyParameterParser() {
99 | }
100 | OnFlyParameterParser.prototype.parse = function (projectDir, filePath, config) {
101 | var pylama_options_file = path.join(projectDir, 'pylama.ini');
102 | projectDir = path.dirname(filePath);
103 | if (util_1.canRead(pylama_options_file)) {
104 | return {
105 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-o', pylama_options_file, '-f', 'pep8', filePath]),
106 | 'projectDir': projectDir
107 | };
108 | }
109 | else {
110 | return {
111 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-f', 'pep8', filePath]),
112 | 'projectDir': projectDir
113 | };
114 | }
115 | };
116 | return OnFlyParameterParser;
117 | }());
118 | exports.OnFlyParameterParser = OnFlyParameterParser;
119 | //# sourceMappingURL=parser.js.map
--------------------------------------------------------------------------------
/lib/parser.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/lib/runner.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /** Module to handle process execution. */
3 | var logger_1 = require('./logger');
4 | var parser_1 = require('./parser');
5 | var cache_1 = require('./cache');
6 | var cp = require('child-process-es6-promise');
7 | var logger = logger_1.Logger.getInstance();
8 | var cache = cache_1.Cache.getInstance();
9 | /** Class to execute process and return read output. */
10 | var ProcessRunner = (function () {
11 | function ProcessRunner() {
12 | this.parser = new parser_1.MessageParser();
13 | }
14 | ProcessRunner.prototype.run = function (textEditor, config, projectDir, cmd, args, runningFlag, tempFile) {
15 | var _this = this;
16 | return new Promise(function (resolve) {
17 | var messages = [];
18 | cp.spawn(cmd, args, { cwd: projectDir })
19 | .then(function (result) {
20 | // Pylama's exit code is 0 when there are no linting errors.
21 | logger.log(">>> NO ERRORS <<<");
22 | logger.log(">>> RAW OUTPUT <<<");
23 | logger.log(result.stdout);
24 | logger.log(">>> END <<<");
25 | return resolve(messages);
26 | })
27 | .catch(function (error) {
28 | // Pylama's exit code is 1 when there are linting errors.
29 | logger.log(">>> RAW OUTPUT <<<");
30 | logger.log(error.stdout);
31 | logger.log(">>> END <<<");
32 | var parsedLines = _this.parser.parseLines(error.stdout);
33 | for (var _i = 0, parsedLines_1 = parsedLines; _i < parsedLines_1.length; _i++) {
34 | var parsedLine = parsedLines_1[_i];
35 | var message = _this.parser.buildMessage(textEditor, parsedLine, config);
36 | messages.unshift(message);
37 | }
38 | runningFlag = false;
39 | if (tempFile) {
40 | tempFile.clean();
41 | }
42 | cache.store(messages);
43 | return resolve(messages);
44 | });
45 | });
46 | };
47 | return ProcessRunner;
48 | }());
49 | exports.ProcessRunner = ProcessRunner;
50 | //# sourceMappingURL=runner.js.map
--------------------------------------------------------------------------------
/lib/runner.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":";AAAA,0CAA0C;AAC1C,uBAAuB,UAAU,CAAC,CAAA;AAClC,uBAA8B,UAAU,CAAC,CAAA;AACzC,sBAAsB,SAAS,CAAC,CAAA;AAEhC,IAAM,EAAE,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAChD,IAAM,MAAM,GAAU,eAAM,CAAC,WAAW,EAAE,CAAC;AAC3C,IAAM,KAAK,GAAS,aAAK,CAAC,WAAW,EAAE,CAAC;AAIxC,uDAAuD;AACvD;IAII;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,sBAAa,EAAE,CAAC;IACtC,CAAC;IACD,2BAAG,GAAH,UAAI,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ;QAApE,iBA8BC;QA7BG,MAAM,CAAC,IAAI,OAAO,CAAC,UAAC,OAAO;YACvB,IAAI,QAAQ,GAAG,EAAE,CAAA;YACjB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAC,GAAG,EAAE,UAAU,EAAC,CAAC;iBACrC,IAAI,CAAC,UAAC,MAAM;gBACT,4DAA4D;gBAC5D,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAChC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAC1B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC;iBACD,KAAK,CAAC,UAAC,KAAK;gBACT,yDAAyD;gBACzD,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBACjC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACzB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAC1B,IAAI,WAAW,GAAG,KAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACvD,GAAG,CAAC,CAAmB,UAAW,EAAX,2BAAW,EAAX,yBAAW,EAAX,IAAW,CAAC;oBAA9B,IAAI,UAAU,oBAAA;oBACf,IAAI,OAAO,GAAG,KAAI,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;oBACvE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;iBAC7B;gBACD,WAAW,GAAG,KAAK,CAAC;gBACpB,EAAE,CAAA,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACV,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACrB,CAAC;gBACD,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACtB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAA;IACN,CAAC;IACL,oBAAC;AAAD,CAAC,AAtCD,IAsCC;AAtCY,qBAAa,gBAsCzB,CAAA"}
--------------------------------------------------------------------------------
/lib/util.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var logger_1 = require('./logger');
3 | var temp = require('temp');
4 | var fs = require('fs');
5 | var logger = logger_1.Logger.getInstance();
6 | var TempFileHandler = (function () {
7 | function TempFileHandler() {
8 | }
9 | TempFileHandler.prototype.create = function (text) {
10 | var tempFile = temp.openSync({ suffix: '.py' });
11 | fs.writeSync(tempFile.fd, text);
12 | fs.closeSync(tempFile.fd);
13 | return new TempFileWrapper(tempFile);
14 | };
15 | return TempFileHandler;
16 | }());
17 | exports.TempFileHandler = TempFileHandler;
18 | var TempFileWrapper = (function () {
19 | function TempFileWrapper(tempFile) {
20 | this.tempFile = tempFile;
21 | this.path = tempFile.path;
22 | }
23 | TempFileWrapper.prototype.clean = function () {
24 | if (this.tempFile == null) {
25 | return;
26 | }
27 | fs.unlink(this.path);
28 | this.path = null;
29 | this.tempFile = null;
30 | };
31 | return TempFileWrapper;
32 | }());
33 | exports.TempFileWrapper = TempFileWrapper;
34 | function canExecute(path) {
35 | logger.log(">>> EXECUTE CHECK <<<");
36 | try {
37 | fs.accessSync(path, fs.R_OK | fs.X_OK);
38 | logger.log("> Path can be executed");
39 | logger.log(">>> END <<<");
40 | return true;
41 | }
42 | catch (err) {
43 | logger.log("> Path can not be executed:");
44 | logger.log(err);
45 | logger.log(">>> END <<<");
46 | return false;
47 | }
48 | }
49 | exports.canExecute = canExecute;
50 | function canRead(path) {
51 | logger.log(">>> READ CHECK <<<");
52 | try {
53 | fs.accessSync(path, fs.R_OK);
54 | logger.log("> Path can be read");
55 | logger.log(">>> END <<<");
56 | return true;
57 | }
58 | catch (err) {
59 | logger.log("> Path can not be read");
60 | logger.log(err);
61 | logger.log(">>> END <<<");
62 | return false;
63 | }
64 | }
65 | exports.canRead = canRead;
66 | //# sourceMappingURL=util.js.map
--------------------------------------------------------------------------------
/lib/util.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";AAAA,uBAAuB,UAAU,CAAC,CAAA;AAElC,IAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,IAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACzB,IAAM,MAAM,GAAU,eAAM,CAAC,WAAW,EAAE,CAAC;AAG3C;IAAA;IASA,CAAC;IANG,gCAAM,GAAN,UAAO,IAAI;QACP,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAC,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;QAC9C,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IACL,sBAAC;AAAD,CAAC,AATD,IASC;AATY,uBAAe,kBAS3B,CAAA;AAGD;IAII,yBAAY,QAAQ;QAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,+BAAK,GAAL;QACI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC;YACxB,MAAM,CAAC;QACX,CAAC;QACD,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACzB,CAAC;IAGL,sBAAC;AAAD,CAAC,AAnBD,IAmBC;AAnBY,uBAAe,kBAmB3B,CAAA;AAGD,oBAA2B,IAAI;IAC3B,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACpC,IAAI,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC;IAChB,CACA;IAAA,KAAK,CAAA,CAAC,GAAG,CAAC,CAAC,CAAC;QACR,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAde,kBAAU,aAczB,CAAA;AAGD,iBAAwB,IAAI;IACxB,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACjC,IAAI,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QACzB,MAAM,CAAC,IAAI,CAAC;IAChB,CACA;IAAA,KAAK,CAAA,CAAC,GAAG,CAAC,CAAC,CAAC;QACR,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QACzB,MAAM,CAAC,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAde,eAAO,UActB,CAAA"}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "linter-python",
3 | "main": "./lib/init",
4 | "version": "3.1.2",
5 | "description": "Linter for python files. Lint operation based on pylama application.",
6 | "repository": "https://github.com/pchomik/linter-python",
7 | "license": "MIT",
8 | "engines": {
9 | "atom": ">=1.0.0 <2.0.0"
10 | },
11 | "scripts": {
12 | "start": "npm run tsc:w",
13 | "afterinstall": "typings install",
14 | "tsc": "tsc",
15 | "tsc:w": "tsc -w",
16 | "typings": "typings"
17 | },
18 | "providedServices": {
19 | "linter": {
20 | "versions": {
21 | "1.0.0": "provideLinter"
22 | }
23 | }
24 | },
25 | "dependencies": {
26 | "atom-package-deps": "^4.0.1",
27 | "child-process-es6-promise": "^1.0.0",
28 | "temp": "^0.8.3",
29 | "atom-linter": "^6.0.0"
30 | },
31 | "package-deps": [
32 | "linter"
33 | ],
34 | "devDependencies": {
35 | "typescript": "^1.8.10",
36 | "typings": "^1.0.4",
37 | "atom": "^1.0.0"
38 | },
39 | "configSchema": {
40 | "executablePath": {
41 | "type": "string",
42 | "default": "pylama",
43 | "description": "Excutable path for external Pylama. Example: /usr/local/bin/pylama.",
44 | "order": 1
45 | },
46 | "withPep8": {
47 | "type": "boolean",
48 | "default": false,
49 | "description": "Run pylama with pep8 linter.",
50 | "order": 2
51 | },
52 | "withPep257": {
53 | "type": "boolean",
54 | "default": false,
55 | "description": "Run pylama with PEP257 linter.",
56 | "order": 3
57 | },
58 | "withMcCabe": {
59 | "type": "boolean",
60 | "default": false,
61 | "description": "Run pylama with McCabe linter.",
62 | "order": 4
63 | },
64 | "withPyflakes": {
65 | "type": "boolean",
66 | "default": false,
67 | "description": "Run pylama with Pyflakes linter.",
68 | "order": 5
69 | },
70 | "withPylint": {
71 | "type": "boolean",
72 | "default": false,
73 | "description": "Run pylama with Pylint linter. To enable this option please execute following command: pip install pylama-pylint.",
74 | "order": 6
75 | },
76 | "skipFiles": {
77 | "type": "string",
78 | "default": "",
79 | "description": "Skip files by masks (comma-separated, ex. */message,py,*/ignore.py).",
80 | "order": 7
81 | },
82 | "ignoreCodes": {
83 | "type": "string",
84 | "default": "",
85 | "description": "Provided codes will be ignored by linters. Example: E111,E114,D101,D102,DW0311.",
86 | "order": 8
87 | },
88 | "optionsFile": {
89 | "type": "string",
90 | "default": "",
91 | "description": "Path to configuration file. By default is /pylama.ini",
92 | "order": 9
93 | },
94 | "force": {
95 | "type": "boolean",
96 | "default": false,
97 | "description": "Force code checking (if linter doesnt allow).",
98 | "order": 10
99 | },
100 | "lintTrigger": {
101 | "type": "string",
102 | "default": "File saved",
103 | "enum": [
104 | "File saved",
105 | "File modified",
106 | "File saved or modified"
107 | ],
108 | "description": "Defines when lint action should be triggered.",
109 | "order": 11
110 | },
111 | "enableDebug": {
112 | "type": "boolean",
113 | "default": false,
114 | "description": "Enable debug console prints.",
115 | "order": 12
116 | },
117 | "limitToSingleInstance": {
118 | "type": "boolean",
119 | "default": true,
120 | "description": "Limit how many pylama binaries can be executed. By default is set to single instance.",
121 | "order": 13
122 | },
123 | "linkColor": {
124 | "type": "color",
125 | "default": "#bf6815",
126 | "description": "Link color for all errors/warning/types",
127 | "order": 14
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/cache.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from './logger';
2 |
3 |
4 | const logger:Logger = Logger.getInstance();
5 |
6 |
7 | export class Cache {
8 | private static _instance:Cache = new Cache();
9 |
10 | private messages:any = {};
11 | private filePointer: string;
12 |
13 | constructor() {
14 | if(Cache._instance){
15 | throw new Error("Error: Instantiation failed: Use Logger.getInstance() instead of new.");
16 | }
17 | Cache._instance = this;
18 | }
19 |
20 | public static getInstance():Cache
21 | {
22 | return Cache._instance;
23 | }
24 |
25 | public store(messages) {
26 | logger.log(">>> NEW MESSAGES STORED IN CACHE <<<");
27 | this.messages[this.filePointer] = messages;
28 | }
29 |
30 | public get() {
31 | logger.log(">>> MESSAGES RETURNED FROM CACHE <<<");
32 | if (!this.messages[this.filePointer]) {
33 | return [];
34 | } else {
35 | return this.messages[this.filePointer];
36 | }
37 | }
38 |
39 | public set(filePath) {
40 | this.filePointer = filePath;
41 | logger.log(`>>> CACHE SET FOR ${this.filePointer} <<<`);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | /** Module to define plugin configuration and react on change. */
2 | import { Logger } from './logger';
3 |
4 | const CompositeDisposable = require('atom').CompositeDisposable;
5 | const logger:Logger = Logger.getInstance();
6 |
7 | declare var atom;
8 |
9 |
10 | /** Plugin runtime configuration. What is really set by the user when Atom is working */
11 | export class PluginRuntimeConfig {
12 |
13 | pylamaArgs: any[] = [];
14 | executablePath: string = '';
15 | enableDebug: boolean = false;
16 | lintOnChange: boolean = false;
17 | lintOnSave: boolean = false;
18 | lintOnFly: boolean = false;
19 | optionsFileSet: boolean = false;
20 | underlineType: string = 'Whole line';
21 | underlineSize: number = 2;
22 | limitToSingleInstance: boolean = true;
23 | linkColor: any = "";
24 | subs: any;
25 |
26 | constructor() {
27 |
28 | this.initialConfg = this.initialConfg.bind(this);
29 | this.updateConfig = this.updateConfig.bind(this);
30 |
31 | this.subs = new CompositeDisposable();
32 | this.subs.add(atom.config.observe('linter-python.executablePath', {}, this.updateConfig));
33 | this.subs.add(atom.config.observe('linter-python.withPep8', {}, this.updateConfig));
34 | this.subs.add(atom.config.observe('linter-python.withPep257', {}, this.updateConfig));
35 | this.subs.add(atom.config.observe('linter-python.withMcCabe', {}, this.updateConfig));
36 | this.subs.add(atom.config.observe('linter-python.withPylint', {}, this.updateConfig));
37 | this.subs.add(atom.config.observe('linter-python.withPyflakes', {}, this.updateConfig));
38 | this.subs.add(atom.config.observe('linter-python.ignoreCodes', {}, this.updateConfig));
39 | this.subs.add(atom.config.observe('linter-python.skipFiles', {}, this.updateConfig));
40 | this.subs.add(atom.config.observe('linter-python.force', {}, this.updateConfig));
41 | this.subs.add(atom.config.observe('linter-python.optionsFile', {}, this.updateConfig));
42 | this.subs.add(atom.config.observe('linter-python.enableDebug', {}, this.updateConfig));
43 | this.subs.add(atom.config.observe('linter-python.lintTrigger', {}, this.updateConfig));
44 | this.subs.add(atom.config.observe('linter-python.underlineSize', {}, this.updateConfig));
45 | this.subs.add(atom.config.observe('linter-python.underlineType', {}, this.updateConfig));
46 | this.subs.add(atom.config.observe('linter-python.limitToSingleInstance', {}, this.updateConfig));
47 | this.subs.add(atom.config.observe('linter-python.linkColor', {}, this.updateConfig));
48 | }
49 |
50 | /** Set default cofiguration values */
51 | initialConfg() {
52 | let linters = [];
53 |
54 | this.pylamaArgs = [];
55 | this.optionsFileSet = false;
56 |
57 | this.executablePath = this.readConfigValue('executablePath');
58 | this.limitToSingleInstance = this.readConfigValue('limitToSingleInstance');
59 | this.linkColor = this.readConfigValue('linkColor');
60 |
61 | this.underlineType = this.readConfigValue('underlineType');
62 | if (this.underlineType == 'Only place with error') {
63 | this.underlineSize = this.readConfigValue('underlineSize');
64 | }
65 |
66 | let enabledDebug = this.readConfigValue('enableDebug');
67 | if (enabledDebug) {
68 | logger.enableLogger();
69 | } else {
70 | logger.disableLogger();
71 | }
72 |
73 | let withMcCabe = this.readConfigValue('withMcCabe');
74 | if (withMcCabe) {
75 | linters.push('mccabe');
76 | }
77 |
78 | let withPyflakes = this.readConfigValue('withPyflakes');
79 | if (withPyflakes) {
80 | linters.push('pyflakes');
81 | }
82 |
83 | let withPylint = this.readConfigValue('withPylint');
84 | if (withPylint) {
85 | linters.push('pylint');
86 | }
87 |
88 | let withPep8 = this.readConfigValue('withPep8');
89 | if (withPep8) {
90 | linters.push('pep8');
91 | }
92 |
93 | let withPep257 = this.readConfigValue('withPep257');
94 | if (withPep257) {
95 | linters.push('pep257');
96 | }
97 |
98 | if (linters.length > 0) {
99 | this.pylamaArgs.push('-l');
100 | this.pylamaArgs.push(linters.join());
101 | }
102 |
103 | let skipFiles = this.readConfigValue('skipFiles');
104 | if (skipFiles.length > 0) {
105 | this.pylamaArgs.push('--skip');
106 | this.pylamaArgs.push(skipFiles);
107 | }
108 |
109 | let ignoreCodes = this.readConfigValue('ignoreCodes');
110 | if (ignoreCodes.length > 0) {
111 | this.pylamaArgs.push('-i');
112 | this.pylamaArgs.push(ignoreCodes);
113 | }
114 |
115 | let optionsFile = this.readConfigValue('optionsFile');
116 | if (optionsFile.length > 0) {
117 | this.optionsFileSet = true;
118 | this.pylamaArgs.push('-o');
119 | this.pylamaArgs.push(optionsFile);
120 | }
121 |
122 | let force = this.readConfigValue('force');
123 | if (force) {
124 | this.pylamaArgs.push('-F');
125 | }
126 |
127 | let lintTrigger = this.readConfigValue('lintTrigger');
128 | if (lintTrigger == 'File saved') {
129 | this.lintOnSave = true;
130 | this.lintOnFly = false;
131 | }
132 | else if (lintTrigger == 'File modified') {
133 | this.lintOnSave = false;
134 | this.lintOnFly = true;
135 | }
136 | else if (lintTrigger == 'File saved or modified') {
137 | this.lintOnSave = true;
138 | this.lintOnFly = true;
139 | }
140 | }
141 |
142 | /** Method to simplify variable reading */
143 | readConfigValue(value) {
144 | try {
145 | return atom.config.get(`linter-python.${value}`);
146 | }
147 | catch(err) {
148 | console.log(err);
149 | return '';
150 | }
151 | }
152 |
153 | /** Method to update configuration after value changing */
154 | updateConfig(value) {
155 | this.initialConfg();
156 | }
157 |
158 | public logCurrentState() {
159 | logger.log(">>> PLUGIN INITIAL CONFIGURATION <<<");
160 | logger.log(`> pylamaArgs = ${this.pylamaArgs}`);
161 | logger.log(`> executablePath = ${this.executablePath}`);
162 | logger.log(`> enableDebug = ${this.enableDebug}`);
163 | logger.log(`> lintOnChange = ${this.lintOnChange}`);
164 | logger.log(`> linkOnFly = ${this.lintOnFly}`);
165 | logger.log(`> lintOnSave = ${this.lintOnSave}`);
166 | logger.log(`> optionsFileSet = ${this.optionsFileSet}`);
167 | logger.log(`> underlineType = ${this.underlineType}`);
168 | logger.log(`> underlineSize = ${this.underlineSize}`);
169 | logger.log(`> limitToSingleInstance = ${this.limitToSingleInstance}`);
170 | logger.log(`> linkColor = ${this.linkColor}`);
171 | logger.log('>>> END <<<');
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/init.ts:
--------------------------------------------------------------------------------
1 | /** Plugin initialization needed by Atom editor and linter plugin. */
2 |
3 | declare var atom;
4 |
5 | import { PluginLinter } from './linter';
6 | import { Logger } from './logger';
7 |
8 | const logger:Logger = Logger.getInstance();
9 |
10 | export = {
11 | activate(state) {
12 | require('atom-package-deps').install('linter-python');
13 | logger.log(">>> PACKAGE \"python-linter\" ACTIVATED <<<");
14 | },
15 |
16 | deactivate() {
17 | logger.log(">>> PACKAGE \"python-linter\" DEACTIVATED <<<");
18 | },
19 |
20 | provideLinter() {
21 | const linter = new PluginLinter();
22 | const provider = {
23 | name: 'Python Linter',
24 | grammarScopes: ['source.python'],
25 | scope: 'file',
26 | lintOnFly: true,
27 | lint: linter.lint,
28 | };
29 | return provider;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/linter.ts:
--------------------------------------------------------------------------------
1 | /** Main body to handle whole process. */
2 |
3 | import { ProcessRunner } from './runner';
4 | import { PluginRuntimeConfig } from './config';
5 | import { SaveParameterParser, OnFlyParameterParser } from './parser';
6 | import { Logger } from './logger';
7 | import { Cache } from './cache';
8 | import { TempFileHandler, canExecute, TempFileWrapper } from './util';
9 |
10 | const fs = require('fs');
11 | const os = require('os');
12 | const temp = require('temp');
13 | const path = require('path');
14 | const logger:Logger = Logger.getInstance();
15 | const cache:Cache = Cache.getInstance();
16 |
17 | declare var atom;
18 |
19 | export class PluginLinter {
20 |
21 | runtimeConfig: PluginRuntimeConfig;
22 | runner: ProcessRunner;
23 | tempFileHandler: TempFileHandler;
24 | running: boolean;
25 | tempFile: TempFileWrapper;
26 | lastFilePath: String;
27 |
28 | constructor() {
29 | this.runtimeConfig = new PluginRuntimeConfig();
30 | this.runtimeConfig.initialConfg();
31 | this.runtimeConfig.logCurrentState();
32 | this.runner = new ProcessRunner();
33 | this.tempFileHandler = new TempFileHandler();
34 | this.running = false;
35 | this.tempFile = null;
36 |
37 | this.lint = this.lint.bind(this);
38 | }
39 |
40 | lint() {
41 | let textEditor = atom.workspace.getActiveTextEditor();
42 | if (!atom.workspace.isTextEditor(textEditor)) {
43 | return Promise.resolve(cache.get());
44 | }
45 | let filePath = textEditor.getPath();
46 | if (!filePath) {
47 | return Promise.resolve(cache.get());
48 | }
49 | let projectDir = this.calculateProjectDir(filePath);
50 | let cmd = this.runtimeConfig.executablePath;
51 | let args = [];
52 |
53 | cache.set(filePath);
54 |
55 | if (this.running == true && this.runtimeConfig.limitToSingleInstance == true) {
56 | logger.log(">>> EXECUTION SKIPPED <<<");
57 | return Promise.resolve(cache.get());
58 | }
59 |
60 | logger.log(">>> INPUT FOR LINTING <<<")
61 | logger.log(`> filePath = ${filePath}`);
62 | logger.log(`> projectDir = ${projectDir}`);
63 | logger.log(`> cmd = ${cmd}`);
64 | logger.log("> args = []")
65 | logger.log('>>> END <<<');
66 |
67 | if (!canExecute(cmd)) {
68 | atom.notifications.addError(`Provided path doesn't exist.\n\n${cmd}\n\nPlease fix pylama path or install latest version.`);
69 | return Promise.resolve(cache.get());
70 | }
71 |
72 | if (this.isForLintOnFly(textEditor)) {
73 | this.tempFile = this.tempFileHandler.create(textEditor.getText());
74 | let parser = new OnFlyParameterParser();
75 | let result= parser.parse(projectDir, this.tempFile.path, this.runtimeConfig);
76 | args = result.args;
77 | projectDir = result.projectDir;
78 | } else if (this.isForLintOnSave(textEditor)) {
79 | let parser = new SaveParameterParser();
80 | let result = parser.parse(projectDir, filePath, this.runtimeConfig);
81 | args = result.args;
82 | projectDir = result.projectDir;
83 | } else {
84 | return Promise.resolve(cache.get());
85 | }
86 |
87 | logger.log(">>> NEW ARGS <<<");
88 | logger.log(`> ${args}`);
89 | logger.log('>>> END <<<');
90 |
91 | return this.runner.run(textEditor, this.runtimeConfig, projectDir, cmd, args, this.running, this.tempFile);
92 | }
93 |
94 | calculateProjectDir(filePath) {
95 | let projectDir = atom.project.relativizePath(filePath)[0]
96 | if (projectDir) {
97 | return projectDir;
98 | }
99 | let fileDir = path.dirname(filePath);
100 | if (fileDir) {
101 | return fileDir;
102 | }
103 | return os.tmpdir();
104 | }
105 |
106 | isForLintOnFly(textEditor) {
107 | if (this.runtimeConfig.lintOnFly && textEditor.isModified()) {
108 | return true;
109 | } else {
110 | return false;
111 | }
112 | }
113 |
114 | isForLintOnSave(textEditor) {
115 | if (this.runtimeConfig.lintOnSave && !textEditor.isModified()) {
116 | return true;
117 | } else {
118 | return false;
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/logger.ts:
--------------------------------------------------------------------------------
1 | /** Module to log debug prints if debug prints are enabled */
2 |
3 | export class Logger {
4 |
5 | private static _instance:Logger = new Logger();
6 |
7 | private _enabled:boolean = false;
8 |
9 | constructor() {
10 | if(Logger._instance){
11 | throw new Error("Error: Instantiation failed: Use Logger.getInstance() instead of new.");
12 | }
13 | Logger._instance = this;
14 | }
15 |
16 | public static getInstance():Logger
17 | {
18 | return Logger._instance;
19 | }
20 |
21 | public enableLogger() {
22 | if (!this._enabled) {
23 | this._enabled = true;
24 | console.log(">>> DEBUG ENABLED <<<");
25 | }
26 | }
27 |
28 | public disableLogger() {
29 | if (this._enabled) {
30 | this._enabled = false;
31 | console.log(">>> DEBUG DISABLED <<<");
32 | }
33 | }
34 |
35 | public log(message) {
36 | if (this._enabled) {
37 | console.log(message);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/parser.ts:
--------------------------------------------------------------------------------
1 | /** Module responsible to read, parse message returned by pylama application.
2 | This module should return also link to github page where all errors
3 | are available.*/
4 | import { Logger } from './logger';
5 | import { canRead } from './util';
6 |
7 | const docUrl = 'https://github.com/pchomik/linter-python-doc/blob/master/errors/'
8 |
9 | const genericRegexp = /(.*):(\d+):(\d+):\s(.\d+)\s*(.*)\[(.*)\]$/; // file:row:col:error:message:tool
10 | const pyflakesRegexp = /(.*):(\d+):(\d+):\s*(.*)\[(.*)\]$/; // file:row:col:message:tool
11 | const logger: Logger = Logger.getInstance();
12 | const path = require('path');
13 | const atomLinter = require('atom-linter');
14 |
15 |
16 | export class MessageParser {
17 |
18 | parseLines(data) {
19 | let results = [];
20 | let lines = data.split(/(\r|\n|\r\n)/).filter(function(line) { return !!line.trim(); });
21 | for (let line of lines) {
22 | let found = line.match(genericRegexp);
23 | if (found) {
24 | results.push({
25 | 'fileName': found[1],
26 | 'row': Number(found[2]),
27 | 'col': Number(found[3]),
28 | 'error': found[4],
29 | 'message': found[5],
30 | 'tool': found[6]
31 | });
32 | }
33 | else {
34 | found = line.match(pyflakesRegexp);
35 | if (found) {
36 | results.push({
37 | 'fileName': found[1],
38 | 'row': Number(found[2]),
39 | 'col': Number(found[3]),
40 | 'error': '',
41 | 'message': found[4],
42 | 'tool': found[5]
43 | });
44 | }
45 | }
46 | }
47 | return results;
48 | }
49 |
50 | buildMessage(textEditor, result, config) {
51 | let line = textEditor.getBuffer().lineForRow(result.row - 1);
52 | let filePath = textEditor.getPath();
53 | let resultType = 'Warning';
54 |
55 | if (result.error.indexOf('E') > -1 || result.error.indexOf('F') > -1) {
56 | resultType = 'Error';
57 | }
58 | let text = this.buildErrorText(result, config);
59 | let range = atomLinter.rangeFromLineNumber(textEditor, result.row -1, result.col - 1);
60 | let message = {
61 | type: resultType,
62 | html: text,
63 | filePath: filePath,
64 | range: range,
65 | };
66 | logger.log(">>> NEW MESSAGE <<");
67 | logger.log(`> type = ${message.type}`)
68 | logger.log(`> html = ${message.html}`)
69 | logger.log(`> filePath = ${message.filePath}`)
70 | logger.log(`> range = ${message.range}`)
71 | logger.log(">>> END <<<");
72 | return message;
73 | }
74 |
75 | buildErrorText(result, config) {
76 | if (!result.tool) {
77 | return `${result.error} ${result.message}`;
78 | }
79 | else if(result.tool == 'mccabe') {
80 | return `${result.error} ${result.message} [${result.tool}]`;
81 | }
82 | else {
83 | return `${result.error} ${result.message} [${result.tool}]`;
84 | }
85 | }
86 | }
87 |
88 |
89 | export class SaveParameterParser {
90 | public parse(projectDir, filePath, config) {
91 | return {
92 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-f', 'pep8', filePath]),
93 | 'projectDir': projectDir
94 | }
95 | }
96 | }
97 |
98 |
99 | export class OnFlyParameterParser {
100 | public parse(projectDir, filePath, config) {
101 | let pylama_options_file = path.join(projectDir, 'pylama.ini');
102 | projectDir = path.dirname(filePath);
103 | if (canRead(pylama_options_file)) {
104 | return {
105 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-o', pylama_options_file, '-f', 'pep8', filePath]),
106 | 'projectDir': projectDir
107 | }
108 | } else {
109 | return {
110 | 'args': config.pylamaArgs.concat(['--sort', 'E,W,D', '-f', 'pep8', filePath]),
111 | 'projectDir': projectDir
112 | }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/runner.ts:
--------------------------------------------------------------------------------
1 | /** Module to handle process execution. */
2 | import { Logger } from './logger';
3 | import { MessageParser } from './parser';
4 | import { Cache } from './cache';
5 |
6 | const cp = require('child-process-es6-promise');
7 | const logger:Logger = Logger.getInstance();
8 | const cache:Cache = Cache.getInstance();
9 |
10 | declare var atom;
11 |
12 | /** Class to execute process and return read output. */
13 | export class ProcessRunner {
14 |
15 | parser: MessageParser;
16 |
17 | constructor() {
18 | this.parser = new MessageParser();
19 | }
20 | run(textEditor, config, projectDir, cmd, args, runningFlag, tempFile) {
21 | return new Promise((resolve) => {
22 | let messages = []
23 | cp.spawn(cmd, args, {cwd: projectDir})
24 | .then((result) => {
25 | // Pylama's exit code is 0 when there are no linting errors.
26 | logger.log(">>> NO ERRORS <<<");
27 | logger.log(">>> RAW OUTPUT <<<");
28 | logger.log(result.stdout);
29 | logger.log(">>> END <<<");
30 | return resolve(messages);
31 | })
32 | .catch((error) => {
33 | // Pylama's exit code is 1 when there are linting errors.
34 | logger.log(">>> RAW OUTPUT <<<");
35 | logger.log(error.stdout);
36 | logger.log(">>> END <<<");
37 | let parsedLines = this.parser.parseLines(error.stdout);
38 | for (let parsedLine of parsedLines) {
39 | let message = this.parser.buildMessage(textEditor, parsedLine, config);
40 | messages.unshift(message);
41 | }
42 | runningFlag = false;
43 | if(tempFile) {
44 | tempFile.clean();
45 | }
46 | cache.store(messages);
47 | return resolve(messages);
48 | });
49 | })
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from './logger';
2 |
3 | const temp = require('temp');
4 | const fs = require('fs');
5 | const logger:Logger = Logger.getInstance();
6 |
7 |
8 | export class TempFileHandler {
9 | track: any;
10 |
11 | create(text) {
12 | let tempFile = temp.openSync({suffix: '.py'});
13 | fs.writeSync(tempFile.fd, text);
14 | fs.closeSync(tempFile.fd);
15 | return new TempFileWrapper(tempFile);
16 | }
17 | }
18 |
19 |
20 | export class TempFileWrapper {
21 | tempFile: any;
22 | path: String;
23 |
24 | constructor(tempFile) {
25 | this.tempFile = tempFile;
26 | this.path = tempFile.path;
27 | }
28 |
29 | clean() {
30 | if (this.tempFile == null) {
31 | return;
32 | }
33 | fs.unlink(this.path);
34 | this.path = null;
35 | this.tempFile = null;
36 | }
37 |
38 |
39 | }
40 |
41 |
42 | export function canExecute(path) {
43 | logger.log(">>> EXECUTE CHECK <<<");
44 | try {
45 | fs.accessSync(path, fs.R_OK | fs.X_OK);
46 | logger.log("> Path can be executed");
47 | logger.log(">>> END <<<");
48 | return true;
49 | }
50 | catch(err) {
51 | logger.log("> Path can not be executed:");
52 | logger.log(err);
53 | logger.log(">>> END <<<");
54 | return false;
55 | }
56 | }
57 |
58 |
59 | export function canRead(path) {
60 | logger.log(">>> READ CHECK <<<");
61 | try {
62 | fs.accessSync(path, fs.R_OK);
63 | logger.log("> Path can be read");
64 | logger.log(">>> END <<<")
65 | return true;
66 | }
67 | catch(err) {
68 | logger.log("> Path can not be read");
69 | logger.log(err);
70 | logger.log(">>> END <<<")
71 | return false;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | """Some."""
2 | from os import path
3 |
4 |
5 | def main():
6 | """Some docstring."""
7 | if path.exists('/tmp'):
8 | return True
9 |
10 |
11 |
12 |
13 | if __name__ == '__main__':
14 | main()
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "moduleResolution": "node",
5 | "sourceMap": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "removeComments": false,
9 | "noImplicitAny": false,
10 | "outDir": "./lib"
11 | },
12 | "exclude": [
13 | "node_modules",
14 | "typings/main",
15 | "typings/main.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "globalDependencies": {
3 | "core-js": "registry:dt/core-js#0.0.0+20160317120654",
4 | "jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
5 | "node": "registry:dt/node#4.0.0+20160509154515"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------