# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Update the pinned versions of Python packages."""

import re

import attr
from PB.recipes.pigweed.update_python_versions import InputProperties

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'pigweed/roll_util',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


def RunSteps(api, props):  # pylint: disable=invalid-name
    checkout = api.checkout(props.checkout_options)
    env = api.environment.init(
        checkout.root, props.environment_options, use_constraint_file=False,
    )

    with env():
        constraint_file = props.path_to_constraint_file
        if not constraint_file:
            api.build.gn_gen(checkout.root, props.build_options)

            # pw_build_PIP_CONSTRAINTS is a GN arg that points to a pip
            # constraint file. For more see
            # https://pigweed.googlesource.com/pigweed/pigweed/+/main/pw_build/python.gni
            gn_args = api.build.get_gn_args(
                checkout_root=checkout.root,
                test_data=[
                    {
                        'name': 'pw_build_PIP_CONSTRAINTS',
                        'current': {'value': ['//foo/bar/constraint.file']},
                    }
                ],
            )
            constraint_file = gn_args['pw_build_PIP_CONSTRAINTS']['current'][
                'value'
            ][0].strip('/')

        assert constraint_file

        # Write list of packages to constraint file.
        cmd = [
            'pw',
            'python-packages',
            'list',
            checkout.root.join(constraint_file),
        ]
        api.step('freeze package list', cmd)

    change = api.auto_roller.attempt_roll(
        api.auto_roller.Options(
            remote=checkout.options.remote,
            upstream_ref=checkout.options.branch,
            dry_run=props.dry_run,
            labels_to_set=api.roll_util.labels_to_set,
            labels_to_wait_on=api.roll_util.labels_to_wait_on,
            bot_commit=props.bot_commit,
        ),
        repo_dir=checkout.root,
        commit_message='roll: Update Python package versions',
    )

    return api.auto_roller.raw_result(change)


def GenTests(api):  # pylint: disable=invalid-name
    def properties(**kwargs):
        new_kwargs = {'dry_run': False}
        new_kwargs.update(api.checkout.git_properties())
        new_kwargs.update(kwargs)
        return api.properties(**new_kwargs)

    yield (
        api.status_check.test('simple')
        + properties()
        + api.auto_roller.success()
    )
