Stephen J. Turnbull writes:
> PermissionsMixin is documented to be *abstract* -- there are *no*
> default permissions in it.  It either does nothing or errors when you
> try to use the methods it declares.[1]
> 
> The permission-checking is (and must be) your code.  For one thing,
> that's what "abstract" means, and in any case *permissions will be
> defined by your application*, and permissions violations are an
> application problem that the app devs should be testing for, if only
> because ransomware is a billion-dollar industry.  Upstream is not
> going to pay your ransom if some hacker walks in a door *you* left
> wide-open and steals all your data.
Permissions are defined and applied separately.
programmers define the permission they wanna see applied.
They apply them by inserting PermissionMixin in the Views inheritance tree.
The Permission appliance logic is not "django app" specific.

> Here's a concrete
> implementation of the case, where O1.a and O2.a don't even share any
> code, and only N2 overrides a after refactoring a into a parent class
> GP.
> [...]
> That's what I would want.
Good for you, but that's aboslutely not what i'm talking about.
I'm talking about a refacto of O1 and O2 which would consist of extracting one 
common parent, so the case where both O's method don't share any code is 
irrelevant to my point here. Since you wouldn't refactor a common parent if no 
code is common to both classes.
I guess you could if they have common attribute tho, but that's just not what 
i'm talking about here.

Also, I'm talking about a proper refactoring that isn't meant to change the 
code behavior at all.

Extracting a common parent class is a refactoring intended to not change the 
classes behavior at all :
```
class O1:
    def method(self):
        print('GP')
        print('N1')
class O2:
    def method(self):
        print('GP')
        print('N2')
```

Can be refactored like that (renaming O1 into N1, and O2 into N2 so we can know 
which class is the refactored version when discussing it later on, but real 
refactoring wouldn't rename it at all):
```
class GP:
    def method(self):
        print('GP')
class N1(GP):
    def method(self):
        super().method()
        print('N1')
class N2(GP):
    def method(self):
        super().method()
        print('N2')
```

This is what most people would consider actual refactoring, as in, it doesn't 
change the behavior of the code at all.
Although some people know about super and MRO in case of MI, so they might be 
able to spot the potential change in behavior here.

If this code is published by a library, as a lib user, doing MI with O1 and O2 
will not behave the same as doing MI with N1 and N2 (again, renamed only so we 
know which is the refactored one in this discussion).

It is reasonable to assume not every lib author know about this MI situation, 
and the breaking change this refactoring is.

As a lib user, how do you prevent this from breaking your code?

Same can be said of the opposite refactoring, consisting of reinserting GP in 
N1 and N2 to only provide O1 and O2.

In other terms, super and MRO aren't so reliable, and that's an example of that.


Steven D'Aprano writes:
> No, that's impossible. That is an inconsistent MRO: it has GP listed 
> twice, which is a bug.
I was just making the point that the actual lines of code being executed before 
the refactoring would have applied in this order, which has, after refactoring, 
the lines in GP appear twice.

Now, why oh why would a class apearing twice be a bug?
Essentially what it means is that that classe's methods can be called twice.
So what?
How's that a bug?
Although, if you're saying it's not possible *today*, and would be considered a 
bug *of today's* MRO, i understand.
But then, what's your point? changing that isn't an issue, we can introduce 
some modules to give the choice to the programmers if they want one class to 
appear multiple times, or not. And default to today's behavior so it's not a 
breaking change.
This would make it possible, if wanted, for a class to appear multiple times, 
and that would definitely be by design, so what's your point?

You seem to believe that MI is supposed to be the way it already is, and any 
attempts at changing it is blaspheme.
I'm not saying that to tease you, it really feels like the idea of changing it 
repulses you on its own.
And that you're saying it's a bug as a slightly more specific way of saying 
"it's bad, period". Or maybe "python shouldn't behave like that, and i wouldn't 
have it any other way". As much as your entitled to your feelings / opinions 
(idk which words applies best here), I don't think they make (here) for a 
compeling argument.



> Pretty much. In general, any change to the MRO is a potential breaking 
> change, unless you design your classes very carefully.
Yeah, and overall it's a control flow problem.
The 'strat' module i've been taking about could be seen as more tooling for 
control flow in MI.
strat is a really dumb name tho, perhaps multiple_inheritance would be better, 
since it would be dedicated to MI control flow.
Actually, a lot of the problems i have with MRO today (but not all) can be 
boiled down to control flow being out of our control when we would benefit from 
more control here, sometimes.

Also, MRO change aren't easy to spot, as class definition isn't enough to tell 
what that class MRO will end up being, in all cases, or how it would integrate 
in MI trees.
Essentially, there are side effects to any class refactoring, due to the way 
MRO works.


> Here's the link for those who can't read French:
> 
> https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.mixins.UserPassesTestMixin.get_test_func
Err sorry, i didn't realise i was sharing the french link, my bad.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/LMCKETHDV347LRQYTKGN7Y7NWM2JENKP/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to