Coverage for tests/test_000_accretive/test_300_namespaces.py: 100%
161 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-06 17:17 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-06 17:17 +0000
1# vim: set filetype=python fileencoding=utf-8:
2# -*- coding: utf-8 -*-
4#============================================================================#
5# #
6# Licensed under the Apache License, Version 2.0 (the "License"); #
7# you may not use this file except in compliance with the License. #
8# You may obtain a copy of the License at #
9# #
10# http://www.apache.org/licenses/LICENSE-2.0 #
11# #
12# Unless required by applicable law or agreed to in writing, software #
13# distributed under the License is distributed on an "AS IS" BASIS, #
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15# See the License for the specific language governing permissions and #
16# limitations under the License. #
17# #
18#============================================================================#
21''' Assert correct function of namespaces. '''
23# mypy: ignore-errors
24# pylint: disable=attribute-defined-outside-init
25# pylint: disable=invalid-name,magic-value-comparison,protected-access
28import pytest
30from itertools import product
32from . import (
33 CONCEALMENT_PACKAGES_NAMES,
34 MODULES_QNAMES,
35 PACKAGE_NAME,
36 PROTECTION_PACKAGES_NAMES,
37 cache_import_module,
38)
41THESE_MODULE_QNAMES = tuple(
42 name for name in MODULES_QNAMES if name.endswith( '.namespaces' ) )
43THESE_CONCEALMENT_MODULE_QNAMES = tuple(
44 name for name in THESE_MODULE_QNAMES
45 if name.startswith( CONCEALMENT_PACKAGES_NAMES ) )
46THESE_NONCONCEALMENT_MODULE_QNAMES = tuple(
47 name for name in THESE_MODULE_QNAMES
48 if not name.startswith( CONCEALMENT_PACKAGES_NAMES ) )
49THESE_PROTECTION_MODULE_QNAMES = tuple(
50 name for name in THESE_MODULE_QNAMES
51 if name.startswith( PROTECTION_PACKAGES_NAMES ) )
52THESE_NONPROTECTION_MODULE_QNAMES = tuple(
53 name for name in THESE_MODULE_QNAMES
54 if not name.startswith( PROTECTION_PACKAGES_NAMES ) )
55THESE_CLASSES_NAMES = ( 'Namespace', )
57base = cache_import_module( f"{PACKAGE_NAME}.__" )
58exceptions = cache_import_module( f"{PACKAGE_NAME}.exceptions" )
61@pytest.mark.parametrize(
62 'module_qname, class_name',
63 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
64)
65def test_100_instantiation( module_qname, class_name ):
66 ''' Class instantiates. '''
67 module = cache_import_module( module_qname )
68 Namespace = getattr( module, class_name )
69 ns1 = Namespace( )
70 assert isinstance( ns1, Namespace )
71 ns2 = Namespace(
72 ( ( 'foo', 1 ), ( 'bar', 2 ) ), { 'unicorn': True }, orb = False )
73 assert isinstance( ns2, Namespace )
74 assert 1 == ns2.foo
75 assert 2 == ns2.bar
76 assert ns2.unicorn
77 assert not ns2.orb
78 assert ( 'foo', 'bar', 'unicorn', 'orb' ) == tuple( ns2.__dict__.keys( ) )
79 assert ( 1, 2, True, False ) == tuple( ns2.__dict__.values( ) )
82@pytest.mark.parametrize(
83 'module_qname, class_name',
84 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
85)
86def test_101_accretion( module_qname, class_name ):
87 ''' Namespace accretes attributes. '''
88 module = cache_import_module( module_qname )
89 Object = getattr( module, class_name )
90 obj = Object( )
91 obj.attr = 42
92 with pytest.raises( exceptions.IndelibleAttributeError ):
93 obj.attr = -1
94 assert 42 == obj.attr
95 with pytest.raises( exceptions.IndelibleAttributeError ):
96 del obj.attr
97 assert 42 == obj.attr
100@pytest.mark.parametrize(
101 'module_qname, class_name',
102 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
103)
104def test_102_string_representation( module_qname, class_name ):
105 ''' Namespace has expected string representations. '''
106 module = cache_import_module( module_qname )
107 factory = getattr( module, class_name )
108 obj = factory( )
109 assert base.discover_fqname( obj ) in repr( obj )
110 obj.a = 1
111 obj.b = 2
112 assert 'a = 1, b = 2' in repr( obj )
115@pytest.mark.parametrize(
116 'module_qname, class_name',
117 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
118)
119def test_105_dictionary_equality( module_qname, class_name ):
120 ''' Dictionary is equivalent to another dictionary with same values. '''
121 from types import SimpleNamespace
122 module = cache_import_module( module_qname )
123 factory = getattr( module, class_name )
124 ns1 = factory( foo = 1, bar = 2 )
125 ns2 = factory( ns1.__dict__ )
126 ns3 = SimpleNamespace( **ns1.__dict__ )
127 assert ns1 == ns2
128 assert ns2 == ns1
129 assert ns1 == ns3
130 assert ns3 == ns1
131 assert not ( ns1 == -1 ) # pylint: disable=superfluous-parens
132 assert ns1 != -1
133 assert ns1 != ( )
134 ns2.baz = 43
135 assert ns1 != ns2
136 assert ns2 != ns1
139@pytest.mark.parametrize(
140 'module_qname, class_name',
141 product( THESE_CONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES )
142)
143def test_110_attribute_concealment( module_qname, class_name ):
144 ''' Namespace conceals attributes. '''
145 module = cache_import_module( module_qname )
146 Object = getattr( module, class_name )
148 class Concealer( Object ):
149 ''' test '''
150 _attribute_visibility_includes_ = frozenset( ( '_private', ) )
152 obj = Concealer( )
153 assert not dir( obj )
154 obj.public = 42
155 assert 'public' in dir( obj )
156 obj._nonpublic = 3.1415926535
157 assert '_nonpublic' not in dir( obj )
158 assert '_private' not in dir( obj )
159 obj._private = 'foo'
160 assert '_private' in dir( obj )
163@pytest.mark.parametrize(
164 'module_qname, class_name',
165 product( THESE_NONCONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES )
166)
167def test_111_attribute_nonconcealment( module_qname, class_name ):
168 ''' Namespace does not conceal attributes. '''
169 module = cache_import_module( module_qname )
170 Object = getattr( module, class_name )
172 class Concealer( Object ):
173 ''' test '''
174 _attribute_visibility_includes_ = frozenset( ( '_private', ) )
176 obj = Concealer( )
177 assert '_attribute_visibility_includes_' in dir( obj )
178 obj.public = 42
179 assert 'public' in dir( obj )
180 obj._nonpublic = 3.1415926535
181 assert '_nonpublic' in dir( obj )
182 assert '_private' not in dir( obj )
183 obj._private = 'foo'
184 assert '_private' in dir( obj )
187@pytest.mark.parametrize(
188 'module_qname, class_name',
189 product( THESE_PROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES )
190)
191def test_150_class_attribute_protection( module_qname, class_name ):
192 ''' Class attributes are protected. '''
193 module = cache_import_module( module_qname )
194 Object = getattr( module, class_name )
195 with pytest.raises( exceptions.IndelibleAttributeError ):
196 Object.__setattr__ = None
197 with pytest.raises( exceptions.IndelibleAttributeError ):
198 del Object.__setattr__
199 Object.foo = 42
200 with pytest.raises( exceptions.IndelibleAttributeError ):
201 Object.foo = -1
202 with pytest.raises( exceptions.IndelibleAttributeError ):
203 del Object.foo
204 # Cleanup.
205 type.__delattr__( Object, 'foo' )
208@pytest.mark.parametrize(
209 'module_qname, class_name',
210 product( THESE_NONPROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES )
211)
212def test_151_class_attribute_nonprotection( module_qname, class_name ):
213 ''' Class attributes are not protected. '''
214 module = cache_import_module( module_qname )
215 Object = getattr( module, class_name )
216 Object.foo = 42
217 assert 42 == Object.foo
218 Object.foo = -1
219 assert -1 == Object.foo
220 del Object.foo
221 assert not hasattr( Object, 'foo' )
224@pytest.mark.parametrize(
225 'module_qname, class_name',
226 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
227)
228def test_900_docstring_sanity( module_qname, class_name ):
229 ''' Class has valid docstring. '''
230 module = cache_import_module( module_qname )
231 Object = getattr( module, class_name )
232 assert hasattr( Object, '__doc__' )
233 assert isinstance( Object.__doc__, str )
234 assert Object.__doc__
237@pytest.mark.parametrize(
238 'module_qname, class_name',
239 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
240)
241def test_901_docstring_describes_namespace( module_qname, class_name ):
242 ''' Class docstring describes namespace. '''
243 module = cache_import_module( module_qname )
244 Object = getattr( module, class_name )
245 fragment = base.generate_docstring( 'description of namespace' )
246 assert fragment in Object.__doc__
249@pytest.mark.parametrize(
250 'module_qname, class_name',
251 product( THESE_MODULE_QNAMES, THESE_CLASSES_NAMES )
252)
253def test_902_docstring_mentions_accretion( module_qname, class_name ):
254 ''' Class docstring mentions accretion. '''
255 module = cache_import_module( module_qname )
256 Object = getattr( module, class_name )
257 fragment = base.generate_docstring( 'instance attributes accretion' )
258 assert fragment in Object.__doc__
261@pytest.mark.parametrize(
262 'module_qname, class_name',
263 product( THESE_CONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES )
264)
265def test_910_docstring_mentions_concealment( module_qname, class_name ):
266 ''' Class docstring mentions concealment. '''
267 module = cache_import_module( module_qname )
268 Object = getattr( module, class_name )
269 fragment = base.generate_docstring( 'instance attributes concealment' )
270 assert fragment in Object.__doc__
273@pytest.mark.parametrize(
274 'module_qname, class_name',
275 product( THESE_NONCONCEALMENT_MODULE_QNAMES, THESE_CLASSES_NAMES )
276)
277def test_911_docstring_not_mentions_concealment( module_qname, class_name ):
278 ''' Class docstring does not mention concealment. '''
279 module = cache_import_module( module_qname )
280 Object = getattr( module, class_name )
281 fragment = base.generate_docstring( 'instance attributes concealment' )
282 assert fragment not in Object.__doc__
285@pytest.mark.parametrize(
286 'module_qname, class_name',
287 product( THESE_PROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES )
288)
289def test_930_docstring_mentions_protection( module_qname, class_name ):
290 ''' Class docstring mentions protection. '''
291 module = cache_import_module( module_qname )
292 Object = getattr( module, class_name )
293 fragment = base.generate_docstring( 'protection of class' )
294 assert fragment in Object.__doc__
297@pytest.mark.parametrize(
298 'module_qname, class_name',
299 product( THESE_NONPROTECTION_MODULE_QNAMES, THESE_CLASSES_NAMES )
300)
301def test_931_docstring_not_mentions_protection( module_qname, class_name ):
302 ''' Class docstring does not mention protection. '''
303 module = cache_import_module( module_qname )
304 Object = getattr( module, class_name )
305 fragment = base.generate_docstring( 'protection of class' )
306 assert fragment not in Object.__doc__