enumerific 1.0.2__tar.gz → 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {enumerific-1.0.2/source/enumerific.egg-info → enumerific-1.0.3}/PKG-INFO +97 -29
  2. {enumerific-1.0.2 → enumerific-1.0.3}/README.md +96 -28
  3. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific/__init__.py +8 -1
  4. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific/exceptions.py +4 -0
  5. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific/extensible.py +121 -22
  6. enumerific-1.0.3/source/enumerific/version.txt +1 -0
  7. {enumerific-1.0.2 → enumerific-1.0.3/source/enumerific.egg-info}/PKG-INFO +97 -29
  8. {enumerific-1.0.2 → enumerific-1.0.3}/tests/test_extensible_enums.py +242 -1
  9. enumerific-1.0.2/source/enumerific/version.txt +0 -1
  10. {enumerific-1.0.2 → enumerific-1.0.3}/LICENSE.md +0 -0
  11. {enumerific-1.0.2 → enumerific-1.0.3}/pyproject.toml +0 -0
  12. {enumerific-1.0.2 → enumerific-1.0.3}/requirements.development.txt +0 -0
  13. {enumerific-1.0.2 → enumerific-1.0.3}/requirements.distribution.txt +0 -0
  14. {enumerific-1.0.2 → enumerific-1.0.3}/requirements.txt +0 -0
  15. {enumerific-1.0.2 → enumerific-1.0.3}/setup.cfg +0 -0
  16. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific/logging.py +0 -0
  17. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific/standard.py +0 -0
  18. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific.egg-info/SOURCES.txt +0 -0
  19. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific.egg-info/dependency_links.txt +0 -0
  20. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific.egg-info/requires.txt +0 -0
  21. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific.egg-info/top_level.txt +0 -0
  22. {enumerific-1.0.2 → enumerific-1.0.3}/source/enumerific.egg-info/zip-safe +0 -0
  23. {enumerific-1.0.2 → enumerific-1.0.3}/tests/test_enumerific_library.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: enumerific
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Simplifies working with Python enums.
5
5
  Author: Daniel Sissman
6
6
  License-Expression: MIT
@@ -41,8 +41,9 @@ The Enumerific library's `Enumeration` class offers the following features:
41
41
  * Enumerific enumerations options can be added after an `Enumeration` class has been created either through extending an existing enumerations class by subclassing or by registering new options directly on an existing enumerations class via the `.register()` method; this is especially useful for cases where enumeration options may not all be known prior to runtime;
42
42
  * Enumerific enumerations options can be removed after an `Enumeration` class has been created via the `.unregister()` method; this specialised behaviour is prevented by default, but can be enabled for advanced use cases;
43
43
  * Enforcement of unique values for all options within an enumeration, unless overridden;
44
- * Support for aliasing enumeration options;
45
- * Support for redefining enumeration options;
44
+ * Support for aliasing enumeration options, and control over this behaviour;
45
+ * Support for backfilling enumeration options on a superclass when subclassing, and control over this behaviour
46
+ * Support for redefining enumeration options, and control over this behaviour;
46
47
  * Support for automatically generating unique number sequences for enumeration options, including powers of two for bitwise enumeration flags, as well as other sequences such as powers of other numbers and factoring;
47
48
  * Support for annotating enumeration options with additional arbitrary key-value pairs, which can be particularly useful for associating additional data with a given enumeration option, which may be accessed later anywhere in code that the enumeration option is available;
48
49
  * Simple one-line reconciliation of `Enumeration` class options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;
@@ -253,7 +254,7 @@ for value in Colors.values():
253
254
  print(value)
254
255
  ```
255
256
 
256
- #### Example 8: Registering New Option
257
+ #### Example 8: Registering New Options
257
258
 
258
259
  ```python
259
260
  from enumerific import Enumeration
@@ -264,11 +265,17 @@ class Colors(Enumeration):
264
265
  BLUE = 3
265
266
 
266
267
  Colors.register("PURPLE", 4)
268
+ Colors.register("GOLD", 5)
267
269
 
268
270
  assert "PURPLE" in Colors
269
271
  assert Colors.PURPLE.name == "PURPLE"
270
272
  assert Colors.PURPLE.value == 4
271
273
  assert Colors.PURPLE == 4
274
+
275
+ assert "GOLD" in Colors
276
+ assert Colors.GOLD.name == "GOLD"
277
+ assert Colors.GOLD.value == 5
278
+ assert Colors.GOLD == 5
272
279
  ```
273
280
 
274
281
  #### Example 9: Subclassing
@@ -281,27 +288,64 @@ class Colors(Enumeration):
281
288
  GREEN = 2
282
289
  BLUE = 3
283
290
 
291
+ # Ensure that Colors has the expected options
292
+ assert "RED" in Colors
293
+ assert "GREEN" in Colors
294
+ assert "BLUE" in Colors
295
+
296
+ # Create a subclass of Colors, inheriting its options
284
297
  class MoreColors(Colors):
285
298
  PURPLE = 4
286
299
  GOLD = 5
287
300
 
301
+ # Ensure that MoreColors inherited the options from Colors, as well as adding its own
302
+ assert "RED" in MoreColors
303
+ assert "GREEN" in MoreColors
304
+ assert "BLUE" in MoreColors
305
+ assert "PURPLE" in MoreColors
306
+ assert "GOLD" in MoreColors
307
+
308
+ # As backfilling is off by default subclass options won't be available on the superclass
309
+ assert not "PURPLE" in Colors
310
+ assert not "GOLD" in Colors
311
+ ```
312
+
313
+ #### Example 10: Subclassing with Backfilling
314
+
315
+ ```python
316
+ from enumerific import Enumeration
317
+
318
+ # To override the default behaviour and to allow backfilling of options from subclasses,
319
+ # the `backfill` keyword argument can be set to `True` when creating the class. This
320
+ # effectively creates another way to extend an existing enumeration class through
321
+ # subclassing and its side-effect of backfilling, compared to using the `.register()`
322
+ # method to add new options to an existing enumeration class:
323
+ class Colors(Enumeration, backfill=True):
324
+ RED = 1
325
+ GREEN = 2
326
+ BLUE = 3
327
+
328
+ assert "RED" in Colors
329
+ assert "GREEN" in Colors
288
330
  assert "BLUE" in Colors
289
- assert Colors.BLUE.name == "BLUE"
290
- assert Colors.BLUE.value == 3
291
- assert Colors.BLUE == 3
292
331
 
332
+ class MoreColors(Colors):
333
+ PURPLE = 4
334
+ GOLD = 5
335
+
336
+ assert "RED" in MoreColors
337
+ assert "GREEN" in MoreColors
338
+ assert "BLUE" in MoreColors
293
339
  assert "PURPLE" in MoreColors
294
- assert MoreColors.PURPLE.name == "PURPLE"
295
- assert MoreColors.PURPLE.value == 4
296
- assert MoreColors.PURPLE == 4
340
+ assert "GOLD" in MoreColors
297
341
 
342
+ # As backfilling has been enabled for the superclass, subclass options are available on
343
+ # both the subclass as seen above as well as on the superclass through backfilling:
344
+ assert "PURPLE" in Colors
298
345
  assert "GOLD" in Colors
299
- assert Colors.GOLD.name == "GOLD"
300
- assert Colors.GOLD.value == 5
301
- assert Colors.GOLD == 5
302
346
  ```
303
347
 
304
- #### Example 10: Subclassing Over
348
+ #### Example 11: Subclassing Over
305
349
 
306
350
  ```python
307
351
  from enumerific import Enumeration
@@ -311,29 +355,34 @@ class Colors(Enumeration):
311
355
  GREEN = 2
312
356
  BLUE = 3
313
357
 
314
- # Subclassed Enumerations can have the same name as the parent class
315
- # The subclass will inherit the enumeration options of its parent
358
+ assert "RED" in Colors
359
+ assert Colors.RED == 1
360
+
361
+ assert "GREEN" in Colors
362
+ assert Colors.GREEN == 2
363
+
364
+ assert "BLUE" in Colors
365
+ assert Colors.BLUE == 3
366
+
367
+ # Subclasses of Enumerations classes can be given the same name as the parent class, so
368
+ # within this scope, the subclass shadows the superclass; the subclass inherits all the
369
+ # enumeration options of its parent(s) superclasses:
316
370
  class Colors(Colors):
317
371
  PURPLE = 4
318
372
  GOLD = 5
319
373
 
374
+ assert "RED" in Colors
375
+ assert "GREEN" in Colors
320
376
  assert "BLUE" in Colors
321
- assert Colors.BLUE.name == "BLUE"
322
- assert Colors.BLUE.value == 3
323
- assert Colors.BLUE == 3
324
377
 
325
378
  assert "PURPLE" in Colors
326
- assert Colors.PURPLE.name == "PURPLE"
327
- assert Colors.PURPLE.value == 4
328
379
  assert Colors.PURPLE == 4
329
380
 
330
381
  assert "GOLD" in Colors
331
- assert Colors.GOLD.name == "GOLD"
332
- assert Colors.GOLD.value == 5
333
382
  assert Colors.GOLD == 5
334
383
  ```
