#35735: For python 3.9+ class property may not be accessible by Django's 
template
system
---------------------------------+----------------------------------------
     Reporter:  Fabian Braun     |                    Owner:  Fabian Braun
         Type:  Bug              |                   Status:  assigned
    Component:  Template system  |                  Version:  5.0
     Severity:  Normal           |               Resolution:
     Keywords:                   |             Triage Stage:  Unreviewed
    Has patch:  1                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+----------------------------------------
Changes (by Fabian Braun):

 * has_patch:  0 => 1


Old description:

> Before python 3.9 class properties were always available through the
> template system. If you had a class
> {{{
> class MyClass:
>     in_template = True
> }}}
> you could access the class property in the template through (if it was
> returned by a callable) `{{ get_my_class.in_template }}`.
>
> The template system first checks if the class is subscriptable (i.e.
> tries `context_value["in_template"]`), will fail and then will get the
> in_template property.
>
> As of python 3.9 some classes actually are subscriptable and trying to
> get the item will not fail: Typing shortcuts introduced syntax like
> `list[int]`. This hides class properties from the template system.
>
> Here's a test (that might go into
> tests/template_tests/syntax_tests/tests_basic.py) which passes on Python
> 3.9 and fails on Python 3.10+:
> {{{
>     @setup({"basic-syntax19b": "{{ klass.in_template }}"})
>     def test_access_class_property(self):
>         class MyClass(list):
>             in_template = True
>
>         def get_my_class():
>             return MyClass
>
>         # Pass the callable to return the class, or it would be resolved
> by the template
>         # engine
>         output = self.engine.render_to_string(
>             "basic-syntax19b",
>             {"klass": get_my_class}
>         )
>         self.assertEqual(output, "True")
> }}}
>
> I'd be happy to propose a fix that will not call a classes'
> `__class_getitem__` method.
>
> Thanks to [https://github.com/benzkji Ben Stähli] and [https://github.com
> /last-partizan Serhii Tereshchenko] for figuring out this issue.
>
> References:
>
> * https://github.com/django-cms/django-cms/issues/7948

New description:

 Before python 3.9 class properties were always available through the
 template system. If you had a class
 {{{
 class MyClass:
     in_template = True
 }}}
 you could access the class property in the template through (if it was
 returned by a callable) `{{ get_my_class.in_template }}`.

 The template system first executes the callable `get_my_class` which we
 assume returns `MyClass`. Then it checks if the class is subscriptable
 (i.e. tries `MyClass["in_template"]`), will fail and then will get the
 in_template property.

 As of python 3.9 some classes actually are subscriptable and trying to get
 the item will not fail: Typing shortcuts introduced syntax like
 `list[int]`. These hide class properties from the template system.

 Here's a test (that might go into
 tests/template_tests/syntax_tests/tests_basic.py) which passes on Python
 3.9 and fails on Python 3.10+:
 {{{
     @setup({"basic-syntax19b": "{{ klass.in_template }}"})
     def test_access_class_property(self):
         class MyClass(list):
             in_template = True

         def get_my_class():
             return MyClass

         # Pass the callable to return the class, or it would be resolved
 by the template
         # engine
         output = self.engine.render_to_string(
             "basic-syntax19b",
             {"klass": get_my_class}
         )
         self.assertEqual(output, "True")
 }}}

 I'd be happy to propose a fix that will not call a classes'
 `__class_getitem__` method.

 Thanks to [https://github.com/benzkji Ben Stähli] and [https://github.com
 /last-partizan Serhii Tereshchenko] for figuring out this issue.

 References:

 * https://github.com/django-cms/django-cms/issues/7948

--
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35735#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070191c357696d-ac12a27d-d61c-4f91-b70a-d0fd62a63c78-000000%40eu-central-1.amazonses.com.

Reply via email to