Browse Source

Fix metadata fields list caching for subclasses

Because the _allFieldsCache attribute gets inherited, when it gets set for a class, all subclasses will also see that list rather than their own, potentially different list. To fix this, use a global dict indexing on the metadata class instead.
master
JustAnotherArchivist 9 months ago
parent
commit
518541eb81
1 changed files with 9 additions and 6 deletions
  1. +9
    -6
      codearchiver/core.py

+ 9
- 6
codearchiver/core.py View File

@@ -104,7 +104,9 @@ class Metadata(list[tuple[str, str]]):
version: int = 0
'''Version, incremented on every backward-incompatible change'''

_allFieldsCache: typing.Optional[tuple[MetadataField]] = None
# This cache needs to be different for each subclass.
# The easiest way to achieve that is by mapping class objects to the corresponding cache.
_allFieldsCache: dict[typing.Type['Metadata'], tuple[MetadataField]] = {}

def append(self, *args):
if len(args) == 1:
@@ -116,12 +118,13 @@ class Metadata(list[tuple[str, str]]):
def _allFields(self):
'''All fields known by this metadata collection, own ones and all from superclasses'''

if type(self)._allFieldsCache is None:
cls = type(self)
if cls not in cls._allFieldsCache:
fields = []
for cls in reversed(type(self).mro()):
fields.extend(getattr(cls, 'fields', []))
type(self)._allFieldsCache = tuple(fields)
return type(self)._allFieldsCache
for cls_ in reversed(cls.mro()):
fields.extend(getattr(cls_, 'fields', []))
cls._allFieldsCache[cls] = tuple(fields)
return cls._allFieldsCache[cls]

def validate(self):
'''Check that all keys and values conform to the specification'''


Loading…
Cancel
Save