summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHombreLaser <buran@silosneeded.com>2024-03-12 23:46:02 -0600
committerHombreLaser <buran@silosneeded.com>2024-03-12 23:46:02 -0600
commita0fcdc83cbc2b440a5836313b2afd1a35698f5ef (patch)
tree60cf56be85de882b8999d990feaaf2cf4f683dba
parentafd4e795e3a7e7b34e0d3127f11c05c0e7a2fede (diff)
Añade pruebas
-rw-r--r--main.py18
-rw-r--r--src/arg_parser.py18
-rw-r--r--src/program.py52
-rw-r--r--src/table.py11
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/conftest.py36
-rw-r--r--tests/test_delete_at.py4
-rw-r--r--tests/test_get_rows.py4
-rw-r--r--tests/test_insert.py4
-rw-r--r--tests/test_row_at.py6
-rw-r--r--tests/test_search.py4
11 files changed, 132 insertions, 25 deletions
diff --git a/main.py b/main.py
index d785261..f4a1ea6 100644
--- a/main.py
+++ b/main.py
@@ -1,23 +1,13 @@
import sys
from src.table import Table
from src.arg_parser import ArgParser
-
-
-help_string = """CSV utils
- Usage:
- python main.py -f file -c COMMAND ATTRIBUTES
- file: ubicación del archivo csv
-
- Comandos disponibles:
- row-at n: imprimir fila en n
- get-rows n: imprimir primeras n filas
- insert "csv string": insertar fila. La fila debe contener exactamente 3 elementos.
- search "lookup": buscar texto lookup en la tabla.
- """
+from src.program import Program
def main():
- ArgParser()
+ program = Program()
+ program.run()
+
if __name__ == '__main__':
main() \ No newline at end of file
diff --git a/src/arg_parser.py b/src/arg_parser.py
index c2db3bd..a5fdb40 100644
--- a/src/arg_parser.py
+++ b/src/arg_parser.py
@@ -1,4 +1,5 @@
import argparse
+import sys
AVAILABLE_COMMANDS_HELP_STRING = """Available commands:
@@ -6,13 +7,24 @@ AVAILABLE_COMMANDS_HELP_STRING = """Available commands:
get-rows n: print first n rows
insert "csv string": insert row at the end, the row must have exactly 3 elements.
search "lookup": search "lookup" in the table.
+ delete-at n: delete row at nth position
"""
class ArgParser:
- def __init__(self):
+ def __init__(self, args=sys.argv):
self.parser = argparse.ArgumentParser()
self.parser.add_argument('-f', required=True, help='CSV file location')
self.parser.add_argument('-c', required=True, help=AVAILABLE_COMMANDS_HELP_STRING, nargs=2)
- self.args = self.parser.parse_args()
- print(self.args) \ No newline at end of file
+ self.args = self.parser.parse_args(args)
+
+ @property
+ def file(self):
+ return self.args.f
+
+ @property
+ def command(self):
+ return self.args.c
+
+ def print_help(self):
+ self.parser.print_help() \ No newline at end of file
diff --git a/src/program.py b/src/program.py
new file mode 100644
index 0000000..1c43ea7
--- /dev/null
+++ b/src/program.py
@@ -0,0 +1,52 @@
+from src.arg_parser import ArgParser
+from src.table import Table
+from src.exceptions import IncompatibleRowLengthError
+import sys
+
+class Program():
+ def __init__(self, args=sys.argv[1:]):
+ self.arg_parser = ArgParser(args=args)
+ self.table = Table(self.arg_parser.file)
+
+ def _command_arg_to_int(self):
+ try:
+ return int(self.arg_parser.command[1])
+ except ValueError:
+ self.arg_parser.print_help()
+ exit()
+
+ def _print_table_result(self, table):
+ for row in table:
+ print(row)
+
+ def run(self):
+ match self.arg_parser.command[0]:
+ case 'row-at':
+ print(self.table.row_at(self._command_arg_to_int()))
+ case 'get-rows':
+ result = self.table.get_rows(self._command_arg_to_int())
+
+ self._print_table_result(result)
+ case 'insert':
+ new_row = tuple(self.arg_parser.command[1].rsplit(','))
+
+ try:
+ self.table.insert(new_row)
+ print('Row added!')
+ except IncompatibleRowLengthError as error:
+ print(error)
+ case 'search':
+ result = self.table.search(self.arg_parser.command[1])
+
+ if result is not None:
+ print(result)
+ else:
+ print('Not found!')
+ case 'delete-at':
+ try:
+ self.table.delete_at(self._command_arg_to_int())
+ print(f"Row at {self._command_arg_to_int()} deleted")
+ except IndexError:
+ print(f"Couldn't find row at {self._command_arg_to_int()}")
+ case _:
+ arg_parser.print_help() \ No newline at end of file
diff --git a/src/table.py b/src/table.py
index 798fc9f..004bd4d 100644
--- a/src/table.py
+++ b/src/table.py
@@ -9,8 +9,7 @@ ROW_SIZE = 3
class Table:
def __init__(self, file_path: str):
self.csv_params = { 'delimiter': ',', 'quotechar': '"' }
- self.csv_file = open(file_path, 'r+', newline='')
- self.writer = csv.writer(self.csv_file, **self.csv_params)
+ self.csv_file = open(file_path, 'r', newline='')
self.rows = [tuple(row) for row in csv.reader(self.csv_file, **self.csv_params)]
def __del__(self):
@@ -18,7 +17,7 @@ class Table:
self.csv_file.close()
def __write_changes(self):
- with open(f"new_{token_hex(8)}.csv", 'w', newline='') as new_table:
+ with open(f"./new_{token_hex(8)}.csv", 'w', newline='') as new_table:
writer = csv.writer(new_table, **self.csv_params)
for row in self.rows:
writer.writerow(row)
@@ -37,13 +36,9 @@ class Table:
raise IncompatibleRowLengthError(len(new_row))
self.rows.append(new_row)
- self.writer.writerow(new_row)
def delete_at(self, to_delete: int):
- try:
- self.rows.pop(to_delete)
- except IndexError:
- return None
+ self.rows.pop(to_delete)
def search(self, lookup: str):
for row in self.rows:
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..f3dbc41
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,36 @@
+from src.program import Program
+from glob import iglob
+import os
+import pytest
+
+
+@pytest.fixture
+def row_at_program():
+ return Program(args=['-f', './tests/test_table.csv', '-c', 'row-at', '2'])
+
+
+@pytest.fixture
+def get_rows_program():
+ return Program(args=['-f', './tests/test_table.csv', '-c', 'get-rows', '2'])
+
+
+@pytest.fixture
+def insert_program():
+ return Program(args=['-f', './tests/test_table.csv', '-c', 'insert', '1969,Ubik,Philip K. Dick'])
+
+
+@pytest.fixture
+def search_program():
+ return Program(args=['-f', './tests/test_table.csv', '-c', 'search', 'Ten Days that Shook the World'])
+
+
+@pytest.fixture
+def delete_at_program():
+ return Program(args=['-f', './tests/test_table.csv', '-c', 'delete-at', '1'])
+
+
+@pytest.fixture(scope='session', autouse=True)
+def delete_created_csv_files():
+ yield
+ for file in iglob("./new_*.csv"):
+ os.remove(file) \ No newline at end of file
diff --git a/tests/test_delete_at.py b/tests/test_delete_at.py
new file mode 100644
index 0000000..02471d1
--- /dev/null
+++ b/tests/test_delete_at.py
@@ -0,0 +1,4 @@
+def test_delete_at(capsys, delete_at_program):
+ delete_at_program.run()
+
+ assert capsys.readouterr()[0] == 'Row at 1 deleted\n' \ No newline at end of file
diff --git a/tests/test_get_rows.py b/tests/test_get_rows.py
new file mode 100644
index 0000000..51b1c43
--- /dev/null
+++ b/tests/test_get_rows.py
@@ -0,0 +1,4 @@
+def test_get_rows(capsys, get_rows_program):
+ get_rows_program.run()
+
+ assert capsys.readouterr()[0] == "('1985', 'Blood Meridian', 'Cormac McCarthy')\n('1851', 'Moby Dick', 'Herman Melville')\n" \ No newline at end of file
diff --git a/tests/test_insert.py b/tests/test_insert.py
new file mode 100644
index 0000000..caaf7ff
--- /dev/null
+++ b/tests/test_insert.py
@@ -0,0 +1,4 @@
+def test_insert(capsys, insert_program):
+ insert_program.run()
+
+ assert capsys.readouterr()[0] == 'Row added!\n' \ No newline at end of file
diff --git a/tests/test_row_at.py b/tests/test_row_at.py
new file mode 100644
index 0000000..6b7c379
--- /dev/null
+++ b/tests/test_row_at.py
@@ -0,0 +1,6 @@
+def test_row_at(capsys, row_at_program):
+ row_at_program.run()
+
+ assert capsys.readouterr()[0].startswith(
+ "('1919', 'Ten Days that Shook the World', 'John Reed')"
+ ) \ No newline at end of file
diff --git a/tests/test_search.py b/tests/test_search.py
new file mode 100644
index 0000000..ecdc550
--- /dev/null
+++ b/tests/test_search.py
@@ -0,0 +1,4 @@
+def test_search(capsys, search_program):
+ search_program.run()
+
+ assert capsys.readouterr()[0] == "('1919', 'Ten Days that Shook the World', 'John Reed')\n" \ No newline at end of file