import arrow
import six

from tilezilla.core import BoundingBox, Band


MAPPING = {
    'timeseries_id': str,
    'acquired': arrow.Arrow,
    'processed': arrow.Arrow,
    'platform': str,
    'instrument': str,
    'bounds': BoundingBox,
    'bands': [Band],
    'metadata': dict,
    'metadata_files': dict
}


def check_attributes(product):
    for attr, _type in six.iteritems(MAPPING):
        assert hasattr(product, attr)
        value = getattr(product, attr)

        if isinstance(_type, type):
            assert isinstance(value, _type)
        else:
            assert isinstance(value, type(_type))
            for item in value:
                assert isinstance(item, tuple(_type))

import arrow
import six

from tilezilla.core import BoundingBox, Band


MAPPING = {
    'timeseries_id': six.string_types,
    'acquired': arrow.Arrow,
    'processed': arrow.Arrow,
    'platform': six.string_types,
    'instrument': six.string_types,
    'bounds': BoundingBox,
    'bands': [Band],
    'metadata': dict,
    'metadata_files': dict
}


def check_attributes(product):
    for attr, _type in six.iteritems(MAPPING):
        assert hasattr(product, attr)
        value = getattr(product, attr)

        if isinstance(_type, (type, tuple)):
            # Type declaration one or more types
            assert isinstance(value, _type)
        else:
            # Type declaration list of types
            assert isinstance(value, type(_type))
            for item in value:
                assert isinstance(item, tuple(_type))

Allow str type comparison in py2/3
Allow str type comparison in py2/3

  import arrow
  import six
  
  from tilezilla.core import BoundingBox, Band
  
  
  MAPPING = {
-     'timeseries_id': str,
+     'timeseries_id': six.string_types,
      'acquired': arrow.Arrow,
      'processed': arrow.Arrow,
-     'platform': str,
+     'platform': six.string_types,
-     'instrument': str,
+     'instrument': six.string_types,
      'bounds': BoundingBox,
      'bands': [Band],
      'metadata': dict,
      'metadata_files': dict
  }
  
  
  def check_attributes(product):
      for attr, _type in six.iteritems(MAPPING):
          assert hasattr(product, attr)
          value = getattr(product, attr)
  
-         if isinstance(_type, type):
+         if isinstance(_type, (type, tuple)):
+             # Type declaration one or more types
              assert isinstance(value, _type)
          else:
+             # Type declaration list of types
              assert isinstance(value, type(_type))
              for item in value:
                  assert isinstance(item, tuple(_type))
  
Allow str type comparison in py2/3
## Code Before:
import arrow
import six

from tilezilla.core import BoundingBox, Band


MAPPING = {
    'timeseries_id': str,
    'acquired': arrow.Arrow,
    'processed': arrow.Arrow,
    'platform': str,
    'instrument': str,
    'bounds': BoundingBox,
    'bands': [Band],
    'metadata': dict,
    'metadata_files': dict
}


def check_attributes(product):
    for attr, _type in six.iteritems(MAPPING):
        assert hasattr(product, attr)
        value = getattr(product, attr)

        if isinstance(_type, type):
            assert isinstance(value, _type)
        else:
            assert isinstance(value, type(_type))
            for item in value:
                assert isinstance(item, tuple(_type))

## Instruction:
Allow str type comparison in py2/3
## Code After:
import arrow
import six

from tilezilla.core import BoundingBox, Band


MAPPING = {
    'timeseries_id': six.string_types,
    'acquired': arrow.Arrow,
    'processed': arrow.Arrow,
    'platform': six.string_types,
    'instrument': six.string_types,
    'bounds': BoundingBox,
    'bands': [Band],
    'metadata': dict,
    'metadata_files': dict
}


def check_attributes(product):
    for attr, _type in six.iteritems(MAPPING):
        assert hasattr(product, attr)
        value = getattr(product, attr)

        if isinstance(_type, (type, tuple)):
            # Type declaration one or more types
            assert isinstance(value, _type)
        else:
            # Type declaration list of types
            assert isinstance(value, type(_type))
            for item in value:
                assert isinstance(item, tuple(_type))
