1

I need to run PyLint to validate my Python files code when building. The python files are under .pyproj (I use Python tools for Visual Studio 2015). How I can do that?

Update:

So far I have code like this:

<Target Name="PythonRunPyLint">
    <PropertyGroup>
        <PyLintWarningRegex><![CDATA[^(?<filename>.+?)\((?<line>\d+),(?<column>\d+)\): warning (?<msg_id>.+?): (?<message>.+?)$]]></PyLintWarningRegex>
    </PropertyGroup>
    <RunPythonCommand Target="pylint.lint"
                             TargetType="module"
                             Arguments="&quot;--msg-template={abspath}({line},{column}): warning {msg_id}: {msg} [{C}:{symbol}]&quot; -r n @(Compile, ' ')"
                             ExecuteIn="console"
                             WorkingDirectory="$(MSBuildProjectDirectory)"
                             WarningRegex="$(PyLintWarningRegex)"
                             RequiredPackages="pylint&gt;=1.0.0"> 
        <Output TaskParameter="ConsoleOutput" PropertyName="OutputText" />
        <Output TaskParameter="ConsoleError" PropertyName="ErrorText" />
    </RunPythonCommand>
</Target>

But when I run msbuild I get output and there's 0 warnings, why regex does not parse warnings (regex is taken from Microsoft.PythonTools.targets and it works when doing Tools > Run PyLint in Visual studio)?

C:\>msbuild TestPylint.pyproj /t:Build
Microsoft (R) Build Engine version 14.0.23107.0
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 15/10/2015 20:10:26.
Project "C:\TestPylint.pyproj" on node 1 (Build target(s)).
PythonRunPyLint:
************* Module TestPylint
C:\TestPylint.py(2,0): warning C0304: Final newline missing [C:missing-final-newline]
C:\TestPylint.py(1,0): warning C0111: Missing module docstring [C:missing-docstring]
No config file found, using default configuration
Done Building Project "C:\TestPylint.pyproj" (Build target(s)) -- FAILED.

Build FAILED.
    0 Warning(s)
    0 Error(s)
Nmktronas
  • 237
  • 3
  • 12

4 Answers4

1

It's not wired up out of the box, but you can add it to your project if you're so inclined. Locate Microsoft.PythonTools.targets, and find <Target Name="PythonRunPyLintCommand" ... inside. Copy that to your project, rename it to something like "PythonRunPyLint", and inside it replace CreatePythonCommandItem with RunPythonCommand. You might also have to remove some attributes on that element (basically any that MSBuild will complain do not exist), and remove the child <Output>.

Then just start build with that target.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • Ok it works now using MsBuild in the command line, how to make it work in Visual Studio when I right click project and choose 'Build'? Currently no warnings or errors are displayed on the Error List window. – Nmktronas Oct 14 '15 at 20:43
  • To get the errors to show in VS, you need to invoke the command on the project node in Solution Explorer - right-click it, select "Python", then in the submenu there's "PyLint" (this item actually comes from `CreatePythonCommandItem` in the .targets file - so this way you can add your own custom commands invoking some Python code to the project if you want). Using normal Build, OTOH will always run the "Build" target. – Pavel Minaev Oct 15 '15 at 01:52
  • I updated the question, I basically want to get warnings and errors from msbuild output, trying similary as in CreatePythonCommandItem but it seems that errors/warnings are not read.. – Nmktronas Oct 15 '15 at 19:09
  • 1
    There's no way to do that currently. IDE only hooks up errors & warnings from commands created with CreatePythonCommandItem, but those have to be invoked through the context menu (as part of the build, all they do is produce MSBuild items that describe the command - the IDE then reads those and fills the menu with them; running the command doesn't actually run the build). With RunPythonCommand you can run things as part of build, but errors/warnings won't be captured - the ErrorRegex and WarningRegex attributes are ignored (actually they shouldn't be here at all, it's an oversight). – Pavel Minaev Oct 16 '15 at 00:08
  • 2
    A well-behaved project system should actually hook up to MSBuild to capture warnings (as it has the necessary APIs and will parse the errors & warnings in the standard MSBuild format automatically), it's just that PTVS does not do that currently. Feel free to file a feature request for this on GitHub. – Pavel Minaev Oct 16 '15 at 00:09
