🔍 Code Extractor

class CommentBase

Maturity: 59

Base class for comment objects that provides common functionality for ReviewComment and ApprovalComment types, managing comment data, metadata, and lifecycle operations.

File:
/tf/active/vicechatdev/CDocs single class/models/workflow_base.py
Lines:
531 - 716
Complexity:
moderate

Purpose

CommentBase serves as an abstract base class for different comment types in a document review/approval system. It handles common comment properties like text, author information, timestamps, resolution status, location/page references, and threading (replies). The class uses a dictionary-based internal storage (_data) with property accessors, tracks modifications, and provides methods for resolving/unresolving comments and managing comment threads. Subclasses must implement the save() method for persistence.

Source Code

class CommentBase:
    """Base class for comments (ReviewComment and ApprovalComment)."""
    
    def __init__(self, data=None):
        """Initialize with optional data dictionary."""
        self._data = data or {}
        self._modified = False
        
        # Set default values if not provided
        if 'UID' not in self._data:
            self._data['UID'] = str(uuid.uuid4())
            self._modified = True
            
        if 'created_at' not in self._data:
            self._data['created_at'] = datetime.now().isoformat()
            self._data['updated_at'] = self._data['created_at']
            self._modified = True
    
    @property
    def uid(self) -> str:
        """Get the UID."""
        return self._data.get('UID', '')
    
    @property
    def text(self) -> str:
        """Get the comment text."""
        return self._data.get('text', '')
    
    @text.setter
    def text(self, value: str) -> None:
        """Set the comment text."""
        self._data['text'] = value
        self._data['updated_at'] = datetime.now().isoformat()
        self._modified = True
    
    @property
    def comment_type(self) -> str:
        """Get the comment type."""
        return self._data.get('comment_type', CommentType.GENERAL)
    
    @comment_type.setter
    def comment_type(self, value: str) -> None:
        """Set the comment type."""
        self._data['comment_type'] = value
        self._modified = True
    
    @property
    def context(self) -> Dict[str, Any]:
        """Get the context information."""
        return self._data.get('context', {})
    
    @context.setter
    def context(self, value: Dict[str, Any]) -> None:
        """Set the context information."""
        self._data['context'] = value
        self._modified = True
    
    @property
    def created_at(self) -> str:
        """Get the creation timestamp."""
        return self._data.get('created_at', '')
    
    @property
    def updated_at(self) -> str:
        """Get the update timestamp."""
        return self._data.get('updated_at', self.created_at)
    
    @property
    def resolved(self) -> bool:
        """Check if the comment is resolved."""
        return self._data.get('resolved', False)
    
    @resolved.setter
    def resolved(self, value: bool) -> None:
        """Set whether the comment is resolved."""
        self._data['resolved'] = value
        self._modified = True

    
    @property
    def author_uid(self) -> str:
        """Get the UID of the comment author."""
        return self._data.get('author_uid', '')
    
    @author_uid.setter
    def author_uid(self, value: str) -> None:
        """Set the UID of the comment author."""
        self._data['author_uid'] = value
        self._modified = True
    
    @property
    def author_name(self) -> str:
        """Get the name of the comment author."""
        return self._data.get('author_name', '')
    
    @author_name.setter
    def author_name(self, value: str) -> None:
        """Set the name of the comment author."""
        self._data['author_name'] = value
        self._modified = True
    
    @property
    def page(self) -> Optional[int]:
        """Get the page number this comment refers to."""
        return self._data.get('page')
    
    @page.setter
    def page(self, value: Optional[int]) -> None:
        """Set the page number this comment refers to."""
        self._data['page'] = value
        self._modified = True
    
    @property
    def location(self) -> Dict[str, Any]:
        """Get the location information (e.g., text selection coordinates)."""
        return self._data.get('location', {})
    
    @location.setter
    def location(self, value: Dict[str, Any]) -> None:
        """Set the location information."""
        self._data['location'] = value
        self._modified = True
    
    @property
    def parent_comment_uid(self) -> Optional[str]:
        """Get the UID of the parent comment if this is a reply."""
        return self._data.get('parent_comment_uid')
    
    @parent_comment_uid.setter
    def parent_comment_uid(self, value: Optional[str]) -> None:
        """Set the UID of the parent comment."""
        self._data['parent_comment_uid'] = value
        self._modified = True
    
    def get_author(self):
        """Get the user object for the comment author."""
        from CDocs.models.user_extensions import DocUser
        if not self.author_uid:
            return None
        return DocUser.get_by_uid(self.author_uid)
    
    def get_replies(self) -> List['CommentBase']:
        """Get replies to this comment. Implemented in subclasses."""
        return []
    
    def is_reply(self) -> bool:
        """Check if this comment is a reply to another comment."""
        return self.parent_comment_uid is not None
    
    def notify_mentioned_users(self) -> bool:
        """Notify users mentioned in comment. Implemented in subclasses."""
        return False
    
    def resolve(self, resolution_text: Optional[str] = None) -> bool:
        """Mark the comment as resolved, optionally with resolution text."""
        self.resolved = True
        
        if resolution_text:
            if 'context' not in self._data:
                self._data['context'] = {}
            
            if 'resolution' not in self._data['context']:
                self._data['context']['resolution'] = {}
            
            self._data['context']['resolution']['text'] = resolution_text
            self._data['context']['resolution']['resolved_at'] = datetime.now().isoformat()
        
        self._data['updated_at'] = datetime.now().isoformat()
        self._modified = True
        return self.save()
    
    def unresolve(self) -> bool:
        """Mark the comment as unresolved."""
        self.resolved = False
        
        if 'context' in self._data and 'resolution' in self._data['context']:
            del self._data['context']['resolution']
        
        self._data['updated_at'] = datetime.now().isoformat()
        self._modified = True
        return self.save()
    
    def save(self) -> bool:
        """Save changes to database."""
        # To be implemented in subclasses
        raise NotImplementedError("Subclasses must implement save method")

Parameters

Name Type Default Kind
bases - -

Parameter Details

data: Optional dictionary containing initial comment data. If None, an empty dictionary is created. The dictionary can contain keys like 'UID', 'text', 'comment_type', 'author_uid', 'author_name', 'page', 'location', 'context', 'resolved', 'parent_comment_uid', 'created_at', 'updated_at'. If 'UID' is not provided, a new UUID is generated. If 'created_at' is not provided, current timestamp is set.

Return Value

Instantiation returns a CommentBase object (or subclass instance) with initialized internal state. Key method returns: uid (str), text (str), comment_type (str), context (Dict), created_at (str), updated_at (str), resolved (bool), author_uid (str), author_name (str), page (Optional[int]), location (Dict), parent_comment_uid (Optional[str]), get_author() returns DocUser or None, get_replies() returns List of CommentBase objects, is_reply() returns bool, notify_mentioned_users() returns bool, resolve() returns bool, unresolve() returns bool, save() raises NotImplementedError.

Class Interface

Methods

__init__(self, data: Optional[Dict[str, Any]] = None) -> None

Purpose: Initialize comment with optional data dictionary, setting defaults for UID and timestamps if not provided

Parameters:

  • data: Optional dictionary containing initial comment data with keys like UID, text, author_uid, etc.

Returns: None

@property uid(self) -> str property

Purpose: Get the unique identifier for this comment

Returns: String UUID of the comment, empty string if not set

@property text(self) -> str property

Purpose: Get the comment text content

Returns: String containing the comment text, empty string if not set

@text.setter text(self, value: str) -> None property

Purpose: Set the comment text and update the updated_at timestamp

Parameters:

  • value: String containing the new comment text

Returns: None

@property comment_type(self) -> str property

Purpose: Get the type/category of this comment

Returns: String representing comment type, defaults to CommentType.GENERAL if not set

@comment_type.setter comment_type(self, value: str) -> None property

Purpose: Set the comment type/category

Parameters:

  • value: String representing the comment type

Returns: None

@property context(self) -> Dict[str, Any] property

Purpose: Get additional context information stored with the comment

Returns: Dictionary containing context data, empty dict if not set

