• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

xvik/gradle-use-python-plugin: Use python modules in gradle build

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

xvik/gradle-use-python-plugin

开源软件地址(OpenSource Url):

https://github.com/xvik/gradle-use-python-plugin

开源编程语言(OpenSource Language):

Groovy 100.0%

开源软件介绍(OpenSource Introduction):

Gradle use-python plugin

License Build Status Appveyor build status codecov

About

Plugin does not install python and pip itself and use globally installed python (by default). It's easier to prepare python manually because python have good compatibility (from user perspective) and does not need to be updated often.

The only plugin intention is to simplify python usage from gradle. By default, plugin creates python virtualenv inside the project and installs all modules there so each project has its own python (copy) and could not be affected by other projects or system changes.

Features:

  • Install required python modules using pip (per project (virtualenv), os user (--user) or globally)
  • Provides task to call python commands, modules or scripts (PythonTask)
  • Could be used as basement for building plugins for specific python modules (like mkdocs plugin)

Who's using (usage examples)

Summary
  • Configuration: python
  • Tasks:
    • checkPython - validate python installation (and create virtualenv if required)
    • pipInstall - install declared pip modules
    • pipUpdates - show the latest available versions for the registered modules
    • pipList - show all installed modules (the same as pipInstall shows after installation)
    • type:PythonTask - call python command/script/module
    • type:PipInstallTask - may be used for custom pip modules installation workflow
Possible pip issue warning (linux/macos)

If pip3 list -o fails with: TypeError: '>' not supported between instances of 'Version' and 'Version' Then simply update installed pip version: python3 -m pip install --upgrade pip

This is a known issue related to incorrectly patched pip packages in some distributions.

Setup

Maven Central Gradle Plugin Portal

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'ru.vyarus:gradle-use-python-plugin:2.3.0'
    }
}
apply plugin: 'ru.vyarus.use-python'

OR

plugins {
    id 'ru.vyarus.use-python' version '2.3.0'
}

Compatibility

Plugin compiled for java 8, compatible with java 11

Gradle Version
5-6 2.3.0
4.x 1.2.0

Snapshots

Snapshots may be used through JitPack
  • Go to JitPack project page
  • Select Commits section and click Get it on commit you want to use or use master-SNAPSHOT to use the most recent snapshot

For gradle before 6.0 use buildscript block with required commit hash as version:

buildscript {
    repositories {
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'ru.vyarus:gradle-use-python-plugin:2450c7e881'
    }
}
apply plugin: 'ru.vyarus.use-python'

For gradle 6.0 and above:

  • Add to settings.gradle (top most!) with required commit hash as version:

    pluginManagement {
        resolutionStrategy {
            eachPlugin {
                if (requested.id.namespace == 'ru.vyarus.use-python') {
                    useModule('ru.vyarus:gradle-use-python-plugin:2450c7e881')
                }
            }
        }
        repositories {
            maven { url 'https://jitpack.io' }
            gradlePluginPortal()          
        }
    }    
  • Use plugin without declaring version:

    plugins {
        id 'ru.vyarus.use-python'
    }

Python & Pip

Make sure python and pip are installed:

python --version  
pip --version

On *nix python usually reference python2. For python3:

python3 --version  
pip3 --version
Windows install

Download and install python manually or use chocolately:

choco install python

In Windows 10 python 3.9 could be installed from Windows Store: just type 'python' in console and windows will open Windows Store's python page. No additional actions required after installation.

Note that windows store python will require minium virtualenv 20.0.11 (or above). (if virtualenv not yet installed then no worry - plugin will install the correct version)

Linux/Macos install

On most *nix distributions python is already installed, but often without pip.

Install pip if required (ubuntu example):

sudo apt-get install python3-pip

Make sure the latest pip installed (required to overcome some older pip problems):

pip3 install -U pip

To install exact pip version:

pip3 install -U pip==20.0.11

Note that on ubuntu pip installed with python3-pip package is 9.0.1, but it did not(!) downgrade module versions (e.g. pip install click 6.6 when click 6.7 is installed will do nothing). Maybe there are other differences, so it's highly recommended to upgrade pip with pip3 install -U pip.

Automatic pip upgrade

As described above, there are different ways of pip installation in linux and, more important, admin permissions are required to upgrade global pip. So it is impossible to upgrade pip from the plugin (in all cases).

