• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Zope / 6263629025

21 Sep 2023 03:12PM UTC coverage: 82.146% (-0.01%) from 82.159%
6263629025

Pull #1164

github

web-flow
[pre-commit.ci lite] apply automatic fixes
Pull Request #1164: Move all linters to pre-commit.

4353 of 6963 branches covered (0.0%)

Branch coverage included in aggregate %.

487 of 487 new or added lines in 186 files covered. (100.0%)

27394 of 31684 relevant lines covered (86.46%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.17
/src/OFS/tests/testObjectManager.py
1
import os
1✔
2
import unittest
1✔
3
from logging import getLogger
1✔
4
from urllib.parse import quote
1✔
5

6
from AccessControl.owner import EmergencyUserCannotOwn
1✔
7
from AccessControl.SecurityManagement import newSecurityManager
1✔
8
from AccessControl.SecurityManagement import noSecurityManager
1✔
9
from AccessControl.SecurityManager import setSecurityPolicy
1✔
10
from AccessControl.users import User
1✔
11
from AccessControl.users import emergency_user
1✔
12
from AccessControl.users import nobody
1✔
13
from AccessControl.users import system
1✔
14
from Acquisition import Implicit
1✔
15
from Acquisition import aq_self
1✔
16
from App.config import getConfiguration
1✔
17
from OFS.interfaces import IItem
1✔
18
from OFS.metaconfigure import setDeprecatedManageAddDelete
1✔
19
from OFS.ObjectManager import ObjectManager
1✔
20
from OFS.SimpleItem import SimpleItem
1✔
21
from zExceptions import BadRequest
1✔
22
from Zope2.App import zcml
1✔
23
from zope.component.testing import PlacelessSetup
1✔
24
from zope.interface import implementer
1✔
25

26

27
logger = getLogger('OFS.subscribers')
1✔
28

29

30
class FauxRoot(Implicit):
1✔
31

32
    id = '/'
1✔
33

34
    def getPhysicalRoot(self):
1✔
35
        return self
1✔
36

37
    def getPhysicalPath(self):
1✔
38
        return ()
×
39

40

41
class FauxUser(Implicit):
1✔
42

43
    def __init__(self, id, login):
1✔
44

45
        self._id = id
1✔
46
        self._login = login
1✔
47

48
    def getId(self):
1✔
49

50
        return self._id
1✔
51

52

53
class DeleteFailed(Exception):
1✔
54
    pass
1✔
55

56

57
class ItemForDeletion(SimpleItem):
1✔
58

59
    def __init__(self, fail_on_delete=False):
1✔
60
        self.id = 'stuff'
1✔
61
        self.before_delete_called = False
1✔
62
        self.fail_on_delete = fail_on_delete
63

64
    def manage_beforeDelete(self, item, container):
1✔
65
        self.before_delete_called = True
1✔
66
        if self.fail_on_delete:
67
            raise DeleteFailed
68

69
    def manage_afterAdd(self, item, container):
1✔
70
        pass
1✔
71

72
    def manage_afterClone(self, item):
1✔
73
        pass
×
74

75

76
@implementer(IItem)
1✔
77
class ObjectManagerWithIItem(ObjectManager):
1✔
78
    """The event subscribers work on IItem."""
79

80

81
class ObjectManagerTests(PlacelessSetup, unittest.TestCase):
1✔
82

83
    def setUp(self):
1✔
84
        super().setUp()
1✔
85
        self.saved_cfg_debug_mode = getConfiguration().debug_mode
1✔
86
        import Zope2.App
1✔
87
        zcml.load_config('meta.zcml', Zope2.App)
1✔
88
        import OFS
1✔
89
        zcml.load_config('configure.zcml', OFS)
1✔
90
        setDeprecatedManageAddDelete(ItemForDeletion)
1✔
91

92
    def tearDown(self):
1✔
93
        noSecurityManager()
1✔
94
        getConfiguration().debug_mode = self.saved_cfg_debug_mode
1✔
95
        super().tearDown()
1✔
96

97
    def setDebugMode(self, mode):
1✔
98
        getConfiguration().debug_mode = mode
1✔
99

100
    def _getTargetClass(self):
1✔
101
        return ObjectManagerWithIItem
1✔
102

103
    def _makeOne(self, *args, **kw):
1✔
104
        return self._getTargetClass()(*args, **kw).__of__(FauxRoot())
1✔
105

106
    def test_interfaces(self):
1✔
107
        from OFS.interfaces import IObjectManager
1✔
108
        from OFS.ObjectManager import ObjectManager
1✔
109
        from zope.container.interfaces import IContainer
1✔
110
        from zope.interface.verify import verifyClass
1✔
111

112
        verifyClass(IContainer, ObjectManager)
1✔
113
        verifyClass(IObjectManager, ObjectManager)
1✔
114

115
    def test_filtered_meta_types(self):
1✔
116

117
        class _DummySecurityPolicy:
1✔
118

119
            def checkPermission(self, permission, object, context):
1✔
120
                return permission == 'addFoo'
1✔
121

122
        om = self._makeOne()
1✔
123
        om.all_meta_types = ({'name': 'Foo', 'permission': 'addFoo'},
1✔
124
                             {'name': 'Bar', 'permission': 'addBar'},
125
                             {'name': 'Baz'})
126
        try:
1✔
127
            oldPolicy = setSecurityPolicy(_DummySecurityPolicy())
1✔
128
            self.assertEqual(len(om.filtered_meta_types()), 2)
1✔
129
            self.assertEqual(om.filtered_meta_types()[0]['name'], 'Foo')
1✔
130
            self.assertEqual(om.filtered_meta_types()[1]['name'], 'Baz')
1✔
131
        finally:
132
            noSecurityManager()
1✔
133
            setSecurityPolicy(oldPolicy)
1✔
134

135
    def test_all_meta_types_adds_zmi_modal(self):
1✔
136
        om = self._makeOne()
1✔
137
        om.meta_types = ({'name': 'Foo'}, {'name': 'Bar'}, {'name': 'Baz'})
1✔
138
        amt = om.all_meta_types()
1✔
139
        for mt in [x for x in amt if x['name'] in ('foo', 'bar', 'baz')]:
1!
140
            self.assertEqual(mt['zmi_show_add_dialog'], 'modal')
×
141

142
        # Pick an example that will be different
143
        for mt in [x for x in amt if x['name'] == 'Virtual Host Monster']:
1✔
144
            self.assertEqual(mt['zmi_show_add_dialog'], '')
1✔
145

146
    def test_setObject_set_owner_with_no_user(self):
1✔
147
        om = self._makeOne()
1✔
148
        newSecurityManager(None, None)
1✔
149
        si = SimpleItem('no_user')
1✔
150
        om._setObject('no_user', si)
1✔
151
        self.assertEqual(si.__ac_local_roles__, None)
1✔
152

153
    def test_setObject_set_owner_with_emergency_user(self):
1✔
154
        om = self._makeOne()
1✔
155
        newSecurityManager(None, emergency_user)
1✔
156
        si = SimpleItem('should_fail')
1✔
157
        self.assertEqual(si.__ac_local_roles__, None)
1✔
158
        self.assertRaises(
1✔
159
            EmergencyUserCannotOwn,
160
            om._setObject, 'should_fail', si)
161

162
    def test_setObject_set_owner_with_system_user(self):
1✔
163
        om = self._makeOne()
1✔
164
        newSecurityManager(None, system)
1✔
165
        si = SimpleItem('system')
1✔
166
        self.assertEqual(si.__ac_local_roles__, None)
1✔
167
        om._setObject('system', si)
1✔
168
        self.assertEqual(si.__ac_local_roles__, None)
1✔
169

170
    def test_setObject_set_owner_with_anonymous_user(self):
1✔
171
        om = self._makeOne()
1✔
172
        newSecurityManager(None, nobody)
1✔
173
        si = SimpleItem('anon')
1✔
174
        self.assertEqual(si.__ac_local_roles__, None)
1✔
175
        om._setObject('anon', si)
1✔
176
        self.assertEqual(si.__ac_local_roles__, None)
1✔
177

178
    def test_setObject_set_owner_with_user(self):
1✔
179
        om = self._makeOne()
1✔
180
        user = User('user', '123', (), ()).__of__(FauxRoot())
1✔
181
        newSecurityManager(None, user)
1✔
182
        si = SimpleItem('user_creation')
1✔
183
        self.assertEqual(si.__ac_local_roles__, None)
1✔
184
        om._setObject('user_creation', si)
1✔
185
        self.assertEqual(si.__ac_local_roles__, {'user': ['Owner']})
1✔
186

187
    def test_setObject_set_owner_with_faux_user(self):
1✔
188
        om = self._makeOne()
1✔
189
        user = FauxUser('user_id', 'user_login').__of__(FauxRoot())
1✔
190
        newSecurityManager(None, user)
1✔
191
        si = SimpleItem('faux_creation')
1✔
192
        self.assertEqual(si.__ac_local_roles__, None)
1✔
193
        om._setObject('faux_creation', si)
1✔
194
        self.assertEqual(si.__ac_local_roles__, {'user_id': ['Owner']})
1✔
195

196
    def test_setObject_no_set_owner_with_no_user(self):
1✔
197
        om = self._makeOne()
1✔
198
        newSecurityManager(None, None)
1✔
199
        si = SimpleItem('should_be_okay')
1✔
200
        self.assertEqual(si.__ac_local_roles__, None)
1✔
201
        om._setObject('should_be_okay', si, set_owner=0)
1✔
202
        self.assertEqual(si.__ac_local_roles__, None)
1✔
203

204
    def test_setObject_no_set_owner_with_emergency_user(self):
1✔
205
        om = self._makeOne()
1✔
206
        newSecurityManager(None, emergency_user)
1✔
207
        si = SimpleItem('should_be_okay')
1✔
208
        self.assertEqual(si.__ac_local_roles__, None)
1✔
209
        om._setObject('should_be_okay', si, set_owner=0)
1✔
210
        self.assertEqual(si.__ac_local_roles__, None)
1✔
211

212
    def test_setObject_no_set_owner_with_system_user(self):
1✔
213
        om = self._makeOne()
1✔
214
        newSecurityManager(None, system)
1✔
215
        si = SimpleItem('should_be_okay')
1✔
216
        self.assertEqual(si.__ac_local_roles__, None)
1✔
217
        om._setObject('should_be_okay', si, set_owner=0)
1✔
218
        self.assertEqual(si.__ac_local_roles__, None)
1✔
219

220
    def test_setObject_no_set_owner_with_anonymous_user(self):
1✔
221
        om = self._makeOne()
1✔
222
        newSecurityManager(None, nobody)
1✔
223
        si = SimpleItem('should_be_okay')
1✔
224
        self.assertEqual(si.__ac_local_roles__, None)
1✔
225
        om._setObject('should_be_okay', si, set_owner=0)
1✔
226
        self.assertEqual(si.__ac_local_roles__, None)
1✔
227

228
    def test_setObject_no_set_owner_with_user(self):
1✔
229
        om = self._makeOne()
1✔
230
        user = User('user', '123', (), ()).__of__(FauxRoot())
1✔
231
        newSecurityManager(None, user)
1✔
232
        si = SimpleItem('should_be_okay')
1✔
233
        self.assertEqual(si.__ac_local_roles__, None)
1✔
234
        om._setObject('should_be_okay', si, set_owner=0)
1✔
235
        self.assertEqual(si.__ac_local_roles__, None)
1✔
236

237
    def test_setObject_no_set_owner_with_faux_user(self):
1✔
238
        om = self._makeOne()
1✔
239
        user = FauxUser('user_id', 'user_login').__of__(FauxRoot())
1✔
240
        newSecurityManager(None, user)
1✔
241
        si = SimpleItem('should_be_okay')
1✔
242
        self.assertEqual(si.__ac_local_roles__, None)
1✔
243
        om._setObject('should_be_okay', si, set_owner=0)
1✔
244
        self.assertEqual(si.__ac_local_roles__, None)
1✔
245

246
    def test_delObject_before_delete(self):
1✔
247
        # Test that manage_beforeDelete is called
248
        om = self._makeOne()
1✔
249
        ob = ItemForDeletion()
1✔
250
        om._setObject(ob.getId(), ob)
1✔
251
        self.assertEqual(ob.before_delete_called, False)
1✔
252
        om._delObject(ob.getId())
1✔
253
        self.assertEqual(ob.before_delete_called, True)
1✔
254

255
    def test_delObject_exception_manager(self):
1✔
256
        # Test exception behavior in manage_beforeDelete
257
        # Manager user
258
        self.setDebugMode(False)
1✔
259
        newSecurityManager(None, system)  # Manager
1✔
260
        om = self._makeOne()
1✔
261
        ob = ItemForDeletion(fail_on_delete=True)
1✔
262
        om._setObject(ob.getId(), ob)
1✔
263
        try:
1✔
264
            logger.disabled = 1
1✔
265
            om._delObject(ob.getId())
1✔
266
        finally:
267
            logger.disabled = 0
1✔
268

269
    def test_delObject_exception(self):
1✔
270
        # Test exception behavior in manage_beforeDelete
271
        # non-Manager user
272
        self.setDebugMode(False)
1✔
273
        om = self._makeOne()
1✔
274
        ob = ItemForDeletion(fail_on_delete=True)
1✔
275
        om._setObject(ob.getId(), ob)
1✔
276
        try:
1✔
277
            logger.disabled = 1
1✔
278
            om._delObject(ob.getId())
1✔
279
        finally:
280
            logger.disabled = 0
1✔
281

282
    def test_delObject_exception_debug_manager(self):
1✔
283
        # Test exception behavior in manage_beforeDelete in debug mode
284
        # Manager user
285
        self.setDebugMode(True)
1✔
286
        newSecurityManager(None, system)  # Manager
1✔
287
        om = self._makeOne()
1✔
288
        ob = ItemForDeletion(fail_on_delete=True)
1✔
289
        om._setObject(ob.getId(), ob)
1✔
290
        try:
1✔
291
            logger.disabled = 1
1✔
292
            om._delObject(ob.getId())
1✔
293
        finally:
294
            logger.disabled = 0
1✔
295

296
    def test_delObject_exception_debug(self):
1✔
297
        # Test exception behavior in manage_beforeDelete in debug mode
298
        # non-Manager user
299
        # It's the only special case: we let exceptions propagate.
300
        self.setDebugMode(True)
1✔
301
        om = self._makeOne()
1✔
302
        ob = ItemForDeletion(fail_on_delete=True)
1✔
303
        om._setObject(ob.getId(), ob)
1✔
304
        try:
1✔
305
            logger.disabled = 1
1✔
306
            self.assertRaises(DeleteFailed, om._delObject, ob.getId())
1✔
307
        finally:
308
            logger.disabled = 0
1✔
309

310
    def test_delObject_exception_debug_deep(self):
1✔
311
        # Test exception behavior in manage_beforeDelete in debug mode
312
        # non-Manager user
313
        # Test for deep subobjects.
314
        self.setDebugMode(True)
1✔
315
        om1 = self._makeOne()
1✔
316
        om2 = self._makeOne()
1✔
317
        ob = ItemForDeletion(fail_on_delete=True)
1✔
318
        om1._setObject('om2', om2, set_owner=False)
1✔
319
        om2._setObject(ob.getId(), ob)
1✔
320
        try:
1✔
321
            logger.disabled = 1
1✔
322
            self.assertRaises(DeleteFailed, om1._delObject, 'om2')
1✔
323
        finally:
324
            logger.disabled = 0
1✔
325

326
    def test_manage_delObjects(self):
1✔
327
        om = self._makeOne()
1✔
328
        ob = ItemForDeletion()
1✔
329
        om._setObject('stuff', ob)
1✔
330
        om.manage_delObjects('stuff')
1✔
331
        self.assertNotIn('stuff', om)
1✔
332

333
        om._setObject('stuff', ob)
1✔
334
        om.manage_delObjects(['stuff'])
1✔
335
        self.assertNotIn('stuff', om)
1✔
336

337
        om._setObject('stuff', ob)
1✔
338
        om.manage_delObjects('stuff')
1✔
339
        self.assertNotIn('stuff', om)
1✔
340

341
    def test_hasObject(self):
1✔
342
        om = self._makeOne()
1✔
343
        self.assertFalse(om.hasObject('_properties'))
1✔
344
        self.assertFalse(om.hasObject('_getOb'))
1✔
345
        self.assertFalse(om.hasObject('__of__'))
1✔
346
        self.assertFalse(om.hasObject('.'))
1✔
347
        self.assertFalse(om.hasObject('..'))
1✔
348
        self.assertFalse(om.hasObject('aq_base'))
1✔
349
        om.zap__ = True
1✔
350
        self.assertFalse(om.hasObject('zap__'))
1✔
351
        self.assertFalse(om.hasObject('foo'))
1✔
352
        si = SimpleItem('foo')
1✔
353
        om._setObject('foo', si)
1✔
354
        self.assertTrue(om.hasObject('foo'))
1✔
355
        om._delObject('foo')
1✔
356
        self.assertFalse(om.hasObject('foo'))
1✔
357

358
    def test_setObject_checkId_ok(self):
1✔
359
        om = self._makeOne()
1✔
360
        si = SimpleItem('1')
1✔
361
        om._setObject('AB-dash_under0123', si)
1✔
362
        si = SimpleItem('2')
1✔
363
        om._setObject('ho.bak~', si)
1✔
364
        si = SimpleItem('3')
1✔
365
        om._setObject('dot.comma,dollar$(hi)hash# space', si)
1✔
366
        si = SimpleItem('4')
1✔
367
        om._setObject('b@r', si)
1✔
368
        si = SimpleItem('5')
1✔
369
        om._setObject('..haha', si)
1✔
370
        si = SimpleItem('6')
1✔
371
        om._setObject('.bashrc', si)
1✔
372

373
    def test_setObject_checkId_bad(self):
1✔
374
        om = self._makeOne()
1✔
375
        si = SimpleItem('111')
1✔
376
        om._setObject('111', si)
1✔
377
        si = SimpleItem('2')
1✔
378
        self.assertRaises(BadRequest, om._setObject, 123, si)
1✔
379
        self.assertRaises(BadRequest, om._setObject, 'a\x01b', si)
1✔
380
        self.assertRaises(BadRequest, om._setObject, '.', si)
1✔
381
        self.assertRaises(BadRequest, om._setObject, '..', si)
1✔
382
        self.assertRaises(BadRequest, om._setObject, '_foo', si)
1✔
383
        self.assertRaises(BadRequest, om._setObject, 'aq_me', si)
1✔
384
        self.assertRaises(BadRequest, om._setObject, 'bah__', si)
1✔
385
        self.assertRaises(BadRequest, om._setObject, '111', si)
1✔
386
        self.assertRaises(BadRequest, om._setObject, 'REQUEST', si)
1✔
387
        self.assertRaises(BadRequest, om._setObject, '/', si)
1✔
388
        self.assertRaises(BadRequest, om._setObject, 'get', si)
1✔
389
        self.assertRaises(BadRequest, om._setObject, 'items', si)
1✔
390
        self.assertRaises(BadRequest, om._setObject, 'keys', si)
1✔
391
        self.assertRaises(BadRequest, om._setObject, 'values', si)
1✔
392
        self.assertRaises(BadRequest, om._setObject, 'foo&bar', si)
1✔
393
        self.assertRaises(BadRequest, om._setObject, 'foo>bar', si)
1✔
394
        self.assertRaises(BadRequest, om._setObject, 'foo<bar', si)
1✔
395
        self.assertRaises(BadRequest, om._setObject, 'foo/bar', si)
1✔
396
        self.assertRaises(BadRequest, om._setObject, '@@ohno', si)
1✔
397
        self.assertRaises(BadRequest, om._setObject, '++ohno', si)
1✔
398

399
    def test_getsetitem(self):
1✔
400
        om = self._makeOne()
1✔
401
        si1 = SimpleItem('1')
1✔
402
        si2 = SimpleItem('2')
1✔
403
        om['1'] = si1
1✔
404
        self.assertIn('1', om)
1✔
405
        self.assertIn(si1, om.objectValues())
1✔
406
        self.assertIn('1', om.objectIds())
1✔
407
        om['2'] = si2
1✔
408
        self.assertIn('2', om)
1✔
409
        self.assertIn(si2, om.objectValues())
1✔
410
        self.assertIn('2', om.objectIds())
1✔
411
        self.assertRaises(BadRequest, om._setObject, '1', si2)
1✔
412
        self.assertRaises(BadRequest, om.__setitem__, '1', si2)
1✔
413

414
    def test_delitem(self):
1✔
415
        om = self._makeOne()
1✔
416
        si1 = SimpleItem('1')
1✔
417
        si2 = SimpleItem('2')
1✔
418
        om['1'] = si1
1✔
419
        om['2'] = si2
1✔
420
        self.assertIn('1', om)
1✔
421
        self.assertIn('2', om)
1✔
422
        del om['1']
1✔
423
        self.assertNotIn('1', om)
1✔
424
        self.assertIn('2', om)
1✔
425
        om._delObject('2')
1✔
426
        self.assertNotIn('2', om)
1✔
427

428
    def test_iterator(self):
1✔
429
        om = self._makeOne()
1✔
430
        si1 = SimpleItem('1')
1✔
431
        si2 = SimpleItem('2')
1✔
432
        om['1'] = si1
1✔
433
        om['2'] = si2
1✔
434
        iterator = iter(om)
1✔
435
        self.assertTrue(hasattr(iterator, '__iter__'))
1✔
436
        self.assertTrue(hasattr(iterator, '__next__'))
1✔
437
        result = [i for i in iterator]
1✔
438
        self.assertIn('1', result)
1✔
439
        self.assertIn('2', result)
1✔
440

441
    def test_len(self):
1✔
442
        om = self._makeOne()
1✔
443
        si1 = SimpleItem('1')
1✔
444
        si2 = SimpleItem('2')
1✔
445
        om['1'] = si1
1✔
446
        om['2'] = si2
1✔
447
        self.assertEqual(len(om), 2)
1✔
448

449
    def test_nonzero(self):
1✔
450
        om = self._makeOne()
1✔
451
        self.assertTrue(om)
1✔
452

453
    def test___getitem___miss(self):
1✔
454
        om = self._makeOne()
1✔
455
        self.assertRaises(KeyError, om.__getitem__, 'nonesuch')
1✔
456

457
    def test___getitem___miss_w_non_instance_attr(self):
1✔
458
        om = self._makeOne()
1✔
459
        self.assertRaises(KeyError, om.__getitem__, 'get')
1✔
460

461
    def test___getitem___hit(self):
1✔
462
        om = self._makeOne()
1✔
463
        si1 = SimpleItem('1')
1✔
464
        om['1'] = si1
1✔
465
        got = om['1']
1✔
466
        self.assertIs(aq_self(got), si1)
1✔
467
        self.assertIs(got.__parent__, om)
1✔
468

469
    def test_get_miss_wo_default(self):
1✔
470
        om = self._makeOne()
1✔
471
        self.assertEqual(om.get('nonesuch'), None)
1✔
472

473
    def test_get_miss_w_default(self):
1✔
474
        om = self._makeOne()
1✔
475
        obj = object()
1✔
476
        self.assertIs(om.get('nonesuch', obj), obj)
1✔
477

478
    def test_get_miss_w_non_instance_attr(self):
1✔
479
        om = self._makeOne()
1✔
480
        self.assertEqual(om.get('get'), None)
1✔
481

482
    def test_get_hit(self):
1✔
483
        om = self._makeOne()
1✔
484
        si1 = SimpleItem('1')
1✔
485
        om['1'] = si1
1✔
486
        got = om.get('1')
1✔
487
        self.assertIs(aq_self(got), si1)
1✔
488
        self.assertIs(got.__parent__, om)
1✔
489

490
    def test_items(self):
1✔
491
        om = self._makeOne()
1✔
492
        si1 = SimpleItem('1')
1✔
493
        om['1'] = si1
1✔
494
        self.assertIn(('1', si1), list(om.items()))
1✔
495

496
    def test_keys(self):
1✔
497
        om = self._makeOne()
1✔
498
        si1 = SimpleItem('1')
1✔
499
        om['1'] = si1
1✔
500
        self.assertIn('1', list(om.keys()))
1✔
501

502
    def test_values(self):
1✔
503
        om = self._makeOne()
1✔
504
        si1 = SimpleItem('1')
1✔
505
        om['1'] = si1
1✔
506
        self.assertIn(si1, list(om.values()))
1✔
507

508
    def test_list_imports(self):
1✔
509
        om = self._makeOne()
1✔
510
        # This must work whether we've done "make instance" or not.
511
        # So list_imports() may return an empty list, or whatever's
512
        # in skel/import. Tolerate both cases.
513
        self.assertIsInstance(om.list_imports(), list)
1✔
514
        for filename in om.list_imports():
1!
515
            self.assertIn(os.path.splitext(filename)[1], ('.zexp', '.xml'))
×
516

517
    def test_manage_get_sortedObjects_quote_id(self):
1✔
518
        # manage_get_sortedObjects now returns a urlquoted version
519
        # of the object ID to create correct links in the ZMI
520
        om = self._makeOne()
1✔
521
        hash_id = '#999'
1✔
522
        om._setObject(hash_id, SimpleItem(hash_id))
1✔
523

524
        result = om.manage_get_sortedObjects('id', 'asc')
1✔
525
        self.assertEqual(len(result), 1)
1✔
526
        self.assertEqual(result[0]['id'], hash_id)
1✔
527
        self.assertEqual(result[0]['quoted_id'], quote(hash_id))
1✔
528

529
    def test_getBookmarkableURLs(self):
1✔
530
        saved_state = getattr(getConfiguration(),
1✔
531
                              'zmi_bookmarkable_urls',
532
                              True)
533
        om = self._makeOne()
1✔
534

535
        # Configuration flag OFF
536
        getConfiguration().zmi_bookmarkable_urls = False
1✔
537
        self.assertFalse(om.getBookmarkableURLs())
1✔
538

539
        # Configuration flag ON
540
        getConfiguration().zmi_bookmarkable_urls = True
1✔
541
        self.assertTrue(om.getBookmarkableURLs())
1✔
542

543
        # Cleanup
544
        getConfiguration().zmi_bookmarkable_urls = saved_state
1✔
545

546
    def test_findChildren(self):
1✔
547
        from OFS.Folder import Folder
1✔
548
        from OFS.Image import File
1✔
549
        from OFS.ObjectManager import findChildren
1✔
550
        top = Folder("top")
1✔
551
        f1 = File("f1", "", b"")
1✔
552
        top._setObject(f1.getId(), f1)
1✔
553
        fo = Folder("fo")
1✔
554
        top._setObject(fo.getId(), fo)
1✔
555
        f2 = File("f2", "", b"")
1✔
556
        fo._setObject(f2.getId(), f2)
1✔
557
        self.assertEqual(
1✔
558
            [ci[0] for ci in findChildren(top)],
559
            ["top/f1",
560
             # surprisingly, `findChildren` ignores folderish children
561
             # "top/fo",
562
             "top/fo/f2"])
563

564
    def test_export_import(self):
1✔
565
        import tempfile
1✔
566
        from os import mkdir
1✔
567
        from os import rmdir
1✔
568
        from os import unlink
1✔
569
        from os.path import join
1✔
570
        from os.path import split
1✔
571

572
        from OFS.Folder import Folder
1✔
573
        from OFS.Image import File
1✔
574
        from transaction import commit
1✔
575
        from ZODB.DB import DB
1✔
576
        from ZODB.DemoStorage import DemoStorage
1✔
577
        try:
1✔
578
            tf = None  # temporary file required for export/import
1✔
579
            # export/import needs the object manager in ZODB
580
            s = DemoStorage()
1✔
581
            db = DB(s)
1✔
582
            c = db.open()
1✔
583
            root = c.root()
1✔
584
            top = Folder("top")
1✔
585
            f = File("f", "", b"")
1✔
586
            top._setObject(f.getId(), f)
1✔
587
            root["top"] = top
1✔
588
            tmp = Folder("tmp")
1✔
589
            top._setObject(tmp.getId(), tmp)
1✔
590
            commit()
1✔
591
            exported = top.manage_exportObject("f", True)
1✔
592
            tdir = tempfile.mkdtemp()
1✔
593
            idir = join(tdir, "import")
1✔
594
            mkdir(idir)
1✔
595
            tf = tempfile.NamedTemporaryFile(
1✔
596
                dir=idir, delete=False)
597
            tf.write(exported)
1✔
598
            tf.close()
1✔
599
            unused, tname = split(tf.name)
1✔
600
            tmp._getImportPaths = _CallResult((tdir,))
1✔
601
            tmp.manage_importObject(tname, set_owner=False,
1✔
602
                                    suppress_events=True)
603
            imp_f = tmp["f"]  # exception if import unsuccessful
1✔
604
            self.assertIsInstance(imp_f, File)
1✔
605
            commit()
1✔
606
        finally:
607
            if tf is not None:  # pragma: no cover
608
                unlink(tf.name)
609
                rmdir(idir)
610
                rmdir(tdir)
611
            c.close()
1✔
612
            db.close()
1✔
613
            s.close()
1✔
614

615

616
class _CallResult:
1✔
617
    """Auxiliary class to provide defined call results."""
618

619
    def __init__(self, result):
1✔
620
        self.result = result
1✔
621

622
    def __call__(self):
1✔
623
        return self.result
1✔
624

625

626
_marker = object()
1✔
627

628

629
class TestCheckValidId(unittest.TestCase):
1✔
630

631
    def _callFUT(self, container, id, allow_dup=_marker):
1✔
632
        from OFS.ObjectManager import checkValidId
1✔
633
        if allow_dup is _marker:
1!
634
            return checkValidId(container, id)
1✔
635
        return checkValidId(container, id, allow_dup)
×
636

637
    def _makeContainer(self):
1✔
638
        return object()
1✔
639

640
    def assertBadRequest(self, id, allow_dup=_marker):
1✔
641
        from zExceptions import BadRequest
1✔
642
        try:
1✔
643
            if allow_dup is not _marker:
1!
644
                self._callFUT(self._makeContainer(), id, allow_dup)
×
645
            else:
646
                self._callFUT(self._makeContainer(), id)
1✔
647
        except BadRequest as e:
1✔
648
            return e
1✔
649
        self.fail("Didn't raise")
650

651
    def test_empty_string(self):
1✔
652
        e = self.assertBadRequest('')
1✔
653
        self.assertEqual(str(e),
1✔
654
                         "('Empty or invalid id specified', '')")
655

656
    def test_unicode(self):
1✔
657
        self._callFUT(self._makeContainer(), 'abc☃')
1✔
658

659
    def test_encoded_unicode(self):
1✔
660
        e = self.assertBadRequest('abcö'.encode())
1✔
661
        self.assertEqual(str(e),
1✔
662
                         "('Empty or invalid id specified', "
663
                         "b'abc\\xc3\\xb6')")
664

665
    def test_unprintable_characters(self):
1✔
666
        # We do not allow the first 31 ASCII characters. \x00-\x19
667
        # We do not allow the DEL character. \x7f
668
        e = self.assertBadRequest('abc\x10')
1✔
669
        self.assertEqual(str(e),
1✔
670
                         'The id "abc\x10" contains characters illegal'
671
                         ' in URLs.')
672
        e = self.assertBadRequest('abc\x7f')
1✔
673
        self.assertEqual(str(e),
1✔
674
                         'The id "abc\x7f" contains characters illegal'
675
                         ' in URLs.')
676

677
    def test_fail_on_brackets_and_ampersand(self):
1✔
678
        # We do not allow this characters as they result in TaintedString (for
679
        # < and >) which are not allowed in hasattr.
680
        e = self.assertBadRequest('<abc>&def')
1✔
681
        self.assertEqual(str(e),
1✔
682
                         'The id "&lt;abc&gt;&amp;def" contains characters '
683
                         'illegal in URLs.')
684

685
    def test_one_dot(self):
1✔
686
        e = self.assertBadRequest('.')
1✔
687
        self.assertEqual(str(e),
1✔
688
                         'The id "." is invalid because it is not '
689
                         'traversable.')
690

691
    def test_two_dots(self):
1✔
692
        e = self.assertBadRequest('..')
1✔
693
        self.assertEqual(str(e),
1✔
694
                         'The id ".." is invalid because it is not '
695
                         'traversable.')
696

697
    def test_underscore(self):
1✔
698
        e = self.assertBadRequest('_abc')
1✔
699
        self.assertEqual(str(e),
1✔
700
                         'The id "_abc" is invalid because it begins with '
701
                         'an underscore.')
702

703
    def test_aq_(self):
1✔
704
        e = self.assertBadRequest('aq_abc')
1✔
705
        self.assertEqual(str(e),
1✔
706
                         'The id "aq_abc" is invalid because it begins with '
707
                         '"aq_".')
708

709
    def test_dunder_suffix(self):
1✔
710
        e = self.assertBadRequest('abc__')
1✔
711
        self.assertEqual(str(e),
1✔
712
                         'The id "abc__" is invalid because it ends with '
713
                         'two underscores.')
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc