AttributesHolder.__bool__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 11

Duplication

Lines 11
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 11
loc 11
rs 9.4285
1
# This Python file uses the following encoding: utf-8
2
"""
3
The :mod:`galactic.context.mixins` package defines mixins classes for defining new types of
4
contexts:
5
6
* :class:`ConcreteIndividual` for defining individuals that own their identifier as a field
7
* :class:`ConcreteAttribute` for defining attributes that own their name and their type as fields
8
* :class:`ContextHolder` for defining elements that own their context as a field
9
* :class:`PopulationHolder` for defining elements that own their population as a field
10
* :class:`ModelHolder` for defining elements that own their model as a field
11
* :class:`AttributesHolder` for defining models that own their attributes as a field
12
* :class:`IndividualsHolder` for defining population that own their individuals as a field
13
* :class:`ValuesHolder` for defining individuals that own their values as a field
14
15
They are widely used for defining
16
17
* :class:`MemoryContext <galactic.context.memory.MemoryContext>`
18
* :class:`MemoryModel <galactic.context.memory.MemoryModel>`
19
* :class:`MemoryPopulation <galactic.context.memory.MemoryPopulation>`
20
* :class:`MemoryAttribute <galactic.context.memory.MemoryAttribute>`
21
* :class:`MemoryIndividual <galactic.context.memory.MemoryIndividual>`
22
23
in the :mod:`galactic.context.memory` package.
24
25
.. versionadded:: 0.0.1
26
"""
27
28
from typing import Generic, MutableMapping, Iterator
29
30
from galactic.context import C, P, M, A, X
31
32
33
# pylint: disable=too-few-public-methods
34
class _Mixin(object):
35
    def __init__(self, **_):
36
        super().__init__()
37
38
39
# pylint: disable=too-few-public-methods,function-redefined
40
class ConcreteIndividual(_Mixin):
41
    """
42
    The :class:`ConcreteIndividual` class is a mixin used in subclassing the
43
    :class:`Individual <galactic.context.Individual>` class for storing their identifier as a field.
44
45
    .. versionadded:: 0.0.1
46
    """
47
48
    def __init__(self, **kwargs):
49
        """
50
        Initialise an individual.
51
52
        Keyword Arguments
53
        -----------------
54
            identifier : :class:`str`
55
                the individual identifier
56
57
        .. versionadded:: 0.0.1
58
        """
59
        super().__init__(**kwargs)
60
        self._identifier = kwargs['identifier']
61
62
    @property
63
    def identifier(self) -> str:
64
        """
65
        Get the individual identifier.
66
67
        Returns
68
        -------
69
            the individual identifier : :class:`str`
70
71
        .. versionadded:: 0.0.1
72
        """
73
        return self._identifier
74
75
76
# pylint: disable=too-few-public-methods
77
class ConcreteAttribute(_Mixin):
78
    """
79
    The :class:`ConcreteAttribute` class is a mixin used in subclassing the
80
    :class:`Attribute <galactic.context.Attribute>` class for storing their name and their type
81
    as a class.
82
83
    .. versionadded:: 0.0.1
84
    """
85
86
    def __init__(self, **kwargs):
87
        """
88
        Initialise an attribute
89
90
        Keyword Arguments
91
        -----------------
92
            name : :class:`str`
93
                the attribute name
94
95
            type : :class:`type <python:type>`
96
                the attribute type
97
98
        .. versionadded:: 0.0.1
99
        """
100
        super().__init__(**kwargs)
101
        self._name = kwargs['name']
102
        self._type = kwargs['type']
103
104
    @property
105
    def name(self) -> str:
106
        """
107
        Get the attribute name.
108
109
        Returns
110
        -------
111
            the attribute name : :class:`str`
112
113
        .. versionadded:: 0.0.1
114
        """
115
        return self._name
116
117
    @property
118
    def type(self) -> type:
