diff --git a/prime_divs.py b/prime_divs.py index 133fc0e370742f8a93617d39642873c143123f5e..1605bf959794095a0ada05b83a02db60674af3a7 100644 --- a/prime_divs.py +++ b/prime_divs.py @@ -1,54 +1,111 @@ -#!/usr/bin/env python3.6 +#!/usr/bin/env python3 +"""Factorise la liste des diviseurs premiers de nombres entiers. +Ce script lit dans un fichier d'entrée une liste d'entiers (tous naturels plus grand ou égal à 2). +Pour chaque entier dans cette liste, il calcule la liste de ses diviseurs premiers. +Ensuite, il écrit dans un fichier de sortie une ligne pour chaque entier avec sa liste de diviseurs premiers. + +Par exemple pour un fichier d'entrée : + + 20414363521583006011 + 13 + 100 + +Le fichier de sortie sera : + + 20414363521583006011 283 72135560146936417 + 13 + 100 2 5 + +Ce script s'utilise comme : + $ python3 prime_divs.py input_filename output_filename +Pour plus d'information, lancez : + $ python3 prime_divs.py -h + +Pour tester le script, lancez : + $ python3 -m pytest +Si vous avez une erreur, installez d'abord pytest : + $ pip3 install -U pytest` +""" + + +import argparse +import logging import os import sys +logger = logging.getLogger() + def is_div(number, i): + """Vérifie si i est un diviseur de number.""" return number % i == 0 def is_prime(number): + """Vérifie si number est un nombre premier.""" for i in range(2, number): if is_div(number, i): return False return True def prime_divs(number): + """Calcule la liste des diviseurs premiers de number.""" prime_dividers = [] for i in range(2, number): if is_prime(i) and is_div(number, i): prime_dividers.append(i) return prime_dividers -def main(fileIn, fileOut): - try: - with open(fileIn) as input, open(fileOut, "w") as output: - for line in input: - try: - number = int(line) - except ValueError: - print(f"Not a valid number: {line}") - continue - - prime_dividers = prime_divs(number) - - res = str(number) - for prime_div in prime_dividers: - res += " " + str(prime_div) - res += "\n" - - output.write(res) - print(res, end="") - except IOError: - print("IOError") - sys.exit(-1) + +def main(input, output): + """Lit chaque entier en entrée, trouve ses disviseurs premiers et écrit en sortie.""" + logger.info("Début de la boucle principale") + for line in input: + + try: + number = int(line) + except ValueError: + logger.warning("Entier mal formatté : %s", line[:-1]) + continue + if number < 2: + logger.warning("Entier plus petit que 2 : %s", line[:-1]) + continue + + prime_dividers = prime_divs(number) + res = str(number) + " " + " ".join(str(div) for div in prime_dividers) + + output.write(res + "\n") + logger.debug(res) + + +def parse_args(args=sys.argv[1:]): + """Analyse les arguments.""" + parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + + parser.add_argument("input_file", type=argparse.FileType('r'), help="Nom du fichier d'entrée") + parser.add_argument("output_file", type=argparse.FileType('w'), help="Nom du fichier de sortie") + + group = parser.add_mutually_exclusive_group() + group.add_argument("-v", "--verbose", default=False, action="store_true", help="Active les informations de débug") + group.add_argument("-q", "--quiet", default=False, action="store_true", help="Désactive toutes les informations") + + arguments = parser.parse_args(args) + + logging.basicConfig(level=logging.INFO, stream=sys.stderr, format="%(levelname)s: %(message)s") + if arguments.quiet: + logger.setLevel(logging.WARNING) + if arguments.verbose: + logger.setLevel(logging.DEBUG) + + return arguments.input_file, arguments.output_file + if __name__ == '__main__': - if len(sys.argv) != 3: - print(f"Usage: {sys.argv[0]} fileIn fileOut") - sys.exit(-1) - if not os.path.isfile(sys.argv[1]): - print(f"{sys.argv[0]}: No such file {sys.argv[1]}") - sys.exit(-1) - main(sys.argv[1], sys.argv[2]) + input_file, output_file = parse_args() + logger.info("Fichiers ouverts") + main(input_file, output_file) + logger.info("Fermeture des fichiers") + input_file.close() + output_file.close() diff --git a/test_prime_divs.py b/test_prime_divs.py new file mode 100644 index 0000000000000000000000000000000000000000..45bcea78be45eab8072182d5bffe8a8bc95e9102 --- /dev/null +++ b/test_prime_divs.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +"""Module de test de prime_divs.py + +Lancez les tests avec : + $ python3 -m pytest +Si vous avez une erreur, installez d'abord pytest : + $ pip3 install -U pytest` +""" + + +from prime_divs import * +import pytest + +@pytest.mark.parametrize("number, i, expected", [ + (10, 2, True), + (5, 5, True), + (3, 2, False), + (15, 4, False), +]) +def test_is_div(number, i, expected): + assert is_div(number, i) == expected + +@pytest.mark.parametrize("number, expected", [ + (2, True), + (4, False), + (13, True), + (97, True), + (100, False), +]) +def test_is_prime(number, expected): + assert is_prime(number) == expected + +@pytest.mark.parametrize("number, expected", [ + (10, [2, 5]), + (100, [2, 5]), + (13, []), + (432, [2, 3]), + (291, [3, 97]), +]) +def test_prime_divs(number, expected): + assert prime_divs(number) == expected