Skip to content

Commit

Permalink
records: refactored 'status' as a systemfield
Browse files Browse the repository at this point in the history
* 'status' is not a db column anymore, instead it is a systemfield
  • Loading branch information
alejandromumo committed Mar 7, 2024
1 parent 65da818 commit 9dac8a5
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 36 deletions.
3 changes: 2 additions & 1 deletion invenio_communities/communities/records/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from ..dumpers.featured import FeaturedDumperExt
from . import models
from .systemfields.access import CommunityAccessField
from .systemfields.community_status import CommunityStatusField
from .systemfields.deletion_status import CommunityDeletionStatusField
from .systemfields.parent_community import ParentCommunityField
from .systemfields.pidslug import PIDSlugField
Expand Down Expand Up @@ -121,7 +122,7 @@ class Community(Record):
custom=CustomFieldsRelation("COMMUNITIES_CUSTOM_FIELDS"),
)

status = ModelField("status", dump_type=str)
status = CommunityStatusField("status")

is_safelisted = IsSafelistedField("is_safelisted")

Expand Down
30 changes: 1 addition & 29 deletions invenio_communities/communities/records/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# under the terms of the MIT License; see LICENSE file for more details.

"""Community database models."""
import enum

from datetime import datetime

from invenio_db import db
Expand All @@ -22,28 +22,6 @@
from .systemfields.deletion_status import CommunityDeletionStatusEnum


class CommunityStatusEnum(enum.Enum):
"""Community status enum."""

NEW = "N"
VERIFIED = "V"
MODERATED = "M"

def __str__(self):
"""Return its value."""
return self.value

def __eq__(self, __value) -> bool:
"""Check if the value is equal to the enum value.
Supports comparison with string values.
"""
if isinstance(__value, str):
return self.value == __value

return super().__eq__(__value)


class CommunityMetadata(db.Model, RecordMetadataBase):
"""Represent a community."""

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

status = db.Column(
ChoiceType(CommunityStatusEnum, impl=db.String(1)),
nullable=False,
default=CommunityStatusEnum.NEW.value,
)


class CommunityFileMetadata(db.Model, RecordMetadataBase, FileRecordModelMixin):
"""File associated with a community."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CERN.
#
# Invenio-communities is free software; you can redistribute it and/or modify
# it under the terms of the MIT License; see LICENSE file for more details.
"""Community status system field."""

import enum

from invenio_records.systemfields import SystemField


class CommunityStatusEnum(enum.Enum):
"""Community status enum."""

NEW = "new"
VERIFIED = "verified"
MODERATED = "moderated"


class CommunityStatus:
"""The community status of the community."""

def __init__(self, status):
"""Initialize the community status."""
self.status = status

@property
def status(self):
"""Get the community status."""
return self._status.value

@status.setter
def status(self, value):
"""Set the community status."""
if value is None:
self._status = CommunityStatusEnum.NEW

elif isinstance(value, str):
self._status = CommunityStatusEnum(value)

elif isinstance(value, CommunityStatusEnum):
self._status = value

else:
raise ValueError(f"Invalid value for community community status: {value}")

def __repr__(self):
"""Return repr(self)."""
return f"<CommunityStatus {self._status.name}: '{self._status.value}'>"

def __str__(self):
"""Return str(self)."""
return self.status

def __eq__(self, other):
"""Check if self and other are equal.
This allows checking against other instances of the same type, strings,
and ``CommunityStatusEnum`` values.
"""
if isinstance(other, type(self)):
return self.status == other.status

elif isinstance(other, CommunityStatusEnum):
return self.status == other.value

elif isinstance(other, str):
return self.status == other

return False


class CommunityStatusField(SystemField):
"""System field for the community status."""

#
# Data descriptor methods (i.e. attribute access)
#
def __get__(self, record, owner=None):
"""Get the status of the community."""
if record is None:
return self # returns the field itself.

status = self._get_cache(record) or CommunityStatus(record.get("status"))

self._set_cache(record, status)
return status

def __set__(self, record, value):
"""Set the status of the community."""
status = CommunityStatus(value)
self._set_cache(record, status)

def pre_commit(self, record):
"""Dump the deletion status to the community before committing."""
status = self._get_cache(record) or CommunityStatus(None)
record[self.key] = status.status
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from invenio_records_resources.records.systemfields.calculated import CalculatedField

from ..models import CommunityStatusEnum
from ..systemfields.community_status import CommunityStatusEnum


class IsSafelistedField(CalculatedField):
Expand Down
8 changes: 4 additions & 4 deletions tests/communities/test_safelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@

from invenio_db import db

from invenio_communities.communities.records.models import CommunityStatusEnum
from invenio_communities.communities.records.systemfields.community_status import (
CommunityStatusEnum,
)


def test_safelist_computed_by_verified_status(
community_service, minimal_community, location, es_clear, unverified_user
):
"""
Test that the safelist feature for communities is computed correctly based on the verified status.
"""
"""Test that the safelist feature for communities is computed correctly based on the verified status."""
# Create a comunity
# Flag it as "verified"
# Validate that the computed field "is_verified" is set to "True"
Expand Down
5 changes: 4 additions & 1 deletion tests/communities/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
from invenio_records_resources.services.errors import PermissionDeniedError
from marshmallow import ValidationError

from invenio_communities.communities.records.models import CommunityStatusEnum
from invenio_communities.communities.records.systemfields.community_status import (
CommunityStatusEnum,
)
from invenio_communities.communities.records.systemfields.deletion_status import (
CommunityDeletionStatusEnum,
)
Expand Down Expand Up @@ -766,6 +768,7 @@ def test_bulk_update_parent_overwrite(


def test_status_new(community_service, minimal_community, location, es_clear, owner):
"""Test the status of a new community."""
c_data = deepcopy(minimal_community)
c_data["slug"] = "test_status_new"
co = community_service.create(data=c_data, identity=owner.identity)
Expand Down

0 comments on commit 9dac8a5

Please sign in to comment.