Add a new json format

master
Salvo 'LtWorf' Tomaselli 2020-08-24 17:55:13 +07:00
parent 2e5d18f418
commit c4bc74d612
No known key found for this signature in database
GPG Key ID: B3A7CF0C801886CF
3 changed files with 60 additions and 25 deletions

@ -57,7 +57,7 @@ def load_relations():
print ("Loading relation %s with name %s..." % (i, relname)) print ("Loading relation %s with name %s..." % (i, relname))
rels[relname] = relation.Relation.load('%s%s' % (examples_path, i)) rels[relname] = relation.Relation.load_csv('%s%s' % (examples_path, i))
print('done') print('done')
@ -239,7 +239,7 @@ def run_test(testname):
o_result = None o_result = None
try: try:
result_rel = relation.Relation.load('%s%s.result' % (tests_path, testname)) result_rel = relation.Relation.load_csv('%s%s.result' % (tests_path, testname))
query = readfile('%s%s.query' % (tests_path, testname)).strip() query = readfile('%s%s.query' % (tests_path, testname)).strip()
o_query = optimizer.optimize_all(query, rels) o_query = optimizer.optimize_all(query, rels)

@ -90,8 +90,15 @@ class UserInterface:
def load(self, filename: str, name: str) -> None: def load(self, filename: str, name: str) -> None:
'''Loads a relation from file, and gives it a name to '''Loads a relation from file, and gives it a name to
be used in subsequent queries.''' be used in subsequent queries.
rel = Relation.load(filename)
Files ending with .csv are loaded as csv, the others are
loaded as json.
'''
if filename.endswith('.csv'):
rel = Relation.load_csv(filename)
else:
rel = Relation.load(filename)
self.set_relation(name, rel) self.set_relation(name, rel)
def unload(self, name: str) -> None: def unload(self, name: str) -> None:
@ -161,8 +168,12 @@ class UserInterface:
if len(name) == 0: if len(name) == 0:
return None return None
if (name.endswith(".csv")): # removes the extension # Removing the extension
name = name[:-4] try:
pos = name.rindex('.')
except ValueError:
return None
name = name[:pos]
if not is_valid_relation_name(name): if not is_valid_relation_name(name):
return None return None

@ -19,7 +19,6 @@
# This module provides a classes to represent relations and to perform # This module provides a classes to represent relations and to perform
# relational operations on them. # relational operations on them.
import csv
from itertools import chain, repeat, product as iproduct from itertools import chain, repeat, product as iproduct
from collections import deque from collections import deque
from typing import FrozenSet, Iterable, List, Dict, Tuple from typing import FrozenSet, Iterable, List, Dict, Tuple
@ -62,21 +61,62 @@ class Relation:
content: FrozenSet[Tuple[CastValue, ...]] content: FrozenSet[Tuple[CastValue, ...]]
@staticmethod @staticmethod
def load(filename: Union[str, Path]) -> 'Relation': def load_csv(filename: Union[str, Path]) -> 'Relation':
''' '''
Load a relation object from a csv file. Load a relation object from a csv file.
The 1st row is the header and the other rows are the content. The 1st row is the header and the other rows are the content.
Types will be inferred automatically
''' '''
import csv
with open(filename) as fp: with open(filename) as fp:
reader = csv.reader(fp) # Creating a csv reader reader = csv.reader(fp) # Creating a csv reader
header = Header(next(reader)) # read 1st line header = Header(next(reader)) # read 1st line
return Relation.create_from(header, reader) return Relation.create_from(header, reader)
@staticmethod
def load(filename: Union[str, Path]) -> 'Relation':
'''
Load a relation object from a json file.
'''
with open(filename) as fp:
from json import load as jload
from typedload import load
return load(jload(fp), Relation)
def save(self, filename: Union[Path, str]) -> None:
'''
Saves the relation in a file.
Will save using the json format
'''
with open(filename, 'w') as fp:
from json import dump as jdump
from typedload import dump
jdump(dump(self), fp)
def save_csv(self, filename: Union[Path, str]) -> None:
'''
Saves the relation in a file. Will save using the csv
format as defined in RFC4180.
'''
import csv
with open(filename, 'w') as fp:
writer = csv.writer(fp) # Creating csv writer
# It wants an iterable containing iterables
head = (self.header,)
writer.writerows(head)
# Writing content, already in the correct format
writer.writerows(self.content)
@staticmethod @staticmethod
def create_from(header: Iterable[str], content: Iterable[List[str]]) -> 'Relation': def create_from(header: Iterable[str], content: Iterable[List[str]]) -> 'Relation':
''' '''
Iterator for the header, and iterator for the content. Iterator for the header, and iterator for the content.
This will infer types.
''' '''
header = Header(header) header = Header(header)
r_content = [] r_content = []
@ -105,22 +145,6 @@ class Relation:
def __contains__(self, key): def __contains__(self, key):
return key in self.content return key in self.content
def save(self, filename: Union[Path, str]) -> None:
'''
Saves the relation in a file. Will save using the csv
format as defined in RFC4180.
'''
with open(filename, 'w') as fp:
writer = csv.writer(fp) # Creating csv writer
# It wants an iterable containing iterables
head = (self.header,)
writer.writerows(head)
# Writing content, already in the correct format
writer.writerows(self.content)
def _rearrange(self, other: 'Relation') -> 'Relation': def _rearrange(self, other: 'Relation') -> 'Relation':
'''If two relations share the same attributes in a different order, this method '''If two relations share the same attributes in a different order, this method
will use projection to make them have the same attributes' order. will use projection to make them have the same attributes' order.
@ -317,7 +341,7 @@ class Relation:
added = True added = True
# If it didn't partecipate, adds it # If it didn't partecipate, adds it
if not added: if not added:
item = chain(i, repeat(None, len(noid))) #FIXME item = chain(i, repeat(None, len(noid)))
content.append(tuple(item)) content.append(tuple(item))
return Relation(header, frozenset(content)) return Relation(header, frozenset(content))