flamenco/addon/flamenco/projects.py
Sybren A. Stüvel 68ac3c03e3 Add-on: compatibility with Python 3.9
Remove some Python 3.10 features to make the add-on compatible with py39.
This is the Python version that's bundled with Blender 2.93 LTS, for which
I got a request to see if it could be supported.

The Blender version still isn't officially supported, but this should make
things at least not immediately fail.
2024-04-24 17:32:01 +02:00

94 lines
2.7 KiB
Python

# SPDX-License-Identifier: GPL-3.0-or-later
# <pep8 compliant>
from pathlib import Path
from typing import Callable
import dataclasses
from .bat.submodules import bpathlib
def for_blendfile(blendfile: Path, strategy: str) -> Path:
"""Return what is considered to be the project directory containing the given file.
If none can be found, the directory containing the current blend file is returned.
If the current blend file has no path (because it was not saved), a ValueError is raised.
:param blendfile: the path of the blend file for which to find the project.
:param strategy: the name of the finder to use, see `finders`.
"""
if blendfile.is_dir():
msg = f"{blendfile} is not a blend file, cannot find project directory"
raise ValueError(msg)
try:
finder_info = finders[strategy]
except KeyError:
msg = f"Unknown strategy {strategy!r}, cannot find project directory"
raise ValueError(msg) from None
return finder_info.finder(blendfile)
def _finder_blender_project(blendfile: Path) -> Path:
return _search_path_marker(blendfile, ".blender_project")
def _finder_git(blendfile: Path) -> Path:
return _search_path_marker(blendfile, ".git")
def _finder_subversion(blendfile: Path) -> Path:
return _search_path_marker(blendfile, ".svn")
def _search_path_marker(blendfile: Path, marker_path: str) -> Path:
"""Go up the directory hierarchy until a file or directory 'marker_path' is found."""
blendfile_dir: Path = bpathlib.make_absolute(blendfile).parent
directory = blendfile_dir
while True:
marker: Path = directory / marker_path
if marker.exists():
return directory
parent = directory.parent
if directory == parent:
# If a directory is its own parent, we're at the root and cannot go
# up further.
break
directory = parent
# Could not find the marker, so use the directory containing the blend file.
return blendfile_dir
Finder = Callable[[Path], Path]
@dataclasses.dataclass
class FinderInfo:
label: str
description: str
finder: Finder
finders: dict[str, FinderInfo] = {
"BLENDER_PROJECT": FinderInfo(
"Blender Project",
"Find a .blend_project directory and use that as indicator for the top level project directory.",
_finder_blender_project,
),
"GIT": FinderInfo(
"Git",
"Find a .git directory and use that as indicator for the top level project directory.",
_finder_git,
),
"SUBVERSION": FinderInfo(
"Subversion",
"Find a .svn directory and use that as indicator for the top level project directory.",
_finder_subversion,
),
}