335
384
 
336
- #### Example 11: Unregistering Existing Option
385
+ #### Example 12: Unregistering Existing Option
337
386
 
338
387
  ```python
339
388
  from enumerific import Enumeration
@@ -352,7 +401,26 @@ assert "GREEN" not in Colors
352
401
  assert "BLUE" in Colors
353
402
  ```
354
403
 
355
- #### Example 12: Aliasing Options
404
+ #### Example 13: Preventing Subclassing of Enumeration Classes
405
+
406
+ ```python
407
+ from enumerific import Enumeration, EnumerationSubclassingError
408
+ import pytest
409
+
410
+ # To prevent an enumeration class from being extended through subclassing, the
411
+ # `subclassable` keyword argument can be set when creating the class; this will
412
+ # result in an `EnumerationSubclassingError` exception being raised on subclassing:
413
+ class Colors(Enumeration, subclassable=False):
414
+ RED = 1
415
+ GREEN = 2
416
+ BLUE = 3
417
+
418
+ with pytest.raises(EnumerationSubclassingError):
419
+ class MoreColors(Colors):
420
+ PURPLE = 4
421
+ ```
422
+
423
+ #### Example 14: Aliasing Options
356
424
 
357
425
  ```python
358
426
  from enumerific import Enumeration
@@ -402,7 +470,7 @@ assert Colors.GREEN.aliases == [Colors.VERTE]
402
470
  assert Colors.BLUE.aliases == [] # BLUE has not been aliased
403
471
  ```
404
472
 
405
- #### Example 13: Non-Unique Options
473
+ #### Example 15: Non-Unique Options
406
474
 
407
475
  ```python
408
476
  from enumerific import Enumeration
@@ -441,7 +509,7 @@ assert Colors.RED == Colors.GREEN
441
509
  assert Colors.BLUE != Colors.RED
442
510
  ```
443
511
 
444
- #### Example 14: Bit Wise Flags
512
+ #### Example 16: Bit Wise Flags
445
513
 
446
514
  ```python
447
515
  from enumerific import Enumeration
@@ -513,7 +581,7 @@ assert Permissions.DELETE in permissions
513
581
  assert str(permissions) == "Permissions.READ|WRITE|DELETE"
514
582
  ```
515
583
 
516
- #### Example 15: Annotating Enumeration Option Values
584
+ #### Example 17: Annotating Enumeration Option Values
517
585
 
518
586
  ```python
519
587
  from enumerific import Enumeration, anno
@@ -557,7 +625,7 @@ assert Colors.PURPLE.rgb == (255, 0, 255)
557
625
  assert Colors.PURPLE.primary is False
558
626
  ```
559
627
 
560
- #### Example 16: Annotating Enumeration Option Values with Automatic Sequencing
628
+ #### Example 18: Annotating Enumeration Option Values with Automatic Sequencing
561
629
 
562
630
  ```python
563
631
  from enumerific import Enumeration, auto
@@ -11,8 +11,9 @@ The Enumerific library's `Enumeration` class offers the following features:
11
11
  * Enumerific enumerations options can be added after an `Enumeration` class has been created either through extending an existing enumerations class by subclassing or by registering new options directly on an existing enumerations class via the `.register()` method; this is especially useful for cases where enumeration options may not all be known prior to runtime;
12
12
  * Enumerific enumerations options can be removed after an `Enumeration` class has been created via the `.unregister()` method; this specialised behaviour is prevented by default, but can be enabled for advanced use cases;
13
13
  * Enforcement of unique values for all options within an enumeration, unless overridden;
14
- * Support for aliasing enumeration options;
15
- * Support for redefining enumeration options;
14
+ * Support for aliasing enumeration options, and control over this behaviour;
15
+ * Support for backfilling enumeration options on a superclass when subclassing, and control over this behaviour
16
+ * Support for redefining enumeration options, and control over this behaviour;
16
17
  * Support for automatically generating unique number sequences for enumeration options, including powers of two for bitwise enumeration flags, as well as other sequences such as powers of other numbers and factoring;
17
18
  * Support for annotating enumeration options with additional arbitrary key-value pairs, which can be particularly useful for associating additional data with a given enumeration option, which may be accessed later anywhere in code that the enumeration option is available;
18
19
  * Simple one-line reconciliation of `Enumeration` class options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;
@@ -223,7 +224,7 @@ for value in Colors.values():
223
224
  print(value)
224
225
  ```
225
226
 
226
- #### Example 8: Registering New Option
227
+ #### Example 8: Registering New Options
227
228
 
