Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ and this project adheres to
`RACKSDB_EXTENSIONS`, and to set default schema, extensions, and database
paths when the matching `racksdb` / `racksdb-web` option is omitted (#149).
- web: Support the same environment variables as CLI.
- pkgs: Add tests dependency on `RFL.build` >= 1.8.0 for parameterized unit
tests.
- pkgs:
- Add tests dependency on `RFL.build` >= 1.8.0 for parameterized unit tests.
- Install `schemas/racksdb.yml` and `schemas/drawings.yml` with the Python
package (#158).
- lib: Resolve default schema paths for pip/source installs and source checkouts
as a fallback for FHS distribution paths.
- docs:
- Mention support of RHEL 10, Fedora 43, SLES and openSUSE 15 and 16, Ubuntu
26.04 LTS.
Expand Down
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ racksdb-web = "racksdb.web.app:RacksDBWebApp.run"
[tool.setuptools.packages.find]
include = ["racksdb*"]

[tool.setuptools.data-files]
"share/racksdb/schemas" = [
"schemas/racksdb.yml",
"schemas/drawings.yml",
]

[project.urls]
"Homepage" = "https://github.com/rackslab/RacksDB"
"Bug Tracker" = "https://github.com/rackslab/RacksDB/issues"
Expand Down
3 changes: 2 additions & 1 deletion racksdb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
RacksDBNotFoundError,
)
from . import bases
from .paths import schema_file


class RacksDB(GenericDB):
DEFAULT_DB = "/var/lib/racksdb"
DEFAULT_SCHEMA = "/usr/share/racksdb/schemas/racksdb.yml"
DEFAULT_SCHEMA = str(schema_file("racksdb.yml"))
DEFAULT_EXT = "/etc/racksdb/extensions.yml"
DEFAULT_UI = "/usr/share/racksdb/frontend"
PREFIX = "RacksDB"
Expand Down
3 changes: 2 additions & 1 deletion racksdb/drawers/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

from ..generic.schema import Schema, SchemaFileLoader, SchemaDefinedTypeLoader
from ..generic.db import GenericDB
from ..paths import schema_file


class DrawingParameters(GenericDB):
DEFAULT_SCHEMA = "/usr/share/racksdb/schemas/drawings.yml"
DEFAULT_SCHEMA = str(schema_file("drawings.yml"))
PREFIX = "DrawingParameters"
DEFINED_TYPES_MODULE = "racksdb.drawers.dtypes"

Expand Down
41 changes: 41 additions & 0 deletions racksdb/paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) 2026 Rackslab
#
# This file is part of RacksDB.
#
# SPDX-License-Identifier: MIT

"""Resolve default paths for schema files shipped with RacksDB."""

import sys
from pathlib import Path

_PACKAGE_ROOT = Path(__file__).resolve().parent
_SOURCE_TREE_SCHEMAS = _PACKAGE_ROOT.parent / "schemas"
_FHS_SCHEMAS_DIR = Path("/usr/share/racksdb/schemas")


def schema_file(name: str) -> Path:
"""Return the best available path for a schema *name*.

Resolution order:

1. Distribution FHS path /usr/share/racksdb/schemas/<name>
2. Pip-installed data files under <prefix>/share/racksdb/schemas/<name>
3. Source tree schemas/<name> next to the repository root (editable checkout)

If none of the above paths exist, the distribution path is returned anyway to
preserve documented path in error messages.
"""
fhs = _FHS_SCHEMAS_DIR / name
if fhs.is_file():
return fhs

pip_path = Path(sys.prefix) / "share" / "racksdb" / "schemas" / name
if pip_path.is_file():
return pip_path

dev_path = _SOURCE_TREE_SCHEMAS / name
if dev_path.is_file():
return dev_path

return fhs
56 changes: 56 additions & 0 deletions racksdb/tests/test_paths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) 2026 Rackslab
#
# This file is part of RacksDB.
#
# SPDX-License-Identifier: MIT

import sys
import unittest
from pathlib import Path
from unittest import mock

from racksdb import RacksDB
from racksdb.drawers.parameters import DrawingParameters
from racksdb.paths import _SOURCE_TREE_SCHEMAS, schema_file


class TestSchemaFile(unittest.TestCase):
FHS = Path("/usr/share/racksdb/schemas/racksdb.yml")

def test_prefers_existing_fhs_path(self):
with mock.patch.object(Path, "is_file", return_value=True):
result = schema_file("racksdb.yml")
self.assertEqual(result, self.FHS)

def test_uses_pip_data_when_fhs_missing(self):
pip_path = Path(sys.prefix) / "share" / "racksdb" / "schemas" / "racksdb.yml"

def is_file(self):
return self == pip_path

with mock.patch.object(Path, "is_file", is_file):
result = schema_file("racksdb.yml")
self.assertEqual(result, pip_path)

def test_uses_source_tree_when_fhs_and_pip_missing(self):
dev_path = _SOURCE_TREE_SCHEMAS / "racksdb.yml"

def is_file(self):
return self == dev_path

with mock.patch.object(Path, "is_file", is_file):
result = schema_file("racksdb.yml")
self.assertEqual(result, dev_path)

def test_returns_fhs_path_when_nothing_found(self):
with mock.patch.object(Path, "is_file", return_value=False):
result = schema_file("racksdb.yml")
self.assertEqual(result, self.FHS)


class TestDefaultSchemaPaths(unittest.TestCase):
def test_racksdb_default_schema_exists(self):
self.assertTrue(Path(RacksDB.DEFAULT_SCHEMA).is_file())

def test_drawing_parameters_default_schema_exists(self):
self.assertTrue(Path(DrawingParameters.DEFAULT_SCHEMA).is_file())
Loading