But, it is possible inside virtualenv or user (--user) scope. Note that plugin creates virtualenv by default (per project independent python environment).

So, in order to use newer pip simply put it as first dependency:

python {
    pip 'pip:10.0.1'
    pip 'some_module:1.0'
}

Here project virtualenv will be created with global pip and newer pip version installed inside environment. Packages installation is sequential, so all other packages will be installed with newer pip (each installation is independent pip command).

The same will work for user scope: python.scope = USER

When applying this trick, consider minimal pip version declared in configuration (python.minPipVersion='9' by default) as minimal pip version required for project setup (instead of minimal version required for work).

Automatic python install

Python is assumed to be used as java: install and forget. It perfectly fits user use case: install python once and plugin will replace all manual work on project environment setup.

It is also easy to configure python on CI (like travis).

If you want automatic python installation, try looking on JetBrain's python-envs plugin. But be careful because it has some caveats (for example, on windows python could be installed automatically just once and requires manual un-installation).

Multi-module projects

When used in multi-module project, plugin will create virtualenv inside the root project directory in order to share the same environment for all modules.

See multi-module setup cases

Travis CI configuration

To make plugin work on travis you'll need to install python3 packages:

language: java  
dist: bionic
jdk: openjdk8

addons:
  apt:
    packages:
    - python3
    - python3-pip
    - python3-setuptools 

before_install:
  - python3 --version
  - pip3 --version
  - pip3 install -U pip

It will be python 3.6 by default (for bionic).

Appveyour CI configuration

To make plugin work on appveyour you'll need to add python to path:

environment:
    matrix:
        - JAVA_HOME: C:\Program Files\Java\jdk1.8.0
          PYTHON: "C:\\Python36-x64"

install:
  - set PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%
  - python --version

Now plugin would be able to find python binary.

To use python 3.9 you'll need to switch image:

image: Visual Studio 2019

See available pythons matrix for more info.

Usage

Declare required modules (optional):

python.pip 'module1:1.0', 'module2:1.0'

or

python {
    pip 'module1:1.0'
    pip 'module2:1.0'
}

Module format is: name:version (will mean name==version in pip notion). Non strict version definition is not allowed (for obvious reasons). Dependencies are installed in declaration order. If duplicate declaration specified then only the latest declaration will be used:

python.pip 'module1:2.0', 'module2:1.0', 'module1:1.0' 

Will install version 1.0 of module1 because it was the latest declaration. "Module overrides" works for all declaration types (see below): the latest declared module version always wins.

Dependencies are installed with pipInstall task which is called before any declared PythonTask.

Note that by default dependencies are installed inside project specific virtualenv (project specific copy of python environment).

Behaviour matrix for possible scope and installVirtualenv configurations:

scope installVirtualenv Behaviour default
GLOBAL ignored packages installed in global scope (pip install name)
USER ignored packages installed in user scope (pip install name --user)
VIRTUALENV_OR_USER true if virtualenv not installed, install it in user scope; create project specific virtualenv and use it default
VIRTUALENV_OR_USER false when virtualenv is not installed install packages in user scope (same as USER); when virtualenv installed create project specific virtualenv and use it
VIRTUALENV true if virtualenv not installed, install it in user scope; create project specific virtualenv and use it
VIRTUALENV false throw error when virtualenv not installed

Note that VIRTUALENV + true and VIRTUALENV_OR_USER + true behaviours are the same. Different scope name here describes behavior for unexpected installVirtualenv=false change (to fail or fallback to user scope).

USER and GLOBAL scopes will ignore local (virtual)environment, even if project-specific environment was created before, with these options global python will be used instead.

Pip module extra features

You can declare modules with extra features in module name to install special version of module (with enabled features):

python.pip 'requests[socks,security]:2.18.4'

IMPORTANT: it is impossible to track if this "variation" of module is installed, so plugin performs up-to-date check for such modules by name only (for example, if 'requests==2.18.4' is already installed). For most cases, this is suitable behaviour because, by default, modules are installed in virtualenv and so you will always have correct module installed. For other cases, you can disable up-to-date checks (delegate all dependencies logic to pip): python.alwaysInstallModules = true

VCS pip modules

You can declare vcs modules: modules installed directly from version control (e.g. git, svn). Format:

vcs+protocol://repo_url/@vcsVersion#egg=pkg-pkgVersion
  • @vcsVersion part is required: prefer using commit version or tag for reproducible builds
  • -pkgVersion is installed module version. Required to be able to compare declared plugin with installed version.

