Skip to content

Commit

Permalink
feat: add pack mount
Browse files Browse the repository at this point in the history
  • Loading branch information
vberlier committed May 1, 2022
1 parent 00fb138 commit 48958f7
Show file tree
Hide file tree
Showing 16 changed files with 99 additions and 40 deletions.
16 changes: 10 additions & 6 deletions beet/core/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,11 @@ def from_zip(cls, origin: ZipFile, name: str) -> SerializeType:
raise NotImplementedError()

@classmethod
def load(cls: Type[FileType], origin: FileOrigin, path: FileSystemPath) -> FileType:
def load(
cls: Type[FileType],
origin: FileOrigin,
path: FileSystemPath = "",
) -> FileType:
"""Load a file from a zipfile or from the filesystem."""
instance = cls.try_load(origin, path)
if instance is None:
Expand All @@ -222,7 +226,9 @@ def load(cls: Type[FileType], origin: FileOrigin, path: FileSystemPath) -> FileT

@classmethod
def try_load(
cls: Type[FileType], origin: FileOrigin, path: FileSystemPath
cls: Type[FileType],
origin: FileOrigin,
path: FileSystemPath = "",
) -> Optional[FileType]:
"""Try to load a file from a zipfile or from the filesystem."""
if isinstance(origin, ZipFile):
Expand Down Expand Up @@ -537,14 +543,12 @@ class PngFile(BinaryFileBase[Image]):

image = FileDeserialize[Image]()

@classmethod
def to_bytes(cls, content: Image) -> bytes:
def to_bytes(self, content: Image) -> bytes:
dst = io.BytesIO()
content.save(dst, format="png")
return dst.getvalue()

@classmethod
def from_bytes(cls, content: bytes) -> Image:
def from_bytes(self, content: bytes) -> Image:
return open_image(io.BytesIO(content))

@classmethod
Expand Down
84 changes: 50 additions & 34 deletions beet/library/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,17 +507,22 @@ def get_extra_info(cls) -> Dict[str, Type[PackFile]]:
@classmethod
def scan(
cls,
pack: FileOrigin,
prefix: str,
origin: FileOrigin,
extend_namespace: Iterable[Type[NamespaceFile]] = (),
extend_namespace_extra: Optional[Mapping[str, Type[PackFile]]] = None,
) -> Iterator[Tuple[str, "Namespace"]]:
"""Load namespaces by walking through a zipfile or directory."""
name, namespace = None, None
filenames = (
map(PurePosixPath, pack.namelist())
if isinstance(pack, ZipFile)
else list_files(pack)
)

if isinstance(origin, ZipFile):
filenames = map(PurePosixPath, origin.namelist())
elif Path(origin).is_file():
filenames = [PurePosixPath()]
else:
filenames = list_files(origin)

preparts = tuple(filter(None, prefix.split("/")))

extra_info = cls.get_extra_info()
if extend_namespace_extra:
Expand All @@ -529,7 +534,7 @@ def scan(

for filename in sorted(filenames):
try:
directory, namespace_dir, *scope, extra_name = filename.parts
directory, namespace_dir, *scope, basename = preparts + filename.parts
except ValueError:
continue

Expand All @@ -541,23 +546,22 @@ def scan(
name, namespace = namespace_dir, cls()

assert name and namespace is not None
extensions = list_extensions(filename)
extensions = list_extensions(PurePosixPath(basename))

if file_type := extra_info.get(path := "/".join(scope + [extra_name])):
namespace.extra[path] = file_type.load(pack, filename)
if file_type := extra_info.get(path := "/".join(scope + [basename])):
namespace.extra[path] = file_type.load(origin, filename)
continue

file_dir: List[str] = []

while path := tuple(scope):
for extension in extensions:
if file_type := scope_map.get((path, extension)):
key = "/".join(
filename.relative_to(Path(directory, name, *path)).parts
)[: -len(extension)]

namespace[file_type][key] = file_type.load(pack, filename)
key = "/".join(file_dir + [basename[: -len(extension)]])
namespace[file_type][key] = file_type.load(origin, filename)
break
else:
scope.pop()
file_dir.insert(0, scope.pop())
continue
break

Expand Down Expand Up @@ -922,30 +926,42 @@ def load(
self.name = self.name[:-4]

if origin:
files = {
filename: loaded
for filename, file_type in self.resolve_extra_info().items()
if (loaded := file_type.try_load(origin, filename))
}

self.extra.merge(files)

namespaces = {
name: namespace
for name, namespace in self.namespace_type.scan(
origin,
self.extend_namespace,
self.extend_namespace_extra,
)
}

self.merge(namespaces) # type: ignore
self.mount("", origin)

if not self.pack_format:
self.pack_format = self.latest_pack_format
if not self.description:
self.description = ""

def mount(self, prefix: str, origin: FileOrigin):
"""Mount files from a zipfile or from the filesystem."""
files: Dict[str, PackFile] = {}

for filename, file_type in self.resolve_extra_info().items():
if not prefix:
if loaded := file_type.try_load(origin, filename):
files[filename] = loaded
elif prefix == filename:
if loaded := file_type.try_load(origin, ""):
files[filename] = loaded
elif filename.startswith(prefix + "/"):
if loaded := file_type.try_load(origin, filename[len(prefix) + 1 :]):
files[filename] = loaded

self.extra.merge(files)

namespaces = {
name: namespace
for name, namespace in self.namespace_type.scan(
prefix,
origin,
self.extend_namespace,
self.extend_namespace_extra,
)
}

self.merge(namespaces) # type: ignore

def dump(self, origin: FileOrigin):
"""Write the content of the pack to a zipfile or to the filesystem"""
extra = {path: item for path, item in self.extra.items() if item is not None}
Expand Down
2 changes: 2 additions & 0 deletions examples/code_mount/beet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pipeline:
- demo
10 changes: 10 additions & 0 deletions examples/code_mount/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from beet import Context


def beet_default(ctx: Context):
ctx.data.mount("data/demo/functions", ctx.directory / "src")
ctx.data.mount("data/owo/functions/foo.mcfunction", ctx.directory / "src/thing.txt")
ctx.data.mount("pack.mcmeta", ctx.directory / "pack.mcmeta")
ctx.assets.mount("assets/minecraft", ctx.directory / "src")
ctx.assets.mount("assets/other/sounds.json", ctx.directory / "src/sounds.json")
ctx.assets.mount("not_in_schema.txt", ctx.directory / "pack.mcmeta")
6 changes: 6 additions & 0 deletions examples/code_mount/pack.mcmeta
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"pack": {
"pack_format": 9,
"description": "aaaaaa"
}
}
1 change: 1 addition & 0 deletions examples/code_mount/src/bar.mcfunction
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say bar
1 change: 1 addition & 0 deletions examples/code_mount/src/foo.mcfunction
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say foo
1 change: 1 addition & 0 deletions examples/code_mount/src/sounds.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions examples/code_mount/src/thing.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say thing
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
say thing
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"pack": {
"pack_format": 9,
"description": "aaaaaa"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"pack": {
"pack_format": 8,
"description": ""
}
}

0 comments on commit 48958f7

Please sign in to comment.