Skip to content

Commit

Permalink
Merge pull request #32 from IBM/v0.1.2.2b
Browse files Browse the repository at this point in the history
V0.1.2.2
  • Loading branch information
victorterpstra authored Dec 9, 2022
2 parents 30348da + 9e2df16 commit 0dc1630
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 28 deletions.
23 changes: 21 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]## [0.1.2.1b0]
## [Unreleased]## [0.1.2.2b3]
### Changed
- setup.py avoids import of dse_do_utils to get __version__
- Removed unused import in dash_common_utils causing failure in PyCharm debug mode

## [0.1.2.1] - 2002-04-28
## [0.1.2.2b2] - 2022-11-15
### Changed
- DoDashApp.read_scenario_tables_from_db_cached only reads tables in the schema, skips others without warning.
- Enabled virtualization in DashTables (Prepare data and Explore Solution)
- Remove restriction on SQLAlchemy version < 1.4

## [0.1.2.2b1] - 2022-10-17
### Changed
- DashApp.run_server(self, **kwargs) with arguments for dash app.run_server()
- Enabled write output to DB after run model.
### Removed
- DashApp.set_run_server_kwargs()

## [0.1.2.2b0] - 2022-09-22
### Changed
- Stop Server button now uses os.kill() instead of deprecated Werkzeug callback

## [0.1.2.1] - 2022-04-28
### Changed
### Added
- Customize the 'brand' name of the dashboard by overriding DashApp.get_navbar_brand_children
Expand Down
41 changes: 30 additions & 11 deletions dse_do_dashboard/dash_app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright IBM All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

import signal
from abc import ABC
from typing import Dict, Optional, List

Expand Down Expand Up @@ -69,7 +69,8 @@ def __init__(self, logo_file_name: str = 'IBM.png',
self.run_server_kwargs: Dict = {} # {"host": "localhost"}

def set_run_server_kwargs(self, **run_server_kwargs):
"""Use to set input arguments for Dash.run_server(), in addition to `debug` and `port`.
"""DEPRECATED (also non-functional). Use `self.run_server(self, **kwargs)` to pass additional arguments.
Use to set input arguments for Dash.run_server(), in addition to `debug` and `port`.
For instance, running locally on a Mac requires host='localhost'. """
if run_server_kwargs is not None:
self.run_server_kwargs = run_server_kwargs
Expand Down Expand Up @@ -112,15 +113,32 @@ def create_dash_app(self):
app.config.suppress_callback_exceptions = True
return app

def run_server(self):
"""Runs the Dash server.
def run_server(self, **kwargs):
'''
Runs the Dash server.
To be called from index.py::
if __name__ == '__main__':
DA.run_server()
"""
self.app.run_server(debug=self.dash_debug, port=self.port, **self.run_server_kwargs)
'''

if 'debug' not in kwargs:
kwargs['debug'] = self.dash_debug
if 'port' not in kwargs:
kwargs['port'] = self.port

self.app.run_server(**kwargs)

# def run_server(self):
# """Runs the Dash server.
# To be called from index.py::
#
# if __name__ == '__main__':
# DA.run_server()
#
# """
# self.app.run_server(debug=self.dash_debug, port=self.port, **self.run_server_kwargs)

def config_cache(self):
self.cache = Cache()
Expand Down Expand Up @@ -481,11 +499,12 @@ def shutdown(self):
"""Shuts-down the Flash web-server, releasing the port.
Relevant in CPD, so the port gets released immediately.
"""
from flask import request
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
os.kill(os.getpid(), signal.SIGTERM)
# from flask import request
# func = request.environ.get('werkzeug.server.shutdown')
# if func is None:
# raise RuntimeError('Not running with the Werkzeug Server')
# func()

def get_table_schema(self, table_name) -> Optional[ScenarioTableSchema]:
pass
25 changes: 22 additions & 3 deletions dse_do_dashboard/do_dash_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,21 +358,40 @@ def read_scenario_tables_from_db_cached(self, scenario_name: str,
Is called from dse_do_dashboard.DoDashApp to create the PlotlyManager."""

if input_table_names is None:
# input_table_names = list(self.dbm.input_db_tables.keys()) #This is not consistent with implementation in ScenarioDbManager! Replace by empty list
# input_table_names = list(self.dbm.input_db_tables.keys()) # This is not consistent with implementation in ScenarioDbManager! Replace by empty list
input_table_names = []
if 'Scenario' in input_table_names: input_table_names.remove('Scenario') # Remove the scenario table
if output_table_names is None: # load all tables by default
output_table_names = self.dbm.output_db_tables.keys()

# VT 2022-09-12: Only read tables that exist in schema:
# TODO: test and enable this code to handle optional tables in DB, like the Warehouse, WarehouseProperties, etc
# input_table_names_in_schema = []
# for input_table_name in input_table_names:
# if input_table_name in self.dbm.input_db_tables.keys():
# input_table_names_in_schema.append(input_table_name)
# else:
# print(f"Warning: DODashApp.read_scenario_tables_from_db_cached: input table {input_table_name} not in schema. Table not read.")
#
# output_table_names_in_schema = []
# for output_table_name in output_table_names:
# if output_table_name in self.dbm.output_db_tables.keys():
# output_table_names_in_schema.append(output_table_name)
# else:
# print(f"Warning: DODashApp.read_scenario_tables_from_db_cached: output table {output_table_name} not in schema. Table not read.")

inputs = {}
for scenario_table_name in input_table_names:
# print(f"read input table {scenario_table_name}")
inputs[scenario_table_name] = self.read_scenario_table_from_db_cached(scenario_name, scenario_table_name)
# TODO: skip scenario_table_name if not in schema
if scenario_table_name in self.dbm.input_db_tables.keys():
inputs[scenario_table_name] = self.read_scenario_table_from_db_cached(scenario_name, scenario_table_name)

outputs = {}
for scenario_table_name in output_table_names:
# print(f"read output table {scenario_table_name}")
outputs[scenario_table_name] = self.read_scenario_table_from_db_cached(scenario_name, scenario_table_name)
if scenario_table_name in self.dbm.output_db_tables.keys():
outputs[scenario_table_name] = self.read_scenario_table_from_db_cached(scenario_name, scenario_table_name)
return inputs, outputs

########################################################################################
Expand Down
5 changes: 4 additions & 1 deletion dse_do_dashboard/main_pages/prepare_data_page_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import pandas as pd
import dash
from dash.dash_table.Format import Format
from dash.exceptions import PreventUpdate

from dse_do_dashboard.main_pages.main_page import MainPage
Expand Down Expand Up @@ -115,6 +116,7 @@ def get_data_table(self, df, table_schema: Optional[ScenarioTableSchema] = None,
],
fixed_rows={'headers': True},
editable=editable,
virtualization=True,
# fixed_columns={'headers': False, 'data': 0}, # Does NOT create a horizontal scroll bar
filter_action="native",
sort_action="native",
Expand All @@ -127,7 +129,8 @@ def get_data_table(self, df, table_schema: Optional[ScenarioTableSchema] = None,
'font_size': '12px',
'textAlign': 'left'},
style_table={
'maxHeight': '400px',
'maxHeight': '600px',
# 'height': '800',
'overflowY': 'scroll'
},
style_header={
Expand Down
11 changes: 8 additions & 3 deletions dse_do_dashboard/utils/dash_common_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
##########################################################################
# Generic Schema NamedTuple classes
##########################################################################
from dash.dash_table.Format import Format


class ForeignKeySchema(NamedTuple):
table_name: str
foreign_keys: List[str]
Expand Down Expand Up @@ -97,11 +100,12 @@ def get_data_table(df, table_schema: Optional[ScenarioTableSchema] = None, edita
id=data_table_id,
data=df.to_dict('records'),
columns=[
{'name': i, 'id': i, 'type': table_type(df[i])}
{'name': i, 'id': i, 'type': table_type(df[i])} # TODO: format 'thousands' separator with: 'format':Format().group(True) or , 'format': Format(group=',', precision=0)
for i in df.columns
],
fixed_rows={'headers': True},
editable=editable,
virtualization=True,
# fixed_columns={'headers': False, 'data': 0}, # Does NOT create a horizontal scroll bar
filter_action="native",
sort_action="native",
Expand All @@ -114,7 +118,7 @@ def get_data_table(df, table_schema: Optional[ScenarioTableSchema] = None, edita
'font_size': '12px',
'textAlign': 'left'},
style_table={
'maxHeight': '400px',
'maxHeight': '800px',
'overflowY': 'scroll'
},
style_header={
Expand Down Expand Up @@ -154,6 +158,7 @@ def get_editable_data_table(df, table_schema: Optional[ScenarioTableSchema]=None
for i in df.columns
],
fixed_rows={'headers': True},
# page_size=20,
editable=True,
# fixed_columns={'headers': False, 'data': 0}, # Does NOT create a horizontal scroll bar
filter_action="native",
Expand Down Expand Up @@ -251,7 +256,7 @@ def get_pivot_table_card_children(df, scenario_name, table_name, pivot_config: O

#####################################
import functools
import plotly.express as px
# import plotly.express as px
import plotly.graph_objects as go
import traceback

Expand Down
5 changes: 3 additions & 2 deletions dse_do_dashboard/utils/domodelrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ def run_model(self, inputs: Inputs) -> Outputs:
return {}

def update_outputs(self, outputs: Outputs):
pass
# self.dbm.update_scenario_output_tables_in_db(scenario_name=self.scenario_name, outputs=outputs)
# print("Update output tables in DB")
self.dbm.update_scenario_output_tables_in_db(scenario_name=self.scenario_name, outputs=outputs)
# print("Done update output tables in DB")


class DoNotebookModelRunner(DoModelRunner):
Expand Down
2 changes: 1 addition & 1 deletion dse_do_dashboard/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
See https://stackoverflow.com/questions/458550/standard-way-to-embed-version-into-python-package
"""

__version__ = "0.1.2.1"
__version__ = "0.1.2.2b3"
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# For DSE_DO_Dashboard:
dash~=2.0.0
dash>=2.0.0
## gunicorn==19.9.0 # May not be necessary
flask_caching==1.10.1
dash_bootstrap_components==1.0.2
Expand Down
30 changes: 26 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright IBM All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

import os
import setuptools

###########################################################
Expand All @@ -17,13 +18,34 @@
with open("README.md", "r") as fh:
long_description = fh.read()

version = '0.1.2.1'
###############################################################################
# To get the __version__.
# See https://packaging.python.org/guides/single-sourcing-package-version/
# This avoids doing an `import dse_do_supply_chain`, which is causing problems
# installing in a WML DO deployment
###############################################################################
def read(rel_path: str) -> str:
here = os.path.abspath(os.path.dirname(__file__))
# intentionally *not* adding an encoding option to open, See:
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
with open(os.path.join(here, rel_path)) as fp:
return fp.read()

def get_version(rel_path: str) -> str:
for line in read(rel_path).splitlines():
if line.startswith("__version__"):
delim = '"' if '"' in line else "'"
return line.split(delim)[1]
raise RuntimeError("Unable to find version string.")
###############################################################################

# version = '0.1.2.2b2'

setuptools.setup(
name="dse_do_dashboard",
# version=dse_do_dashboard.__version__,
# version=__version__,
version=version,
version=get_version("dse_do_dashboard/version.py"),
author="Victor Terpstra",
author_email="[email protected]",
description="Decision Optimization Dashboard for IBM Cloud Pak for Data DO projects",
Expand All @@ -39,8 +61,8 @@
'dash-bootstrap-templates',
'dash_pivottable',
'dash_daq',
'sqlalchemy>=1.3.23, <1.4',
'pandas<1.4', # Pandas 1.4 requires sqlalchemy 1.4, see https://pandas.pydata.org/docs/dev/whatsnew/v1.4.0.html
'sqlalchemy>=1.3.23',
'pandas', # Pandas 1.4 requires sqlalchemy 1.4, see https://pandas.pydata.org/docs/dev/whatsnew/v1.4.0.html
'plotly', # 5.5.0 is causing problems installing on CPD
'openpyxl',
'diskcache', # For long-running callbacks
Expand Down

0 comments on commit 0dc1630

Please sign in to comment.