Renamed processing-logs to little-sisiters-vocab.
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
# Hints
|
||||
|
||||
## General
|
||||
|
||||
- The [Python documentation for `str`][python-str-doc] has an overview of the Python `str` type.
|
||||
|
||||
## 1. Get message from a log line
|
||||
|
||||
- Strings in Python have [lots of convenient instance methods][str-type-methods] for cleaning, splitting, manipulating, and creating new strings. Extracting values from a string could be done by splitting it based on a substring, for example.
|
||||
|
||||
## 2. Get log level from a log line
|
||||
|
||||
- Strings also have methods that help convert letters from lower to uppercase and vice-versa.
|
||||
|
||||
## 3. Reformat a log line
|
||||
|
||||
Strings are immutable, but can be combined together to make new strings, or have elements replaced. This goal can be accomplished by using string methods, or operators like `+` or `+=` (which are overloaded to work with strings).
|
||||
Python also has a concept of string formatting, like many other languages.
|
||||
|
||||
- The [`str.join()`][str-join] method is useful to join an iterable of strings into one string by interspersing them with a common value, e.g. `":".join("abcde")` would create `"a:b:c:d:e"`.
|
||||
- [`str.format()`][str-format] is an idiomatic way to do string interpolation in Python (inserting one or more string value(s) into another).
|
||||
- [Format strings][format-str] are another convenient way to interpolate values into a string. This strategy is particularly useful when more than one named variable needs to be inserted into a final output.
|
||||
|
||||
[python-str-doc]: https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str
|
||||
[str-type-methods]: https://docs.python.org/3/library/stdtypes.html#str
|
||||
[str-join]: https://docs.python.org/3/library/stdtypes.html#str.join
|
||||
[str-format]: https://docs.python.org/3/library/stdtypes.html#str.format
|
||||
[format-str]: https://docs.python.org/3/library/string.html#formatstrings
|
||||
@@ -1,47 +0,0 @@
|
||||
# Instructions
|
||||
|
||||
In this exercise you'll be processing log-lines.
|
||||
|
||||
Each log line is a string formatted as follows: `"[<LEVEL>]: <MESSAGE>"`.
|
||||
|
||||
There are three different log levels:
|
||||
|
||||
- `INFO`
|
||||
- `WARNING`
|
||||
- `ERROR`
|
||||
|
||||
You have three tasks, each of which will take a log line and ask you to do something with it.
|
||||
|
||||
## 1. Extract a message from a log line
|
||||
|
||||
Implement the `extract_message` to return a log line's message:
|
||||
|
||||
```python
|
||||
>>> extract_message("[ERROR]: Invalid operation")
|
||||
'Invalid operation'
|
||||
```
|
||||
|
||||
The message should be trimmed of any whitespace.
|
||||
|
||||
```python
|
||||
>>> extract_message("[ERROR]: Invalid operation.\t\n")
|
||||
'Invalid operation.'
|
||||
```
|
||||
|
||||
## 2. Change a message's loglevel.
|
||||
|
||||
Implement the `change_log_level` function to replace a log line's current log level with a new one:
|
||||
|
||||
```python
|
||||
>>> change_log_level("[INFO]: Fatal Error.", "ERROR")
|
||||
'[ERROR]: Fatal Error.'
|
||||
```
|
||||
|
||||
## 3. Reformat a log line
|
||||
|
||||
Implement the `reformat` function to reformat the log line, putting the message first and the log level after it in parentheses:
|
||||
|
||||
```python
|
||||
>>> reformat("[INFO]: Operation completed")
|
||||
'Operation completed (info)'
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
# Introduction
|
||||
|
||||
A `str` typed object in Python is an immutable sequence of Unicode code points. This could include letters, numbers, punctuation, etc. To manipulate strings, Python provides string methods that can transform a string into other types, create new strings based on method arguments, or return information about the string. Strings can be concatenated with `+`.
|
||||
|
||||
Immutability means that a string's value doesn't change; methods that appear to modify a string actually return a new instance of `str`.
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"blurb": "Learn about strings by processing log files.",
|
||||
"authors": [
|
||||
"aldraco"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"strings.py"
|
||||
],
|
||||
"test": [
|
||||
"strings_test.py"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.py"
|
||||
]
|
||||
},
|
||||
"forked_from": [
|
||||
"csharp/strings"
|
||||
]
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
# Design
|
||||
|
||||
## Goal
|
||||
|
||||
The goal of this exercise is to teach the student about Python strings, and familiarize them with string manipulation in Python.
|
||||
|
||||
## Things to teach
|
||||
|
||||
- Know that Python has a `str` type.
|
||||
- Know how to find items in a string.
|
||||
- Know how to manipulate strings to create new strings.
|
||||
- Familiarize one's self with string instance methods in Python.
|
||||
- Learn about string formatting.
|
||||
|
||||
## Things not to teach
|
||||
|
||||
- Regex: `regex` is a useful tool for a solution, but isn't required.
|
||||
- Iteration: Although strings are iterable, this is not the focus of this exercise.
|
||||
|
||||
## Concepts
|
||||
|
||||
The Concepts this exercise unlocks are:
|
||||
|
||||
- `strings-basic`: know about `str` type in Python, know some basic methods, know about formatting.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `functions`: The student should be familiar with creating functions.
|
||||
|
||||
## Representer
|
||||
|
||||
This exercise does not require any logic to be added to the [representer][representer]
|
||||
|
||||
## Analyzer
|
||||
|
||||
This exercise does not require any logic to be added to the [analyzer][analyzer].
|
||||
|
||||
[analyzer]: https://github.com/exercism/python-analyzer
|
||||
[representer]: https://github.com/exercism/python-representer
|
||||
@@ -1,27 +0,0 @@
|
||||
import re
|
||||
|
||||
LOGLINE_RE = r"\[(?P<level>INFO|ERROR|WARN)\] (?P<msg>.*)"
|
||||
|
||||
|
||||
def _extract_pieces(message):
|
||||
pieces = re.search(LOGLINE_RE, message)
|
||||
return pieces.group("level"), pieces.group("msg")
|
||||
|
||||
def _extract_pieces_no_regex_groups(message):
|
||||
words = [word for word in re.split("[\s\[\]]", message) if word]
|
||||
return words[0], " ".join(words[1:])
|
||||
|
||||
def _extract_pieces_no_regex(message):
|
||||
words = [word for word in message.strip().replace("]", "[").split("[") if word]
|
||||
return words[0], words[1].strip()
|
||||
|
||||
def change_log_level(message, new_loglevel):
|
||||
"""Change loglevel of message to new_loglevel."""
|
||||
return f"[{new_loglevel}] {extract_message(message)}"
|
||||
|
||||
def extract_message(message):
|
||||
return _extract_pieces_no_regex(message)[1]
|
||||
|
||||
def reformat(message):
|
||||
loglevel, msg = _extract_pieces_no_regex_groups(message)
|
||||
return f"{msg} ({loglevel.lower()})"
|
||||
@@ -1,8 +0,0 @@
|
||||
def extract_message():
|
||||
pass
|
||||
|
||||
def change_log_level():
|
||||
pass
|
||||
|
||||
def reformat():
|
||||
pass
|
||||
@@ -1,53 +0,0 @@
|
||||
import unittest
|
||||
from strings import extract_message, change_log_level, reformat
|
||||
|
||||
|
||||
class TestLogLines(unittest.TestCase):
|
||||
def test_message(self):
|
||||
self.assertEqual(
|
||||
extract_message("[INFO] Hello there."),
|
||||
"Hello there.",
|
||||
msg="Should correctly extract a basic message.",
|
||||
)
|
||||
|
||||
def test_message_with_punctuation(self):
|
||||
self.assertEqual(
|
||||
extract_message("[WARN] File not found: exercism_practice.py"),
|
||||
"File not found: exercism_practice.py",
|
||||
msg="Should preserve punctuation and whitespace from original message.",
|
||||
)
|
||||
|
||||
def test_level_word_remains_in_message(self):
|
||||
self.assertEqual(
|
||||
extract_message("[ERROR] Error while serializing data."),
|
||||
"Error while serializing data.",
|
||||
msg="Should preserve a loglevel word that is actually part of the message.",
|
||||
)
|
||||
|
||||
def test_change_loglevel(self):
|
||||
self.assertEqual(
|
||||
change_log_level("[ERROR] No configs found, but not a big deal.", "INFO"),
|
||||
"[INFO] No configs found, but not a big deal.",
|
||||
msg="Should replace the loglevel.",
|
||||
)
|
||||
|
||||
def test_change_loglevel_with_loglevel_in_message(self):
|
||||
self.assertEqual(
|
||||
change_log_level("[WARN] Warning: file does not exist.", "INFO"),
|
||||
"[INFO] Warning: file does not exist.",
|
||||
msg="Should not replace loglevel names that are part of the message.",
|
||||
)
|
||||
|
||||
def test_reformat(self):
|
||||
self.assertEqual(
|
||||
reformat("[WARN] Warning: file not found."),
|
||||
"Warning: file not found. (warn)",
|
||||
msg="Should reformat with lowercase loglevel. ",
|
||||
)
|
||||
|
||||
def test_capture_message_when_contains_loglevel_string(self):
|
||||
self.assertEqual(
|
||||
extract_message("[WARN] Warning: file not found. Will WARN once."),
|
||||
"Warning: file not found. Will WARN once.",
|
||||
msg="Should extract loglevel inside brackets, not from messsage, even if message contains something that looks like a loglevel.",
|
||||
)
|
||||
Reference in New Issue
Block a user