text: # -*- coding: utf-8 -*-
  
  # Copyright 2016 Resonai Ltd. All rights reserved
  #
  # 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
  #
  #     http://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.
  
  """
  yabt Target extraction tests
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  :author: Itamar Ostricher
  """
  
  
  from os import path
  
  import pytest
  
  from .buildcontext import BuildContext
  from .extend import (
      Plugin, PropType as PT, register_build_func, register_builder_sig,
      register_manipulate_target_hook)
  from .target_extraction import args_to_props, extractor, handle_typed_args
  from .target_utils import Target
  
  
  @pytest.yield_fixture
  def with_spam_builder_sig():
      Plugin.remove_builder('Spam')
      register_builder_sig('Spam', ['foo',
                                    ('bar', PT.str),
                                    ('cats', PT.StrList, None),
                                    ('cat_list', PT.File, None),
                                    ])
      yield
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_valid_positional_args():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam', 'foo', 'bar'], kwargs={})
      assert target.props == {'name': 'my-spam', 'foo': 'foo', 'bar': 'bar',
                              'deps': None, 'cachable': True,
                              'cats': None, 'cat_list': None,
                              'build_params': None,
                              'license': None,
                              'packaging_params': None,
                              'policies': None,
                              'attempts': 1,
                              'runtime_params': None,
                              }
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_missing_one_pos_arg():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam', 'foo'], kwargs={})
      assert ("Spam() missing 1 required positional argument: 'bar'"
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_missing_two_pos_args():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam'], kwargs={})
      assert ("Spam() missing 2 required positional arguments: 'foo', 'bar'"
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_missing_all_pos_args():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=[], kwargs={})
      assert ("Spam() missing 3 required positional arguments: "
              "'name', 'foo', 'bar'" in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_valid_mix_pos_kwargs():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam'], kwargs={'foo': 'foo', 'bar': 'bar'})
      assert target.props == {'name': 'my-spam', 'foo': 'foo', 'bar': 'bar',
                              'deps': None, 'cachable': True,
                              'cats': None, 'cat_list': None,
                              'build_params': None,
                              'license': None,
                              'packaging_params': None,
                              'policies': None,
                              'attempts': 1,
                              'runtime_params': None,
                              }
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_mix_pos_kwargs_missing_pos_arg():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam'], kwargs={'bar': 'bar'})
      assert ("Spam() missing 1 required positional argument: 'foo'"
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_mix_pos_kwargs_dup_arg():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam'], kwargs={'name': 'my-spam'})
      assert ("Spam() got multiple values for argument 'name'"
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_mix_pos_kwargs_unexpected_kwarg():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam'], kwargs={'wtf': 'wait-for-it'})
      assert ("Spam() got an unexpected keyword argument 'wtf'"
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_build_sig_args_to_props_too_many_pos_args():
      target = Target(builder_name='Spam')
      with pytest.raises(TypeError) as excinfo:
          args_to_props(target, Plugin.builders['Spam'],
                        args=['my-spam', 'foo', 'bar', None, None, None, None,
                              None, None, None, None, None, 'w00t', '14th'],
                        kwargs={})
      assert ('Spam() takes from 3 to 13 positional arguments, but 14 were given'
              in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_target_extraction_bad_target_names(basic_conf):
      for bad_name in ['.', 'bad:name', ':', 'bad@name', '@', '**', 'foo/bar']:
          target = Target(builder_name='Spam')
          args_to_props(target, Plugin.builders['Spam'],
                        args=[bad_name, 'foo', 'bar'], kwargs={})
          with pytest.raises(ValueError) as excinfo:
              handle_typed_args(target, Plugin.builders['Spam'], 'spams')
          assert ("Invalid target name: `{}'".format(bad_name)
                  in str(excinfo.value))
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_typed_args_not_str():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam', 'foo', 123], kwargs={})
      with pytest.raises(TypeError) as excinfo:
          handle_typed_args(target, Plugin.builders['Spam'], 'spams')
      assert 'bar: got `123`, expected string value' in str(excinfo.value)
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_typed_args_valid_defaults():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam', 'foo', 'bar'], kwargs={})
      handle_typed_args(target, Plugin.builders['Spam'], 'spams')
      assert target.props == {'name': 'spams:my-spam', 'foo': 'foo',
                              'bar': 'bar', 'deps': [], 'cachable': True,
                              'cats': [], 'cat_list': None,
                              'build_params': {},
                              'license': [],
                              'packaging_params': {},
                              'policies': [],
                              'attempts': 1,
                              'runtime_params': {},
                              }
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_typed_args_valid_non_default():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam', 'foo', 'bar', ('my cat', 'other cat'),
                          '../lists/from-vet-4', '../hams:my-ham'],
                    kwargs={})
      handle_typed_args(target, Plugin.builders['Spam'], 'spams')
      assert target.props == {'name': 'spams:my-spam', 'foo': 'foo',
                              'bar': 'bar', 'deps': ['hams:my-ham'],
                              'cachable': True, 'cats': ['my cat', 'other cat'],
                              'cat_list': path.join('lists', 'from-vet-4'),
                              'build_params': {},
                              'license': [],
                              'packaging_params': {},
                              'policies': [],
                              'attempts': 1,
                              'runtime_params': {},
                              }
  
  
  @pytest.mark.usefixtures('with_spam_builder_sig')
  def test_file_arg_from_project_root():
      target = Target(builder_name='Spam')
      args_to_props(target, Plugin.builders['Spam'],
                    args=['my-spam', 'foo', 'bar'],
                    kwargs={'cat_list': '//lists/from-vet-4'})
      handle_typed_args(target, Plugin.builders['Spam'], 'spams')
      assert target.props == {'name': 'spams:my-spam', 'foo': 'foo',
                              'bar': 'bar', 'deps': [], 'cachable': True,
                              'cats': [],
                              'cat_list': path.join('lists', 'from-vet-4'),
                              'build_params': {},
                              'license': [],
                              'packaging_params': {},
                              'policies': [],
                              'attempts': 1,
                              'runtime_params': {},
                              }
  