monde de merde

This commit is contained in:
Awen Lelu 2025-12-01 17:46:26 +01:00
parent 9333a29e4b
commit 72b2d71c75
8 changed files with 97 additions and 6 deletions

Binary file not shown.

27
flake.lock generated Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1764522689,
"narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

31
flake.nix Normal file
View File

@ -0,0 +1,31 @@
{
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
outputs =
{ nixpkgs, ... }:
{
devShells.x86_64-linux =
let
python = pkgs.python312;
pythonEnv = python.withPackages (
ps: with ps; [
pip
ipython
pylint
black
ruff
jedi-language-server
pytest
]
);
pkgs = import nixpkgs { system = "x86_64-linux"; };
in
{
default = pkgs.mkShell {
packages = [
pythonEnv
];
};
};
};
}

43
main.py
View File

@ -3,6 +3,11 @@ This module has no real meaning.
Simply implemented for evaluating students. Simply implemented for evaluating students.
""" """
from pathlib import Path
from itertools import chain
import re
import string
def list_filenames_of_log_files(*foldernames) -> list: def list_filenames_of_log_files(*foldernames) -> list:
""" """
List all the `*.log` files stored in the folders specified by foldernames. List all the `*.log` files stored in the folders specified by foldernames.
@ -14,10 +19,21 @@ def list_filenames_of_log_files(*foldernames) -> list:
:raises FileNotFoundError: If one of the speficied folders does not exist :raises FileNotFoundError: If one of the speficied folders does not exist
""" """
return foldernames def walk(folder):
if not folder.exists():
raise FileNotFoundError(f"{folder} does not exist")
for subfold, childfolds, files in folder.walk():
for f in files:
if ".log" in f:
yield subfold / f
# final cast as list would generally be omited but due to the test expecting
# an indexable object, this cast is need. It would be more idiomatic to return
# a generator and iterate over it tho.
return list(chain(*[walk(Path(foldername)) for foldername in foldernames]))
def list_ipv4_listed_in_logfiles(*foldernames) -> list : def list_ipv4_listed_in_logfiles(*foldernames) -> list:
""" """
Parse all the `*.log` files stored in the folders specified by foldernames. Parse all the `*.log` files stored in the folders specified by foldernames.
This method returns a list of ip adresses stored in those files. This method returns a list of ip adresses stored in those files.
@ -30,10 +46,18 @@ def list_ipv4_listed_in_logfiles(*foldernames) -> list :
:raises FileNotFoundError: If one of the speficied folders does not exist :raises FileNotFoundError: If one of the speficied folders does not exist
""" """
return foldernames def get_ip_from_file(file):
matcher = re.compile(r"(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})")
with open(file) as f:
for line in f:
if match := matcher.search(line):
yield match.group()
# cast to a set to delete duplicates
# cast to a list 'caus the test is hardcoded to get a list
return list(set(chain(*[get_ip_from_file(file) for file in list_filenames_of_log_files(*foldernames)])))
def cryptarithme(message:str = "SEND + MORE = MONEY") -> list: def cryptarithme(message: str = "SEND + MORE = MONEY") -> list:
""" """
The `message` is a formatted mathematical operation. The `message` is a formatted mathematical operation.
Each letter represents a number between 0 and 9. Each letter represents a number between 0 and 9.
@ -64,10 +88,19 @@ def cryptarithme(message:str = "SEND + MORE = MONEY") -> list:
:raises ValueError: If the string cannot be parsed properly. :raises ValueError: If the string cannot be parsed properly.
:raises CryptarithmeError : If the string is not a possible Cryptarithme :raises CryptarithmeError : If the string is not a possible Cryptarithme
""" """
# check for syntax
for i, character in enumerate(message):
if character not in [*string.ascii_uppercase, "+", "=", " "]:
raise ValueError(f"illegal character {character} at {i}")
if len([i for i in message if i == "="]) >= 2 or len([i for i in message if i == "+"]) >= 2:
raise ValueError("too much =")
return message return message
class CryptarithmeError(Exception):
pass
if __name__ == '__main__': if __name__ == "__main__":
# list_filenames_of_log_files('data') # list_filenames_of_log_files('data')
# list_ipv4_listed_in_logfiles('data') # list_ipv4_listed_in_logfiles('data')
# cryptarithme('A + A +A= B') # cryptarithme('A + A +A= B')

View File

@ -43,4 +43,4 @@ def test_refactoring_has_brought_a_generator():
with open("main.py") as f: with open("main.py") as f:
lines : str = f.read() lines : str = f.read()
found = re.search("yield", lines) found = re.search("yield", lines)
assert found, "No bonus linked to refactoring to a generator" assert found, "No bonus linked to refactoring to a generator"