Skip to content

Commit

Permalink
FrozenClass performance fix (#452)
Browse files Browse the repository at this point in the history
* Fix for `FrozenClass` where attributes could be added multiple times.

* Didn't find a nice quick fix for attributes being added to all classes

* Fixed test
  • Loading branch information
brownbaerchen authored Jul 29, 2024
1 parent 97e238e commit 63c2b79
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
15 changes: 12 additions & 3 deletions pySDC/helpers/pysdc_helper.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import logging


class FrozenClass(object):
"""
Helper class to freeze a class, i.e. to avoid adding more attributes
Expand Down Expand Up @@ -43,9 +46,15 @@ def add_attr(cls, key, raise_error_if_exists=False):
key (str): The key to add
raise_error_if_exists (bool): Raise an error if the attribute already exists in the class
"""
if key in cls.attrs and raise_error_if_exists:
raise TypeError(f'Attribute {key!r} already exists in {cls.__name__}!')
cls.attrs += [key]
logger = logging.getLogger(cls.__name__)
if key in cls.attrs:
if raise_error_if_exists:
raise TypeError(f'Attribute {key!r} already exists in {cls.__name__}!')
else:
logger.debug(f'Skip adding attribute {key!r} because it already exists in {cls.__name__}!')
else:
cls.attrs += [key]
logger.debug(f'Added attribute {key!r} to {cls.__name__}')

def _freeze(self):
"""
Expand Down
36 changes: 36 additions & 0 deletions pySDC/tests/test_helpers/test_frozen_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest


@pytest.mark.base
def test_frozen_class():
from pySDC.helpers.pysdc_helper import FrozenClass

class Dummy(FrozenClass):
pass

me = Dummy()
me.add_attr('foo')

me.foo = 0

you = Dummy()
you.foo = 1
assert me.foo != you.foo, 'Attribute is shared between class instances'

me = Dummy()
assert me.foo is None, 'Attribute persists after reinstantiation'

me.add_attr('foo')
assert Dummy.attrs.count('foo') == 1, 'Attribute was added too many times'

class Dummy2(FrozenClass):
pass

Dummy2.add_attr('bar')
you = Dummy2()
you.bar = 5
assert me.bar is None, 'Attribute was set across classes'


if __name__ == '__main__':
test_frozen_class()

0 comments on commit 63c2b79

Please sign in to comment.