Skip to content
Snippets Groups Projects
Commit 18a4b9e9 authored by Marek Chrastina's avatar Marek Chrastina
Browse files

Add list option

parent 0cae282a
No related branches found
Tags
1 merge request!1Add py script
Pipeline #7993 passed
......@@ -15,7 +15,7 @@ pylint:
- export PYTHONIOENCODING=UTF-8
- export LC_CTYPE=en_US.UTF-8
- python setup.py egg_info
- pip install $(paste -d " " -s pipupgradedependencies.egg-info/requires.txt)
- pip install $(paste -d " " -s pipdeps.egg-info/requires.txt)
script:
- pylint $(find . -type f -name "*.py")
......@@ -25,7 +25,7 @@ build:
artifacts:
expire_in: 1 day
paths:
- dist/pipupgradedependencies*tar.gz
- dist/pipdeps*tar.gz
before_script:
- export PYTHONIOENCODING=UTF-8
- export LC_CTYPE=en_US.UTF-8
......
......@@ -631,7 +631,7 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
pipupgradedependencies
pipdeps
Copyright (C) 2019 IT4Innovations National Supercomputing Center,
VSB - Technical University of Ostrava, Czech Republic
......@@ -653,7 +653,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
pipupgradedependencies Copyright (C) 2019
pipdeps Copyright (C) 2019
IT4Innovations National Supercomputing Center,
VSB - Technical University of Ostrava, Czech Republic
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
......
# pipupgradedependencies
# pipdeps
Pipupgradedependencies upgrades all outdated packages with respect to existing dependencies.
Pipdeps shows/upgrades outdated packages with respect to existing dependencies.
Python 2.7 is required.
## Usage
```console
pipupgradedependencies
usage: pipdeps [-h] (-l | -u)
Pipdeps shows/upgrades outdated packages with respect to existing
dependencies.
optional arguments:
-h, --help show this help message and exit
-l, --list show upgradable packages and versions
-u, --upgrade upgrade upgradable packages
```
"""
pipupgradedependencies init
pipdeps init
"""
__import__('pkg_resources').declare_namespace(__name__)
"""
pipdeps
"""
import argparse
import json
import distutils.version
import os
import urllib2
import re
import subprocess
import sys
import packaging.specifiers
import packaging.version
def arg_parse():
"""
argument parser
"""
parser = argparse.ArgumentParser(
description="Pipdeps shows/upgrades outdated packages with respect to existing \
dependencies."
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-l', '--list',
action='store_true',
help="show upgradable packages and versions")
group.add_argument('-u', '--upgrade',
action='store_true',
help="upgrade upgradable packages")
return parser.parse_args()
def check_strict_version(version):
"""
Return true if version is strict, otherwise return false
"""
try:
distutils.version.StrictVersion(version)
except ValueError:
return False
return True
def upgrade_pip():
"""
pip install --upgrade pip
"""
subprocess.check_call(["pip", "install", "--upgrade", "pip"], stderr=subprocess.STDOUT)
def upgrade_package(package, versions):
"""
pip install --upgrade "<package><versions>"
"""
subprocess.check_call(
["pip", "install", "--upgrade", "%s==%s" % (package, "".join(versions))],
stderr=subprocess.STDOUT
)
def get_outdated_packages():
"""
pip list --outdated
"""
outdated_packages = subprocess.check_output(
["pip", "list", "--outdated"],
stderr=subprocess.STDOUT
)
return [line.split()[0] for line in outdated_packages.strip().split("\n")[2:]]
def get_dependencies_tree():
"""
pipdeptree --json-tree
"""
pipdeptree = subprocess.check_output(
["pipdeptree", "--json-tree"],
stderr=subprocess.STDOUT
)
return json.loads(pipdeptree.strip())
def json_search(jsonpipdeptree, package, key):
"""
find package dependencies in json tree
"""
if isinstance(jsonpipdeptree, dict):
keys = jsonpipdeptree.keys()
if 'package_name' in keys and key in keys:
if re.search(r'^%s$' % package, jsonpipdeptree['package_name'], re.IGNORECASE):
yield jsonpipdeptree[key]
for child_val in json_search(jsonpipdeptree['dependencies'], package, key):
yield child_val
elif isinstance(jsonpipdeptree, list):
for item in jsonpipdeptree:
for item_val in json_search(item, package, key):
yield item_val
def find_available_versions(package_name):
"""
Return descending list of available strict version
"""
url = "https://pypi.python.org/pypi/%s/json" % (package_name,)
data = json.load(urllib2.urlopen(urllib2.Request(url)))
versions = data["releases"].keys()
data = [version for version in versions if check_strict_version(version)]
return sorted(data, key=distutils.version.StrictVersion, reverse=True)
def find_upgradable_version(available_version, installed_version, required_version):
"""
Return upgradable version, otherwise return none.
"""
while True:
try:
version = available_version.pop(0)
except IndexError:
break
aver = packaging.version.Version(version)
iver = packaging.version.Version(installed_version)
rver = packaging.specifiers.SpecifierSet(",".join(required_version))
if rver.contains(aver):
if aver == iver:
break
elif aver > iver:
return version
return None
def find_upgradable_packages(package_list, jsonpipdeptree, exclude=None):
"""
Collect data about upgradable packages and return as list of dictionaries
"""
result = []
for package in package_list:
if isinstance(exclude, list):
if package in exclude:
continue
dependencies = [_ for _ in json_search(jsonpipdeptree, package, 'required_version')]
dependencies = list(set(dependencies))
if not [dep for dep in dependencies if re.search(r'(^==.*|^\d.*)', dep) is not None]:
installed_version = "".join(list(set(
[_ for _ in json_search(jsonpipdeptree, package, 'installed_version')]
)))
required_version = [dep for dep in dependencies if 'Any' not in dep]
available_version = find_available_versions(package)
upgradable_version = find_upgradable_version(
available_version, installed_version, required_version)
rev = {'package': package,
'installed_version': installed_version,
'required_version': required_version,
'available_version': available_version}
if upgradable_version is not None:
rev['upgradable_version'] = upgradable_version
result.append(rev)
return result
def main():
"""
main function
"""
os.environ["PYTHONWARNINGS"] = "ignore:DEPRECATION"
arguments = arg_parse()
upgrade_pip()
outdated_packages = get_outdated_packages()
while True:
upgradable_packages = find_upgradable_packages(outdated_packages, get_dependencies_tree())
if arguments.list:
if upgradable_packages:
print upgradable_packages
sys.exit(1)
else:
print "There is nothing to upgrade."
sys.exit(0)
try:
package = upgradable_packages.pop(-1)
except IndexError:
break
upgrade_package(package['package'], package['upgradable_version'])
print "Done."
if __name__ == "__main__":
main()
"""
pipupgradedependencies
"""
import argparse
import json
import os
import re
import subprocess
import sys
def upgrade_pip():
"""
pip install --upgrade pip
"""
try:
subprocess.check_call(["pip", "install", "--upgrade", "pip"], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(1)
def upgrade_package(package, versions):
"""
pip install --upgrade "<package><versions>"
"""
try:
subprocess.check_call(
["pip", "install", "--upgrade",
"%s%s" % (package, "".join(versions))],
stderr=subprocess.STDOUT
)
except subprocess.CalledProcessError:
sys.exit(1)
def get_outdated_packages():
"""
pip list --outdated
"""
try:
outdated_packages = subprocess.check_output(
["pip", "list", "--outdated"],
stderr=subprocess.STDOUT
)
except subprocess.CalledProcessError:
sys.exit(1)
return [line.split()[0] for line in outdated_packages.strip().split("\n")[2:]]
def get_dependencies_tree():
"""
pipdeptree --json-tree
"""
try:
pipdeptree = subprocess.check_output(
["pipdeptree", "--json-tree"],
stderr=subprocess.STDOUT
)
except subprocess.CalledProcessError:
sys.exit(1)
return json.loads(pipdeptree.strip())
def find_dependencies(jsonpipdeptree, package):
"""
find package dependencies in json tree
"""
if isinstance(jsonpipdeptree, dict):
keys = jsonpipdeptree.keys()
if 'package_name' in keys and 'required_version' in keys:
if re.search(r'^%s$' % package, jsonpipdeptree['package_name'], re.IGNORECASE):
yield jsonpipdeptree['required_version']
for child_val in find_dependencies(jsonpipdeptree['dependencies'], package):
yield child_val
elif isinstance(jsonpipdeptree, list):
for item in jsonpipdeptree:
for item_val in find_dependencies(item, package):
yield item_val
def filter_dependencies(package_list, jsonpipdeptree, exclude):
"""
return list of outdated packages that do not have strict dependency version
"""
filtered_dependencies = []
for package in package_list:
if package in exclude:
continue
dependencies = [_ for _ in find_dependencies(jsonpipdeptree, package)]
dependencies = list(set(dependencies))
if not [dep for dep in dependencies if re.search(r'(^==.*|^\d.*)', dep) is not None]:
filtered_dependencies.append(
{'package': package,
'versions': [dep for dep in dependencies if 'Any' not in dep]}
)
return filtered_dependencies
def arg_parse():
"""
argument parser
"""
parser = argparse.ArgumentParser(
description="Pipupgradedependencies upgrades all outdated packages with respect to \
existing dependencies."
)
parser.parse_args()
def main():
"""
main function
"""
os.environ["PYTHONWARNINGS"] = "ignore:DEPRECATION"
arg_parse()
upgrade_pip()
outdated_packages = get_outdated_packages()
finished_upgrades = []
while True:
filtered_outdated_packages = filter_dependencies(
outdated_packages, get_dependencies_tree(), finished_upgrades
)
try:
package = filtered_outdated_packages[-1]
except IndexError:
break
finished_upgrades.append(package['package'])
upgrade_package(package['package'], package['versions'])
if len(filtered_outdated_packages) == len(finished_upgrades):
break
print "Done."
if __name__ == "__main__":
main()
"""
pipupgradedependencies setup
pipdeps setup
"""
from setuptools import setup, find_packages
setup(
name='pipupgradedependencies',
name='pipdeps',
description='Pipupgradedependencies upgrades all outdated packages with respect to existing \
dependencies.',
description='Pipdeps shows/upgrades outdated packages with respect to existing \
dependencies.',
classifiers=[
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
......@@ -17,11 +17,11 @@ setup(
author='IT4Innovations',
author_email='support@it4i.cz',
url='https://code.it4i.cz/sccs/pip-upgradedependencies',
url='https://code.it4i.cz/sccs/pip-deps',
license='GPLv3+',
packages=find_packages(),
namespace_packages=['pipupgradedependencies'],
namespace_packages=['pipdeps'],
zip_safe=False,
version='0.0.1',
#version_format='{tag}',
......@@ -29,11 +29,12 @@ setup(
setup_requires=['setuptools-markdown'],
#setup_requires=['setuptools-git-version', 'setuptools-markdown'],
install_requires=[
'packaging',
'pipdeptree',
],
entry_points={
'console_scripts': [
'pipupgradedependencies = pipupgradedependencies.pipupgradedependencies:main',
'pipdeps = pipdeps.pipdeps:main',
]
}
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment