Preface
Goal: Add common feature such as configuration, terminal interface, and web server
This is a multiparts article.
13: TOML Configuration
Instead of polluting our script with user configuration.
We could put our variable in a configuration outside the script.
The latest popular format is after the YAML
era is TOML
.
This TOML
syntax looks like INI
, but support indentation.
Official Documentation
TOML Validation
Testing
Checking TOML validation can be done here:
TOML Configuration
Our configuration could be splitted, between development and production. With each has its own settings.
- spath
- spreadsheet file
- Websocket: IP address
- Websocket: Port
You can examine the complete config.toml
for our project.
For example, we can set the mode:
# environment: "development" or "production"
environment = "development"
Then we can set development configuration is as below, we use broadcast IP.
[development]
[development.sheetGlobal]
site = "0.0.0.0"
port = "8765"
path = "/home/epsi/awatch/code-02-enh"
file = "test-c.xlsx"
[development.sheetDaily]
site = "0.0.0.0"
port = "8767"
path = "/home/epsi/awatch/code-02-enh"
file = "test-d.xlsx"
While the production is as below:
[production]
[production.sheetGlobal]
site = "localhost"
port = "8765"
path = 'C:\Users\GK 35\Documents'
file = "global.xlsx"
[production.sheetDaily]
site = "localhost"
port = "8767"
path = 'C:\Users\GK 35\Documents'
file = "daily.xlsx"
Simple TOML Reader
The code is shorter than I thought.
import tomli
import pprint
sheet_ident = 'sheetGlobal'
with open('config.toml', 'rb') as file_obj:
config_root = tomli.load(file_obj)
env = config_root['environment']
config_env = config_root[env]
config_sheet = config_env[sheet_ident]
pprint.pprint(config_sheet)
With output as below dictionary:
Constructor Changes
Simplify Constructor Parameter
Since we can’t use -
,
consider, name our class to xl2web_24.py
.
The simple reader above could be apply to our parent class.
import asyncio, websockets, json, os, tomli
from watchfiles import awatch
# Excel to Web, Base Class
class Xl2WebBase:
def __init__(self, sheet_ident):
with open('config.toml', 'rb') as file_obj:
config_root = tomli.load(file_obj)
env = config_root['environment']
config_env = config_root[env]
config_sheet = config_env[sheet_ident]
# save initial parameter
self.filepath = config_sheet['path']
self.filename = config_sheet['file']
self.site = config_sheet['site']
self.port = config_sheet['port']
# websocket broadcast collection
self.connections = set()
# self.xlsx required in descendent class
self.xlsx = None
Beside the constructor. The rest remain the same.
We still have to alter our descendant class. But the idea is we can create class instance with something like:
example = Xl2Web_c('sheetGlobal')
or
example = Xl2Web_d('sheetDaily')
Instead of this long paramater argument.
example = Xl2Web_c(
'/home/epsi/awatch/code-02-enh', 'test-c.xlsx',
'localhost', 8765)
This way, for any changes, user does not need to alter the script directly.
Descendant Changes: First Sheet
Since we alter the parent class filename,
we should also change the import
statement.
import asyncio, openpyxl, time
import xl2web_24
from openpyxl import load_workbook
# Excel to Web, Example Class
class Xl2Web_c(xl2web_24.Xl2WebBase):
...
# Program Entry Point
example = Xl2Web_c('sheetGlobal')
...
Descendant Changes: Second Sheet
And so does the other script for the second script.
import asyncio, openpyxl, time
import xl2web_24
from openpyxl import load_workbook
# Excel to Web, Example Class
class Xl2Web_d(xl2web_24.Xl2WebBase):
...
# Program Entry Point
example = Xl2Web_d('sheetDaily')
...
Output in Terminal
Check in terminal, if everything work as usual.
What is Next 🤔?
We are done with configuration. But we still have issue. The end user still have to run two script, and maybe web server. Three script at once is annoying.
This can be solved by running them into just one script. Each task in separate panel.
Consider continue reading [ Excel - Monitor - Dual Rich Panel ].