228
229
  ```python
229
230
  from enumerific import Enumeration
@@ -234,11 +235,17 @@ class Colors(Enumeration):
234
235
  BLUE = 3
235
236
 
236
237
  Colors.register("PURPLE", 4)
238
+ Colors.register("GOLD", 5)
237
239
 
238
240
  assert "PURPLE" in Colors
239
241
  assert Colors.PURPLE.name == "PURPLE"
240
242
  assert Colors.PURPLE.value == 4
241
243
  assert Colors.PURPLE == 4
244
+
245
+ assert "GOLD" in Colors
246
+ assert Colors.GOLD.name == "GOLD"
247
+ assert Colors.GOLD.value == 5
248
+ assert Colors.GOLD == 5
242
249
  ```
243
250
 
244
251
  #### Example 9: Subclassing
@@ -251,27 +258,64 @@ class Colors(Enumeration):
251
258
  GREEN = 2
252
259
  BLUE = 3
253
260
 
261
+ # Ensure that Colors has the expected options
262
+ assert "RED" in Colors
263
+ assert "GREEN" in Colors
264
+ assert "BLUE" in Colors
265
+
266
+ # Create a subclass of Colors, inheriting its options
254
267
  class MoreColors(Colors):
255
268
  PURPLE = 4
256
269
  GOLD = 5
257
270
 
271
+ # Ensure that MoreColors inherited the options from Colors, as well as adding its own
272
+ assert "RED" in MoreColors
273
+ assert "GREEN" in MoreColors
274
+ assert "BLUE" in MoreColors
275
+ assert "PURPLE" in MoreColors
276
+ assert "GOLD" in MoreColors
277
+
278
+ # As backfilling is off by default subclass options won't be available on the superclass
279
+ assert not "PURPLE" in Colors
280
+ assert not "GOLD" in Colors
281
+ ```
282
+
283
+ #### Example 10: Subclassing with Backfilling
284
+
285
+ ```python
286
+ from enumerific import Enumeration
287
+
288
+ # To override the default behaviour and to allow backfilling of options from subclasses,
289
+ # the `backfill` keyword argument can be set to `True` when creating the class. This
290
+ # effectively creates another way to extend an existing enumeration class through
291
+ # subclassing and its side-effect of backfilling, compared to using the `.register()`
292
+ # method to add new options to an existing enumeration class:
293
+ class Colors(Enumeration, backfill=True):
294
+ RED = 1
295
+ GREEN = 2
296
+ BLUE = 3
297
+
298
+ assert "RED" in Colors
299
+ assert "GREEN" in Colors
258
300
  assert "BLUE" in Colors
259
- assert Colors.BLUE.name == "BLUE"
260
- assert Colors.BLUE.value == 3
261
- assert Colors.BLUE == 3
262
301
 
302
+ class MoreColors(Colors):
303
+ PURPLE = 4
304
+ GOLD = 5
305
+
306
+ assert "RED" in MoreColors
307
+ assert "GREEN" in MoreColors
308
+ assert "BLUE" in MoreColors
263
309
  assert "PURPLE" in MoreColors
264
- assert MoreColors.PURPLE.name == "PURPLE"
265
- assert MoreColors.PURPLE.value == 4
266
- assert MoreColors.PURPLE == 4
310
+ assert "GOLD" in MoreColors
267
311
 
312
+ # As backfilling has been enabled for the superclass, subclass options are available on
313
+ # both the subclass as seen above as well as on the superclass through backfilling:
314
+ assert "PURPLE" in Colors
268
315
  assert "GOLD" in Colors
269
- assert Colors.GOLD.name == "GOLD"
270
- assert Colors.GOLD.value == 5
271
- assert Colors.GOLD == 5
272
316
  ```
273
317
 
274
- #### Example 10: Subclassing Over
318
+ #### Example 11: Subclassing Over
275
319
 
276
320
  ```python
277
321
  from enumerific import Enumeration
@@ -281,29 +325,34 @@ class Colors(Enumeration):
281
325
  GREEN = 2
282
326
  BLUE = 3
283
327
 
284
- # Subclassed Enumerations can have the same name as the parent class
285
- # The subclass will inherit the enumeration options of its parent
328
+ assert "RED" in Colors
329
+ assert Colors.RED == 1
330
+
331
+ assert "GREEN" in Colors
332
+ assert Colors.GREEN == 2
333
+
334
+ assert "BLUE" in Colors
335
+ assert Colors.BLUE == 3
336
+
337
+ # Subclasses of Enumerations classes can be given the same name as the parent class, so
338
+ # within this scope, the subclass shadows the superclass; the subclass inherits all the
339
+ # enumeration options of its parent(s) superclasses:
286
340
  class Colors(Colors):
287
341
  PURPLE = 4
288
342
  GOLD = 5
289
343
 
344
+ assert "RED" in Colors
345
+ assert "GREEN" in Colors
290
346
  assert "BLUE" in Colors
291
- assert Colors.BLUE.name == "BLUE"
292
- assert Colors.BLUE.value == 3
293
- assert Colors.BLUE == 3
294
347
 
295
348
  assert "PURPLE" in Colors
296
- assert Colors.PURPLE.name == "PURPLE"
297
- assert Colors.PURPLE.value == 4
298
349
  assert Colors.PURPLE == 4
299
350
 
300
351
  assert "GOLD" in Colors
301
- assert Colors.GOLD.name == "GOLD"
302
- assert Colors.GOLD.value == 5
303
352
  assert Colors.GOLD == 5
304
353
  ```
305
354
 
306
- #### Example 11: Unregistering Existing Option
355
+ #### Example 12: Unregistering Existing Option
307
356
 
308
357
  ```python
309
358
  from enumerific import Enumeration
@@ -322,7 +371,26 @@ assert "GREEN" not in Colors
322
371
  assert "BLUE" in Colors
323
372
  ```
324
373
 
325
- #### Example 12: Aliasing Options
374
+ #### Example 13: Preventing Subclassing of Enumeration Classes
375
+
376
+ ```python
377
+ from enumerific import Enumeration, EnumerationSubclassingError
378
+ import pytest
379
+
380
+ # To prevent an enumeration class from being extended through subclassing, the
381
+ # `subclassable` keyword argument can be set when creating the class; this will
382
+ # result in an `EnumerationSubclassingError` exception being raised on subclassing:
383
+ class Colors(Enumeration, subclassable=False):
384
+ RED = 1
385
+ GREEN = 2
386
+ BLUE = 3
387
+
388
+ with pytest.raises(EnumerationSubclassingError):
389
+ class MoreColors(Colors):
390
+ PURPLE = 4
391
+ ```
392
+
393
+ #### Example 14: Aliasing Options
326
394
 
327
395
  ```python
328
396
  from enumerific import Enumeration
@@ -372,7 +440,7 @@ assert Colors.GREEN.aliases == [Colors.VERTE]
372
440
  assert Colors.BLUE.aliases == [] # BLUE has not been aliased
373
441
  ```
374
442
 
375
- #### Example 13: Non-Unique Options
443
+ #### Example 15: Non-Unique Options
376
444
 
377
445
  ```python
378
446
  from enumerific import Enumeration
@@ -411,7 +479,7 @@ assert Colors.RED == Colors.GREEN
411
479
  assert Colors.BLUE != Colors.RED
412
480
  ```
413
481
 
414
- #### Example 14: Bit Wise Flags
482
+ #### Example 16: Bit Wise Flags
415
483
 
416
484
  ```python
417
485
  from enumerific import Enumeration
@@ -483,7 +551,7 @@ assert Permissions.DELETE in permissions
483
551
  assert str(permissions) == "Permissions.READ|WRITE|DELETE"
484
552
  ```
485
553
 
486
- #### Example 15: Annotating Enumeration Option Values
554
+ #### Example 17: Annotating Enumeration Option Values
487
555
 
488
556
  ```python
489
557
  from enumerific import Enumeration, anno
@@ -527,7 +595,7 @@ assert Colors.PURPLE.rgb == (255, 0, 255)
527
595
  assert Colors.PURPLE.primary is False
528
596
  ```
529
597
 
530
- #### Example 16: Annotating Enumeration Option Values with Automatic Sequencing
598
+ #### Example 18: Annotating Enumeration Option Values with Automatic Sequencing
531
599
 
532
600
  ```python
533
601
  from enumerific import Enumeration, auto
@@ -2,7 +2,14 @@ from enum import *
2
2
 
3
3
  from .logging import logger
4
4
 
5
- from .exceptions import EnumValueError
5
+ from .exceptions import (
6
+ EnumValueError,
7
+ EnumerationError,
8
+ EnumerationOptionError,
9
+ EnumerationSubclassingError,
10
+ EnumerationExtensibilityError,
11
+ EnumerationNonUniqueError,
12
+ )
6
13
 
7
14
  from .extensible import (
8
15
  Enumeration,
@@ -14,5 +14,9 @@ class EnumerationSubclassingError(EnumerationError):
14
14
  pass
15
15
 
16
16
 
17
+ class EnumerationExtensibilityError(EnumerationError):
18
+ pass
19
+
20
+
17
21
  class EnumerationNonUniqueError(EnumerationError):
18
22
  pass