diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..4af1f51 Binary files /dev/null and b/__pycache__/main.cpython-312.pyc differ diff --git a/__pycache__/test_cryptarithme.cpython-312-pytest-8.4.2.pyc b/__pycache__/test_cryptarithme.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 0000000..77a0d2f Binary files /dev/null and b/__pycache__/test_cryptarithme.cpython-312-pytest-8.4.2.pyc differ diff --git a/__pycache__/test_list_filenames_of_log_files.cpython-312-pytest-8.4.2.pyc b/__pycache__/test_list_filenames_of_log_files.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 0000000..0d4d896 Binary files /dev/null and b/__pycache__/test_list_filenames_of_log_files.cpython-312-pytest-8.4.2.pyc differ diff --git a/__pycache__/test_list_ipv4_listed_in_logfiles.cpython-312-pytest-8.4.2.pyc b/__pycache__/test_list_ipv4_listed_in_logfiles.cpython-312-pytest-8.4.2.pyc new file mode 100644 index 0000000..a35f6dd Binary files /dev/null and b/__pycache__/test_list_ipv4_listed_in_logfiles.cpython-312-pytest-8.4.2.pyc differ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..31a72ac --- /dev/null +++ b/flake.lock @@ -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 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..9c7af49 --- /dev/null +++ b/flake.nix @@ -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 + ]; + }; + }; + }; +} diff --git a/main.py b/main.py index d0445c1..28269ac 100644 --- a/main.py +++ b/main.py @@ -3,6 +3,11 @@ This module has no real meaning. 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: """ 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 """ - 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. 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 """ - 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. 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 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 +class CryptarithmeError(Exception): + pass -if __name__ == '__main__': +if __name__ == "__main__": # list_filenames_of_log_files('data') # list_ipv4_listed_in_logfiles('data') # cryptarithme('A + A +A= B') diff --git a/test_list_ipv4_listed_in_logfiles.py b/test_list_ipv4_listed_in_logfiles.py index c619470..7631fc7 100644 --- a/test_list_ipv4_listed_in_logfiles.py +++ b/test_list_ipv4_listed_in_logfiles.py @@ -43,4 +43,4 @@ def test_refactoring_has_brought_a_generator(): with open("main.py") as f: lines : str = f.read() found = re.search("yield", lines) - assert found, "No bonus linked to refactoring to a generator" \ No newline at end of file + assert found, "No bonus linked to refactoring to a generator"