Skip to content

Commit a452af8

Browse files
valentin-pBethanyGgithub-actions[bot]
authored andcommitted
enums. iterate on the log-level exercise (exercism#2811)
* enums. iterate on the log-level exercise * chnage hints and other files * minor changes * minor fixes * straightforward changes * [CI] Format code Co-authored-by: BethanyG <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 5800795 commit a452af8

File tree

11 files changed

+265
-228
lines changed

11 files changed

+265
-228
lines changed

concepts/enums/about.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
In Python, [an enum][enum-docs] is a set of unique names that are bound unique, **constant** values. Enums are defined by inheriting an `Enum` class. Built-in enum types are available in the module `enum` and the class `Enum` can be imported using `from enum import Enum`.
2+
3+
```python
4+
class Color(Enum):
5+
RED = 1
6+
GREEN = 2
7+
```
8+
9+
Note that the values of the enum members can be any data types such as str, tuple, float, etc.
10+
11+
```python
12+
class Color(Enum):
13+
RED = 'red'
14+
GREEN = 'green'
15+
```
16+
17+
Enums can also be created via the following [functional API][enum-functional-api].
18+
19+
```python
20+
Animal = Enum('Animal', 'ANT BEE CAT DOG')
21+
list(Animal)
22+
#=> [<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
23+
24+
Animal.ANT.value
25+
#=> 1
26+
```
27+
28+
When assigning the same value to two members in an enum, the latter assigned member will be an alias to the formed one. It is not allowed to use the same name for two members of an enum.
29+
30+
```python
31+
class Color(Enum):
32+
RED = 1
33+
GREEN = 2
34+
ALIAS_OF_RED = 1
35+
36+
Color.ALIAS_OF_RED
37+
#=> <Color.RED: 1>
38+
```
39+
40+
Iterating through the members of the enum can be done with the standard `for member in` syntax:
41+
42+
```python
43+
for member in Color:
44+
print((member.name, member.value))
45+
#=> (RED, 1)
46+
#=> (GREEN, 2)
47+
48+
# __members__.items() helps you to loop through alias as well
49+
for member in Color.__members__.items():
50+
print(member)
51+
#=>('RED', <Color.RED: 1>)
52+
#=>('GREEN', <Color.GREEN: 2>)
53+
#=>('ALIAS_OF_RED', <Color.RED: 1>)
54+
```
55+
56+
Enum members can be compared using [`is` (_identity operator_)][identity-keyword] or `is not`. The `==` or `!=` (_equality operators_) work likewise.
57+
58+
```python
59+
a = Color.RED
60+
61+
a is Color.RED
62+
#=> True
63+
64+
a == Color.RED
65+
#=> True
66+
```
67+
68+
To assign integer values, the [`auto()` function][enum-auto-docs] starts with `1` and automatically sets subsequent values.
69+
70+
```python
71+
class Shape(Enum):
72+
CIRCLE = auto()
73+
SQUARE = auto()
74+
OVAL = auto()
75+
```
76+
77+
To disallow aliasing (_preventing duplicate values with different names_), the `@unique` decorator may be used.
78+
79+
```python
80+
@unique
81+
class Shape(Enum):
82+
CIRCLE = 1
83+
SQUARE = 2
84+
TRIANGLE = 1
85+
#=> ValueError: duplicate values found in <enum 'Shape'>: TRIANGLE -> CIRCLE
86+
```
87+
88+
To access an enum member for a given value, this notation can be used: `EnumName(value)`.
89+
90+
```python
91+
g = Color(2)
92+
93+
g is Color.GREEN
94+
#=> True
95+
96+
g
97+
#=> <Color.GREEN: 2>
98+
```
99+
100+
A custom [restricted `Enum`][restricted-enums] can be written by subclassing `Enum` with any mix-in or data-type. For example:
101+
102+
```python
103+
class StrEnum(str, Enum):
104+
pass
105+
```
106+
107+
[enum-docs]: https://docs.python.org/3/library/enum.html
108+
[enum-auto-docs]: https://docs.python.org/3/library/enum.html#using-auto
109+
[enum-functional-api]: https://docs.python.org/3/library/enum.html#functional-api
110+
[restricted-enums]: https://docs.python.org/3/library/enum.html#restricted-enum-subclassing
111+
[identity-keyword]: https://www.w3schools.com/python/ref_keyword_is.asp

concepts/enums/links.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"url": "https://docs.python.org/3/library/enum.html",
4+
"description": "enum documentation"
5+
},
6+
{
7+
"url": "https://www.w3schools.com/python/ref_keyword_is.asp",
8+
"description": "identity keyword"
9+
},
10+
{
11+
"url": "https://docs.python.org/3/library/enum.html#using-auto",
12+
"description": "enum auto documentation"
13+
},
14+
{
15+
"url": "https://docs.python.org/3/library/enum.html#functional-api",
16+
"description": "enum functional api"
17+
},
18+
{
19+
"url": "https://docs.python.org/3/library/enum.html#restricted-enum-subclassing",
20+
"description": "restricted enum"
21+
}
22+
]

