Skip to content

Instantly share code, notes, and snippets.

@patkujawa-wf
Last active July 28, 2021 20:52
Show Gist options
  • Save patkujawa-wf/e7bf49c9d72383baa1b54c573c91acc4 to your computer and use it in GitHub Desktop.
Save patkujawa-wf/e7bf49c9d72383baa1b54c573c91acc4 to your computer and use it in GitHub Desktop.
pubupgrade: Combine your dart pubspec files' information so that you can easily upgrade your pubspec.yaml to the versions in your pubspec.lock
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import sys
import re
import yaml # PyYAML
def merge(yamlfile, lockfile, outf=None, comment_previous_version=False,
include_dev=True, only_upgrade=True):
"""
"""
lock_data = yaml.safe_load(lockfile)
lock_versions_by_package_name = {
name: details['version'] for name, details in lock_data['packages'].items()
}
print('lock_versions_by_package_name')
print(lock_versions_by_package_name)
yaml_data = yaml.safe_load(yamlfile)
dep_versions_by_package_name = {
name: details['version'] if isinstance(details, dict) and details.get(
'version') else details for name, details in yaml_data['dependencies'].items()
}
print('dep_versions_by_package_name')
print(dep_versions_by_package_name)
# dev_dependencies are optional
if include_dev:
dev_dep_versions_by_package_name = {
name: details['version'] if isinstance(details, dict) and details.get(
'version') else details for name, details in yaml_data['dev_dependencies'].items()
}
print('dev_dep_versions_by_package_name')
print(dev_dep_versions_by_package_name)
dep_versions_by_package_name.update(dev_dep_versions_by_package_name)
def get_replacement(line, maybe_package, new_version):
previous_version = dep_versions_by_package_name.get(maybe_package) # type: str
if not previous_version:
return line
if isinstance(previous_version, dict):
# Likely a path dep; nothing to do
return line
if '>' in previous_version:
is_gte = '>=' in previous_version
equals_or_blank = '=' if is_gte else ''
if '<' in previous_version:
# upper_range includes the equals sign if present
upper_range = re.sub(r'.*?<([^ #]+)', r'\1', previous_version)
new_version = '>{}{} <{}'.format(equals_or_blank, new_version, upper_range)
else:
new_version = '>{}{}'.format(equals_or_blank, new_version)
else:
new_version = '^{}'.format(new_version)
addendum = ''
if previous_version != new_version and comment_previous_version:
addendum = ' # was {}'.format(previous_version)
replacement = line.replace(previous_version, new_version).replace(
'\n', '{}\n'.format(addendum)
)
return replacement
outf = outf or open('{}.updated'.format(yamlfile.name), 'w')
yamlfile.seek(0)
looking_for_version_key = False
maybe_package = None
new_version = None
for line in yamlfile:
if looking_for_version_key:
if 'version' in line:
looking_for_version_key = False
outf.write(get_replacement(line, maybe_package, new_version))
else:
outf.write(line)
continue
maybe_package_and_version = line.strip().split(':')
maybe_package = maybe_package_and_version[0]
# TODO might need to strip out known keys that could be package names, e.g. 'path', 'url'
new_version = lock_versions_by_package_name.get(maybe_package)
if new_version:
package_and_version_on_same_line = len(maybe_package_and_version) == 2 and \
maybe_package_and_version[
1] # can't be empty either
if package_and_version_on_same_line:
outf.write(get_replacement(line, maybe_package, new_version))
else:
looking_for_version_key = True
outf.write(line)
continue
else:
outf.write(line)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Copy version numbers from pubspec.lock to pubspec.yaml.'
)
parser.add_argument(
'yaml', type=argparse.FileType('r'),
help='path to pubspec.yaml file'
)
parser.add_argument(
'lock', type=argparse.FileType('r'),
help='path to pubspec.lock file'
)
parser.add_argument(
'--out', '-o', default=sys.stdout, type=argparse.FileType('w'),
help='file where the merged output should go'
)
parser.add_argument(
'--comment-previous-version', '-p', default=False, action='store_true',
help='includes the previous version as a code comment (default=false)'
)
parser.add_argument(
'--no-include-dev', dest='include_dev', default=False, action='store_false',
help='also upgrades dev dependencies (default=true)'
)
# TODO
# parser.add_argument(
# '--only-upgrade', '-u', default=True, type=bool,
# help='disallows downgrading deps'
# )
args = parser.parse_args()
merge(
args.yaml, args.lock,
outf=args.out,
comment_previous_version=args.comment_previous_version,
include_dev=args.include_dev,
# args.only_upgrade,
)
@patkujawa-wf
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment