GithubHelp home page GithubHelp logo

Comments (4)

lafrech avatar lafrech commented on May 30, 2024

More on this.

The use case presented in the tests above is a bit silly because you can't call __init__ in Document template anyway.

Also, I should be more explicit about the fact that the point is to get to the parent implementation.

I suppose in some cases, getting the template is enough. The method from the template is unchanged in the implementation. But as soon as the method does stuff in DB, we need the implementation's method. And the implementation from the same instance. Good thing, we do have a link to the instance and the template class so we can do that:

    def test_super_in_inheritance(self):

        class Parent(Document):

            def get_impl_from_tmpl(self, tmpl):
                return self.opts.instance.retrieve_document(tmpl)

            class Meta:
                allow_inheritance = True

            name = fields.StrField()

            def get_name(self):
                return self.name

        class Child(Parent):

            def get_name(self):
                # Option 1 - Works using template's get_name method
                name = Parent.get_name(self)
                # Option 2 - Works using implementation's get_name method
                name = self.get_impl_from_tmpl(Parent).get_name(self)
                return name[0]


        ParentImpl = self.instance.register(Parent)
        ChildImpl = self.instance.register(Child)

        child = ChildImpl(name='Toto')
        child.get_name()

Rather than using super(), we can specify the parent explicitly.

Option 1 - The parent class we pass in there will be the template, or the implementation if the document is registered into an implementation with the same name in the namespace (not sure I'm clear, but this is the same mechanism as in above comment).

Option 2 - Or Document could have an extra method to use the instance (self) and the parent template to get to the parent implementation in the same instance. The method is get_impl_from_tmpl. In my test, it is defined in Parent but in uMongo it would be in Document. Downside of this, you need to call this yourself so you can't use inheritance seamlessly. Good thing is you always get an implementation class so you can do DB stuff in the inherited method.

Pitfall, this breaks if you act silly and replace Parent in the namespace:

        ParentImpl = self.instance.register(Parent)
        ChildImpl = self.instance.register(Child)

        Parent = 'Let me try something stupid'
        child = ChildImpl(name='Toto')
        child.get_name()

from umongo.

touilleMan avatar touilleMan commented on May 30, 2024

Yeah, __init__ and super() seems really hard to cleanly build from template to implementation.
From my point of view it's not such a big deal given a Document rotate around it data from the database and so should not initialize anything but them.

However, we could create a special callback method (i.g. _on_init()) that would be called when the document is initialized. This would solve the trouble and we could even create an error message in the builder when copying fields from template to implementation if we found an __init__ field.

from umongo.

lafrech avatar lafrech commented on May 30, 2024

From my point of view it's not such a big deal given a Document rotate around it data from the database and so should not initialize anything but them.

I don't understand this sentence.

However, we could create a special callback method (i.g. _on_init()) that would be called when the document is initialized.

Sure. Although you sometimes want more flexibility so you might need pre_init and post_init.

But __init__ is not the only method with an issue, is it?

I mean, sometimes, you want to override your own methods, like my get_name example and I think this is also broken.

Here's an updated proposal, this time using super() and passing the class as a string to avoid relying on the namespace not being messed up with:

    def test_super_in_inheritance(self):

        class Parent(Document):

            def get_impl_from_tmpl(self, tmpl):
                return self.opts.instance.retrieve_document(tmpl)

            class Meta:
                allow_inheritance = True

            name = fields.StrField()

            def get_name(self):
                return self.name

        class Child(Parent):

            def get_name(self):
                name = super(self.get_impl_from_tmpl('Child'), self).get_name()
                return name[0]

        ParentImpl = self.instance.register(Parent)
        ChildImpl = self.instance.register(Child)

        child = ChildImpl(name='Toto')
        child.get_name()

Using super() this way lets it deal with multi-inheritance and complicated stuff I wouldn't like to screw up.

from umongo.

lafrech avatar lafrech commented on May 30, 2024

Another proposal with a _super method:

    def test_super_in_inheritance(self):

        class Parent(Document):

            def _super(self, tmpl):
                return super(_get_impl_from_tmpl(self, tmpl))

            def _get_impl_from_tmpl(self, tmpl):
                return self.opts.instance.retrieve_document(tmpl)

            class Meta:
                allow_inheritance = True

            name = fields.StrField()

            def get_name(self):
                return self.name

        class Child(Parent):

            def get_name(self):
                name = self._super('Child').get_name()
                return name[0]

        ParentImpl = self.instance.register(Parent)
        ChildImpl = self.instance.register(Child)

        child = ChildImpl(name='Toto')
        child.get_name()

Or with custom _super() as a static method, to be as close as builtin super as possible. But it's a bit of a pity to pass self manually just so that it looks more like the builtin.

    def test_super_in_inheritance(self):

        class Parent(Document):

            @staticmethod
            def _super(tmpl, self):
                return super(_get_impl_from_tmpl(self, tmpl))

            def _get_impl_from_tmpl(self, tmpl):
                return self.opts.instance.retrieve_document(tmpl)

            class Meta:
                allow_inheritance = True

            name = fields.StrField()

            def get_name(self):
                return self.name

        class Child(Parent):

            def get_name(self):
                name = self._super('Child', self).get_name()
                return name[0]

        ParentImpl = self.instance.register(Parent)
        ChildImpl = self.instance.register(Child)

        child = ChildImpl(name='Toto')
        child.get_name()

from umongo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.