Skip to content

Commit

Permalink
ShipDict : gestion de l'option -z (--gzip) de merger.py
Browse files Browse the repository at this point in the history
resolves flotpython#45
  • Loading branch information
aollier committed Dec 12, 2020
1 parent 310c913 commit 8ce019f
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 29 deletions.
38 changes: 20 additions & 18 deletions data/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class Compare(object):
"""
An object for comparing a file with its reference version
A class for comparing a file with its reference version
that is expected to be found in <filename>.ref
"""

Expand All @@ -17,15 +17,8 @@ class Compare(object):
re.compile("<color>[0-9a-f]+</color>"),
]

def __init__(self, filename, ref_name=None):
"""
create object from its filename
compute reference filename if not specified
"""
self.filename = filename
self.ref_name = ref_name or f"{self.filename}.ref"

def _bool_compare(self):
@staticmethod
def _bool_compare(fn_fm, fnref_fm):
"""
returns True if both files match - modulo ignored portions
- and False otherwise
Expand All @@ -37,13 +30,13 @@ def _bool_compare(self):
# contents[1] for the reference version
contents = [None, None]

for i, name in enumerate((self.filename, self.ref_name)):
for i, (name, fm) in enumerate((fn_fm, fnref_fm)):
try:
with open(name, "r", newline="\n") as input:
with fm.open(name, mode=fm.READ) as input:
full = input.read()
# remove ignored portions
for ignore in self.ignore_regexps:
full = re.sub(ignore, '', full)
# remove ignored portions
for ignore in Compare.ignore_regexps:
full = ignore.sub('', full)
contents[i] = full
# if anything goes wrong we just return False
except Exception as e:
Expand All @@ -52,13 +45,22 @@ def _bool_compare(self):
# result is True if both contents match
return contents[0] == contents[1]

def compare_and_print(self):
@staticmethod
def compare_and_print(fn_fm, fnref_fm):
"""
Checks for equality and prints a one-liner
returns a boolean that says if both files indeed are equal
Args:
fn_fm: tuple of filename to test and filemanager
fnref_fm: tuple of filename of reference and filemanager
"""
bool_result = self._bool_compare()
filename, _ = fn_fm
ref_name, fm = fnref_fm
# compute reference filename if not specified
ref_name = ref_name or f"{filename}.ref"
bool_result = Compare._bool_compare(fn_fm, (ref_name, fm))
status = "OK" if bool_result else "KO"
message = f"Comparing {self.filename} and {self.ref_name} -> {status}"
message = f"Comparing {filename} and {ref_name} -> {status}"
print(message)
return bool_result
24 changes: 24 additions & 0 deletions data/factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import abc

# application import
import file_manager


class Factory(abc.ABC):

@staticmethod
@abc.abstractmethod
def make_filemanager():
pass

class GzipFileManagerFactory(Factory):

@staticmethod
def make_filemanager():
return file_manager.GzipFileManager()

class TextFileManagerFactory(Factory):

@staticmethod
def make_filemanager():
return file_manager.TextFileManager()
41 changes: 41 additions & 0 deletions data/file_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import abc
import gzip
import contextlib


class FileManager(abc.ABC):

@staticmethod
@abc.abstractmethod
def open(filename, mode):
pass


class GzipFileManager(FileManager):

READ = "rt"
WRITE = "wt"

@staticmethod
@contextlib.contextmanager
def open(filename, mode):
file = gzip.open(filename, encoding="UTF-8", mode=mode, newline="\n")
try:
yield file
finally:
file.close()


class TextFileManager(FileManager):

READ = "r"
WRITE = "w"

@staticmethod
@contextlib.contextmanager
def open(filename, mode):
file = open(filename, encoding="UTF-8", mode=mode, newline="\n")
try:
yield file
finally:
file.close()
25 changes: 17 additions & 8 deletions data/merger.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Version : 3.0

# standard library imports
import gzip
import json
import glob
from argparse import ArgumentParser
#

# application imports
import factory
from shipdict import ShipDict
from kml import KML
from compare import Compare
Expand Down Expand Up @@ -50,6 +48,11 @@ def __init__(self):

self.ship_dict = ShipDict()

if self.args.gzip:
self.factory = factory.GzipFileManagerFactory()
else:
self.factory = factory.TextFileManagerFactory()

def merge(self, json_filenames):
"""
given a list of json filenames, decode the JSON content
Expand Down Expand Up @@ -95,7 +98,8 @@ def write_ships_summary(self, ships, out_name):