For example:

python.pip 'git+https://github.com/ictxiangxin/boson/@b52727f7170acbedc5a1b4e1df03972bd9bb85e3#egg=boson-0.9'

Declares module boson version 0.9, installed from git commit b52727f7170acbedc5a1b4e1df03972bd9bb85e3 (it may be tag name or branch, but prefer not using branch names).

pipInstall will be considered up-to-date if boson==0.9 is already installed. Note that declared module version is completely free: you can set any version (0.10, 1.2, etc.), it is not checked and used only for up-to-date validation.

WARNING: module version part assumed to follow the last dash, so if you specify version like somethinf-12.0-alpha.1 it would be parsed incorrectly (as package somethinf-12.0 version alpha.1)! Don't use dashes in a version!

Vcs module installation is: source checkout and module build (using setup.py). You may need to specify subdirectory as &subdirectory=pkg_dir (see docs)

To avoid installation problems, package version is not used for actual installation (in spite of the fact that its official convention, it doesnt work in some cases). For example, module above will be installed as (no -0.9):

pip install git+https://github.com/ictxiangxin/boson/@b52727f7170acbedc5a1b4e1df03972bd9bb85e3#egg=boson

All pip supported vcs could be used: git, svn, hg, bzr

If up-to-date logic, implemented by pipInstall task, does not suit your needs, you can always disable it with python.alwaysInstallModules = true (pip always called). But this will be slower.

NOTE: since pip 20, compiled vcs module is cached (before it was build on each execution), but it is possible to disable cache (for all modules) with python.usePipCache=false configuration (applies --no-cache-dir pip flag)

Extra pip repositories

To add additional pip repositories (probably self-hosted):

python {
    extraIndexUrls = ["http://extra-url.com", "http://extra-url.com"]
}

or with shortcut method (shortcut may be used multiple times):

python {
    extraIndexUrls "http://extra-url.com", "http://extra-url2.com" 
}

Extra urls will be applied as --extra-index-url flag for pip commands supporting it: install, download, list and wheel. By default, it only affects pipInstall and pipList tasks. Applied for all BasePipTask, so if you have custom pip tasks, it would be affected too.

In case of ssl problems (stale or self-signed certificated), mark domains as trusted:

python {
    trustedHosts = ["extra-url.com"]
}

or

python {
    trustedHosts "extra-url.com"
}

Applied as --trusted-host option only for pipInstall (because pip install is the only command supporting this option).

NOTE: if, for some reason, you don't want to specify it for all pip tasks, you can configure exact task, for example: pipInstall.extraIndexUrls = ["http://extra-url.com", "http://extra-url2.com"]

Extra pip install options

It is impossible to support directly all possible pip install options usages directly with api (safe way), so there is a direct configuration for an additional options. For example:

pipInstall.options('--upgrade-strategy', 'only-if-needed')

Shortcut method above may be called multiple times:

pipInstall.options('--a', 'value')
pipInstall.options('--b', 'value')

Or you can use property directly:

pipInstall.options = ['--a', 'value', '--b', 'value']

Virtualenv

When you declare any pip modules, plugin will try to use virtualenv in order to install required modules locally (for current project only).

If virtualenv is not installed - it will be installed automatically in --user scope. If you don't want automatic installation then disable it:

python.installVirtualenv = false

Plugin installs exact pip version declared in python.virtualenvVersion (by default, 16.7.9). This way, plugin will always install only known to be working version and avoid side effects of "just released" versions (note that pip 20 is a major rewrite and may still contain side effects).

In any case, plugin checks if virtualenv is already installed and use it to create local environment (if not, then fall back to --user scope by default). Virtualenv usage is driven by declared scope, so if you don't want to use it set:

python.scope = USER // or GLOBAL

With USER (or GLOBAL) scope, virtualenv will not be used, even if it's already created in project (plugin will ignore it and use global python).

If you already use virtualenv in your project (have created manually environment), then simply point plugin to use it:

python.envPath = 'path/to/your/env'

It will automatically change pythonPath configuration accordingly.

NOTE: plugin will not create environment if you don't use any modules. If you still want to use project specific environment (without declared pip modules) then create it manually: python3 -m virtualenv .gradle/python (default location). Plugin will recognize existing env and use it.

