Skip to content

Commit 9dac8a5

Browse files
committed
records: refactored 'status' as a systemfield
* 'status' is not a db column anymore, instead it is a systemfield
1 parent 65da818 commit 9dac8a5

6 files changed

Lines changed: 111 additions & 36 deletions

File tree

invenio_communities/communities/records/api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from ..dumpers.featured import FeaturedDumperExt
3535
from . import models
3636
from .systemfields.access import CommunityAccessField
37+
from .systemfields.community_status import CommunityStatusField
3738
from .systemfields.deletion_status import CommunityDeletionStatusField
3839
from .systemfields.parent_community import ParentCommunityField
3940
from .systemfields.pidslug import PIDSlugField
@@ -121,7 +122,7 @@ class Community(Record):
121122
custom=CustomFieldsRelation("COMMUNITIES_CUSTOM_FIELDS"),
122123
)
123124

124-
status = ModelField("status", dump_type=str)
125+
status = CommunityStatusField("status")
125126

126127
is_safelisted = IsSafelistedField("is_safelisted")
127128

invenio_communities/communities/records/models.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# under the terms of the MIT License; see LICENSE file for more details.
99

1010
"""Community database models."""
11-
import enum
11+
1212
from datetime import datetime
1313

1414
from invenio_db import db
@@ -22,28 +22,6 @@
2222
from .systemfields.deletion_status import CommunityDeletionStatusEnum
2323

2424

25-
class CommunityStatusEnum(enum.Enum):
26-
"""Community status enum."""
27-
28-
NEW = "N"
29-
VERIFIED = "V"
30-
MODERATED = "M"
31-
32-
def __str__(self):
33-
"""Return its value."""
34-
return self.value
35-
36-
def __eq__(self, __value) -> bool:
37-
"""Check if the value is equal to the enum value.
38-
39-
Supports comparison with string values.
40-
"""
41-
if isinstance(__value, str):
42-
return self.value == __value
43-
44-
return super().__eq__(__value)
45-
46-
4725
class CommunityMetadata(db.Model, RecordMetadataBase):
4826
"""Represent a community."""
4927

@@ -61,12 +39,6 @@ class CommunityMetadata(db.Model, RecordMetadataBase):
6139
default=CommunityDeletionStatusEnum.PUBLISHED.value,
6240
)
6341

64-
status = db.Column(
65-
ChoiceType(CommunityStatusEnum, impl=db.String(1)),
66-
nullable=False,
67-
default=CommunityStatusEnum.NEW.value,
68-
)
69-
7042

7143
class CommunityFileMetadata(db.Model, RecordMetadataBase, FileRecordModelMixin):
7244
"""File associated with a community."""
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright (C) 2024 CERN.
4+
#
5+
# Invenio-communities is free software; you can redistribute it and/or modify
6+
# it under the terms of the MIT License; see LICENSE file for more details.
7+
"""Community status system field."""
8+
9+
import enum
10+
11+
from invenio_records.systemfields import SystemField
12+
13+
14+
class CommunityStatusEnum(enum.Enum):
15+
"""Community status enum."""
16+
17+
NEW = "new"
18+
VERIFIED = "verified"
19+
MODERATED = "moderated"
20+
21+
22+
class CommunityStatus:
23+
"""The community status of the community."""
24+
25+
def __init__(self, status):
26+
"""Initialize the community status."""
27+
self.status = status
28+
29+
@property
30+
def status(self):
31+
"""Get the community status."""
32+
return self._status.value
33+
34+
@status.setter
35+
def status(self, value):
36+
"""Set the community status."""
37+
if value is None:
38+
self._status = CommunityStatusEnum.NEW
39+
40+
elif isinstance(value, str):
41+
self._status = CommunityStatusEnum(value)
42+
43+
elif isinstance(value, CommunityStatusEnum):
44+
self._status = value
45+
46+
else:
47+
raise ValueError(f"Invalid value for community community status: {value}")
48+
49+
def __repr__(self):
50+
"""Return repr(self)."""
51+
return f"<CommunityStatus {self._status.name}: '{self._status.value}'>"
52+
53+
def __str__(self):
54+
"""Return str(self)."""
55+
return self.status
56+
57+
def __eq__(self, other):
58+
"""Check if self and other are equal.
59+
60+
This allows checking against other instances of the same type, strings,
61+
and ``CommunityStatusEnum`` values.
62+
"""
63+
if isinstance(other, type(self)):
64+
return self.status == other.status
65+
66+
elif isinstance(other, CommunityStatusEnum):
67+
return self.status == other.value
68+
69+
elif isinstance(other, str):
70+
return self.status == other
71+
72+
return False
73+
74+
75+
class CommunityStatusField(SystemField):
76+
"""System field for the community status."""
77+
78+
#
79+
# Data descriptor methods (i.e. attribute access)
80+
#
81+
def __get__(self, record, owner=None):
82+
"""Get the status of the community."""
83+
if record is None:
84+
return self # returns the field itself.
85+
86+
status = self._get_cache(record) or CommunityStatus(record.get("status"))
87+
88+
self._set_cache(record, status)
89+
return status
90+
91+
def __set__(self, record, value):
92+
"""Set the status of the community."""
93+
status = CommunityStatus(value)
94+
self._set_cache(record, status)
95+
96+
def pre_commit(self, record):
97+
"""Dump the deletion status to the community before committing."""
98+
status = self._get_cache(record) or CommunityStatus(None)
99+
record[self.key] = status.status

invenio_communities/communities/records/systemfields/is_safelisted.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from invenio_records_resources.records.systemfields.calculated import CalculatedField
1010

11-
from ..models import CommunityStatusEnum
11+
from ..systemfields.community_status import CommunityStatusEnum
1212

1313

1414
class IsSafelistedField(CalculatedField):

tests/communities/test_safelist.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010

1111
from invenio_db import db
1212

13-
from invenio_communities.communities.records.models import CommunityStatusEnum
13+
from invenio_communities.communities.records.systemfields.community_status import (
14+
CommunityStatusEnum,
15+
)
1416

1517

1618
def test_safelist_computed_by_verified_status(
1719
community_service, minimal_community, location, es_clear, unverified_user
1820
):
19-
"""
20-
Test that the safelist feature for communities is computed correctly based on the verified status.
21-
"""
21+
"""Test that the safelist feature for communities is computed correctly based on the verified status."""
2222
# Create a comunity
2323
# Flag it as "verified"
2424
# Validate that the computed field "is_verified" is set to "True"

tests/communities/test_services.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
from invenio_records_resources.services.errors import PermissionDeniedError
2222
from marshmallow import ValidationError
2323

24-
from invenio_communities.communities.records.models import CommunityStatusEnum
24+
from invenio_communities.communities.records.systemfields.community_status import (
25+
CommunityStatusEnum,
26+
)
2527
from invenio_communities.communities.records.systemfields.deletion_status import (
2628
CommunityDeletionStatusEnum,
2729
)
@@ -766,6 +768,7 @@ def test_bulk_update_parent_overwrite(
766768

767769

768770
def test_status_new(community_service, minimal_community, location, es_clear, owner):
771+
"""Test the status of a new community."""
769772
c_data = deepcopy(minimal_community)
770773
c_data["slug"] = "test_status_new"
771774
co = community_service.create(data=c_data, identity=owner.identity)

0 commit comments

Comments
 (0)