print(f"Opening {filename} for listing ships")

with open(filename, 'w', newline="\n") as summary:
tfm = factory.TextFileManagerFactory.make_filemanager()
with tfm.open(filename, tfm.WRITE) as summary:
# one line to say how many ships we have seen
summary.write(f"Found {len(ships)} ships\n")
# ships are expected to be sorted already
Expand Down Expand Up @@ -131,8 +135,8 @@ def write_kml_output(self, ships, out_name):
# message
print(f"Opening {kml_filename} for ship {out_name}")
# open a plain file or compressed file as requested
with gzip.open(kml_filename, 'w', newline="\n") if self.args.gzip \
else open(kml_filename, 'w', newline="\n") as out:
fm = self.factory.make_filemanager()
with fm.open(kml_filename, mode=fm.WRITE) as out:
out.write(contents)
# return filename
return kml_filename
Expand Down Expand Up @@ -199,8 +203,13 @@ def main(self):
else:
# for each of the 2 files, compare contents with the reference
# that is expected to be in this directory with a .ref extension
ok_summary = Compare(summary_filename).compare_and_print()
ok_kml = Compare(kml_filename).compare_and_print()
tfm = factory.TextFileManagerFactory.make_filemanager()
ok_summary = Compare.compare_and_print(
(summary_filename, tfm),
(None, tfm))
ok_kml = Compare.compare_and_print(
(kml_filename, self.factory.make_filemanager()),
("ALL_SHIPS.kml.ref", tfm))
# is everything fine ?
ok = ok_summary and ok_kml
# if so return 0 otherwise 1
Expand Down
16 changes: 13 additions & 3 deletions w6/w6-s8-x1-classes-merger.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Dans les exercices de cette semaine-là nous avions uniquement utilisé des type

+++

On a écrit une application complète, constituée de 4 modules ; on vous donne le code de trois de ces modules et vous devez écrire le module manquant.
On a écrit une application complète, constituée de 6 modules ; on vous donne le code de cinq de ces modules et vous devez écrire le module manquant.

+++

Expand Down Expand Up @@ -175,11 +175,13 @@ Quel que soit le format choisi, une fois installé ceci doit vous donner trois f

+++

Vous pouvez à présent aller chercher les 3 modules suivants :
Vous pouvez à présent aller chercher les 5 modules suivants :

* [`merger.py`](data/merger.py)
* [`compare.py`](data/compare.py)
* [`kml.py`](data/kml.py)
* [`file_manager.py`](data/file_manager.py)
* [`factory.py`](data/factory.py)

et les sauver dans le même répertoire.

Expand All @@ -203,7 +205,7 @@ Votre but dans cet exercice est d'écrire le module manquant `shipdict.py` qui p

Le point d'entrée s'appelle `merger.py`

Il utilise trois modules annexes, qui sont :
Il utilise cinq modules annexes, qui sont :

* `shipdict.py`, qui implémente les classes
* `Position` qui contient une latitude, une longitude, et un timestamp
Expand All @@ -216,6 +218,14 @@ Il utilise trois modules annexes, qui sont :
* `kml.py` qui implémente
* la classe `KML` dans laquelle sont concentrées les fonctions liées à la génération de KML ; c'est notamment en fonction de nos objectifs pédagogiques que ce choix a été fait.

* `file_manager.py`, au travers du module `factory`, qui implémente
* la classe `TextFileManager` qui gère l'ouverture et la fermeture de simples fichiers texte
* la classe `GzipFileManager` qui gère l'ouverture et la fermeture de fichiers texte compressés avec le logiciel gzip

* `factory.py` qui implémente
* la classe `TextFileManagerFactory` qui crée des objets de type `TextFileManager`
* la classe `GzipFileManagerFactory` qui crée des objets de type `GzipFileManager`

+++

##### Lancement
Expand Down

0 comments on commit 8ce019f

Please sign in to comment.