exercises/concept/log-levels/.docs/after.md

Lines changed: 0 additions & 91 deletions
This file was deleted.

exercises/concept/log-levels/.docs/hints.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,28 @@
44

55
## 1. Parse log level
66

7-
- You need to use string splits to split the log message to multiple parts.
8-
- Once you have the required part of the string split you can use LogLevel(`string`) to return
7+
- Use [`str.split`](https://www.w3schools.com/python/ref_string_split.asp) to extract the log level from the message.
8+
- With the extracted part of the string, access and return the enum member using `LogLevel(string)`.
99

1010
## 2. Support unknown log level
1111

12-
- You need to first check if the value is in the LogLevel enum before calling LogLevel(`string`) and return.
12+
- Create a new Unknown log level member in the existing enum.
13+
- Check if the extracted part of the string is a value of the enum `LogLevel`.
14+
- If the value does not match any of the enum member values, then return the Unknown member of `LogLevel`.
1315

1416
## 3. Convert log line to short format
1517

16-
- You need to do an if else with all the members of the LogLevel and return the String along with the int value as per the given format. ( You need to use a `==` operator )
18+
- Find the code (an integer) of the log level based on the log level, multiple solutions are possible: if statements, another enum or any other solution.
19+
- Use string formatting to return a properly formatted code level and message.
1720

1821
## 4. Create an Alias
1922

20-
- You just have to return the newly created alias value to the function output.
23+
- Create the new alias member named Warn in the existing enum.
24+
- Return the newly created member.
2125

2226
## 5. All Member Names and Values
2327

24-
- You need to iterate over all the members in the enum and return a tuple containing (member.name, member.value) in a list.
28+
- Iterate on all the members of the enum and return a list of tuple.
29+
- The tuple can be constructed with `(item1, item2)`.
30+
- The name and value of the enum can be accessed with `member.name` and `member.value`.
31+
- Return the list containing all the tuples.
Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
1-
In this exercise you'll be processing log-lines.
1+
In this exercise, you'll be processing log messages with six severity levels.
22

33
Each log line is a string formatted as follows: `"[<LVL>]: <MESSAGE>"`.
44

55
These are the different log levels:
66

7-
- `TRC` (trace)
8-
- `DBG` (debug)
9-
- `INF` (info)
10-
- `WRN` (warning)
11-
- `ERR` (error)
12-
- `FTL` (fatal)
13-
14-
You have three tasks.
7+
| LEVEL | LVL |
8+
| --------- | ----- |
9+
| `Trace` | `TRC` |
10+
| `Debug` | `DBG` |
11+
| `Info` | `INF` |
12+
| `Warning` | `WRN` |
13+
| `Error` | `ERR` |
14+
| `Fatal` | `FTL` |
1515

1616
## 1. Parse log level
1717

18-
Define a `LogLevel` enum that has six elements corresponding to the above log levels.
19-
20-
- `Trace`
21-
- `Debug`
22-
- `Info`
23-
- `Warning`
24-
- `Error`
25-
- `Fatal`
26-
27-
Define the `parse_log_level` function which will take the 1 parameter, the log message. Return the Type of Log Level the log message belongs to.
28-
29-
Note: The `LogLevel` enum has to be defined on top of the file (outside the function).
18+
Define a `LogLevel` enum that has six elements corresponding to the log levels defined above.
19+
Next, define the `parse_log_level` function which takes the log message as parameter and returns the enum member of its level.
3020

3121
```python
3222
parse_log_level("[INF]: File deleted")
@@ -35,64 +25,61 @@ parse_log_level("[INF]: File deleted")
3525

3626
## 2. Support unknown log level
3727

38-
Unfortunately, occasionally some log lines have an unknown log level. To gracefully handle these log lines, add an `Unknown` element to the `LogLevel` enum which should be returned when parsing an unknown log level:
28+
Unfortunately, some log messages occasionally appear with an _unknown_ severity. To gracefully handle these 'mysterious' log messages in the function `parse_log_level`, add an `Unknown` member to the `LogLevel` enum which is returned when parsing an unknown log level:
3929

4030
```python
4131
parse_log_level("[XYZ]: Overly specific, out of context message")
4232
#=> LogLevel.Unknown
4333
```
4434

45-
## 3. Convert log line to short format
35+
## 3. Convert a log message to the short format
4636

47-
The log level of a log line is quite verbose. To reduce the disk space needed to store the log lines, a short format is developed: `"[<ENCODED_LEVEL>]:<MESSAGE>"`.
37+
The log level of a log line is quite verbose. To reduce the disk space needed to store the log messages, a short format is defined: `"[<CODE_LEVEL>]:<MESSAGE>"`.
4838

49-
The encoded log level is simple mapping of a log level to a number:
39+
The log level codes follow a straightforward mapping:
5040

51-
- `Trace` - `0`
52-
- `Debug` - `1`
53-
- `Info` - `4`
54-
- `Warning` - `5`
55-
- `Error` - `6`
56-
- `Fatal` - `7`
57-
- `Unknown` - `42`
41+
| LEVEL | CODE |
42+
| --------- | ---- |
43+
| `Trace` | `0` |
44+
| `Debug` | `1` |
45+
| `Info` | `4` |
46+
| `Warning` | `5` |
47+
| `Error` | `6` |
48+
| `Fatal` | `7` |
49+
| `Unknown` | `42` |
5850

59-
Define the `convert_to_short_log()` which takes 2 parameters.
51+
Define the `convert_to_short_log()` function, which takes two parameters:
6052

61-
1. Log level - The Log level of the log sent. ex: LogLevel.Error
62-
2. Log Message
53+
1. Log level - The Log level of the log sent. ex: `LogLevel.Error`.
54+
2. Log Message - The message of type `str`.
6355

6456
```python
6557
convert_to_short_log(LogLevel.Error, "Stack overflow")
6658
# => "6:Stack overflow"
6759
```
6860

69-
## 4. Create an Alais
61+
## 4. Create an Alias
7062

71-
It looks like the user has created logs for `LogLevel.Warn` instead of `LogLevel.Warning`. Create an `alias` for `LogLevel.Warning` and return the alias name. This can be done on the same enum class you have defined at the top of the file.
63+
It looks like the user has created logs for `LogLevel.Warn` instead of `LogLevel.Warning`. Create an `alias` for `LogLevel.Warning` and return the new alias member in the function `get_warn_alias`.
7264

73-
Note: Both the LogLevels should point to same value. ie: LogLevel.Warning = "WRN" & LogLevel.Warn = "WRN"
65+
This can be done on the same enum class `LogLevel` already defined at the top of the file. Both the LogLevels should point to same value: `"WRN"`.
7466

7567
```python
76-
return_alias()
68+
get_warn_alias()
7769
#=> LogLevel.Warn
78-
return_alias() == LogLevel.Warning
70+
71+
get_warn_alias() == LogLevel.Warning
7972
#=> True
8073
```
8174

8275
## 5. All Member Names and Values
8376

84-
Define the function `return_members()` that will take 1 parameter.
85-
86-
1. This parameter will take a randomly created enum.
77+
Define the function `get_members()`.
8778

88-
You should return the (name, value) in tuple format of all the members in a list.
79+
This function should return a list of tuples `(name, value)` containing all the members of the enum `LogLevel`.
8980

9081
```python
91-
92-
class Color(enum.Enum):
93-
RED = 'red'
94-
GREEN = 'green'
95-
96-
return_members(Color)
97-
#=> [('RED', 'red'), ('GREEN', 'green')]
82+
get_members()
83+
#=> [('Trace', 'TRC'), ('Debug', 'DBG'), ('Info', 'INF'), ('Warning', 'WRN'),
84+
# ('Error', 'ERR'), ('Fatal', 'FTL'), ('Unknown', 'UKN')]
9885
```

0 commit comments

Comments
 (0)