text: from schematics.models import Model
  from schematics.types import IntType, StringType
  from schematics.types.serializable import serializable
  from schematics.types.compound import ModelType, DictType
  
  
  def test_basic_type():
      class PlayerInfo(Model):
          categories = DictType(StringType)
  
      info = PlayerInfo(dict(categories={
          "math": "math",
          "batman": "batman",
      }))
  
      assert info.categories["math"] == "math"
  
      d = info.serialize()
      assert d == {
          "categories": {
              "math": "math",
              "batman": "batman",
          }
      }
  
  
  def test_dict_type_with_model_type():
      class CategoryStats(Model):
          category_slug = StringType()
          total_wins = IntType()
  
      class PlayerInfo(Model):
          categories = DictType(ModelType(CategoryStats))
          #TODO: Maybe it would be cleaner to have
          #       DictType(CategoryStats) and implicitly convert to ModelType(CategoryStats)
  
      info = PlayerInfo(dict(categories={
          "math": {
              "category_slug": "math",
              "total_wins": 1
          },
          "batman": {
              "category_slug": "batman",
              "total_wins": 3
          }
      }))
  
      math_stats = CategoryStats({"category_slug": "math", "total_wins": 1})
      assert info.categories["math"] == math_stats
  
      d = info.serialize()
      assert d == {
          "categories": {
              "math": {
                  "category_slug": "math",
                  "total_wins": 1
              },
              "batman": {
                  "category_slug": "batman",
                  "total_wins": 3
              }
          }
      }
  
  
  def test_dict_type_with_model_type_init_with_instance():
      class ExperienceLevel(Model):
          level = IntType()
  
      class CategoryStats(Model):
          category_slug = StringType()
          total_wins = IntType()
  
          @serializable(type=ModelType(ExperienceLevel))
          def xp_level(self):
              return ExperienceLevel(dict(level=self.total_wins))
  
      class PlayerInfo(Model):
          id = IntType()
          categories = DictType(ModelType(CategoryStats))
          #TODO: Maybe it would be cleaner to have
          #       DictType(CategoryStats) and implicitly convert to ModelType(CategoryStats)
  
      math_stats = CategoryStats({
          "category_slug": "math",
          "total_wins": 1
      })
  
      info = PlayerInfo(dict(id=1, categories={
          "math": math_stats,
      }))
  
      assert info.categories["math"] == math_stats
  
      d = info.serialize()
  
      assert d == {
          "id": 1,
          "categories": {
              "math": {
                  "category_slug": "math",
                  "total_wins": 1,
                  "xp_level": {
                      "level": 1
                  }
              },
          }
      }
  
  
  def test_with_empty():
      class CategoryStatsInfo(Model):
          slug = StringType()
  
      class PlayerInfo(Model):
          categories = DictType(
              ModelType(CategoryStatsInfo),
              default=lambda: {},
              serialize_when_none=True,
          )
  
      info = PlayerInfo()
  
      assert info.categories == {}
  
      d = info.serialize()
      assert d == {
          "categories": {},
      }
  
  
  def test_key_type():
      def player_id(value):
          return long(value)
  
      class CategoryStatsInfo(Model):
          slug = StringType()
  
      class PlayerInfo(Model):
          categories = DictType(ModelType(CategoryStatsInfo), coerce_key=player_id)
  
      stats = CategoryStatsInfo({
          "slug": "math",
      })
  
      info = PlayerInfo({
          "categories": {
              1L: {"slug": "math"}
          },
      })
  
      assert info.categories == {1: stats}
  
      d = info.serialize()
      assert d == {
          "categories": {1L: {"slug": "math"}}
      }
  