@context.setter context(self, value: Dict[str, Any]) -> None property

Purpose: Set additional context information for the comment

Parameters:

  • value: Dictionary containing context data

Returns: None

@property created_at(self) -> str property

Purpose: Get the timestamp when the comment was created

Returns: ISO format timestamp string, empty string if not set

@property updated_at(self) -> str property

Purpose: Get the timestamp when the comment was last updated

Returns: ISO format timestamp string, falls back to created_at if not set

@property resolved(self) -> bool property

Purpose: Check if the comment has been marked as resolved

Returns: Boolean indicating resolution status, False if not set

@resolved.setter resolved(self, value: bool) -> None property

Purpose: Set whether the comment is resolved

Parameters:

  • value: Boolean indicating if comment should be marked resolved

Returns: None

@property author_uid(self) -> str property

Purpose: Get the unique identifier of the comment author

Returns: String UID of the author, empty string if not set

@author_uid.setter author_uid(self, value: str) -> None property

Purpose: Set the unique identifier of the comment author

Parameters:

  • value: String UID of the author

Returns: None

@property author_name(self) -> str property

Purpose: Get the display name of the comment author

Returns: String name of the author, empty string if not set

@author_name.setter author_name(self, value: str) -> None property

Purpose: Set the display name of the comment author

Parameters:

  • value: String name of the author

Returns: None

@property page(self) -> Optional[int] property

Purpose: Get the page number this comment refers to in the document

Returns: Integer page number or None if not set

@page.setter page(self, value: Optional[int]) -> None property

Purpose: Set the page number this comment refers to

Parameters:

  • value: Integer page number or None

Returns: None

@property location(self) -> Dict[str, Any] property

Purpose: Get spatial location information like text selection coordinates

Returns: Dictionary containing location data (e.g., x, y, width, height), empty dict if not set

@location.setter location(self, value: Dict[str, Any]) -> None property

Purpose: Set spatial location information for the comment

Parameters:

  • value: Dictionary containing location data

Returns: None

@property parent_comment_uid(self) -> Optional[str] property

Purpose: Get the UID of the parent comment if this is a reply

Returns: String UID of parent comment or None if this is a top-level comment

@parent_comment_uid.setter parent_comment_uid(self, value: Optional[str]) -> None property

Purpose: Set the UID of the parent comment to create a reply relationship

Parameters:

  • value: String UID of parent comment or None

Returns: None

get_author(self) -> Optional[DocUser]

Purpose: Retrieve the DocUser object for the comment author from the database

Returns: DocUser object if author_uid is set and user exists, None otherwise

get_replies(self) -> List['CommentBase']

Purpose: Get all reply comments to this comment (must be implemented in subclasses)

Returns: List of CommentBase objects that are replies, empty list in base class

is_reply(self) -> bool

Purpose: Check if this comment is a reply to another comment

Returns: Boolean True if parent_comment_uid is set, False otherwise

notify_mentioned_users(self) -> bool

Purpose: Send notifications to users mentioned in the comment (must be implemented in subclasses)

Returns: Boolean indicating success, False in base class

resolve(self, resolution_text: Optional[str] = None) -> bool

Purpose: Mark the comment as resolved with optional resolution text and timestamp

Parameters:

  • resolution_text: Optional string describing the resolution

Returns: Boolean indicating if save was successful

unresolve(self) -> bool

Purpose: Mark the comment as unresolved and remove resolution metadata

Returns: Boolean indicating if save was successful

save(self) -> bool

Purpose: Persist comment changes to database (must be implemented in subclasses)

Returns: Boolean indicating save success

Attributes

Name Type Description Scope
_data Dict[str, Any] Internal dictionary storing all comment data including UID, text, timestamps, author info, location, context, and resolution status instance
_modified bool Flag tracking whether the comment has been modified since last save, set to True by property setters instance

Dependencies

  • typing
  • datetime
  • uuid
  • logging
  • CDocs.db.db_operations
  • CDocs.db.schema_manager
  • CDocs.config
  • CDocs.models.user_extensions
  • CDocs.models.document

Required Imports