0

I ended up with the following code:

<Target Name="Build">
    <RunPythonCommand Target="pylint.lint"
                         TargetType="module"
                         Arguments="&quot;--msg-template={path}({line},{column}): warning: [{msg_id}{obj}] {msg}&quot; -r n @(Compile, ' ')"
                         ExecuteIn="console"
                         WorkingDirectory="$(MSBuildProjectDirectory)"
                         RequiredPackages="pylint&gt;=1.0.0"
                         ConsoleToMSBuild="true"
                         ContinueOnError="true">
          <Output TaskParameter="ConsoleOutput" ItemName="OutputText" />
          <Output TaskParameter="ConsoleError" PropertyName="ErrorText" />
    </RunPythonCommand>
     <WriteLinesToFile
            File="lint_output.txt"
            Lines="@(OutputText)"
            Overwrite="true"
            Encoding="Unicode"/>
     <Exec ContinueOnError="true"
          IgnoreExitCode="true"
          Command='type lint_output.txt'/>
  </Target>

Now msbuild TestPylint.pyproj /t:Build counts errors/warnings also errors/warnings are shown on Visual Studio Error List window.

Task WriteLinesToFile is used because I did not found any other way for msbuild to recognize errors/warnings <Exec Command="echo $(OutputText)/> (if OutputText is property) simply does not work!

Nmktronas
  • 237
  • 3
  • 12
0

A slight variation on the solution presented by @Nmktronas.

<Target Name="CoreCompile">
  <ResolveEnvironment ContinueOnError="WarnAndContinue">
    <Output TaskParameter="InterpreterPath" PropertyName="InterpreterPath" />
  </ResolveEnvironment>
  <Exec Condition="Exists($(InterpreterPath))"
        Command="(set PYTHONPATH=$(SearchPath)) &amp; &quot;$(InterpreterPath)&quot; -m pylint.lint &quot;--msg-template={path}({line},{column}): warning: [{msg_id}{obj}] {msg}&quot; -r n @(Compile, ' ')"
        WorkingDirectory="$(MSBuildProjectDirectory)"
        IgnoreExitCode="true" />
</Target>
PaulB
  • 99
  • 1
  • 3
0

The question is old, but I have spent some time on this issue. I suggest some improvements to the accepted answer by @Nmktronas, that solve the following problems:

  1. PyLint runs only after the Rebuild Command, and not after the Build Command.
  2. Annoying Console window popups during build.

Please see the comments in the code snippet.

  <!-- Problem: PyLint is running only for Rebuild command, and never runs for Build command.
       Solution: https://github.com/Microsoft/PTVS/issues/816: "The Outputs parameter of Target 
         node won't work, but if you add an item group called OutputFiles then we will compare 
         date/time stamps against those when deciding to build." -->
  <ItemGroup>
    <!-- Visible="false" prevents the file from showing in the Solution Window.-->
    <OutputFiles Include="lint_output.txt" 
                 Visible="false"/>
  </ItemGroup>

  <Target Name="BeforeBuild">
    <!-- ExecuteIn="none" value prevents appearance of the Console window. -->
    <RunPythonCommand Target="pylint.lint"
                      TargetType="module"
                      Arguments="&quot;--msg-template={path}({line},{column}): warning: [{msg_id}{obj}] {msg}&quot; -r n @(Compile, ' ')"
                      ExecuteIn="none"
                      WorkingDirectory="$(MSBuildProjectDirectory)"
                      RequiredPackages="pylint&gt;=1.0.0"
                      ConsoleToMSBuild="true"
                      ContinueOnError="true">
      <Output TaskParameter="ConsoleOutput" ItemName="OutputText" />
      <Output TaskParameter="ConsoleError" PropertyName="ErrorText" />
    </RunPythonCommand>
    <WriteLinesToFile File="lint_output.txt"
                      Lines="@(OutputText)"
                      Overwrite="true"
                      Encoding="Unicode"/>
    <Exec ContinueOnError="true"
          IgnoreExitCode="true"
          Command='type lint_output.txt'/>
  </Target>
Artyom
  • 36
  • 4