119
        """
120
        Get the attribute type.
121
122
        Returns
123
        -------
124
            the attribute type : :class:`type <python:type>`
125
126
        .. versionadded:: 0.0.1
127
        """
128
        return self._type
129
130
131
# pylint: disable=too-few-public-methods
132
class ContextHolder(_Mixin, Generic[C]):
133
    """
134
    The :class:`ContextHolder[C] <ContextHolder>` is a mixin used for storing an element context as
135
    a field.
136
137
    It's a generic class that depends of a :class:`Context <galactic.context.Context>` subclass
138
    :class:`C`.
139
140
    .. versionadded:: 0.0.1
141
    """
142
143
    def __init__(self, **kwargs):
144
        """
145
        Initialise an element by setting its context.
146
147
        Keyword Arguments
148
        -----------------
149
            context : :class:`C`
150
                the context
151
152
        .. versionadded:: 0.0.1
153
        """
154
        super().__init__(**kwargs)
155
        self._context = kwargs['context']
156
157
    # noinspection PyTypeChecker
158
    @property
159
    def context(self) -> C:
160
        """
161
        Get the context.
162
163
        Returns
164
        -------
165
            the context : :class:`C`
166
167
        .. versionadded:: 0.0.1
168
        """
169
        return self._context
170
171
172
# pylint: disable=too-few-public-methods
173
class PopulationHolder(_Mixin, Generic[P]):
174
    """
175
    The :class:`PopulationHolder[P] <PopulationHolder>` is a mixin used for storing an element
176
    population as a field.
177
178
    It's a generic class that depends of a :class:`Population <galactic.context.Population>`
179
    subclass :class:`P`.
180
181
    .. versionadded:: 0.0.1
182
    """
183
184
    def __init__(self, **kwargs):
185
        """
186
        Initialise an element by setting its population.
187
188
        Keyword Arguments
189
        -----------------
190
            population: :class:`P`
191
                the population
192
193
        .. versionadded:: 0.0.1
194
        """
195
        super().__init__(**kwargs)
196
        self._population = kwargs['population']
197
198
    # noinspection PyTypeChecker
199
    @property
200
    def population(self) -> P:
201
        """
202
        Get the population.
203
204
        Returns
205
        -------
206
            the population : :class:`P`
207
208
        .. versionadded:: 0.0.1
209
        """
210
        return self._population
211
212
213
# pylint: disable=too-few-public-methods
214
class ModelHolder(_Mixin, Generic[M]):
215
    """
216
    The :class:`ModelHolder[M] <ModelHolder>` class is a mixin used for storing an element model as
217
    a field.
218
219
    It's a generic class that depends of a :class:`Model <galactic.context.Model>` subclass
220
    :class:`M`.
221
222
    .. versionadded:: 0.0.1
223
    """
224
225
    def __init__(self, **kwargs):
226
        """
227
        Initialise an element by setting its model.
228
229
        Keyword Arguments
230
        -----------------
231
            model : :class:`M`
232
                the model
233
234
        .. versionadded:: 0.0.1
235
        """
236
        super().__init__(**kwargs)
237
        self._model = kwargs['model']
238
239
    # noinspection PyTypeChecker
240
    @property
241
    def model(self) -> M:
242
        """
243
        Get the model.
244
245
        Returns
246
        -------
247
            the model : :class:`M`
248
249
        .. versionadded:: 0.0.1
250
        """
251
        return self._model
252
253
254
# pylint: disable=too-few-public-methods
255 View Code Duplication
class AttributesHolder(_Mixin, Generic[A], MutableMapping[str, A]):
256
    """
257
    The :class:`AttributesHolder[A] <AttributesHolder>` class is a mixin used for storing the model
258
    attributes in memory.
259
260
    It's a generic class that depends of an :class:`Attribute <galactic.context.Attribute>`
261
    subclass :class:`A`.
262
263
    .. versionadded:: 0.0.1
264
    """
265
266
    def __init__(self, **kwargs):
267
        """
268
        Initialise an attribute holder.
269
270
        Keyword Arguments
271
        -----------------
272
            attributes : :class:`Iterable[A] <python:collections.abc.Iterable>`
273
                the attributes
274
275
        .. versionadded:: 0.0.1
276
        """
277
        super().__init__(**kwargs)
278
        self._attributes = {attribute.name: attribute for attribute in kwargs['attributes']}
279
280
    def __getitem__(self, name: str) -> A:
281
        """
282
        Get an attribute using its name
283
284
        Parameters
285
        ----------
286
            name : :class:`str`
287
                the attribute name
288
289
        Returns
290
        -------
291
            the attribute : A
292
293
        Raises
294
        ------
295
            KeyError
296
                if this attributes holder does not contain an attribute with this name.
297
298
        .. versionadded:: 0.0.1
299
        """
300
        return self._attributes[name]
301
302
    def __setitem__(self, name: str, attribute: A) -> None:
303
        """
304
        Set an attribute using its name
305
306
        Parameters
307
        ----------
308
            name : :class:`str`
309
                the attribute name
310
            attribute: :class:`A`
311
312
        .. versionadded:: 0.0.1
313
        """
314
        self._attributes[name] = attribute
315
316
    def __delitem__(self, name: str) -> None:
317
        """
318
        Delete an attribute using its name
319
320
        Parameters
321
        ----------
322
            name : :class:`str`
323
                the attribute name
324
325
        Raises
326
        ------
327
            KeyError
328
                if this attributes holder does not contain an attribute with this name.
329
330
        .. versionadded:: 0.0.1
331
        """
332
        del self._attributes[name]
333
334
    def __iter__(self) -> Iterator[str]:
335
        """
336
        Get an iterator over the attribute names.
337
338
        Returns
339
        -------
340
            an iterator : :class:`Iterator[str] <python:collections.abc.Iterator>`
341
342
        .. versionadded:: 0.0.1
343
        """
344
        return iter(self._attributes)
345
346
    def __len__(self) -> int:
347
        """
348
        Get the number of attributes.
349
350
        Returns
351
        -------
352
            the number of attributes : :class:`int`
353
354
        .. versionadded:: 0.0.1
355
        """
356
        return len(self._attributes)
357
358
    def __bool__(self):
359
        """
360
        Get the boolean value of an attribute holder.
361
362
        Returns
363
        -------
364
            the boolean value : :class:`bool`
365
366
        .. versionadded:: 0.0.1
367
        """
368
        return bool(self._attributes)
369
370
371
# pylint: disable=too-few-public-methods
372 View Code Duplication
class IndividualsHolder(_Mixin, Generic[X], MutableMapping[str, X]):
373
    """
374
    The :class:`IndividualsHolder[X] <IndividualsHolder>` class  is a mixin used for storing the
375
    population individuals in memory.
376
377
    It's a generic class that depends of an :class:`Individual <galactic.context.Individual>`
378
    subclass :class:`X`.
379
380
    .. versionadded:: 0.0.1
381
    """
382
383
    def __init__(self, **kwargs):
384
        """
385
        Initialise an individuals holder.
386
387
        Keyword Arguments
388
        -----------------
389
            individuals : :class:`Iterable[A] <python:collections.abc.Iterable>`
390
                the individuals
391
392
        .. versionadded:: 0.0.1
393
        """
394
        super().__init__(**kwargs)
395
        self._individuals = {individual.identifier: individual for individual in
396
                             kwargs['individuals']}
397
398
    def __getitem__(self, identifier: str) -> X:
399
        """
400
        Get an individual using its identifier.
401
402
        Parameters
403
        ----------
404
            identifier : :class:`str`
405
                the individual identifier
406
407
        Returns
408
        -------
409
            the individual : :class: `X`
410
411
        Raises
412
        ------
413
            KeyError
414
                if the identifier does not belong to the individuals holder.
415
416
        .. versionadded:: 0.0.1
417
        """
418
        return self._individuals[identifier]
419
420
    def __delitem__(self, identifier: str) -> None:
421
        """
422
        Delete an individual using its identifier.
423
424
        Parameters
425
        ----------
426
            identifier : :class:`str`
427
                the individual identifier
428
429
        Raises
430
        ------
431
            KeyError
432
                if the identifier does not belong to the individuals holder.
433
434
        .. versionadded:: 0.0.1
435
        """
436
        del self._individuals[identifier]
437
438
    def __setitem__(self, identifier: str, individual: X) -> None:
439
        """
440
        Set an individual using its identifier.
441
442
        Parameters
443
        ----------
444
            identifier : :class:`str`
445
                the individual identifier
446
447
            individual: :class:`X`
448
                an individual
449
450
        .. versionadded:: 0.0.1
451
        """
452
        self._individuals[identifier] = individual
453
454
    def __iter__(self) -> Iterator[str]:
455
        """
456
        Get an iterator over the individual identifiers.
457
458
        Returns
459
        -------
460
            an iterator : :class:`Iterator[str] <python:collections.abc.Iterator>`
461
462
        .. versionadded:: 0.0.1
463
        """
464
        return iter(self._individuals)
465
466
    def __len__(self) -> int:
467
        """
468
        Get the number of individuals.
469
470
        Returns
471
        -------
472
            the number of indidivuals : :class:`int`
473
474
        .. versionadded:: 0.0.1
475
        """
476
        return len(self._individuals)
477
478
    def __bool__(self) -> bool:
479
        """
480
        Get the boolean representation of the individuals holder.
481
482
        Returns
483
        -------
484
            the boolean representation : :class:`bool`
485
486
        .. versionadded:: 0.0.1
487
        """
488
        return bool(self._individuals)
489
490
491
# pylint: disable=too-few-public-methods
492
class ValuesHolder(_Mixin):
493
    """
494
    The :class:`ValuesHolder[A] <ValuesHolder>` class is a mixin for storing the individual values
495
    in memory.
496
497
    It's a generic class that depends of an :class:`Attribute <galactic.context.Attribute>` subclass
498
    :class:`A`.
499
500
    .. versionadded:: 0.0.1
501
    """
502
503
    def __init__(self, **kwargs):
504
        """
505
        Initialise a values holder.
506
507
        Keyword Arguments
508
        -----------------
509
            values : :class:`Mapping[str, object] <python:collections.abc.Mapping>`
510
                the initial (name, value) pairs
511
512
        .. versionadded:: 0.0.1
513
        """
514
        super().__init__(**kwargs)
515
        self._values = {name: value for name, value in kwargs['values'].items()}
516
517
    def __getitem__(self, name: str) -> object:
518
        """
519
        Get a value using the attribute name.
520
521
        Parameters
522
        ----------
523
            name : :class:`str`
524
                the attribute name
525
526
        Returns
527
        -------
528
            the value : :class:`object`
529
530
        Raises
531
        ------
532
            KeyError
533
                if the name does not belong to the values holder.
534
535
        .. versionadded:: 0.0.1
536
        """
537
        return self._values[name]
538
539
    def __setitem__(self, name: str, value) -> None:
540
        """
541
        Set the value of an attribute.
542
543
        Parameters
544
        ----------
545
            name : :class:`str`
546
                the attribute name
547
            value : :class:`object`
548
                the new value
549
550
        .. versionadded:: 0.0.1
551
        """
552
        self._values[name] = value
553
554
    def __delitem__(self, name: str):
555
        """
556
        Delete a value using the attribute name.
557
558
        Parameters
559
        ----------
560
            name : :class:`str`
561
                the attribute name
562
563
        Raises
564
        ------
565
            KeyError
566
                if the name does not belong to the values holder.
567
568
        .. versionadded:: 0.0.1
569
        """
570
        del self._values[name]
571