from typing import List, Optional, Dict, Any, Union, Type
from datetime import datetime
import uuid
import logging

Conditional/Optional Imports

These imports are only needed under specific conditions:

from CDocs.models.user_extensions import DocUser

Condition: only when calling get_author() method to retrieve user objects

Required (conditional)
from CDocs.db import db_operations as db

Condition: required by subclasses for database operations

Optional
from CDocs.db.schema_manager import NodeLabels, RelTypes

Condition: required by subclasses for database schema definitions

Optional
from CDocs.config import settings

Condition: required by subclasses for configuration access

Optional
from CDocs.models.document import DocumentVersion

Condition: required by subclasses for document version operations

Optional

Usage Example

# Note: CommentBase is abstract, typically used via subclasses
# Example showing typical usage pattern:

from datetime import datetime
import uuid

# Subclass implementation example
class ReviewComment(CommentBase):
    def save(self):
        # Implement actual save logic
        return True

# Create new comment
comment = ReviewComment()
comment.text = "This section needs clarification"
comment.author_uid = "user-123"
comment.author_name = "John Doe"
comment.comment_type = "REVIEW"
comment.page = 5
comment.location = {"x": 100, "y": 200, "width": 150, "height": 20}
comment.save()

# Create reply to existing comment
reply = ReviewComment()
reply.text = "I agree, let me update this"
reply.author_uid = "user-456"
reply.author_name = "Jane Smith"
reply.parent_comment_uid = comment.uid
reply.save()

# Check if comment is a reply
if reply.is_reply():
    print(f"This is a reply to {reply.parent_comment_uid}")

# Resolve comment
comment.resolve(resolution_text="Updated as requested")

# Access comment properties
print(f"Comment UID: {comment.uid}")
print(f"Created: {comment.created_at}")
print(f"Updated: {comment.updated_at}")
print(f"Resolved: {comment.resolved}")

# Get author information
author = comment.get_author()
if author:
    print(f"Author: {author.name}")

# Unresolve if needed
comment.unresolve()

Best Practices

  • This is an abstract base class - always use through subclasses that implement the save() method
  • The _modified flag tracks changes but persistence depends on calling save() method
  • All property setters automatically update the 'updated_at' timestamp and set _modified=True
  • UID is auto-generated if not provided during initialization using uuid.uuid4()
  • Timestamps are stored as ISO format strings (datetime.now().isoformat())
  • The context property is a flexible dictionary for storing additional metadata
  • Resolution information is stored in context['resolution'] with text and timestamp
  • Use resolve() and unresolve() methods rather than directly setting resolved property for proper metadata handling
  • The get_author() method performs a database lookup, so cache results if calling multiple times
  • get_replies() and notify_mentioned_users() return default values in base class - subclasses should override
  • parent_comment_uid creates a threading relationship - use is_reply() to check if comment is a reply
  • Location and page properties allow spatial/positional references within documents
  • Always check if save() returns True to confirm successful persistence
  • The _data dictionary is the single source of truth for all comment state

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class ApprovalComment_v2 75.8% similar

    A model class representing a comment made during document approval workflows, with support for resolution tracking, replies, and database persistence.

    From: /tf/active/vicechatdev/CDocs single class/models/approval.py
  • class ApprovalComment_v1 73.8% similar

    A model class representing a comment made during a document approval cycle, with support for resolution tracking and database persistence.

    From: /tf/active/vicechatdev/CDocs/models/approval.py
  • class ReviewComment 72.7% similar

    A model class representing a comment made during document review, with support for resolution tracking, replies, and integration with review cycles.

    From: /tf/active/vicechatdev/CDocs single class/models/review.py
  • class ApprovalComment 72.4% similar

    Model class representing a comment made during a document approval cycle, with support for resolution tracking and database persistence.

    From: /tf/active/vicechatdev/CDocs/models/approval_bis.py
  • class ReviewComment_v1 71.7% similar

    A model class representing a comment made during document review, with support for resolution tracking and database persistence.

    From: /tf/active/vicechatdev/CDocs/models/review.py
← Back to Browse