<s> """<STR_LIT>""" <EOL> import datetime <EOL> import uuid <EOL> import pytz <EOL> from zope . interface import implementer <EOL> from persistent import Persistent <EOL> import colander <EOL> import deform . widget <EOL> from pyramid . location import lineage <EOL> from pyramid . security import has_permission <EOL> from pyramid . threadlocal import get_current_registry <EOL> from pyramid . traversal import resource_path <EOL> from substanced . interfaces import ( <EOL> ILock , <EOL> ILockService , <EOL> WriteLock , <EOL> UserToLock , <EOL> ) <EOL> from substanced . content import ( <EOL> content , <EOL> service <EOL> ) <EOL> from substanced . folder import ( <EOL> _AutoNamingFolder , <EOL> Folder , <EOL> ) <EOL> from substanced . objectmap import ( <EOL> reference_target_property , <EOL> reference_targetid_property , <EOL> ) <EOL> from substanced . property import PropertySheet <EOL> from substanced . util import ( <EOL> find_objectmap , <EOL> find_service , <EOL> get_oid , <EOL> ) <EOL> from substanced . schema import Schema <EOL> from substanced . _compat import INT_TYPES <EOL> class LockingError ( Exception ) : <EOL> def __init__ ( self , lock ) : <EOL> self . lock = lock <EOL> class LockError ( LockingError ) : <EOL> """<STR_LIT>""" <EOL> class UnlockError ( LockingError ) : <EOL> """<STR_LIT>""" <EOL> def now ( ) : <EOL> return datetime . datetime . utcnow ( ) . replace ( tzinfo = pytz . UTC ) <EOL> class LockOwnerSchema ( colander . SchemaNode ) : <EOL> title = '<STR_LIT>' <EOL> schema_type = colander . Int <EOL> @ property <EOL> def widget ( self ) : <EOL> context = self . bindings [ '<STR_LIT>' ] <EOL> principals = find_service ( context , '<STR_LIT>' ) <EOL> if principals is None : <EOL> values = [ ] <EOL> else : <EOL> values = [ ( get_oid ( group ) , name ) for name , group in <EOL> principals [ '<STR_LIT>' ] . items ( ) ] <EOL> return deform . widget . Select2Widget ( values = values ) <EOL> def validator ( self , node , value ) : <EOL> context = self . bindings [ '<STR_LIT>' ] <EOL> objectmap = find_objectmap ( context ) <EOL> if not value in objectmap . objectid_to_path : <EOL> raise colander . Invalid ( node , '<STR_LIT>' % value ) <EOL> class LockResourceSchema ( colander . SchemaNode ) : <EOL> title = '<STR_LIT>' <EOL> schema_type = colander . String <EOL> widget = deform . widget . TextInputWidget ( ) <EOL> missing = colander . null <EOL> def preparer ( self , value ) : <EOL> context = self . bindings [ '<STR_LIT>' ] <EOL> request = self . bindings [ '<STR_LIT>' ] <EOL> objectmap = find_objectmap ( context ) <EOL> if value is colander . null : <EOL> return colander . null <EOL> try : <EOL> resource = objectmap . object_for ( tuple ( value . split ( '<STR_LIT:/>' ) ) ) <EOL> except ValueError : <EOL> return None <EOL> if not has_permission ( '<STR_LIT>' , resource , request ) : <EOL> return False <EOL> return resource <EOL> def validator ( self , node , value ) : <EOL> if value is None : <EOL> raise colander . Invalid ( node , '<STR_LIT>' ) <EOL> if value is False : <EOL> raise colander . Invalid ( <EOL> node , <EOL> '<STR_LIT>' <EOL> ) <EOL> class LockSchema ( Schema ) : <EOL> ownerid = LockOwnerSchema ( ) <EOL> timeout = colander . SchemaNode ( <EOL> colander . Int ( ) , <EOL> validator = colander . Range ( <NUM_LIT:0> ) , <EOL> default = <NUM_LIT> , <EOL> title = '<STR_LIT>' , <EOL> ) <EOL> infinite = colander . SchemaNode ( <EOL> colander . Boolean ( ) , <EOL> default = False , <EOL> missing = False , <EOL> title = '<STR_LIT>' , <EOL> description = '<STR_LIT>' , <EOL> ) <EOL> last_refresh = colander . SchemaNode ( <EOL> colander . DateTime ( ) , <EOL> title = '<STR_LIT>' , <EOL> default = now ( ) , <EOL> ) <EOL> comment = colander . SchemaNode ( <EOL> colander . String ( ) , <EOL> validator = colander . Length ( max = <NUM_LIT:255> ) , <EOL> missing = None , <EOL> title = '<STR_LIT>' , <EOL> ) <EOL> resource = LockResourceSchema ( ) <EOL> class LockPropertySheet ( PropertySheet ) : <EOL> schema = LockSchema ( ) <EOL> def get ( self ) : <EOL> result = PropertySheet . get ( self ) <EOL> resource = result . get ( '<STR_LIT>' ) <EOL> if resource is None : <EOL> resource = colander . null <EOL> else : <EOL> resource = resource_path ( resource ) <EOL> result [ '<STR_LIT>' ] = resource <EOL> return result <EOL> def set ( self , appstruct ) : <EOL> resource = appstruct . get ( '<STR_LIT>' ) <EOL> if resource is colander . null : <EOL> appstruct [ '<STR_LIT>' ] = None <EOL> return PropertySheet . set ( self , appstruct ) <EOL> @ content ( <EOL> '<STR_LIT>' , <EOL> icon = '<STR_LIT>' , <EOL> add_view = '<STR_LIT>' , <EOL> ) <EOL> @ implementer ( ILock ) <EOL> class Lock ( Persistent ) : <EOL> """<STR_LIT>""" <EOL> owner = reference_target_property ( UserToLock ) <EOL> resource = reference_target_property ( WriteLock ) <EOL> ownerid = reference_targetid_property ( UserToLock ) <EOL> resourceid = reference_targetid_property ( WriteLock ) <EOL> def __init__ ( self , <EOL> infinite = False , <EOL> timeout = <NUM_LIT> , <EOL> comment = None , <EOL> last_refresh = None , <EOL> ) : <EOL> self . timeout = timeout <EOL> self . comment = comment <EOL> self . infinite = infinite <EOL> if last_refresh is None : <EOL> last_refresh = now ( ) <EOL> self . last_refresh = last_refresh <EOL> def refresh ( self , timeout = None , when = None ) : <EOL> """<STR_LIT>""" <EOL> if timeout is not None : <EOL> self . timeout = timeout <EOL> if when is None : <EOL> when = now ( ) <EOL> self . last_refresh = when <EOL> def expires ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . timeout is None : <EOL> return None <EOL> return self . last_refresh + datetime . timedelta ( seconds = self . timeout ) <EOL> def is_valid ( self , when = None ) : <EOL> """<STR_LIT>""" <EOL> objectmap = find_objectmap ( self ) <EOL> if objectmap is not None : <EOL> if self . resourceid is None : <EOL> return False <EOL> if when is None : <EOL> when = now ( ) <EOL> expires = self . expires ( ) <EOL> if expires is None : <EOL> return True <EOL> return expires >= when <EOL> @ property <EOL> def depth ( self ) : <EOL> return '<STR_LIT>' if self . infinite else '<STR_LIT:0>' <EOL> def commit_suicide ( self ) : <EOL> """<STR_LIT>""" <EOL> del self . __parent__ [ self . __name__ ] <EOL> @ service ( <EOL> '<STR_LIT>' , <EOL> icon = '<STR_LIT>' , <EOL> service_name = '<STR_LIT>' , <EOL> add_view = '<STR_LIT>' , <EOL> ) <EOL> @ implementer ( ILockService ) <EOL> class LockService ( Folder , _AutoNamingFolder ) : <EOL> __sdi_addable__ = ( '<STR_LIT>' , ) <EOL> def next_name ( self , subobject ) : <EOL> lock_id = str ( uuid . uuid4 ( ) ) <EOL> return lock_id <EOL> def _get_ownerid ( self , owner_or_ownerid ) : <EOL> ownerid = get_oid ( owner_or_ownerid , None ) <EOL> if ownerid is None : <EOL> ownerid = owner_or_ownerid <EOL> if not isinstance ( ownerid , INT_TYPES ) : <EOL> raise ValueError ( <EOL> '<STR_LIT>' % owner_or_ownerid <EOL> ) <EOL> return ownerid <EOL> def borrow_lock ( <EOL> self , <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = WriteLock , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> objectmap = find_objectmap ( self ) <EOL> ownerid = self . _get_ownerid ( owner_or_ownerid ) <EOL> locks = objectmap . targets ( resource , locktype ) <EOL> for lock in locks : <EOL> if lock . is_valid ( ) : <EOL> if lock . ownerid == ownerid : <EOL> return lock <EOL> else : <EOL> raise LockError ( lock ) <EOL> else : <EOL> lock . commit_suicide ( ) <EOL> break <EOL> def lock ( <EOL> self , <EOL> resource , <EOL> owner_or_ownerid , <EOL> timeout = None , <EOL> comment = None , <EOL> locktype = WriteLock , <EOL> infinite = False , <EOL> ) : <EOL> lock = self . borrow_lock ( resource , owner_or_ownerid , locktype ) <EOL> if lock is not None : <EOL> when = now ( ) <EOL> lock . refresh ( timeout , when ) <EOL> return lock <EOL> registry = get_current_registry ( ) <EOL> lock = registry . content . create ( '<STR_LIT>' , <EOL> ) <EOL> self . add_next ( lock ) <EOL> lock . ownerid = self . _get_ownerid ( owner_or_ownerid ) <EOL> lock . resource = resource <EOL> lock . timeout = timeout <EOL> lock . comment = comment <EOL> lock . infinite = infinite <EOL> return lock <EOL> def unlock ( <EOL> self , <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = WriteLock , <EOL> ) : <EOL> objectmap = find_objectmap ( self ) <EOL> ownerid = self . _get_ownerid ( owner_or_ownerid ) <EOL> locks = objectmap . targets ( resource , locktype ) <EOL> lock = None <EOL> for lock in locks : <EOL> if not lock . is_valid ( ) : <EOL> lock . commit_suicide ( ) <EOL> elif lock . ownerid == ownerid : <EOL> lock . commit_suicide ( ) <EOL> break <EOL> else : <EOL> raise UnlockError ( lock ) <EOL> def unlock_token ( <EOL> self , <EOL> token , <EOL> owner_or_ownerid , <EOL> ) : <EOL> ownerid = self . _get_ownerid ( owner_or_ownerid ) <EOL> lock = self . get ( token ) <EOL> if lock is None : <EOL> raise UnlockError ( None ) <EOL> if not lock . is_valid ( ) : <EOL> lock . commit_suicide ( ) <EOL> raise UnlockError ( None ) <EOL> if lock . ownerid != ownerid : <EOL> raise UnlockError ( lock ) <EOL> lock . commit_suicide ( ) <EOL> def discover ( self , resource , <EOL> include_invalid = False , <EOL> include_lineage = True , <EOL> locktype = WriteLock ) : <EOL> objectmap = find_objectmap ( self ) <EOL> valid = [ ] <EOL> if include_lineage : <EOL> resources = lineage ( resource ) <EOL> else : <EOL> resources = [ resource ] <EOL> for res in resources : <EOL> locks = objectmap . targets ( res , locktype ) <EOL> for lock in locks : <EOL> if include_invalid or lock . is_valid ( ) : <EOL> valid . append ( lock ) <EOL> return valid <EOL> def _get_lock_service ( resource ) : <EOL> locks = find_service ( resource , '<STR_LIT>' ) <EOL> if locks is None : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> return locks <EOL> def lock_resource ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> timeout = None , <EOL> comment = None , <EOL> locktype = WriteLock , <EOL> infinite = False , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> locks = _get_lock_service ( resource ) <EOL> return locks . lock ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> timeout = timeout , <EOL> comment = comment , <EOL> locktype = locktype , <EOL> infinite = infinite , <EOL> ) <EOL> def could_lock_resource ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = WriteLock , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> locks = _get_lock_service ( resource ) <EOL> locks . borrow_lock ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = locktype , <EOL> ) <EOL> return True <EOL> def unlock_resource ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = WriteLock , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> locks = _get_lock_service ( resource ) <EOL> return locks . unlock ( <EOL> resource , <EOL> owner_or_ownerid , <EOL> locktype = locktype <EOL> ) <EOL> def unlock_token ( <EOL> resource , <EOL> token , <EOL> owner_or_ownerid , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> locks = _get_lock_service ( resource ) <EOL> return locks . unlock_token ( <EOL> token , <EOL> owner_or_ownerid , <EOL> ) <EOL> def discover_resource_locks ( <EOL> resource , <EOL> include_invalid = False , <EOL> include_lineage = True , <EOL> locktype = WriteLock , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> locks = _get_lock_service ( resource ) <EOL> return locks . discover ( <EOL> resource , <EOL> include_invalid = include_invalid , <EOL> include_lineage = include_lineage , <EOL> locktype = locktype <EOL> ) <EOL> def includeme ( config ) : <EOL> config . add_permission ( '<STR_LIT>' ) <EOL> config . add_propertysheet ( '<STR_LIT>' , LockPropertySheet , ILock ) <EOL> config . include ( '<STR_LIT>' ) <EOL> config . include ( '<STR_LIT>' ) </s>
