Skip to content

Commit

Permalink
fix: improve file handler api
Browse files Browse the repository at this point in the history
- auto-detect text/binary
- add class methode from_other
  • Loading branch information
simontaurus committed Sep 16, 2023
1 parent cb768d1 commit 84fcbff
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 8 deletions.
16 changes: 15 additions & 1 deletion src/osw/controller/file/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import abstractmethod
from typing import IO
from typing import IO, Any

from osw.core import model

Expand Down Expand Up @@ -52,3 +52,17 @@ def get_to(self, other: "FileController"):
"""
with self.get() as f:
other.put(f)

@classmethod
def from_other(cls, other: "FileController", **kwargs: Any) -> "FileController":
"""Create an instance based on another file controller
copying all common attributes
Parameters
----------
other
another file controller to copy from
kwargs
additional attributes to be set
"""
return other.cast(cls, **kwargs)
22 changes: 19 additions & 3 deletions src/osw/controller/file/local.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import os
import shutil
from io import TextIOBase
from pathlib import Path
from typing import IO, Optional
from typing import IO, List, Optional

from osw.controller.file.base import FileController
from osw.core import model


class LocalFileController(FileController, model.LocalFile):
label: Optional[model.Label] = model.Label(text="Unnamed file")
"""File controller for local files"""

label: Optional[List[model.Label]] = [model.Label(text="Unnamed file")]
"""the label of the file, defaults to 'Unnamed file'"""
path: Path
"""the path to the file"""

@classmethod
def from_other(cls, other: "FileController", path: Path) -> "LocalFileController":
return other.cast(cls, path=path)

def __init__(self, **kwargs):
super().__init__(**kwargs)
self._set_metadata()

class Config:
arbitrary_types_allowed = True
Expand All @@ -20,7 +33,10 @@ def get(self) -> IO:

def put(self, file: IO):
self._set_metadata()
with open(self.path, "wb") as f:
mode = "wb"
if isinstance(file, TextIOBase):
mode = "w"
with open(self.path, mode) as f:
# f.write(file.read()) # in-memory - limited by available RAM
shutil.copyfileobj(file, f) # chunked copy

Expand Down
19 changes: 17 additions & 2 deletions src/osw/controller/file/wiki.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import functools
import os
from typing import IO, Optional
from typing import IO, List, Optional

from osw.controller.file.base import FileController
from osw.controller.file.remote import RemoteFileController
Expand All @@ -10,14 +10,26 @@


class WikiFileController(model.WikiFile, RemoteFileController):
"""File controller for wiki files"""

label: Optional[List[model.Label]] = [model.Label(text="Unnamed file")]
"""the label of the file, defaults to 'Unnamed file'"""
osw: OSW
"""the OSW instance to connect with"""
namespace: Optional[str] = "File"
"""the namespace of the file, defaults to 'File'"""
title: Optional[str] = None
"""the title of the file, defaults to the auto-generated OSW-ID"""
suffix: Optional[str] = None
"""the suffix of the file, defaults to the suffix of the title"""

class Config:
arbitrary_types_allowed = True

@classmethod
def from_other(cls, other: FileController, osw: OSW) -> "WikiFileController":
return super().from_other(other, osw=osw)

def get(self) -> IO:
self._init()
file = self.osw.site._site.images[self.title]
Expand Down Expand Up @@ -76,7 +88,10 @@ def put_from(self, other: FileController):
# lf = file.cast(LocalFileController)
# self.meta.wiki_page.title.removesuffix(lf.path.suffix)
# self.meta.wiki_page.title += lf.path.suffix
return super().put_from(other)
# copy over metadata
if self.label == [model.Label(text="Unnamed file")]:
self.label = other.label
super().put_from(other)

def delete(self):
file_page_name = f"{self.namespace}:{self.title}"
Expand Down
Binary file added tests/integration/test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions tests/integration/test_file_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ def test_file_controller(wiki_domain, wiki_username, wiki_password):
mode = "replace"
osw.fetch_schema(OSW.FetchSchemaParam(schema_title=cat, mode=mode))

run_test(osw, "tests/integration/test.svg", "tests/integration/test2.svg")
run_test(osw, "tests/integration/test.png", "tests/integration/test2.png")


def run_test(osw, file_path_1, file_path_2):
from osw.controller.file.local import LocalFileController
from osw.controller.file.wiki import WikiFileController

lf = model.LocalFile(label=[model.Label(text="Test File")]).cast(
LocalFileController, path="tests/integration/test.svg"
LocalFileController, path=file_path_1
)

# wf = WikiFileController.from_local(lf) # does not work due to missing attributes 'title' and 'osw'
Expand All @@ -43,7 +48,7 @@ def test_file_controller(wiki_domain, wiki_username, wiki_password):
title = wf.namespace + ":" + wf.title
# title = "File:OSW1b3fea404fe344c78ffd2d7a46bb468e.svg"
wf2 = osw.load_entity(title).cast(WikiFileController, osw=osw)
lf2 = LocalFileController(path="tests/integration/test2.svg")
lf2 = LocalFileController(path=file_path_2)
lf2.put_from(wf2)
# wf2.get_to(lf2)

Expand Down

0 comments on commit 84fcbff

Please sign in to comment.