# Path: shrubbery/db/fields/reverse/reverse_dict.py
# class ReverseDictField(models.ForeignKey):
#     def __init__(self, target, key='key', value='value', **kwargs):
#         assert kwargs.get('null', False) is False, "ReverseDictField may not be null"
#         super(ReverseDictField, self).__init__(target, **kwargs)
#         self.value = value
#         self.key = key      
#         
#     def contribute_to_related_class(self, cls, related):
#         setattr(cls, related.get_accessor_name(), ReverseDictDescriptor(related))
# 
# Path: shrubbery/db/fields/reverse/reverse_list.py
# class ReverseListField(models.ForeignKey):
#     def __init__(self, to, index='index', value='value', **kwargs):
#         assert kwargs.get('null', False) is False, "ReverseDictField may not be null"
#         super(ReverseListField, self).__init__(to, **kwargs)
#         self.index = index
#         self.value = value
# 
#     def slice(self, manager, s):
#         return [getattr(item, self.value) for item in manager._slice(s)]
# 
#     def contribute_to_related_class(self, cls, related):
#         setattr(cls, related.get_accessor_name(), ReverseListDescriptor(related))
# 
# class ListField(VirtualField):
#     def __init__(self, value_field, **kwargs):
#         if isinstance(value_field, (str, models.base.ModelBase)):
#             value_field = models.ForeignKey(value_field, 
#                 null=kwargs.pop('null', False), 
#                 blank=kwargs.pop('blank', False), 
#                 related_name=kwargs.pop('related_name', None),
#             )
#         else:
#             assert "null" not in kwargs, "ListField does not support `null`, use `null` on its value field."
#             assert "blank" not in kwargs, "ListField does not support `blank`, use `blank` on its value field."            
#         self.value_field = value_field
#         self.index_field_name = kwargs.pop('index_field_name', 'index')
#         self.value_field_name = kwargs.pop('value_field_name', 'value')
#         self.db_table = kwargs.pop('db_table', None)
#         super(VirtualField, self).__init__(**kwargs)
# 
#     def contribute_to_class(self, cls, name):
#         super(ListField, self).contribute_to_class(cls, name)
#         self.list_model = create_list_model(cls, name, self.value_field, 
#             index=self.index_field_name, 
#             value=self.value_field_name, 
#             db_table=self.db_table,
#             field_cls=ReverseListField,
#         )
# 
# class ManyToManyList(models.ManyToManyField):
#     def __init__(self, to, **kwargs):
#         assert "through" not in kwargs, "ManyToManyList cannot use an explicit through model."
#         self.list_descriptor = kwargs.pop('list_descriptor', None)
#         self.index_field_name = kwargs.pop('index_field_name', 'index')
#         self.value_field_name = kwargs.pop('value_field_name', 'value')        
#         super(ManyToManyList, self).__init__(to, **kwargs)
#         
#     def contribute_to_class(self, cls, name):
#         if not self.list_descriptor:
#             self.list_descriptor = "%s_list" % name.replace('_set', '')
#         to = self.rel.to
#         self.rel.through = create_list_model(cls, self.list_descriptor, models.ForeignKey(to), 
#             index=self.index_field_name, 
#             value=self.value_field_name, 
#             db_table=self.db_table,
#             field_cls=ReverseManyToManyListField,
#         )
#         self.creates_table = False
#         super(ManyToManyList, self).contribute_to_class(cls, name)


import unittest
from django.db import models
from shrubbery.db.fields.reverse import ReverseDictField, ReverseListField, ListField, ManyToManyList
        abstract = True
        app_label = "db"

class A(TestModel):
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

class B(TestModel):
    name = models.CharField(max_length=30)
    a_set = ManyToManyList(A)

    def __str__(self):
        return self.name

class Attrib(TestModel):
    b = ReverseDictField('B', key='key', value='value', related_name='attribs')
    key = models.CharField(max_length=30)
    value = models.CharField(max_length=30)
    
    def __str__(self):
        return 'attribute of %s key=%s value=%s' % (self.b, self.key, self.value)

class AttribType(TestModel):
    name = models.CharField(max_length=30)
    def __str__(self):
        return self.name
    
class TypedAttrib(TestModel):

