Skip to content

Commit

Permalink
.ci/generate_bear_requirements: Add Update & Check
Browse files Browse the repository at this point in the history
This commits updates the script to use ruamel.yaml
which is better fork of PyYaml.
Also adds Update and Check mode for diffing and
updating Bear-Requirements yaml.

Closes coala#2444
  • Loading branch information
nemani committed Jul 4, 2018
1 parent b51144b commit 2f532de
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 12 deletions.
84 changes: 75 additions & 9 deletions .ci/generate_bear_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import argparse
import copy
import itertools
import json
import os
import sys
from collections import OrderedDict

from yaml import dump
from ruamel.yaml import YAML, RoundTripDumper
from ruamel.yaml.comments import CommentedMap
from pyprint.NullPrinter import NullPrinter

from coalib.bears.BEAR_KIND import BEAR_KIND
Expand All @@ -30,6 +31,10 @@
from dependency_management.requirements.NpmRequirement import NpmRequirement
from dependency_management.requirements.PipRequirement import PipRequirement

yaml = YAML(typ='rt')
yaml.default_flow_style = False
yaml.Dumper = RoundTripDumper

BEAR_REQUIREMENTS_YAML = "bear-requirements.yaml"
_VERSION_OPERATORS = ('<', '>', '~', '=', '-', '!')

Expand All @@ -51,6 +56,11 @@ def get_args():
parser.add_argument('--bear-dirs', '-d', nargs='+', metavar='DIR',
help='additional directories which may contain bears')

parser.add_argument('--check', '-c', action='store_true',
help='performs a dry run, and reports differences.')
parser.add_argument('--update', '-u', action='store_true',
help='updates "bear-requirements.yaml" '
'instead of overwriting')
args = parser.parse_args()

return args
Expand Down Expand Up @@ -124,7 +134,7 @@ def _to_entry(requirement, default_operator):


def _get_requirements(requirements, default_operator, exclude=[]):
return dict(
return CommentedMap(
(requirement.package, _to_entry(requirement, default_operator))
for requirement in requirements
if requirement.package not in exclude
Expand All @@ -144,6 +154,48 @@ def get_pip_requirements(requirements):
return _get_requirements(requirements, '~=', inherited_requirements)


def deep_update(target, src):
for key, value in src.items():
if not key in target:
target[key] = copy.deepcopy(value)
else:
if isinstance(value, list):
target[key].extend(value)
elif isinstance(value, dict):
deep_update(target[key], value)
elif isinstance(value, set):
target[key].update(value.copy())
else:
target[key] = copy.copy(value)


def deep_diff(target, src):
errors = []
for key, value in src.items():
if not key in target:
errors.append((key, 'Missing'))
elif target[key] != value:
if isinstance(value, list):
if [x for x in value if x not in target[key]]:
errors.append(key)
elif isinstance(value, dict):
if target[key] != value:
e = deep_diff(target[key], value)
errors.append((key, e))
elif isinstance(value, set):
if set(target[key]).symmetric_difference(value):
errors.append(key)
else:
errors.append((key, target[key]))
return errors


def sort_requirements(req_dict):
for reqs in ['pip_requirements', 'npm_requirements', 'gem_requirements']:
req_dict[reqs] = CommentedMap(sorted(req_dict[reqs].items(),
key=lambda t: t[0]))


if __name__ == '__main__':
args = get_args()

Expand All @@ -155,18 +207,32 @@ def get_pip_requirements(requirements):
pip_reqs, npm_reqs, gem_reqs = (
get_all_requirements(get_all_bears(bear_dirs)))

requirements = {}
requirements['overrides'] = 'coala-build.yaml'
requirements['pip_requirements'] = get_pip_requirements(pip_reqs)
requirements['npm_requirements'] = get_npm_requirements(npm_reqs)
requirements = CommentedMap()
requirements['gem_requirements'] = get_gem_requirements(gem_reqs)
requirements['npm_requirements'] = get_npm_requirements(npm_reqs)
requirements['pip_requirements'] = get_pip_requirements(pip_reqs)

if args.update or args.check:
input_file = open(os.path.join(PROJECT_DIR, BEAR_REQUIREMENTS_YAML),'r')
input_requirments = yaml.load(input_file)

new_requirments = copy.deepcopy(input_requirments)
deep_update(new_requirments, requirements)
sort_requirements(new_requirments)

if args.update:
requirements = new_requirments

output = None
if args.check:
changed = deep_diff(input_requirments, new_requirments)
if changed:
yaml.dump(y, sys.stdout)
exit()

if args.output == '-':
output = sys.stdout
else:
output = open(args.output, 'w')

dump(requirements, output, default_flow_style=False)
yaml.dump(requirements, output)
output.close()
2 changes: 2 additions & 0 deletions .moban.dt/bears-test-requirements.txt.jj2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{% include 'test-requirements.txt.jj2' %}
ruamel.yaml~=0.15.42
2 changes: 1 addition & 1 deletion .moban.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ configuration:
targets:
- setup.py: bears-setup.py.jj2
- requirements.txt: requirements.txt.jj2
- test-requirements.txt: test-requirements.txt.jj2
- test-requirements.txt: core-test-requirements.txt.jj2
- bears/VERSION: VERSION.jj2
- Gemfile: Gemfile.jj2
- package.json: package.json.jj2
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ script:
- pip install $(ls ./dist/*.whl)"[alldeps]"
- bash .ci/tests.sh
# Ensure bear requirements are in sync with the bear PipRequirement
- .ci/generate_bear_requirements.py
- .ci/generate_bear_requirements.py --check --update
- git diff --exit-code
- coala --non-interactive
- codecov
Expand Down
4 changes: 3 additions & 1 deletion bear-requirements.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This is an automatically generated file.
# And should not be edited by hand.
overrides: coala-build.yaml
gem_requirements:
brakeman:
version: ~>4.1.1
Expand Down Expand Up @@ -114,7 +117,6 @@ npm_requirements:
version: '>=1.7.3'
write-good:
version: ~0.9.1
overrides: coala-build.yaml
pip_requirements:
HTTPolice:
version: ~=0.5.2
Expand Down
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pytest-xdist~=1.15
requests-mock~=1.2
pip!=9.0.2, !=10.0.*
wheel~=0.29
ruamel.yaml~=0.15.42

0 comments on commit 2f532de

Please sign in to comment.