Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
centaurialpha committed Apr 7, 2024
1 parent 0aa4238 commit 790e803
Show file tree
Hide file tree
Showing 29 changed files with 272 additions and 369 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ line-length = 100

[tool.ruff.lint]
select = [ "A", "B", "C90", "D", "E", "EM", "F", "I", "N", "PTH", "RUF", "W",]
ignore = ["D103", "D102", "D101", "D100", "D107", "D104", "D105", "EM101"]
ignore = ["D103", "D102", "D101", "D100", "D107", "D104", "D105", "EM101", "N802", "N815", "EM102"]
exclude = ["windows/*", "tests/*"]
72 changes: 34 additions & 38 deletions src/pireal/core/relation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@

# This module is based on Relational: <https://github.com/ltworf/relational>

import re
import itertools
import re

from pireal.utils import eval_expr
from pireal.core.rtypes import RType
from pireal.core.ordered_set import OrderedSet
from pireal.core.rtypes import RType
from pireal.utils import eval_expr

IS_VALID_FIELD_NAME = re.compile("^[_á-úa-zA-Z][_á-úa-zA-Z0-9]*$")


class Error(Exception):
"""Base exception"""
"""Base exception."""


class FieldError(Error):
Expand All @@ -43,7 +43,7 @@ def __init__(self, campo, msg=None):


class InvalidFieldNameError(FieldError):
"""Excepción lanzada cuando un nombre de campo no es válido"""
"""Excepción lanzada cuando un nombre de campo no es válido."""

def __init__(self, campo, msg=None):
super().__init__(
Expand All @@ -59,7 +59,7 @@ def __init__(self, campo, msg=None):


class FieldNotInHeaderError(FieldError):
"""Excepción lanzada cuando un campo no existe en la relación"""
"""Excepción lanzada cuando un campo no existe en la relación."""

def __init__(self, campo, relacion, msg=None):
super().__init__(
Expand All @@ -69,8 +69,11 @@ def __init__(self, campo, relacion, msg=None):


class WrongSizeError(Error):
"""Excepción lanzada cuando se trata de insertar un tamaño de
tuplas diferente a los que acepta la relación"""
"""Wrong Size.
Excepción lanzada cuando se trata de insertar un tamaño de
tuplas diferente a los que acepta la relación
"""

def __init__(self, expected, got, msg=None):
if msg is None:
Expand All @@ -89,13 +92,13 @@ class UnionCompatibleError(Error):


def union_compatible(operation):
"""Decorador que comprueba que dos relaciones sean compatibles"""
"""Decorador que comprueba que dos relaciones sean compatibles."""

def inner(self, *args, **kwargs):
header_other = args[0].header
if len(self._header) != len(header_other):
raise UnionCompatibleError(
"Union not compatible for '{}'".format(operation.__name__)
f"Union not compatible for '{operation.__name__}'"
)
return operation(self, *args, **kwargs)

Expand Down Expand Up @@ -134,37 +137,33 @@ def update(self, row, column, new_value):
self.content[row] = tuple(old)

def append_row(self):
"""Agrega una fila/tupla al final"""

"""Agrega una fila/tupla al final."""
nulls = []
for _ in range(self.degree()):
nulls.append("null ({})".format(self._null_count))
self._null_count += 1
self.insert(tuple(nulls))

def cardinality(self):
"""Devuelve la cantidad de filas de la relación"""

"""Devuelve la cantidad de filas de la relación."""
return len(self.content)

def degree(self):
"""Devuelve el grado de la relación"""

"""Devuelve el grado de la relación."""
return len(self._header)

def project(self, *args):
"""
The project operator returns a new relation.
"""Return a new relation.
Extract columns (attributes) resulting in a vertical subset of
attributes of the relation
"""

indexes = []
for arg in args:
try:
indexes.append(self._header.index(arg))
except ValueError as reason:
raise FieldNotInHeaderError(str(reason).split()[0], self.name)
raise FieldNotInHeaderError(str(reason).split()[0], self.name) from None
# New fields
header = [self._header[i] for i in indexes]
# New relation
Expand All @@ -177,11 +176,10 @@ def project(self, *args):
return new_relation

def select(self, expression):
"""
The select operator returns a new relation with the tuples that
satisfy an expression.
"""
"""Return a new relation.
with the tuples thatsatisfy an expression.
"""
new_relation = Relation()
new_relation.header = self._header

Expand Down Expand Up @@ -254,11 +252,11 @@ def fouter(self, other_relation):

@union_compatible
def union(self, other_relation):
"""
The union is defined as: R ∪ S. Returns the set of tuples in R,
"""R U S.
Returns the set of tuples in R,
or S, or both. R and S must be compatible unions.
"""

new_relation = Relation()
new_relation.header = self._header
content = self.content.union(other_relation.content)
Expand All @@ -270,11 +268,11 @@ def union(self, other_relation):

@union_compatible
def difference(self, other_relation):
"""
The difference is defined as: R - S. It is the set of all tuples
"""R - S.
It is the set of all tuples
in R, but not in S. R and S must be compatible unions
"""

new_relation = Relation()
new_relation.header = self._header
content = self.content - other_relation.content
Expand All @@ -284,11 +282,11 @@ def difference(self, other_relation):

@union_compatible
def intersect(self, other_relation):
"""
The intersection is defined as: R ∩ S. corresponds to the set of
"""R ∩ S.
Corresponds to the set of
all tuples in R and S, R and S compatible unions.
"""

new_relation = Relation()
new_relation.header = self._header
content = self.content.intersection(other_relation.content)
Expand All @@ -299,14 +297,14 @@ def intersect(self, other_relation):
return new_relation

def product(self, other_relation):
"""
The cartesian product is defined as: R x S, its outline
"""R x S.
its outline
corresponds to a combination of all tuples in R with each S
tuples, and attributes corresponding to those of R followed by S.
This method throws an exception when you are duplicate field names
"""

for field in self._header:
if field in other_relation.header:
raise DuplicateFieldError(field)
Expand All @@ -321,8 +319,6 @@ def product(self, other_relation):
return new_relation

def __str__(self):
"""Magic method. Returns a representation of the relation"""

header = ""
for field in self._header:
header += "| " + field.center(10) + " "
Expand Down
4 changes: 0 additions & 4 deletions src/pireal/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with Pireal; If not, see <http://www.gnu.org/licenses/>.

"""
Metadata
"""

__author__ = "Gabriel Acosta"
__email__ = "acostadariogabriel at gmail"
__source_code__ = "https://github.com/centaurialpha/pireal"
Expand Down
53 changes: 18 additions & 35 deletions src/pireal/gui/central_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,32 @@
# You should have received a copy of the GNU General Public License
# along with Pireal; If not, see <http://www.gnu.org/licenses/>.

import os
import csv
import logging
from pathlib import Path
import os
from collections import defaultdict
from pathlib import Path

from PyQt6.QtWidgets import QWidget
from PyQt6.QtWidgets import QVBoxLayout
from PyQt6.QtWidgets import QStackedWidget
from PyQt6.QtWidgets import QFileDialog
from PyQt6.QtWidgets import QMessageBox
from PyQt6.QtGui import QShortcut

from PyQt6.QtGui import QKeySequence
from PyQt6.QtCore import Qt
from PyQt6.QtCore import QSettings
from PyQt6.QtCore import QSettings, Qt
from PyQt6.QtGui import QKeySequence, QShortcut
from PyQt6.QtWidgets import (
QFileDialog,
QMessageBox,
QStackedWidget,
QVBoxLayout,
QWidget,
)

import pireal
from pireal.dirs import EXAMPLE_DB_FILENAME
from pireal import settings
from pireal.core import (
file_manager,
pfile,
)
from pireal import translations as tr
from pireal.core import file_manager, pfile
from pireal.dirs import DATA_SETTINGS, EXAMPLE_DB_FILENAME
from pireal.gui import start_page
from pireal.gui.database_container import DatabaseContainer
from pireal.gui.dialogs import (
preferences,
new_relation_dialog,
)
from pireal.gui.dialogs import new_relation_dialog, preferences
from pireal.gui.dialogs.new_database_dialog import DBInputDialog
from pireal.gui.lateral_widget import RelationItemType
from pireal.dirs import DATA_SETTINGS
from pireal import translations as tr

# Logger
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -117,8 +109,8 @@ def rdb_container_to_pdb_container(self):

def create_database(self):
"""Show a wizard widget to create a new database,
only have one database open at time."""

only have one database open at time.
"""
if self.created:
return self.__say_about_one_db_container_at_time()
db_container_filepath = DBInputDialog.ask_db_name(parent=self)
Expand Down Expand Up @@ -248,11 +240,9 @@ def save_query_as(self):
db_container.save_query_as()

def __sanitize_data(self, data):
"""
Este método convierte el contenido de la base de datos a un
"""Este método convierte el contenido de la base de datos a un
diccionario para un mejor manejo despues
"""

# FIXME: controlar cuando al final de la línea hay una coma
data_dict = defaultdict(list)
for line_count, line in enumerate(data.splitlines()):
Expand Down Expand Up @@ -281,7 +271,6 @@ def __sanitize_data(self, data):

def remove_last_widget(self):
"""Remove last widget from stacked"""

widget = self.stack.widget(self.stack.count() - 1)
self.stack.removeWidget(widget)

Expand All @@ -295,7 +284,6 @@ def close_query(self):

def close_database(self) -> None:
"""Close the database and return to the main widget"""

pireal_instance = pireal.get_pireal_instance()
db_container = pireal_instance.db_container
if db_container is None:
Expand Down Expand Up @@ -450,7 +438,6 @@ def _create_relation(relation, relation_name):

def load_relation(self, filename=""):
"""Load Relation file"""

filenames = []
if not filename:
if self._last_open_folder is None:
Expand Down Expand Up @@ -478,24 +465,20 @@ def load_relation(self, filename=""):

def add_start_page(self):
"""This function adds the Start Page to the stacked widget"""

sp = start_page.StartPage()
self.add_widget(sp)

def show_settings(self):
"""Show settings dialog on stacked"""

settings_dialog = preferences.SettingsDialog(self)
settings_dialog.exec()

def widget(self, index):
"""Returns the widget at the given index"""

return self.stack.widget(index)

def add_widget(self, widget):
"""Appends and show the given widget to the Stacked"""

index = self.stack.addWidget(widget)
self.stack.setCurrentIndex(index)

Expand Down
Loading

0 comments on commit 790e803

Please sign in to comment.