Removed default JSON files and submoduled JSON encoder class
This commit is contained in:
parent
8c180ca285
commit
4a9d1c5e3c
8 changed files with 65 additions and 88 deletions
|
|
@ -30,7 +30,7 @@ from labthings.extensions import find_extensions
|
||||||
from openflexure_microscope.api.microscope import default_microscope as api_microscope
|
from openflexure_microscope.api.microscope import default_microscope as api_microscope
|
||||||
from openflexure_microscope.api.utilities import init_default_extensions, list_routes
|
from openflexure_microscope.api.utilities import init_default_extensions, list_routes
|
||||||
from openflexure_microscope.api.v2 import views
|
from openflexure_microscope.api.v2 import views
|
||||||
from openflexure_microscope.config import JSONEncoder
|
from openflexure_microscope.json import JSONEncoder
|
||||||
from openflexure_microscope.paths import (
|
from openflexure_microscope.paths import (
|
||||||
OPENFLEXURE_EXTENSIONS_PATH,
|
OPENFLEXURE_EXTENSIONS_PATH,
|
||||||
OPENFLEXURE_VAR_PATH,
|
OPENFLEXURE_VAR_PATH,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import dateutil.parser
|
||||||
|
|
||||||
from openflexure_microscope.camera import piexif
|
from openflexure_microscope.camera import piexif
|
||||||
from openflexure_microscope.camera.piexif._exceptions import InvalidImageDataError
|
from openflexure_microscope.camera.piexif._exceptions import InvalidImageDataError
|
||||||
from openflexure_microscope.config import JSONEncoder
|
from openflexure_microscope.json import JSONEncoder
|
||||||
|
|
||||||
EXIF_FORMATS = ["JPG", "JPEG", "TIF", "TIFF"]
|
EXIF_FORMATS = ["JPG", "JPEG", "TIF", "TIFF"]
|
||||||
THUMBNAIL_SIZE = (200, 150)
|
THUMBNAIL_SIZE = (200, 150)
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,9 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from fractions import Fraction
|
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
import numpy as np
|
from .json import JSONEncoder
|
||||||
from labthings.json import LabThingsJSONEncoder
|
from .paths import CONFIGURATION_FILE_PATH, SETTINGS_FILE_PATH
|
||||||
|
|
||||||
from .paths import (
|
|
||||||
CONFIGURATION_FILE_PATH,
|
|
||||||
DEFAULT_CONFIGURATION_FILE_PATH,
|
|
||||||
DEFAULT_SETTINGS_FILE_PATH,
|
|
||||||
SETTINGS_FILE_PATH,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class OpenflexureSettingsFile:
|
class OpenflexureSettingsFile:
|
||||||
|
|
@ -33,7 +24,12 @@ class OpenflexureSettingsFile:
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
# Initialise basic config file with defaults if it doesn't exist
|
# Initialise basic config file with defaults if it doesn't exist
|
||||||
initialise_file(self.path, populate=defaults)
|
initialise_file(
|
||||||
|
self.path,
|
||||||
|
# Populate with default dictionary, or empty JSON if empty
|
||||||
|
populate=json.dumps(defaults, cls=JSONEncoder, indent=2, sort_keys=True)
|
||||||
|
or "{}\n",
|
||||||
|
)
|
||||||
|
|
||||||
def load(self) -> dict:
|
def load(self) -> dict:
|
||||||
"""
|
"""
|
||||||
|
|
@ -78,32 +74,6 @@ class OpenflexureSettingsFile:
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
|
||||||
class JSONEncoder(LabThingsJSONEncoder):
|
|
||||||
"""
|
|
||||||
A custom JSON encoder, with type conversions for PiCamera fractions, Numpy integers, and Numpy arrays
|
|
||||||
"""
|
|
||||||
|
|
||||||
def default(self, o):
|
|
||||||
if isinstance(o, UUID):
|
|
||||||
return str(o)
|
|
||||||
# PiCamera fractions
|
|
||||||
elif isinstance(o, Fraction):
|
|
||||||
return float(o)
|
|
||||||
# Numpy integers
|
|
||||||
elif isinstance(o, np.integer):
|
|
||||||
return int(o)
|
|
||||||
# Numpy arrays
|
|
||||||
elif isinstance(o, np.ndarray):
|
|
||||||
return o.tolist()
|
|
||||||
# UUIDs
|
|
||||||
elif isinstance(o, UUID):
|
|
||||||
return str(o)
|
|
||||||
else:
|
|
||||||
# call base class implementation which takes care of
|
|
||||||
# raising exceptions for unsupported types
|
|
||||||
return LabThingsJSONEncoder.default(self, o)
|
|
||||||
|
|
||||||
|
|
||||||
# HANDLE BASIC LOADING AND SAVING OF SETTINGS FILES
|
# HANDLE BASIC LOADING AND SAVING OF SETTINGS FILES
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -184,21 +154,14 @@ def initialise_file(config_path, populate: str = "{}\n"):
|
||||||
outfile.write(populate)
|
outfile.write(populate)
|
||||||
|
|
||||||
|
|
||||||
# Load the default settings
|
|
||||||
with open(DEFAULT_SETTINGS_FILE_PATH, "r") as default_settings:
|
|
||||||
DEFAULT_SETTINGS = default_settings.read()
|
|
||||||
|
|
||||||
#: Default user settings object
|
#: Default user settings object
|
||||||
user_settings = OpenflexureSettingsFile(
|
user_settings = OpenflexureSettingsFile(path=SETTINGS_FILE_PATH)
|
||||||
path=SETTINGS_FILE_PATH, defaults=DEFAULT_SETTINGS
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Load the default configuration
|
|
||||||
with open(DEFAULT_CONFIGURATION_FILE_PATH, "r") as default_configuration:
|
|
||||||
DEFAULT_CONFIGURATION = default_configuration.read()
|
|
||||||
|
|
||||||
#: Default user settings object
|
#: Default user settings object
|
||||||
user_configuration = OpenflexureSettingsFile(
|
user_configuration = OpenflexureSettingsFile(
|
||||||
path=CONFIGURATION_FILE_PATH, defaults=DEFAULT_CONFIGURATION
|
path=CONFIGURATION_FILE_PATH,
|
||||||
|
defaults={
|
||||||
|
"camera": {"type": "PiCamera"},
|
||||||
|
"stage": {"type": "SangaStage", "port": None},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
31
openflexure_microscope/json.py
Normal file
31
openflexure_microscope/json.py
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
from fractions import Fraction
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from labthings.json import LabThingsJSONEncoder
|
||||||
|
|
||||||
|
|
||||||
|
class JSONEncoder(LabThingsJSONEncoder):
|
||||||
|
"""
|
||||||
|
A custom JSON encoder, with type conversions for PiCamera fractions, Numpy integers, and Numpy arrays
|
||||||
|
"""
|
||||||
|
|
||||||
|
def default(self, o):
|
||||||
|
if isinstance(o, UUID):
|
||||||
|
return str(o)
|
||||||
|
# PiCamera fractions
|
||||||
|
elif isinstance(o, Fraction):
|
||||||
|
return float(o)
|
||||||
|
# Numpy integers
|
||||||
|
elif isinstance(o, np.integer):
|
||||||
|
return int(o)
|
||||||
|
# Numpy arrays
|
||||||
|
elif isinstance(o, np.ndarray):
|
||||||
|
return o.tolist()
|
||||||
|
# UUIDs
|
||||||
|
elif isinstance(o, UUID):
|
||||||
|
return str(o)
|
||||||
|
else:
|
||||||
|
# call base class implementation which takes care of
|
||||||
|
# raising exceptions for unsupported types
|
||||||
|
return LabThingsJSONEncoder.default(self, o)
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"camera": {
|
|
||||||
"type": "PiCamera"
|
|
||||||
},
|
|
||||||
"stage": {
|
|
||||||
"type": "SangaStage",
|
|
||||||
"port": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"fov": [
|
|
||||||
4100,
|
|
||||||
3146
|
|
||||||
],
|
|
||||||
"jpeg_quality": 100
|
|
||||||
}
|
|
||||||
|
|
@ -38,18 +38,6 @@ def logs_file_path(filename: str):
|
||||||
os.makedirs(logs_dir)
|
os.makedirs(logs_dir)
|
||||||
return os.path.join(logs_dir, filename)
|
return os.path.join(logs_dir, filename)
|
||||||
|
|
||||||
|
|
||||||
# HANDLE DEFAULTS FILES STORED IN THIS APPLICATION
|
|
||||||
|
|
||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
|
|
||||||
#: Path of default (first-run) microscope settings
|
|
||||||
DEFAULT_SETTINGS_FILE_PATH = os.path.join(HERE, "microscope_settings.default.json")
|
|
||||||
#: Path of default (first-run) microscope configuration
|
|
||||||
DEFAULT_CONFIGURATION_FILE_PATH = os.path.join(
|
|
||||||
HERE, "microscope_configuration.default.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
# BASE PATHS
|
# BASE PATHS
|
||||||
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from .error_sources import ErrorSource
|
||||||
|
|
||||||
ERROR_SOURCES = []
|
ERROR_SOURCES = []
|
||||||
|
|
||||||
|
|
@ -8,27 +9,35 @@ def trace_config_exceptions():
|
||||||
error_sources = []
|
error_sources = []
|
||||||
|
|
||||||
from openflexure_microscope.paths import (
|
from openflexure_microscope.paths import (
|
||||||
DEFAULT_CONFIGURATION_FILE_PATH,
|
CONFIGURATION_FILE_PATH,
|
||||||
SETTINGS_FILE_PATH,
|
SETTINGS_FILE_PATH,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
default_config = json.load(DEFAULT_CONFIGURATION_FILE_PATH)
|
default_config = json.load(CONFIGURATION_FILE_PATH)
|
||||||
if not default_config:
|
if not default_config:
|
||||||
error_sources.append("default_config_empty")
|
error_sources.append(ErrorSource(
|
||||||
|
"Configuration file is missing or empty. This may occur if the server has never been started."
|
||||||
|
))
|
||||||
except Exception as e: # pylint: disable=W0703
|
except Exception as e: # pylint: disable=W0703
|
||||||
logging.error("Error parsing config:")
|
logging.error("Error parsing config:")
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
error_sources.append("default_config_error")
|
error_sources.append(ErrorSource(
|
||||||
|
f"Configuration file is malformed. You can reset to the default configuration by deleting {CONFIGURATION_FILE_PATH}."
|
||||||
|
))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
default_settings = json.load(SETTINGS_FILE_PATH)
|
default_settings = json.load(SETTINGS_FILE_PATH)
|
||||||
if not default_settings:
|
if not default_settings:
|
||||||
error_sources.append("default_settings_empty")
|
error_sources.append(ErrorSource(
|
||||||
|
"Settings file is missing or empty. This may occur if the server has never been started."
|
||||||
|
))
|
||||||
except Exception as e: # pylint: disable=W0703
|
except Exception as e: # pylint: disable=W0703
|
||||||
logging.error("Error parsing settings:")
|
logging.error("Error parsing settings:")
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
error_sources.append("default_settings_error")
|
error_sources.append(ErrorSource(
|
||||||
|
f"Settings file is malformed. You can reset to the default settings by deleting {SETTINGS_FILE_PATH}."
|
||||||
|
))
|
||||||
|
|
||||||
return error_sources
|
return error_sources
|
||||||
|
|
||||||
|
|
@ -39,7 +48,9 @@ def main():
|
||||||
try:
|
try:
|
||||||
from openflexure_microscope import config as _
|
from openflexure_microscope import config as _
|
||||||
except Exception as e: # pylint: disable=W0703
|
except Exception as e: # pylint: disable=W0703
|
||||||
error_sources.append("config_settings_import_error")
|
error_sources.append(ErrorSource(
|
||||||
|
"Error importing configuration submodule. This could be an error in our code."
|
||||||
|
))
|
||||||
logging.error("Error importing config:")
|
logging.error("Error importing config:")
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
error_sources.extend(trace_config_exceptions())
|
error_sources.extend(trace_config_exceptions())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue