<NME> __init__.py
<BEF> import persistent
import six

from . import fields
from . import exceptions
from zope.lifecycleevent import modified
from zerodb.intid import IdStore
from zerodb.trees import family32
from zerodb.catalog import Catalog
from zerodb.models.fields import Field, Text


class ModelMeta(type):
    def __init__(cls, name, bases, dct):
        if bases != (persistent.Persistent,):  # Only subclasses of Model can do it, not Model itself
            used_fields = set(filter(lambda key:
                    not key.startswith("_") and
    """

    def __init__(self, **kw):
        indexed_fields = set(filter(lambda key:
                not key.startswith("_") and
                isinstance(getattr(self.__class__, key), indexable.Indexable),
            self.__class__.__dict__.keys()))

        required_fields = set(filter(lambda key: getattr(self.__class__, key).default is None, indexed_fields))

        missed_fields = required_fields.difference(kw)
        if missed_fields:
            raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))
    Data model to easily create indexable persistent objects.
    If an object declares a property from indexable, this property is indexed.
    *All* other properties are stored but unindexed

    Example:
        >>> class Page(Model):
        ...     title = indexable.Field()
        ...     text = indexable.Text()

        ... page = Page(title="Hello", text="World", extra=12345)
    """

    # TODO we should (?) provide some way to save model definition into the database
    # and generate model class from there.
    # This could be valuable when working with json which doesn't keep any python code
    # Or we should make a method which allows to generate a new model from json

    __modelname__ = None
    __family__ = family32

    def __init__(self, **kw):
        missed_fields = self._z_required_fields.difference(kw)
        if missed_fields:
            raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))

        for field in self._z_default_fields.difference(kw):
            default = getattr(self.__class__, field).default
            if callable(default):
                default = default()
            setattr(self, field, default)

        for field, value in six.iteritems(kw):
            setattr(self, field, value)

    def __setattr__(self, name, value):
        origattr = getattr(self, name, None)
        if origattr is not None and name in self._z_indexed_fields and \
                not isinstance(origattr, fields.Indexable) and hasattr(self, "_p_uid"):  # reindex notify
            modified(self, name)
        super(Model, self).__setattr__(name, value)

    def __lt__(self, other):
        return id(self) < id(other)

    @classmethod
    def create_store(cls):
        """Returns intid.IdStore storage for this class"""
        return IdStore(family=cls.__family__)

    @classmethod
    def create_catalog(cls):
        """Creates and returns catalog for this model with indexes in it"""
        catalog = Catalog()  # TODO: specify family as a parameter
        for name in cls._z_indexed_fields:
            field = getattr(cls, name)

            if field.virtual:
                # Tuple discriminator means virtual field.
                # Index has to look it up in model._z_virtual_fields,
                # where model = obj.__class__
                discriminator = (name,)
            else:
                discriminator = None

            catalog[name] = field.Index(discriminator or name)
        return catalog

<MSG> Set model instance attributes based on fields

<DFF> @@ -18,13 +18,24 @@ class Model(persistent.Persistent):
     """
 
     def __init__(self, **kw):
+        # This set will go to metaclass
         indexed_fields = set(filter(lambda key:
                 not key.startswith("_") and
                 isinstance(getattr(self.__class__, key), indexable.Indexable),
             self.__class__.__dict__.keys()))
 
+        # This set will go to metaclass
         required_fields = set(filter(lambda key: getattr(self.__class__, key).default is None, indexed_fields))
 
+        # Indexed fields which have default values
+        default_fields = indexed_fields.difference(required_fields).difference(kw)
+
         missed_fields = required_fields.difference(kw)
         if missed_fields:
             raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))
+
+        for field in default_fields:
+            setattr(self, field, getattr(self.__class__, field).default)
+
+        for field, value in kw.iteritems():
+            setattr(self, field, value)

{'commit': 'diff --git a/zerodb/models/__init__.py b/zerodb/models/__init__.py\nindex d74c65a..eaa708e 100644\n--- a/zerodb/models/__init__.py\n+++ b/zerodb/models/__init__.py\n@@ -18,13 +18,24 @@ class Model(persistent.Persistent):\n     """\n \n     def __init__(self, **kw):\n+        # This set will go to metaclass\n         indexed_fields = set(filter(lambda key:\n                 not key.startswith("_") and\n                 isinstance(getattr(self.__class__, key), indexable.Indexable),\n             self.__class__.__dict__.keys()))\n \n+        # This set will go to metaclass\n         required_fields = set(filter(lambda key: getattr(self.__class__, key).default is None, indexed_fields))\n \n+        # Indexed fields which have default values\n+        default_fields = indexed_fields.difference(required_fields).difference(kw)\n+\n         missed_fields = required_fields.difference(kw)\n         if missed_fields:\n             raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))\n+\n+        for field in default_fields:\n+            setattr(self, field, getattr(self.__class__, field).default)\n+\n+        for field, value in kw.iteritems():\n+            setattr(self, field, value)\n', 'commit_subject': 'Set model instance attributes based on fields', 'repo_name': 'zerodb/zerodb', 'committer': {'name': 'Michael Egorov', 'email': '5e74db1f2273065a15b5d0c69c12827c20f86755@gmail.com', 'time_sec': '1428186055', 'tz_offset': '-420', 'date': {'seconds': '1428186055'}}, 'commit_tree': 'a531aa3eabfcac7701a047b4b3fead90c5d6c119', 'commit_message': 'Set model instance attributes based on fields\n', 'language_name': 'Shell', 'license': 'agpl-3.0', 'hunks': '@@ -18,13 +18,24 @@ class Model(persistent.Persistent):\n     """\n \n     def __init__(self, **kw):\n+        # This set will go to metaclass\n         indexed_fields = set(filter(lambda key:\n                 not key.startswith("_") and\n                 isinstance(getattr(self.__class__, key), indexable.Indexable),\n             self.__class__.__dict__.keys()))\n \n+        # This set will go to metaclass\n         required_fields = set(filter(lambda key: getattr(self.__class__, key).default is None, indexed_fields))\n \n+        # Indexed fields which have default values\n+        default_fields = indexed_fields.difference(required_fields).difference(kw)\n+\n         missed_fields = required_fields.difference(kw)\n         if missed_fields:\n             raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))\n+\n+        for field in default_fields:\n+            setattr(self, field, getattr(self.__class__, field).default)\n+\n+        for field, value in kw.iteritems():\n+            setattr(self, field, value)\n', 'addition_count': 11, 'deletion_count': 0, 'src_file': 'a/zerodb/models/__init__.py', 'tgt_file': 'b/zerodb/models/__init__.py', 'file_extension': '.py', 'before_file': 'import persistent\nimport six\n\nfrom . import fields\nfrom . import exceptions\nfrom zope.lifecycleevent import modified\nfrom zerodb.intid import IdStore\nfrom zerodb.trees import family32\nfrom zerodb.catalog import Catalog\nfrom zerodb.models.fields import Field, Text\n\n\nclass ModelMeta(type):\n    def __init__(cls, name, bases, dct):\n        if bases != (persistent.Persistent,):  # Only subclasses of Model can do it, not Model itself\n            used_fields = set(filter(lambda key:\n                    not key.startswith("_") and\n    """\n\n    def __init__(self, **kw):\n        indexed_fields = set(filter(lambda key:\n                not key.startswith("_") and\n                isinstance(getattr(self.__class__, key), indexable.Indexable),\n            self.__class__.__dict__.keys()))\n\n        required_fields = set(filter(lambda key: getattr(self.__class__, key).default is None, indexed_fields))\n\n        missed_fields = required_fields.difference(kw)\n        if missed_fields:\n            raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))\n    Data model to easily create indexable persistent objects.\n    If an object declares a property from indexable, this property is indexed.\n    *All* other properties are stored but unindexed\n\n    Example:\n        >>> class Page(Model):\n        ...     title = indexable.Field()\n        ...     text = indexable.Text()\n\n        ... page = Page(title="Hello", text="World", extra=12345)\n    """\n\n    # TODO we should (?) provide some way to save model definition into the database\n    # and generate model class from there.\n    # This could be valuable when working with json which doesn\'t keep any python code\n    # Or we should make a method which allows to generate a new model from json\n\n    __modelname__ = None\n    __family__ = family32\n\n    def __init__(self, **kw):\n        missed_fields = self._z_required_fields.difference(kw)\n        if missed_fields:\n            raise exceptions.ModelException("You should provide fields: " + ", ".join(map(str, missed_fields)))\n\n        for field in self._z_default_fields.difference(kw):\n            default = getattr(self.__class__, field).default\n            if callable(default):\n                default = default()\n            setattr(self, field, default)\n\n        for field, value in six.iteritems(kw):\n            setattr(self, field, value)\n\n    def __setattr__(self, name, value):\n        origattr = getattr(self, name, None)\n        if origattr is not None and name in self._z_indexed_fields and \\\n                not isinstance(origattr, fields.Indexable) and hasattr(self, "_p_uid"):  # reindex notify\n            modified(self, name)\n        super(Model, self).__setattr__(name, value)\n\n    def __lt__(self, other):\n        return id(self) < id(other)\n\n    @classmethod\n    def create_store(cls):\n        """Returns intid.IdStore storage for this class"""\n        return IdStore(family=cls.__family__)\n\n    @classmethod\n    def create_catalog(cls):\n        """Creates and returns catalog for this model with indexes in it"""\n        catalog = Catalog()  # TODO: specify family as a parameter\n        for name in cls._z_indexed_fields:\n            field = getattr(cls, name)\n\n            if field.virtual:\n                # Tuple discriminator means virtual field.\n                # Index has to look it up in model._z_virtual_fields,\n                # where model = obj.__class__\n                discriminator = (name,)\n            else:\n                discriminator = None\n\n            catalog[name] = field.Index(discriminator or name)\n        return catalog\n', 'message': 'Set model instance attributes based on fields\n', 'author_name': 'Michael Egorov', 'lang': 'py'}