Ejemplo n.º 1
0
 def setUp(self):
     self.id_property = model_property.ModelProperty(
         SubclassOfBaseModel, SubclassOfBaseModel.id)
     self.ndb_property = model_property.ModelProperty(
         SubclassOfBaseModel, SubclassOfBaseModel.value)
     self.ndb_repeated_property = model_property.ModelProperty(
         RepeatedValueModel, RepeatedValueModel.values)
Ejemplo n.º 2
0
    def __call__(self, model_relationships):
        """Registers the property relationships of self._model_kind yielded by
        the generator.

        See RelationshipsOf's docstring for a usage example.

        Args:
            model_relationships: callable. Expected to yield tuples of type
                (Property, list(class)), where the properties are from the
                argument provided to the function.

        Returns:
            generator. The same object.
        """
        self._validate_name_of_model_relationships(model_relationships)

        yielded_items = model_relationships(self._model_class)
        for property_instance, referenced_models in yielded_items:
            property_of_model = model_property.ModelProperty(
                self._model_class, property_instance)
            self._ID_REFERENCING_PROPERTIES[property_of_model].update(
                self._get_model_kind(m)
                for m in referenced_models if m is not self._model_class)

        return model_relationships
Ejemplo n.º 3
0
 def test_init_raises_value_error_when_property_is_not_in_model(
         self) -> None:
     with self.assertRaisesRegex(
             ValueError,
             'not a property of'):  # type: ignore[no-untyped-call]
         model_property.ModelProperty(SubclassOfBaseModel,
                                      SubclassOfNdbModel.value)
Ejemplo n.º 4
0
    def test_init_raises_type_error_when_property_is_not_an_ndb_property(
            self) -> None:
        model = SubclassOfBaseModel(value='123')

        with self.assertRaisesRegex(
                TypeError,
                'not an NDB Property'):  # type: ignore[no-untyped-call]
            model_property.ModelProperty(SubclassOfBaseModel, model.value)
Ejemplo n.º 5
0
    def test_equality(self):
        self.assertNotEqual(self.id_property, self.ndb_property)
        self.assertNotEqual(self.ndb_property, self.ndb_repeated_property)
        self.assertNotEqual(self.ndb_repeated_property, self.id_property)

        self.assertEqual(
            self.id_property,
            model_property.ModelProperty(
                SubclassOfBaseModel, SubclassOfBaseModel.id))
        self.assertEqual(
            self.ndb_property,
            model_property.ModelProperty(
                SubclassOfBaseModel, SubclassOfBaseModel.value))
        self.assertEqual(
            self.ndb_repeated_property,
            model_property.ModelProperty(
                RepeatedValueModel, RepeatedValueModel.values))
Ejemplo n.º 6
0
    def test_hash_of_ndb_property(self):
        ndb_property_set = {
            model_property.ModelProperty(
                SubclassOfBaseModel, SubclassOfBaseModel.value),
        }

        self.assertIn(self.ndb_property, ndb_property_set)
        self.assertNotIn(self.id_property, ndb_property_set)
        self.assertNotIn(self.ndb_repeated_property, ndb_property_set)
Ejemplo n.º 7
0
    def test_message(self) -> None:
        error = base_validation_errors.ModelRelationshipError(
            model_property.ModelProperty(FooModel, FooModel.bar_id), '123',
            'BarModel', '123')

        self.assertEqual(
            error.stderr, 'ModelRelationshipError in FooModel(id="123"): '
            'FooModel.bar_id="123" should correspond to the ID of an '
            'existing BarModel, but no such model exists')
Ejemplo n.º 8
0
    def test_hash_of_ndb_repeated_property(self):
        ndb_repeated_property_set = {
            model_property.ModelProperty(
                RepeatedValueModel, RepeatedValueModel.values),
        }

        self.assertIn(self.ndb_repeated_property, ndb_repeated_property_set)
        self.assertNotIn(self.id_property, ndb_repeated_property_set)
        self.assertNotIn(self.ndb_property, ndb_repeated_property_set)
Ejemplo n.º 9
0
    def test_hash_of_id_property(self) -> None:
        id_property_set = {
            model_property.ModelProperty(SubclassOfBaseModel,
                                         SubclassOfBaseModel.id),
        }

        self.assertIn(self.id_property, id_property_set)
        self.assertNotIn(self.ndb_property, id_property_set)
        self.assertNotIn(self.ndb_repeated_property, id_property_set)
Ejemplo n.º 10
0
 def test_init_raises_type_error_when_model_is_unrelated_to_base_model(
         self) -> None:
     with self.assertRaisesRegex(TypeError, 'not a subclass of BaseModel'
                                 ):  # type: ignore[no-untyped-call]
         # ModelProperty has model_class argument, which can only accept
         # classes that are inherited from BaseModel. But here we are
         # passing a class that is inherited from datastore_services.Model.
         # Thus to silent mypy error, we added an ignore here.
         model_property.ModelProperty(
             SubclassOfNdbModel,
             SubclassOfNdbModel.value)  # type: ignore[arg-type]
Ejemplo n.º 11
0
    def test_init_raises_type_error_when_model_is_not_a_class(self) -> None:
        model = SubclassOfBaseModel()

        with self.assertRaisesRegex(
                TypeError,
                'not a model class'):  # type: ignore[no-untyped-call]
            # ModelProperty has model_class argument, which can only accept
            # classes that are inherited from BaseModel. But here we are
            # passing an object of SubclassOfBaseModel. So, to avoid mypy
            # error we added an ignore here.
            model_property.ModelProperty(
                model, SubclassOfBaseModel.value)  # type: ignore[arg-type]
    def get_property_of(self, model_class, property_name):
        """Helper method to create a ModelProperty.

        Args:
            model_class: *. A subclass of BaseModel.
            property_name: str. The name of the property to get.

        Returns:
            ModelProperty. An object that encodes both property and the model it
            belongs to.
        """
        return model_property.ModelProperty(
            model_class, getattr(model_class, property_name))
Ejemplo n.º 13
0
    def get_model_kind_references(cls, model_kind, property_name):
        """Returns the kinds of models referenced by the given property.

        Args:
            model_kind: str. The kind of model the property belongs to.
            property_name: str. The property's name.

        Returns:
            list(str). The kinds of models referenced by the given property.
        """
        model_cls = job_utils.get_model_class(model_kind)
        prop = model_property.ModelProperty(
            model_cls, getattr(model_cls, property_name))
        return cls._ID_REFERENCING_PROPERTIES.get(prop, set())
Ejemplo n.º 14
0
    def test_reports_error_when_id_property_target_does_not_exist(self):
        self.put_multi([
            # UserEmailPreferencesModel.id -> UserSettingsModel.id.
            self.create_model(user_models.UserEmailPreferencesModel,
                              id=self.VALID_USER_ID),
            # UserSettingsModel missing.
        ])

        self.assert_job_output_is([
            base_validation_errors.ModelRelationshipError(
                model_property.ModelProperty(
                    user_models.UserEmailPreferencesModel,
                    user_models.UserEmailPreferencesModel.id),
                self.VALID_USER_ID, 'UserSettingsModel', self.VALID_USER_ID),
        ])
Ejemplo n.º 15
0
    def get_model_kind_references(cls, model_kind: str,
                                  property_name: str) -> Set[str]:
        """Returns the kinds of models referenced by the given property.

        Args:
            model_kind: str. The kind of model the property belongs to.
            property_name: str. The property's name.

        Returns:
            set(str). The kinds of models referenced by the given property.
        """
        model_cls = job_utils.get_model_class(model_kind)
        # Here model_cls is of type Type[datastore_services.Model] but from the
        # implementation of ModelProperty it is clear that it can only accept
        # Type[base_models.BaseModel]. So to narrow down the type, we used
        # assert statement here.
        assert issubclass(model_cls, base_models.BaseModel)
        prop = model_property.ModelProperty(model_cls,
                                            getattr(model_cls, property_name))
        return cls._ID_REFERENCING_PROPERTIES.get(prop, set())
Ejemplo n.º 16
0
    def test_reports_missing_id_property_target_even_if_sibling_property_is_valid(self):  # pylint: disable=line-too-long
        self.put_multi([
            self.create_model(
                auth_models.UserAuthDetailsModel,
                id=self.VALID_USER_ID,
                # Value is not None, so UserIdentifiersModel must exist.
                gae_id='abc',
                # Value is None, so missing UserIdByFirebaseAuthIdModel is OK.
                firebase_auth_id=None),
            self.create_model(
                auth_models.UserIdentifiersModel,
                user_id=self.VALID_USER_ID,
                # Should be gae_id='abc', so error will occur.
                id='123'),
        ])

        self.assert_job_output_is([
            base_validation_errors.ModelRelationshipError(
                model_property.ModelProperty(
                    auth_models.UserAuthDetailsModel,
                    auth_models.UserAuthDetailsModel.gae_id),
                self.VALID_USER_ID, 'UserIdentifiersModel', 'abc'),
        ])
Ejemplo n.º 17
0
 def test_init_raises_value_error_when_property_is_not_in_model(self):
     with self.assertRaisesRegex(ValueError, 'not a property of'):
         model_property.ModelProperty(
             SubclassOfBaseModel, SubclassOfNdbModel.value)
Ejemplo n.º 18
0
 def test_init_raises_type_error_when_model_is_unrelated_to_base_model(self):
     with self.assertRaisesRegex(TypeError, 'not a subclass of BaseModel'):
         model_property.ModelProperty(
             SubclassOfNdbModel, SubclassOfNdbModel.value)
Ejemplo n.º 19
0
    def test_init_raises_type_error_when_model_is_not_a_class(self):
        model = SubclassOfBaseModel()

        with self.assertRaisesRegex(TypeError, 'not a model class'):
            model_property.ModelProperty(model, SubclassOfBaseModel.value)
Ejemplo n.º 20
0
 def test_init_with_ndb_repeated_property(self):
     # Does not raise.
     model_property.ModelProperty(
         RepeatedValueModel, RepeatedValueModel.values)
Ejemplo n.º 21
0
 def test_init_with_ndb_property(self):
     # Does not raise.
     model_property.ModelProperty(
         SubclassOfBaseModel, SubclassOfBaseModel.value)
Ejemplo n.º 22
0
 def test_init_with_id_property(self) -> None:
     # Does not raise.
     model_property.ModelProperty(SubclassOfBaseModel,
                                  SubclassOfBaseModel.id)
Ejemplo n.º 23
0
    def test_init_raises_type_error_when_property_is_not_an_ndb_property(self):
        model = SubclassOfBaseModel(value='123')

        with self.assertRaisesRegexp(TypeError, 'not an NDB Property'):
            model_property.ModelProperty(SubclassOfBaseModel, model.value)