"""Basic type with children typically to create process structures."""
from BTrees.Length import Length
from pyramid.registry import Registry
from pyramid.traversal import get_current_registry
from substanced.folder import Folder
from substanced.util import find_service
from substanced.interfaces import IFolder
from zope.interface import implementer
from zope.deprecation import deprecated
import adhocracy_core.sheets.name
import adhocracy_core.sheets.pool
import adhocracy_core.sheets.metadata
import adhocracy_core.sheets.title
import adhocracy_core.sheets.workflow
import adhocracy_core.sheets.localroles
from adhocracy_core.events import ResourceWillBeDeleted
from adhocracy_core.interfaces import IPool
from adhocracy_core.resources import add_resource_type_to_registry
from adhocracy_core.resources import resource_meta
from adhocracy_core.resources.base import Base
from adhocracy_core.utils import now
from adhocracy_core.utils import find_graph
[docs]class IBasicPool(IPool):
"""Basic Pool."""
deprecated('IBasicPool', 'Backward compatible code, use organisation or pool')
@implementer(IPool, IFolder)
[docs]class Pool(Base, Folder):
"""An Auto-Naming Folder.
Custom names are allowed and coexists with the autogenerated names.
The next_name method sequentially increments the last name:
``0000001``, then ``0000002``, and so on.
"""
# The pool needs to provide IFolder to make substance.util.find_service
# work
_autoname_length = 7
def __init__(self, data=None, family=None):
"""Counter that should increment if descendants are changed."""
Folder.__init__(self, data=data, family=family)
Base.__init__(self)
self.__changed_descendants_counter__ = Length()
[docs] def next_name(self, subobject, prefix='') -> str:
"""Generate name to add subobject to the folder.
This method does:
- increment the last generated name associated to the prefix.
- zero-filling the left hand side of the result with 7 zeros.
- add prefix to the left hand side if any
If the generated Name exists add timestamp to the right side.
"""
number = self._get_next_number(prefix)
name = prefix + self._zfill(number)
if name in self.data:
timestamp = now().isoformat()
name += '_' + timestamp
return name
[docs] def add_next(self, subobject, prefix=''):
"""Add a subobject and name it automatically.
Use the name returned by this folder's ``next_name`` method.
"""
name = self.next_name(subobject, prefix=prefix)
return self.add(name, subobject, send_events=False)
def _zfill(self, name):
return str(int(name)).zfill(self._autoname_length)
def _get_next_number(self, prefix):
last = getattr(self, '_autoname_last_' + prefix, None)
if last is None:
last = Length()
setattr(self, '_autoname_last_' + prefix, last)
number = last.value
last.change(1)
return number
[docs] def find_service(self, service_name, *sub_service_names):
"""Return the :term:`service` for the given context."""
return find_service(self, service_name, *sub_service_names)
[docs] def remove(self, name, send_events: bool=True, registry: Registry=None,
**kwargs):
"""Delete subresource `name` from database.
:raises KeyError: if `name` is not a valid subresource name
"""
subresource = self[name]
registry = registry or get_current_registry(self)
if send_events: # pragma: no branch
event = ResourceWillBeDeleted(object=subresource,
parent=self,
registry=registry)
registry.notify(event)
graph = find_graph(subresource)
references = graph.get_refernces_for_removal_notificaton(subresource)
res = super().remove(name,
registry=registry,
send_events=send_events,
**kwargs)
graph.send_back_reference_removal_notificatons(references, registry)
return res
pool_meta = resource_meta._replace(
iresource=IPool,
content_class=Pool,
permission_create='create_pool',
is_implicit_addable=False,
basic_sheets=(adhocracy_core.sheets.name.IName,
adhocracy_core.sheets.title.ITitle,
adhocracy_core.sheets.pool.IPool,
adhocracy_core.sheets.metadata.IMetadata,
adhocracy_core.sheets.workflow.IWorkflowAssignment,
adhocracy_core.sheets.localroles.ILocalRoles,
),
extended_sheets=(),
element_types=(IPool,),
)
basicpool_meta = pool_meta._replace(
iresource=IBasicPool,
is_implicit_addable=True,
)
[docs]def includeme(config):
"""Add resource type to registry."""
add_resource_type_to_registry(basicpool_meta, config)
add_resource_type_to_registry(pool_meta, config)