IMPORTANT: virtualenv creates local python copy (by default in .gradle/python). Copy is created from global python and later used instead of global python. If you want to change used python version in the environment, then manually remove .gradle/python so it could be created again (from global python).

To copy environment instead of symlinking (default) set (--always-copy):

python.envCopy = true

Scope

Pip dependencies could be installed per project, for current user (~/) or globally.

Default behaviour:

  • if virtualenv module installed (or automatically installed, see above): manage pip dependencies per project (env .gradle/python created)
  • if no virtualenv - use user scope (--user pip flag): pip modules are installed only for current user (this avoid permission problems on linux)

To change defaults:

python.scope = VIRTUALENV
  • GLOBAL - install modules globally (this may not work on linux due to permissions)
  • USER - use --user flag to install for current user only
  • VIRTUALENV_OR_USER - default
  • VIRTUALENV - use virtualenv (if module not installed - error thrown)

Note that values may be declared without quotes because it's an enum which values are declared as project ext properties (ext.USER==ru.vyarus.gradle.plugin.python.PythonExtension.Scope.USER).

Complete behaviour matrix see above

Check modules updates

To quick check if new versions are available for the registered pip modules use pipUpdates task:

:pipUpdates
The following modules could be updated:

	package            version latest type 
	------------------ ------- ------ -----
	click              6.6     6.7    wheel

Note that it will not show versions for transitive modules, only for modules specified directly in python.pip.

To see all available updates (without filtering):

pipUpdates.all = true

NOTE: If you see an error like

TypeError: '>' not supported between instances of 'Version' and 'SetuptoolsVersion'

then update pip:

pip install -U pip

Call python

Call python command:

task cmd(type: PythonTask) {
    command = "-c print('sample')"
}

called: python -c print('sample') on win and python -c exec("print('sample')") on *nix (exec applied automatically for compatibility)

Call multi-line command:

task cmd(type: PythonTask) {
    command = "-c \"import sys; print(sys.prefix)\""
}

called: python -c "import sys; print(sys.prefix)" on win and python -c exec("import sys; print(sys.prefix)") on *nix

NOTE: it is important to wrap script with space in quotes (otherwise parser will incorrectly parse arguments).

Call module:

task mod(type: PythonTask) {
    module = 'sample' 
    command = "mod args"
}

called: python -m sample mod args

Call script:

task script(type: PythonTask) { 
    command = "path/to/script.py 1 2"
}

called: python path/to/script.py 1 2 (arguments are optional, just for demo)

String command is used for simplicity, but it could be array/collection of args:

task script(type: PythonTask) { 
    command = ['path/to/script.py', '1', '2'] 
}
Command parsing

When command passed as string it is manually parsed to arguments array (split by space):

  • Spaces in quotes are ignored: "quoted space" or 'quoted space'
  • Escaped spaces are ignored: with\\ space (argument will be used with simple space then - escape removed).
  • Escaped quotes are ignored: "with \\"interrnal quotes\\" inside". But pay attention that it must be 2 symbols \\" and not \" because otherwise it is impossible to detect escape.

To view parsed arguments run gradle with -i flag (enable info logs). In case when command can't be parsed properly (bug in parser or unsupported case) use array of arguments instead of string.

Environment variables

By default, executed python can access system environment variables (same as System.getenv()).

To declare custom (process specific) variables:

task sample(type: PythonTask) {
       command = "-c \"import os;print('variables: '+os.getenv('some', 'null')+' '+os.getenv('foo', 'null'))\""
       environment 'some', 1
       environment 'other', 2
       environment(['foo': 'bar', 'baz': 'bag'])
}

Map based declaration (environment(['foo': 'bar', 'baz': 'bag'])) does not remove previously declared variables (just add all vars from map), but direct assignment environment = ['foo': 'bar', 'baz': 'bag'] will reset variables.

System variables will be available even after declaring custom variables (of course, custom variables could override global value).

NOTE: environment variable could also be declared in extension to apply for all python commands: python.environment 'some', 1 (if environments declared both globally (through extension) and directly on task, they would be merged)

Configuration

Python location

On linux, plugin will use python3 if available (and fall back to python if not). To use different binary use:

python {
    pythonBinary = 'python'
}

This will force python 2 for linux. Also, this may be handy if python binary is named differently.

To use non global python:

python {
    pythonPath = 'path/to/python/binray/'
}

pythonPath must be set to directory containing python binary (e.g. 'path/to/python/binray/python.e


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap