Skip to content

Commit

Permalink
feat(Waiter): simplify Waiter class by making DictConfig argument req…
Browse files Browse the repository at this point in the history
…uired at instantiation time

now Waiter is instanciated in __init__.py and cli.py and passed to components that need it
it is not imported from __init__.py
change scheduled_tasks.py accordingly
  • Loading branch information
Michele-Alberti committed Jan 3, 2025
1 parent d0ca762 commit 9b351a4
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 69 deletions.
12 changes: 4 additions & 8 deletions dlunch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

# Relative imports
from . import models
from . import core
from .core import __version__
from .core import __version__, Waiter
from . import gui
from .auth import AuthUser

Expand All @@ -22,10 +21,6 @@
"pkg_path", lambda pkg: str(importlib.resources.files(pkg))
)

# APP WAITER ------------------------------------------------------------------
# Create the waiter instance
waiter = core.Waiter()

# APP FACTORY FUNCTION --------------------------------------------------------


Expand All @@ -40,9 +35,10 @@ def create_app(config: DictConfig) -> pn.Template:
"""
log.info("starting initialization process")

# Create an instance of AuthUser (which has also an instance of AuthContext
# among its attributes)
# Create an instance of AuthUser (that includes an instance of AuthContext)
# and a waiter instance
auth_user = AuthUser(config=config)
waiter = Waiter(config=config)

log.info("initialize database")
# Create tables
Expand Down
6 changes: 1 addition & 5 deletions dlunch/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from . import auth
from . import models
from . import create_app, create_backend, waiter
from . import create_app, create_backend

# LOGGER ----------------------------------------------------------------------
log: logging.Logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -38,10 +38,6 @@ def run_app(config: DictConfig) -> None:
config (DictConfig): hydra configuration object.
"""

# Configure waiter
log.info("set waiter config")
waiter.set_config(config)

# Set auth configurations
log.info("set auth context and encryption")
auth_context = auth.AuthContext(config=config)
Expand Down
6 changes: 3 additions & 3 deletions dlunch/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .models import create_database, create_engine, SCHEMA, Data, metadata_obj

# Waiter Imports
from . import waiter
from .core import Waiter

# Auth imports
from . import auth
Expand Down Expand Up @@ -50,7 +50,7 @@ def cli(ctx, hydra_overrides: tuple | None):

# Instance auth context and waiter
auth_context = auth.AuthContext(config=config)
waiter.set_config(config)
waiter = Waiter(config=config)

# Store common objects in context
ctx.obj = {
Expand Down Expand Up @@ -247,7 +247,7 @@ def clean_tables(obj):

# Drop table
try:
waiter.clean_tables()
obj["waiter"].clean_tables()
click.secho("done", fg="green")
except Exception as e:
# Generic error
Expand Down
72 changes: 22 additions & 50 deletions dlunch/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,17 @@ class Waiter:
"""Class that defines main functions used to manage Data-Lunch operations.
Args:
config (DictConfig| None): Hydra configuration object. Defaults to None.
config (DictConfig| None): Hydra configuration object.
Raise:
ValueError: when calling (unmangled) methods, if the configuration is not set.
"""

def __init__(self, config: DictConfig | None = None):
self.config: DictConfig | None = None
def __init__(self, config: DictConfig):
self.config: DictConfig = config
"""Hydra configuration object"""

# Define decorator to raise an error if the configuration is not set
def _common_decorator(func):
def wrapper(*args, **kwargs):
if self.config is None:
raise ValueError("waiter configuration is not set")
return func(*args, **kwargs)

return wrapper

# Set decorator to unmangled methods (do not apply to set_config method)
for method_name in [
item
for item in dir(self)
if not item.startswith("_") and not (item == "set_config")
]:
attr = getattr(self, method_name)
# Check if the attribute is a method
if callable(attr):
wrapped = _common_decorator(attr)
setattr(self, method_name, wrapped)
self.auth_user: AuthUser = AuthUser(config=config)
"""Object with authenticated user data and related methods"""

def set_config(self, config: DictConfig):
"""Set the configuration for the Waiter instance.
Expand All @@ -84,7 +65,8 @@ def set_config(self, config: DictConfig):
"""
self.config = config

def get_host_name(self) -> str:
@property
def hostname(self) -> str:
"""Return hostname.
This function behavior changes if called from localhost, Docker container or
Expand Down Expand Up @@ -308,9 +290,6 @@ def reload_menu(
gi (gui.GraphicInterface): graphic interface object (used to interact with Panel widgets).
"""

# Read user from Panel state
auth_user = AuthUser(config=self.config)

# Create session
session = models.create_session(self.config)

Expand All @@ -332,13 +311,13 @@ def reload_menu(
# Check guest override button status (if not in table use False)
gi.toggle_guest_override_button.value = models.get_flag(
config=self.config,
id=f"{auth_user.name}_guest_override",
id=f"{self.auth_user.name}_guest_override",
value_if_missing=False,
)

# Set no more orders toggle button and the change order time button
# visibility and activation
if auth_user.is_guest(allow_override=False):
if self.auth_user.is_guest(allow_override=False):
# Deactivate the no_more_orders_button for guest users
gi.toggle_no_more_order_button.disabled = True
gi.toggle_no_more_order_button.visible = False
Expand All @@ -354,7 +333,7 @@ def reload_menu(
gi.change_order_time_takeaway_button.visible = True

# Guest graphic configuration
if auth_user.is_guest():
if self.auth_user.is_guest():
# If guest show guest type selection group
gi.person_widget.widgets["guest"].disabled = False
gi.person_widget.widgets["guest"].visible = True
Expand Down Expand Up @@ -583,11 +562,10 @@ def reload_menu(
)
# Stats top text
stats_and_info_text = gi.build_stats_and_info_text(
auth_user=auth_user,
auth_user=self.auth_user,
df_stats=df_stats,
user=auth_user.name,
version=__version__,
host_name=self.get_host_name(),
host_name=self.hostname,
stylesheets=[self.config.panel.gui.css_files.stats_info_path],
)
# Remove NotAGuest (non-guest users)
Expand Down Expand Up @@ -637,9 +615,6 @@ def send_order(
gi (gui.GraphicInterface): graphic interface object (used to interact with Panel widgets).
"""

# Read user from Panel state
auth_user = AuthUser(config=self.config)

# Get username updated at each key press
username_key_press = gi.person_widget._widgets["username"].value_input

Expand Down Expand Up @@ -668,12 +643,12 @@ def send_order(
# If auth is active, check if a guests is using a name reserved to a
# privileged user
if (
auth_user.is_guest()
self.auth_user.is_guest()
and (
username_key_press
in auth_user.auth_context.list_privileged_users()
in self.auth_user.auth_context.list_privileged_users()
)
and (auth_user.auth_context.is_auth_active())
and (self.auth_user.auth_context.is_auth_active())
):
pn.state.notifications.error(
f"{username_key_press} is a reserved name<br>Please choose a different one",
Expand All @@ -690,16 +665,16 @@ def send_order(

# Check if a privileged user is ordering for an invalid name
if (
not auth_user.is_guest()
not self.auth_user.is_guest()
and (
username_key_press
not in (
name
for name in auth_user.auth_context.list_privileged_users()
for name in self.auth_user.auth_context.list_privileged_users()
if name != "guest"
)
)
and (auth_user.auth_context.is_auth_active())
and (self.auth_user.auth_context.is_auth_active())
):
pn.state.notifications.error(
f"{username_key_press} is not a valid name<br>for a privileged user<br>Please choose a different one",
Expand Down Expand Up @@ -733,7 +708,7 @@ def send_order(
try:
# Add User
# Do not pass guest for privileged users (default to NotAGuest)
if auth_user.is_guest():
if self.auth_user.is_guest():
new_user = models.Users(
id=username_key_press,
guest=person.guest,
Expand Down Expand Up @@ -818,9 +793,6 @@ def delete_order(
gi (gui.GraphicInterface): graphic interface object (used to interact with Panel widgets).
"""

# Read user from Panel state
auth_user = AuthUser(config=self.config)

# Get username, updated on every keypress
username_key_press = gi.person_widget._widgets["username"].value_input

Expand Down Expand Up @@ -850,12 +822,12 @@ def delete_order(
# If auth is active, check if a guests is deleting an order of a
# privileged user
if (
auth_user.is_guest()
self.auth_user.is_guest()
and (
username_key_press
in auth_user.auth_context.list_privileged_users()
in self.auth_user.auth_context.list_privileged_users()
)
and (auth_user.auth_context.is_auth_active())
and (self.auth_user.auth_context.is_auth_active())
):
pn.state.notifications.error(
f"You do not have enough privileges<br>to delete<br>{username_key_press}'s order",
Expand Down
3 changes: 1 addition & 2 deletions dlunch/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,6 @@ def build_stats_and_info_text(
self,
auth_user: AuthUser,
df_stats: pd.DataFrame,
user: str,
version: str,
host_name: str,
stylesheets: list = [],
Expand Down Expand Up @@ -1022,7 +1021,7 @@ def build_stats_and_info_text(
<path d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14z" />
</svg>
<span>
<strong>User:</strong> <i>{user}</i>
<strong>User:</strong> <i>{auth_user.name}</i>
</span>
</div>
<div class="icon-container">
Expand Down
5 changes: 4 additions & 1 deletion dlunch/scheduled_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

from . import auth
from . import cloud
from . import core
from . import models
from . import waiter

# LOGGER ----------------------------------------------------------------------
log: logging.Logger = logging.getLogger(__name__)
Expand All @@ -32,6 +32,9 @@ def clean_files_db(config: DictConfig) -> callable:
callable: function to be scheduled.
"""

# Create instance of Waiter
waiter = core.Waiter(config=config)

async def scheduled_function() -> None:
"""Clean menu, orders, users and flags tables. Delete also local files."""
log.info(f"clean task (files and db) executed at {dt.datetime.now()}")
Expand Down

0 comments on commit 9b351a4

Please sign in to comment.