1
0
mirror of https://github.com/joouha/euporie.git synced 2021-05-12 23:12:12 +03:00

Add a configuration file

Configuration settings are saved and can be modified in a configuration file. The config file is validated using `jsonschema` before loading.

This also adds logging to euporie using `rich`.
This commit is contained in:
Josiah Outram Halstead
2021-05-12 16:44:56 +01:00
parent f8a19398dc
commit 687c4f96b4
6 changed files with 155 additions and 52 deletions

View File

@@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
__version__ = "0.1.7"
_app_name = "europie"
logo = ""
import euporie.log # noqa E401

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import logging
import sys
from functools import partial
from pathlib import Path
@@ -40,6 +41,8 @@ from euporie.notebook import Notebook
from euporie.term import TermAppMixin
from euporie.text import FormatTextProcessor
log = logging.getLogger(__name__)
class App(Application, TermAppMixin):
def __init__(self, *args, **kwargs):
@@ -414,8 +417,10 @@ class App(Application, TermAppMixin):
def open_file(self, path):
path = Path(path).expanduser()
log.info(f"Opening file {path}")
open_paths = [x.path for x in self.files]
if path in open_paths:
log.info(f"File {path} already open, activating")
self.active_notebook = open_paths.index(path)
else:
self.open_paths.append(path)

View File

@@ -1,19 +1,58 @@
# -*- coding: utf-8 -*-
import json
import logging
import os
import sys
from functools import lru_cache
from pathlib import Path
import jsonschema
from euporie import _app_name
DEFAULT_CONFIG = {
"max_notebook_width": 120,
"background": 1,
"background_character": "·",
"pygments_style": "default",
"editing_mode": "emacs",
"show_line_numbers": True,
log = logging.getLogger(__name__)
CONFIG_SCHEMA = {
"title": "Euporie Configuration",
"description": "A configuration for euporie",
"type": "object",
"properties": {
"max_notebook_width": {
"description": "The maximum width of the notebook",
"type": "integer",
"minimum": 1,
"default": 120,
},
"background": {
"description": "The background pattern to use",
"type": "integer",
"minimum": 0,
"maximum": 4,
"default": 1,
},
"background_character": {
"description": "The character to use to draw the background",
"type": "string",
"maxLength": 1,
"default": "·",
},
"pygments_style": {
"description": "The name of the pygments style for syntax highlighting",
"type": "string",
"default": "default",
},
"editing_mode": {
"description": "The key-binding style to use for text editing",
"type": "string",
"pattern": "(emacs|vi)",
"default": "emacs",
},
"show_line_numbers": {
"description": "Whether line numbers are shown by default",
"type": "boolean",
"default": True,
},
},
}
@@ -21,6 +60,7 @@ class Config:
win = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")
def __init__(self):
super().__setattr__("valid", True)
self.load_defaults()
self.load_config_file()
@@ -45,12 +85,29 @@ class Config:
@property
def json_data(self):
if self.config_file_path.exists():
if self.valid and self.config_file_path.exists():
with open(self.config_file_path, "r") as f:
try:
return json.load(f)
json_data = json.load(f)
except json.decoder.JSONDecodeError:
pass
log.error(
"Could not parse the configuration file: "
f"{self.config_file_path}\n"
"Is it valid json?"
)
super().__setattr__("valid", False)
else:
try:
jsonschema.validate(instance=json_data, schema=CONFIG_SCHEMA)
except jsonschema.ValidationError as error:
log.error(
f"Error in config file: {self.config_file_path}\n"
f"{error}"
)
super().__setattr__("valid", False)
else:
return json_data
log.warning("The configuration file was not loaded")
return {}
def set(self, attr, value):
@@ -58,22 +115,33 @@ class Config:
setattr(self, attr, value)
def toggle(self, attr):
if hasattr(self, attr) and isinstance(getattr(self, attr), (bool, int)):
setattr(self, attr, not getattr(self, attr))
if hasattr(self, attr):
current = getattr(self, attr)
schema = CONFIG_SCHEMA["properties"][attr]
if schema["type"] == "boolean":
setattr(self, attr, not current)
elif schema["type"] == "integer":
setattr(
self,
attr,
schema["minimum"]
+ (current - schema["minimum"] + 1) % (schema["maximum"] + 1),
)
def load_defaults(self):
for key, value in DEFAULT_CONFIG.items():
super().__setattr__(key, value)
for key, schema in CONFIG_SCHEMA["properties"].items():
super().__setattr__(key, schema["default"])
def load_config_file(self):
for key, value in self.json_data.items():
super().__setattr__(key, value)
def __setattr__(self, name, value):
json_data = self.json_data
json_data[name] = value
with open(self.config_file_path, "w") as f:
json.dump(json_data, f, indent=4)
if self.valid:
json_data = self.json_data
json_data[name] = value
with open(self.config_file_path, "w") as f:
json.dump(json_data, f, indent=2)
return super().__setattr__(name, value)

23
euporie/log.py Normal file
View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
import logging
from prompt_toolkit.patch_stdout import StdoutProxy
from rich.console import Console
from rich.logging import RichHandler
log_stdout = StdoutProxy(raw=True)
handlers = [
# logging.StreamHandler(log_stdout),
RichHandler(
console=Console(file=log_stdout, force_terminal=True),
markup=True,
rich_tracebacks=True,
)
]
logging.basicConfig(
level=logging.WARNING,
handlers=handlers,
format="%(message)s",
)

71
poetry.lock generated
View File

@@ -45,7 +45,7 @@ lxml = ["lxml"]
[[package]]
name = "black"
version = "21.5b0"
version = "21.5b1"
description = "The uncompromising code formatter."
category = "dev"
optional = false
@@ -61,7 +61,7 @@ toml = ">=0.10.1"
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
d = ["aiohttp (>=3.6.0)", "aiohttp-cors"]
python2 = ["typed-ast (>=1.4.2)"]
[[package]]
@@ -85,11 +85,14 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "click"
version = "7.1.2"
version = "8.0.0"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
python-versions = ">=3.6"
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
@@ -402,7 +405,7 @@ scipy = ["scipy"]
[[package]]
name = "numpy"
version = "1.20.2"
version = "1.20.3"
description = "NumPy is the fundamental package for array computing with Python."
category = "main"
optional = true
@@ -811,7 +814,7 @@ images-timg = ["timg"]
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "5a3a70dd8fa41770a686cfdf40d67d82aa829092289a4f33e8070b8bb3d7d42d"
content-hash = "70e29ae43a273474c96e94a5e3c524785027c4672e946e54a4cb215c7a1387a6"
[metadata.files]
appdirs = [
@@ -832,8 +835,8 @@ beautifulsoup4 = [
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
]
black = [
{file = "black-21.5b0-py3-none-any.whl", hash = "sha256:0e80435b8a88f383c9149ae89d671eb2095b72344b0fe8a1d61d2ff5110ed173"},
{file = "black-21.5b0.tar.gz", hash = "sha256:9dc2042018ca10735366d944c2c12d9cad6dec74a3d5f679d09384ea185d9943"},
{file = "black-21.5b1-py3-none-any.whl", hash = "sha256:8a60071a0043876a4ae96e6c69bd3a127dad2c1ca7c8083573eb82f92705d008"},
{file = "black-21.5b1.tar.gz", hash = "sha256:23695358dbcb3deafe7f0a3ad89feee5999a46be5fec21f4f1d108be0bcdb3b1"},
]
cffi = [
{file = "cffi-1.14.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991"},
@@ -879,8 +882,8 @@ chardet = [
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
]
click = [
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
{file = "click-8.0.0-py3-none-any.whl", hash = "sha256:e90e62ced43dc8105fb9a26d62f0d9340b5c8db053a814e25d95c19873ae87db"},
{file = "click-8.0.0.tar.gz", hash = "sha256:7d8c289ee437bcb0316820ccee14aefcb056e58d31830ecab8e47eda6540e136"},
]
colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
@@ -1057,30 +1060,30 @@ networkx = [
{file = "networkx-2.5.1.tar.gz", hash = "sha256:109cd585cac41297f71103c3c42ac6ef7379f29788eb54cb751be5a663bb235a"},
]
numpy = [
{file = "numpy-1.20.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e9459f40244bb02b2f14f6af0cd0732791d72232bbb0dc4bab57ef88e75f6935"},
{file = "numpy-1.20.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a8e6859913ec8eeef3dbe9aed3bf475347642d1cdd6217c30f28dee8903528e6"},
{file = "numpy-1.20.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:9cab23439eb1ebfed1aaec9cd42b7dc50fc96d5cd3147da348d9161f0501ada5"},
{file = "numpy-1.20.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:9c0fab855ae790ca74b27e55240fe4f2a36a364a3f1ebcfd1fb5ac4088f1cec3"},
{file = "numpy-1.20.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:61d5b4cf73622e4d0c6b83408a16631b670fc045afd6540679aa35591a17fe6d"},
{file = "numpy-1.20.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:d15007f857d6995db15195217afdbddfcd203dfaa0ba6878a2f580eaf810ecd6"},
{file = "numpy-1.20.2-cp37-cp37m-win32.whl", hash = "sha256:d76061ae5cab49b83a8cf3feacefc2053fac672728802ac137dd8c4123397677"},
{file = "numpy-1.20.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bad70051de2c50b1a6259a6df1daaafe8c480ca98132da98976d8591c412e737"},
{file = "numpy-1.20.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:719656636c48be22c23641859ff2419b27b6bdf844b36a2447cb39caceb00935"},
{file = "numpy-1.20.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:aa046527c04688af680217fffac61eec2350ef3f3d7320c07fd33f5c6e7b4d5f"},
{file = "numpy-1.20.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2428b109306075d89d21135bdd6b785f132a1f5a3260c371cee1fae427e12727"},
{file = "numpy-1.20.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e8e4fbbb7e7634f263c5b0150a629342cc19b47c5eba8d1cd4363ab3455ab576"},
{file = "numpy-1.20.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:edb1f041a9146dcf02cd7df7187db46ab524b9af2515f392f337c7cbbf5b52cd"},
{file = "numpy-1.20.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:c73a7975d77f15f7f68dacfb2bca3d3f479f158313642e8ea9058eea06637931"},
{file = "numpy-1.20.2-cp38-cp38-win32.whl", hash = "sha256:6c915ee7dba1071554e70a3664a839fbc033e1d6528199d4621eeaaa5487ccd2"},
{file = "numpy-1.20.2-cp38-cp38-win_amd64.whl", hash = "sha256:471c0571d0895c68da309dacee4e95a0811d0a9f9f532a48dc1bea5f3b7ad2b7"},
{file = "numpy-1.20.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4703b9e937df83f5b6b7447ca5912b5f5f297aba45f91dbbbc63ff9278c7aa98"},
{file = "numpy-1.20.2-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:abc81829c4039e7e4c30f7897938fa5d4916a09c2c7eb9b244b7a35ddc9656f4"},
{file = "numpy-1.20.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:377751954da04d4a6950191b20539066b4e19e3b559d4695399c5e8e3e683bf6"},
{file = "numpy-1.20.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:6e51e417d9ae2e7848314994e6fc3832c9d426abce9328cf7571eefceb43e6c9"},
{file = "numpy-1.20.2-cp39-cp39-win32.whl", hash = "sha256:780ae5284cb770ade51d4b4a7dce4faa554eb1d88a56d0e8b9f35fca9b0270ff"},
{file = "numpy-1.20.2-cp39-cp39-win_amd64.whl", hash = "sha256:924dc3f83de20437de95a73516f36e09918e9c9c18d5eac520062c49191025fb"},
{file = "numpy-1.20.2-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:97ce8b8ace7d3b9288d88177e66ee75480fb79b9cf745e91ecfe65d91a856042"},
{file = "numpy-1.20.2.zip", hash = "sha256:878922bf5ad7550aa044aa9301d417e2d3ae50f0f577de92051d739ac6096cee"},
{file = "numpy-1.20.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:70eb5808127284c4e5c9e836208e09d685a7978b6a216db85960b1a112eeace8"},
{file = "numpy-1.20.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6ca2b85a5997dabc38301a22ee43c82adcb53ff660b89ee88dded6b33687e1d8"},
{file = "numpy-1.20.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c5bf0e132acf7557fc9bb8ded8b53bbbbea8892f3c9a1738205878ca9434206a"},
{file = "numpy-1.20.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db250fd3e90117e0312b611574cd1b3f78bec046783195075cbd7ba9c3d73f16"},
{file = "numpy-1.20.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:637d827248f447e63585ca3f4a7d2dfaa882e094df6cfa177cc9cf9cd6cdf6d2"},
{file = "numpy-1.20.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8b7bb4b9280da3b2856cb1fc425932f46fba609819ee1c62256f61799e6a51d2"},
{file = "numpy-1.20.3-cp37-cp37m-win32.whl", hash = "sha256:67d44acb72c31a97a3d5d33d103ab06d8ac20770e1c5ad81bdb3f0c086a56cf6"},
{file = "numpy-1.20.3-cp37-cp37m-win_amd64.whl", hash = "sha256:43909c8bb289c382170e0282158a38cf306a8ad2ff6dfadc447e90f9961bef43"},
{file = "numpy-1.20.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f1452578d0516283c87608a5a5548b0cdde15b99650efdfd85182102ef7a7c17"},
{file = "numpy-1.20.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6e51534e78d14b4a009a062641f465cfaba4fdcb046c3ac0b1f61dd97c861b1b"},
{file = "numpy-1.20.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e515c9a93aebe27166ec9593411c58494fa98e5fcc219e47260d9ab8a1cc7f9f"},
{file = "numpy-1.20.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1c09247ccea742525bdb5f4b5ceeacb34f95731647fe55774aa36557dbb5fa4"},
{file = "numpy-1.20.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:66fbc6fed94a13b9801fb70b96ff30605ab0a123e775a5e7a26938b717c5d71a"},
{file = "numpy-1.20.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ea9cff01e75a956dbee133fa8e5b68f2f92175233de2f88de3a682dd94deda65"},
{file = "numpy-1.20.3-cp38-cp38-win32.whl", hash = "sha256:f39a995e47cb8649673cfa0579fbdd1cdd33ea497d1728a6cb194d6252268e48"},
{file = "numpy-1.20.3-cp38-cp38-win_amd64.whl", hash = "sha256:1676b0a292dd3c99e49305a16d7a9f42a4ab60ec522eac0d3dd20cdf362ac010"},
{file = "numpy-1.20.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:830b044f4e64a76ba71448fce6e604c0fc47a0e54d8f6467be23749ac2cbd2fb"},
{file = "numpy-1.20.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:55b745fca0a5ab738647d0e4db099bd0a23279c32b31a783ad2ccea729e632df"},
{file = "numpy-1.20.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5d050e1e4bc9ddb8656d7b4f414557720ddcca23a5b88dd7cff65e847864c400"},
{file = "numpy-1.20.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9c65473ebc342715cb2d7926ff1e202c26376c0dcaaee85a1fd4b8d8c1d3b2f"},
{file = "numpy-1.20.3-cp39-cp39-win32.whl", hash = "sha256:16f221035e8bd19b9dc9a57159e38d2dd060b48e93e1d843c49cb370b0f415fd"},
{file = "numpy-1.20.3-cp39-cp39-win_amd64.whl", hash = "sha256:6690080810f77485667bfbff4f69d717c3be25e5b11bb2073e76bb3f578d99b4"},
{file = "numpy-1.20.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e465afc3b96dbc80cf4a5273e5e2b1e3451286361b4af70ce1adb2984d392f9"},
{file = "numpy-1.20.3.zip", hash = "sha256:e55185e51b18d788e49fe8305fd73ef4470596b33fc2c1ceb304566b99c71a69"},
]
packaging = [
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},

View File

@@ -25,6 +25,7 @@ mtable = {version = "^0.1.10", optional = true}
html5lib = {version = "^1.1", optional = true}
Pillow = "^8.2.0"
jupyter-client = "6.1.12"
jsonschema = "^3.2.0"
[tool.poetry.extras]
html-mtable = ["mtable", "html5lib"]