def _getUndoInfo(self, context, principal, first, last): specification = {} if context is not None: locatable = IPhysicallyLocatable(context, None) if locatable is not None: location = Prefix(locatable.getPath()) specification.update({'location': location}) if principal is not None: # TODO: The 'user' in the transactions is a concatenation # of 'path' and 'user' (id). 'path' used to be the path # of the user folder in Zope 2. ZopePublication currently # does not set a path, so ZODB lets the path default to # '/'. We should change ZODB3 to set no default path at # some point path = '/' # default for now specification.update({'user_name': path + ' ' + principal.id}) entries = self.__db.undoInfo(first, last, specification) # We walk through the entries, augmenting the dictionaries # with some additional items we have promised in the interface for entry in entries: entry['datetime'] = datetime.fromtimestamp(entry['time']) entry['principal'] = None user_name = entry['user_name'] if user_name: # TODO: This is because of ZODB3/Zope2 cruft regarding # the user path (see comment above). This 'if' block # should go away. split = user_name.split() if len(split) == 2: user_name = split[1] if user_name: try: principal = zope.component.getUtility( IAuthentication).getPrincipal(user_name) entry['principal'] = principal except PrincipalLookupError: # principals might have passed away pass except NotFoundError: # BBB Backward Compatibility warnings.warn( "An authentication utility raised a NotFoundError in " "getPrincipals. Raising NotFoundError in this " "method is deprecated and will no-longer be supported " "staring in Zope 3.3. PrincipalLookupError should " "be raised instead.", DeprecationWarning) return entries
def test(self): setup.setUpTraversal() root = Root() f1 = contained(C(), root, name='f1') f2 = contained(SiteManagerContainer(), f1, name='f2') f3 = contained(C(), f2, name='f3') adapter = IPhysicallyLocatable(f3) self.assertEqual(adapter.getPath(), '/f1/f2/f3') self.assertEqual(adapter.getName(), 'f3') self.assertEqual(adapter.getRoot(), root) self.assertEqual(adapter.getNearestSite(), root) setup.createSiteManager(f2) self.assertEqual(adapter.getNearestSite(), f2)
def annotateTransaction(self, txn, request, ob): """Set some useful meta-information on the transaction. This information is used by the undo framework, for example. This method is not part of the `IPublication` interface, since it's specific to this particular implementation. """ if request.principal is not None: txn.setUser(request.principal.id) # Work around methods that are usually used for views bare = removeSecurityProxy(ob) if isinstance(bare, instancemethod): ob = bare.im_self # set the location path path = None locatable = IPhysicallyLocatable(ob, None) if locatable is not None: # Views are made children of their contexts, but that # doesn't necessarily mean that we can fully resolve the # path. E.g. the family tree of a resource cannot be # resolved completely, as the site manager is a dead end. try: path = locatable.getPath() except (AttributeError, TypeError): pass if path is not None: txn.setExtendedInfo('location', path) # set the request type iface = IRequest for iface in providedBy(request): if iface.extends(IRequest): break iface_dotted = iface.__module__ + '.' + iface.getName() txn.setExtendedInfo('request_type', iface_dotted) return txn