Как запустить PyLint для.pyproj при сборке с помощью MsBuild?

Мне нужно запустить PyLint для проверки кода файлов Python при сборке. Файлы Python находятся в.pyproj (я использую инструменты Python для Visual Studio 2015). Как я могу это сделать?

Обновить:

Пока у меня есть такой код:

<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>

Но когда я запускаю msbuild, я получаю вывод и появляется 0 предупреждений, почему регулярное выражение не анализирует предупреждения (регулярное выражение взято из Microsoft.PythonTools.targets и работает, когда выполняется Tools > Run PyLint в 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)

3 ответа

Решение

Я получил следующий код:

<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>

Сейчас msbuild TestPylint.pyproj /t:Build подсчитывает ошибки / предупреждения, а также ошибки / предупреждения отображаются в окне списка ошибок Visual Studio.

Задача WriteLinesToFile используется, потому что я не нашел другого способа для msbuild распознавать ошибки / предупреждения <Exec Command="echo $(OutputText)/> (если OutputText является свойством) просто не работает!

Он не подключен из коробки, но вы можете добавить его в свой проект, если вы так склонны. разместить Microsoft.PythonTools.targets, и найти <Target Name="PythonRunPyLintCommand" ... внутри. Скопируйте это в свой проект, переименуйте его во что-то вроде "PythonRunPyLint" и внутри замените CreatePythonCommandItem с RunPythonCommand, Возможно, вам также придется удалить некоторые атрибуты этого элемента (в основном те, на которые MSBuild будет жаловаться, не существует) и удалить дочерний элемент. <Output>,

Тогда просто начните строить с этой целью.

Небольшое изменение решения, представленного @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>

Вопрос старый, но я потратил некоторое время на это. Я предлагаю некоторые улучшения принятого ответа @Nmktronas, которые решают следующие проблемы:

  1. PyLint запускается только после команды Rebuild, но не после команды Build.
  2. Раздражающие всплывающие окна консоли во время сборки.

См. Комментарии во фрагменте кода.

  <!-- 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>
Другие вопросы по тегам