ManimCommunity / manim

A community-maintained Python framework for creating mathematical animations.
https://www.manim.community
MIT License
20.46k stars 1.5k forks source link

CONFIG dictionaries stuff #7

Closed huguesdevimeux closed 3 years ago

huguesdevimeux commented 4 years ago

We have discussed about the variable CONFIGpreviously on discord. What should we do about it ?

I personally think we should modify at least a little bit of its architecture. it alters the readability a lot. One problem with that would be that in changing CONFIG we would have to review the entire architecture of the code.

What do you think?

naveen521kk commented 3 years ago

Is dataclassess introduced in python 3.7 right?

Some updates, dataclassess is supported in python 3.6 but not as a default module instead can be installed as a dependency from pip. I had know about this which working poetry and rich causeing me trouble lol.

huguesdevimeux commented 3 years ago

But uuh .. isn't the plan to use attrs instead of dataclasses ?

correct, kilacoda. We're not going to use dataclasses, but attrs, which supports most python versions, including python 2

eulertour commented 3 years ago

I talked some with Grant and he's now planning to migrate toward using regular classes, so it'd be better for consistency if we did that. Is anyone opposed to that?

leotrs commented 3 years ago

As opposed to dataclasses OR attrs?

eulertour commented 3 years ago

My takeaway from #271 is that attrs don't fit our use case. Dataclasses might but we don't know what problems we might run into so it'd be safer to stick with vanilla python. If someone is willing to vouch for dataclasses then maybe it'd be worth going back and asking him about it, but my prediction is that it will have some quirk like attrs that makes it difficult to adapt.

leotrs commented 3 years ago

In principle I tend to agree. There's some stuff about attrs use of __post__init that doesn't sit well with me, and it seems to me that it will be a problem when moving away from CONFIG.

Cc. @PgBiel

cobordism commented 3 years ago

The thing that CONFIG does really nicely is it allows anyone to easily create derived classes with a few default values changed.

class myRedText(Text):
    CONFIG = {
        colour: "RED"
    }

(or whatever the correct syntax is here) is a lot simpler than

class myRedText(Text):
    def __init__(self, *args, **kwargs):
        c = kwargs.pop("colour", "RED")
        super().__init__(self, args, colour=c, kwargs)

or sth like that. (don't criticise my syntax in a github comment :)

My question is, how do dataclasses impact my ability to quickly and easily create such derived classes?

and maybe red text isn't the best example. another example might be TextMobjectFromPresetString

leotrs commented 3 years ago

I don't know about dataclasses, but. The example you mention is indeed very convenient for a dev who is defining derived classes. However, this happens extremely rarely compared to the number of times that a user needs to use a class, or read the documentation, or would like to use autocompletion. CONFIG dictionaries make all of these almost impossible. So it's about the trade off of convenient for the dev or convenient for the user.

leotrs commented 3 years ago

Also, the latest point brought up is that it may be better to not use either dataclasses or CONFIG. We're waiting for @PgBiel input.

cobordism commented 3 years ago

this happens extremely rarely

As someone who learned python by learning how to make manim videos and reading 3b1b code, I naturally assumed that this happens all the time! Indeed I have been doing a lot of this :D

But I am starting to learn that the 3b1b code is somewhat idiosyncratic and may not be the best guide.

leotrs commented 3 years ago

As someone who learned python by learning how to make manim videos and reading 3b1b code

yikes

PgBiel commented 3 years ago

My takeaway from #271 is that attrs don't fit our use case. Dataclasses might but we don't know what problems we might run into so it'd be safer to stick with vanilla python. If someone is willing to vouch for dataclasses then maybe it'd be worth going back and asking him about it, but my prediction is that it will have some quirk like attrs that makes it difficult to adapt.

What is this quirk you speak about?

But, vanilla classes could work fine if we do it right. If you have any ideas about this, you could make some model or prototype or something so that I can better understand what you have in mind

eulertour commented 3 years ago

@PgBiel The issues at the top of #271 https://github.com/ManimCommunity/manim/pull/271#issue-466912315

PgBiel commented 3 years ago

Regarding the first issue, I'm yet to come upon it, so I'll take a look later

Regarding the second, I'm pretty sure there are ways to bypass that; specifying types again is only necessary because of how python handles types in class attrs: it adds them to clazz.__annotations__, and, if you don't specify a type, the attribute is not stored there. However, if we don't use the automatic type to annotation feature for those cases, simply using a = attr.ib(b) instead of the fancy a: fulltype = b might have it automatically infer that the type is the same as that of the attribute in the superclass (I'm yet to test this, but I believe this could work).

Anyway, we could work with vanilla classes. However, I believe we should keep attrs for specific classes. We should use it where convenient, and maybe in important classes or something (to be discussed later).

leotrs commented 3 years ago

It seems to me that a lot of the confusion here was moving from the current implementation using CONFIG dicts directly to attrs/dataclasses.

Now I'm more inclined to first move to vanilla classes ASAP, and then decide which classes to implement using attrs. Now that #620 is merged, I can work on removing CONFIG entirely and using vanilla classes. Once that's done we can revisit which classes need to move to attrs.

Yes, it's more work, but I'm willing to do it.

cobordism commented 3 years ago

Now I'm more inclined to first move to vanilla classes ASAP

This is now done in PR #783 The plan is to merge that just after release 0.1.1 - so that it will be included in the subsequent 0.2.0 but we have a whole month to clean up.

However, once 783 is merged we have to address the question of how we want to refactor this going forward. dataclasses? fastcore? ... We may also need a different approach for those CONFIGs that used to be part of mobjects that a user might instantiate vs the CONFIGS that were in Scenes that a user was meant to subclass (like GraphScene for example). The former only requires keyword arguments to the constructor, the latter might require a custom __init__().

...Of course, why a GraphScene is a scene at all, as opposed to a Graph being a mobject is another question entirely ...

leotrs commented 3 years ago

we have to address the question of how we want to refactor this going forward. dataclasses? fastcore? ...

The question is: what do our classes need right now? I'm not certain we necessarily have a problem that needs to be fixed right now. (Other than the following point you make, of course...)

We may also need a different approach for those CONFIGs that used to be part of mobjects that a user might instantiate vs the CONFIGS that were in Scenes that a user was meant to subclass (like GraphScene for example). The former only requires keyword arguments to the constructor, the latter might require a custom init().

I'm fairly certain that most (if not all) of the CONFIG keys of GraphScene can just be replaced by setting attributes at the top of the construct function. The code

class MyScene(GraphScene):
    CONFIG = {"x_min": -1}
    def construct(self):
        self.setup_axes()

Can be replaced with

class MyScene(GraphScene):
    def construct(self):
        self.x_min = -1
        self.setup_axes()

In fact, we could encourage use of Scene.setup() for this purpose.

...Of course, why a GraphScene is a scene at all, as opposed to a Graph being a mobject is another question entirely ...

I think we must answer this question before choosing if we need to migrate to any other class and/or how and when. What is the concrete problem that needs to be addressed after we remove CONFIG once and for all?

cobordism commented 3 years ago

closed by PR #783

For discussions on future refactoring, please open new dedicated issues.