Source code for stalker.models.status

# -*- coding: utf-8 -*-
# Stalker a Production Asset Management System
# Copyright (C) 2009-2017 Erkan Ozgur Yilmaz
#
# This file is part of Stalker.
#
# Stalker is free software: you can redistribute it and/or modify
# it under the terms of the Lesser GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License.
#
# Stalker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# Lesser GNU General Public License for more details.
#
# You should have received a copy of the Lesser GNU General Public License
# along with Stalker.  If not, see <http://www.gnu.org/licenses/>

from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship, validates

from stalker.db.session import DBSession
from stalker.db.declarative import Base
from stalker.models.entity import Entity
from stalker.models.mixins import TargetEntityTypeMixin
from stalker.models.mixins import CodeMixin

from stalker.log import logging_level
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging_level)


[docs]class Status(Entity, CodeMixin): """Defines object statutes. No extra parameters, use the *code* attribute to give a short name for the status. A Status object can be compared with a string value and it will return if the lower case name or lower case code of the status matches the lower case form of the given string:: >>> from stalker import Status >>> a_status = Status(name="On Hold", code="OH") >>> a_status == "on hold" True >>> a_status != "complete" True >>> a_status == "oh" True >>> a_status == "another status" False :param name: The name long name of this Status. :param code: The code of this Status, its generally the short version of the name attribute. """ __auto_name__ = False __tablename__ = "Statuses" __mapper_args__ = {"polymorphic_identity": "Status"} status_id = Column( "id", Integer, ForeignKey("Entities.id"), primary_key=True, ) def __init__(self, name=None, code=None, **kwargs): kwargs['name'] = name kwargs['code'] = code super(Status, self).__init__(**kwargs) self.code = code def __eq__(self, other): """the equality operator """ from stalker import __string_types__ if isinstance(other, __string_types__): return self.name.lower() == other.lower() or \ self.code.lower() == other.lower() else: return super(Status, self).__eq__(other) and \ isinstance(other, Status) def __hash__(self): """the overridden __hash__ method """ return super(Status, self).__hash__()
[docs]class StatusList(Entity, TargetEntityTypeMixin): """Type specific list of :class:`.Status` instances. Holds multiple :class:`.Status`\ es to be used as a choice list for several other classes. A StatusList can only be assigned to only one entity type. So a :class:`.Project` can only have one suitable StatusList object which is designed for :class:`.Project` entities. The list of statuses in StatusList can be accessed by using a list like indexing and it also supports string indexes only for getting the item, you can not set an item with string indices: >>> from stalker import Status, StatusList >>> status1 = Status(name="Complete", code="CMPLT") >>> status2 = Status(name="Work in Progress", code="WIP") >>> status3 = Status(name="Pending Review", code="PRev") >>> a_status_list = StatusList(name="Asset Status List", statuses=[status1, status2, status3], target_entity_type="Asset") >>> a_status_list[0] <Status (Complete, CMPLT)> >>> a_status_list["complete"] <Status (Complete, CMPLT)> >>> a_status_list["WIP"] <Status (Work in Progress, WIP)> :param statuses: This is a list of :class:`.Status` instances, so you can prepare different StatusLists for different kind of entities using the same pool of :class:`.Status`\ es. :param target_entity_type: use this parameter to specify the target entity type that this StatusList is designed for. It accepts classes or names of classes. For example:: from stalker import Status, StatusList, Project status_list = [ Status(name="Waiting To Start", code="WTS"), Status(name="On Hold", code="OH"), Status(name="In Progress", code="WIP"), Status(name="Waiting Review", code="WREV"), Status(name="Approved", code="APP"), Status(name="Completed", code="CMPLT"), ] project_status_list = StatusList( name="Project Status List", statuses=status_list, target_entity_type="Project" ) # or project_status_list = StatusList( name="Project Status List", statuses=status_list, target_entity_type=Project ) now with the code above you can not assign the ``project_status_list`` object to any other class than a ``Project`` object. The StatusList instance can be empty, means it may not have anything in its :attr:`.StatusList.statuses`. But it is useless. The validation for empty statuses list is left to the SOM user. """ __auto_name__ = True __tablename__ = "StatusLists" __mapper_args__ = {"polymorphic_identity": "StatusList"} __unique_target__ = True status_list_id = Column( "id", Integer, ForeignKey("Entities.id"), primary_key=True ) statuses = relationship( "Status", secondary="StatusList_Statuses", doc="List of :class:`.Status` objects, showing the possible statuses" ) def __init__(self, statuses=None, target_entity_type=None, **kwargs): super(StatusList, self).__init__(**kwargs) TargetEntityTypeMixin.__init__(self, target_entity_type, **kwargs) if statuses is None: statuses = [] self.statuses = statuses @validates("statuses") def _validate_statuses(self, key, status): """validates the given status """ if not isinstance(status, Status): raise TypeError( "All of the elements in %s.statuses must be an instance of " "stalker.models.status.Status, and not %s" % (self.__class__.__name__, status.__class__.__name__) ) return status def __eq__(self, other): """the equality operator """ return super(StatusList, self).__eq__(other) and \ isinstance(other, StatusList) and \ self.statuses == other.statuses and \ self.target_entity_type == other.target_entity_type def __hash__(self): """the overridden __hash__ method """ return super(StatusList, self).__hash__() def __getitem__(self, key): """the indexing attributes for getting item """ with DBSession.no_autoflush: return_item = None from stalker import __string_types__ if isinstance(key, __string_types__): for item in self.statuses: if item == key: return_item = item else: return_item = self.statuses[key] return return_item def __setitem__(self, key, value): """the indexing attributes for setting item """ self.statuses[key] = value def __delitem__(self, key): """the indexing attributes for deleting item """ del self.statuses[key] def __len__(self): """the indexing attributes for getting the length """ return len(self.statuses)
# StatusList_Statuses Table StatusList_Statuses = Table( "StatusList_Statuses", Base.metadata, Column( "status_list_id", Integer, ForeignKey("StatusLists.id"), primary_key=True ), Column( "status_id", Integer, ForeignKey("Statuses.id"), primary_key=True ) )