
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.
94 lines
2.7 KiB
Python
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,
|
|
),
|
|
}
|