# 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/gerrit',
    '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()
    )