# Path: shrubbery/db/fields/reverse/reverse_dict.py
# class ReverseDictField(models.ForeignKey):
#     def __init__(self, target, key='key', value='value', **kwargs):
#         assert kwargs.get('null', False) is False, "ReverseDictField may not be null"
#         super(ReverseDictField, self).__init__(target, **kwargs)
#         self.value = value
#         self.key = key      
#         
#     def contribute_to_related_class(self, cls, related):
#         setattr(cls, related.get_accessor_name(), ReverseDictDescriptor(related))
# 
# Path: shrubbery/db/fields/reverse/reverse_list.py
# class ReverseListField(models.ForeignKey):
#     def __init__(self, to, index='index', value='value', **kwargs):
#         assert kwargs.get('null', False) is False, "ReverseDictField may not be null"
#         super(ReverseListField, self).__init__(to, **kwargs)
#         self.index = index
#         self.value = value
# 
#     def slice(self, manager, s):
#         return [getattr(item, self.value) for item in manager._slice(s)]
# 
#     def contribute_to_related_class(self, cls, related):
#         setattr(cls, related.get_accessor_name(), ReverseListDescriptor(related))
# 
# class ListField(VirtualField):
#     def __init__(self, value_field, **kwargs):
#         if isinstance(value_field, (str, models.base.ModelBase)):
#             value_field = models.ForeignKey(value_field, 
#                 null=kwargs.pop('null', False), 
#                 blank=kwargs.pop('blank', False), 
#                 related_name=kwargs.pop('related_name', None),
#             )
#         else:
#             assert "null" not in kwargs, "ListField does not support `null`, use `null` on its value field."
#             assert "blank" not in kwargs, "ListField does not support `blank`, use `blank` on its value field."            
#         self.value_field = value_field
#         self.index_field_name = kwargs.pop('index_field_name', 'index')
#         self.value_field_name = kwargs.pop('value_field_name', 'value')
#         self.db_table = kwargs.pop('db_table', None)
#         super(VirtualField, self).__init__(**kwargs)
# 
#     def contribute_to_class(self, cls, name):
#         super(ListField, self).contribute_to_class(cls, name)
#         self.list_model = create_list_model(cls, name, self.value_field, 
#             index=self.index_field_name, 
#             value=self.value_field_name, 
#             db_table=self.db_table,
#             field_cls=ReverseListField,
#         )
# 
# class ManyToManyList(models.ManyToManyField):
#     def __init__(self, to, **kwargs):
#         assert "through" not in kwargs, "ManyToManyList cannot use an explicit through model."
#         self.list_descriptor = kwargs.pop('list_descriptor', None)
#         self.index_field_name = kwargs.pop('index_field_name', 'index')
#         self.value_field_name = kwargs.pop('value_field_name', 'value')        
#         super(ManyToManyList, self).__init__(to, **kwargs)
#         
#     def contribute_to_class(self, cls, name):
#         if not self.list_descriptor:
#             self.list_descriptor = "%s_list" % name.replace('_set', '')
#         to = self.rel.to
#         self.rel.through = create_list_model(cls, self.list_descriptor, models.ForeignKey(to), 
#             index=self.index_field_name, 
#             value=self.value_field_name, 
#             db_table=self.db_table,
#             field_cls=ReverseManyToManyListField,
#         )
#         self.creates_table = False
#         super(ManyToManyList, self).contribute_to_class(cls, name)


# Path: shrubbery/db/tests/reverse_fields.py
import unittest
from django.db import models
from shrubbery.db.fields.reverse import ReverseDictField, ReverseListField, ListField, ManyToManyList

        abstract = True
        app_label = "db"

class A(TestModel):
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

class B(TestModel):
    name = models.CharField(max_length=30)
    a_set = ManyToManyList(A)

    def __str__(self):
        return self.name

class Attrib(TestModel):
    b = ReverseDictField('B', key='key', value='value', related_name='attribs')
    key = models.CharField(max_length=30)
    value = models.CharField(max_length=30)
    
    def __str__(self):
        return 'attribute of %s key=%s value=%s' % (self.b, self.key, self.value)

class AttribType(TestModel):
    name = models.CharField(max_length=30)
    def __str__(self):
        return self.name
    
class TypedAttrib(TestModel):

    b = ReverseDictField('B', key='type', value='value', related_name='tattribs')