Skip to content

Commit

Permalink
Save current work
Browse files Browse the repository at this point in the history
  • Loading branch information
tb1337 committed Feb 5, 2024
1 parent 37bfc44 commit 6c8110f
Show file tree
Hide file tree
Showing 24 changed files with 198 additions and 65 deletions.
2 changes: 2 additions & 0 deletions pypaperless/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ async def request( ## pylint: disable=too-many-arguments
**kwargs: Any,
) -> AsyncGenerator[aiohttp.ClientResponse, None]:
"""Perform a request."""
if method == "post":
pass
res = await self._session.request(
method,
path,
Expand Down
6 changes: 4 additions & 2 deletions pypaperless/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class PaperlessModelProtocol(Protocol):
_api_path: str
_data: dict[str, Any]
_fetched: bool
_params: dict[str, Any]

def _get_dataclass_fields(self) -> list[Field]: ...

Expand All @@ -71,8 +72,9 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):
"""Initialize a `PaperlessModel` instance."""
super().__init__(api)
self._data = {}
self._fetched = False
self._data.update(data)
self._fetched = False
self._params: dict[str, Any] = {}

@final
@classmethod
Expand Down Expand Up @@ -118,7 +120,7 @@ def _set_dataclass_fields(self) -> None:

async def load(self) -> None:
"""Get `model data` from DRF."""
data = await self._api.request_json("get", self._api_path)
data = await self._api.request_json("get", self._api_path, params=self._params)

self._data.update(data)
self._set_dataclass_fields()
Expand Down
33 changes: 20 additions & 13 deletions pypaperless/models/classifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
class Correspondent( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.PermissionFieldsMixin,
models.SecurableMixin,
models.UpdatableMixin,
models.DeletableMixin,
):
Expand All @@ -39,12 +39,13 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):


@dataclass(init=False)
class CorrespondentDraft(
class CorrespondentDraft( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.SecurableDraftMixin,
models.CreatableMixin,
):
"""Represent a new Paperless `Correspondent`, which is not stored in Paperless."""
"""Represent a new `Correspondent`, which is not yet stored in Paperless."""

_api_path = API_PATH["correspondents"]

Expand All @@ -56,14 +57,13 @@ class CorrespondentDraft(
}

name: str | None = None
owner: int | None = None


@dataclass(init=False)
class DocumentType( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.PermissionFieldsMixin,
models.SecurableMixin,
models.UpdatableMixin,
models.DeletableMixin,
):
Expand All @@ -84,12 +84,13 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):


@dataclass(init=False)
class DocumentTypeDraft(
class DocumentTypeDraft( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.SecurableDraftMixin,
models.CreatableMixin,
):
"""Represent a new Paperless `DocumentType`, which is not stored in Paperless."""
"""Represent a new `DocumentType`, which is not yet stored in Paperless."""

_api_path = API_PATH["document_types"]

Expand All @@ -108,7 +109,7 @@ class DocumentTypeDraft(
class StoragePath( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.PermissionFieldsMixin,
models.SecurableMixin,
models.UpdatableMixin,
models.DeletableMixin,
):
Expand All @@ -130,12 +131,13 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):


@dataclass(init=False)
class StoragePathDraft(
class StoragePathDraft( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.SecurableDraftMixin,
models.CreatableMixin,
):
"""Represent a new Paperless `StoragePath`, which is not stored in Paperless."""
"""Represent a new `StoragePath`, which is not yet stored in Paperless."""

_api_path = API_PATH["storage_paths"]

Expand All @@ -156,7 +158,7 @@ class StoragePathDraft(
class Tag( # pylint: disable=too-many-ancestors,too-many-instance-attributes
PaperlessModel,
models.MatchingFieldsMixin,
models.PermissionFieldsMixin,
models.SecurableMixin,
models.UpdatableMixin,
models.DeletableMixin,
):
Expand All @@ -180,12 +182,13 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):


@dataclass(init=False)
class TagDraft(
class TagDraft( # pylint: disable=too-many-ancestors
PaperlessModel,
models.MatchingFieldsMixin,
models.SecurableDraftMixin,
models.CreatableMixin,
):
"""Represent a new Paperless `Tag`, which is not stored in Paperless."""
"""Represent a new `Tag`, which is not yet stored in Paperless."""

_api_path = API_PATH["tags"]

Expand All @@ -208,6 +211,7 @@ class TagDraft(

class CorrespondentHelper( # pylint: disable=too-many-ancestors
HelperBase[Correspondent],
helpers.SecurableMixin,
helpers.CallableMixin[Correspondent],
helpers.DraftableMixin[CorrespondentDraft],
helpers.IterableMixin[Correspondent],
Expand All @@ -223,6 +227,7 @@ class CorrespondentHelper( # pylint: disable=too-many-ancestors

class DocumentTypeHelper( # pylint: disable=too-many-ancestors
HelperBase[DocumentType],
helpers.SecurableMixin,
helpers.CallableMixin[DocumentType],
helpers.DraftableMixin[DocumentTypeDraft],
helpers.IterableMixin[DocumentType],
Expand All @@ -238,6 +243,7 @@ class DocumentTypeHelper( # pylint: disable=too-many-ancestors

class StoragePathHelper( # pylint: disable=too-many-ancestors
HelperBase[StoragePath],
helpers.SecurableMixin,
helpers.CallableMixin[StoragePath],
helpers.DraftableMixin[StoragePathDraft],
helpers.IterableMixin[StoragePath],
Expand All @@ -253,6 +259,7 @@ class StoragePathHelper( # pylint: disable=too-many-ancestors

class TagHelper( # pylint: disable=too-many-ancestors
HelperBase[Tag],
helpers.SecurableMixin,
helpers.CallableMixin[Tag],
helpers.DraftableMixin[TagDraft],
helpers.IterableMixin[Tag],
Expand Down
20 changes: 19 additions & 1 deletion pypaperless/models/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""PyPaperless common types."""

from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import Enum, StrEnum
from typing import Any

Expand Down Expand Up @@ -75,6 +75,24 @@ def _missing_(cls: type, value: object) -> "MatchingAlgorithmType": # noqa ARG0
return MatchingAlgorithmType.UNKNOWN


# mixins/models/securable
@dataclass(kw_only=True)
class PermissionSetType:
"""Represent a Paperless permission set."""

users: list[int] = field(default_factory=list)
groups: list[int] = field(default_factory=list)


# mixins/models/securable
@dataclass(kw_only=True)
class PermissionTableType:
"""Represent a Paperless permissions type."""

view: PermissionSetType = field(default_factory=PermissionSetType)
change: PermissionSetType = field(default_factory=PermissionSetType)


# documents
class RetrieveFileMode(StrEnum):
"""Represent a subtype of `DownloadedDocument`."""
Expand Down
3 changes: 2 additions & 1 deletion pypaperless/models/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
@dataclass(init=False)
class Document( # pylint: disable=too-many-instance-attributes, too-many-ancestors
PaperlessModel,
models.PermissionFieldsMixin,
models.SecurableMixin,
models.UpdatableMixin,
models.DeletableMixin,
):
Expand Down Expand Up @@ -461,6 +461,7 @@ def draft(self, pk: int | None = None, **kwargs: Any) -> DocumentNoteDraft:

class DocumentHelper( # pylint: disable=too-many-ancestors
HelperBase[Document],
helpers.SecurableMixin,
helpers.CallableMixin[Document],
helpers.DraftableMixin[DocumentDraft],
helpers.IterableMixin[Document],
Expand Down
10 changes: 6 additions & 4 deletions pypaperless/models/mails.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@dataclass(init=False)
class MailAccount(
PaperlessModel,
models.PermissionFieldsMixin,
models.SecurableMixin,
): # pylint: disable=too-many-instance-attributes
"""Represent a Paperless `MailAccount`."""

Expand All @@ -42,7 +42,7 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):
@dataclass(init=False)
class MailRule(
PaperlessModel,
models.PermissionFieldsMixin,
models.SecurableMixin,
): # pylint: disable=too-many-instance-attributes
"""Represent a Paperless `MailRule`."""

Expand Down Expand Up @@ -78,10 +78,11 @@ def __init__(self, api: "Paperless", data: dict[str, Any]):
self._api_path = self._api_path.format(pk=data.get("id"))


class MailAccountHelper(
class MailAccountHelper( # pylint: disable=too-many-ancestors
HelperBase[MailAccount],
helpers.CallableMixin[MailAccount],
helpers.IterableMixin[MailAccount],
helpers.SecurableMixin,
):
"""Represent a factory for Paperless `MailAccount` models."""

Expand All @@ -91,10 +92,11 @@ class MailAccountHelper(
_resource_cls = MailAccount


class MailRuleHelper(
class MailRuleHelper( # pylint: disable=too-many-ancestors
HelperBase[MailRule],
helpers.CallableMixin[MailRule],
helpers.IterableMixin[MailRule],
helpers.SecurableMixin,
):
"""Represent a factory for Paperless `MailRule` models."""

Expand Down
2 changes: 2 additions & 0 deletions pypaperless/models/mixins/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
from .callable import CallableMixin
from .draftable import DraftableMixin
from .iterable import IterableMixin
from .securable import SecurableMixin

__all__ = (
"CallableMixin",
"DraftableMixin",
"IterableMixin",
"SecurableMixin",
)
7 changes: 7 additions & 0 deletions pypaperless/models/mixins/helpers/callable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from pypaperless.models.base import HelperProtocol, ResourceT

from .securable import SecurableMixin


class CallableMixin(HelperProtocol[ResourceT]): # pylint: disable=too-few-public-methods
"""Provide methods for calling a specific resource item."""
Expand All @@ -26,6 +28,11 @@ async def __call__(
"id": pk,
}
item = self._resource_cls.create_with_data(self._api, data)

# set requesting full permissions
if SecurableMixin in type(self).__bases__ and getattr(self, "_request_full_perms", False):
item._params.update({"full_perms": "true"}) # pylint: disable=protected-access

if not lazy:
await item.load()
return item
4 changes: 3 additions & 1 deletion pypaperless/models/mixins/helpers/draftable.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ def draft(self, **kwargs: Any) -> ResourceT:
raise DraftNotSupported("Helper class has no _draft_cls attribute.")
kwargs.update({"id": -1})

return self._draft_cls.create_with_data(self._api, data=kwargs, fetched=True)
item = self._draft_cls.create_with_data(self._api, data=kwargs, fetched=True)

return item
23 changes: 23 additions & 0 deletions pypaperless/models/mixins/helpers/securable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""SecurableMixin for PyPaperless helpers."""


class SecurableMixin: # pylint: disable=too-few-public-methods
"""Provide the `request_full_permissions` property for PyPaperless helpers."""

_request_full_perms: bool = False

@property
def request_permissions(self) -> bool:
"""Return whether the helper requests items with the `permissions` table, or not.
Documentation: https://docs.paperless-ngx.com/api/#permissions
"""
return self._request_full_perms

@request_permissions.setter
def request_permissions(self, value: bool) -> None:
"""Set whether the helper requests items with the `permissions` table, or not.
Documentation: https://docs.paperless-ngx.com/api/#permissions
"""
self._request_full_perms = value
7 changes: 5 additions & 2 deletions pypaperless/models/mixins/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"""Mixins for PyPaperless models."""

from .creatable import CreatableMixin
from .data_fields import MatchingFieldsMixin, PermissionFieldsMixin
from .data_fields import MatchingFieldsMixin # , PermissionFieldsMixin
from .deletable import DeletableMixin
from .securable import SecurableDraftMixin, SecurableMixin
from .updatable import UpdatableMixin

__all__ = (
"CreatableMixin",
"DeletableMixin",
"MatchingFieldsMixin",
"PermissionFieldsMixin",
# "PermissionFieldsMixin",
"UpdatableMixin",
"SecurableMixin",
"SecurableDraftMixin",
)
19 changes: 6 additions & 13 deletions pypaperless/models/mixins/models/creatable.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,6 @@ async def save(self) -> int | str | tuple[int, int]:
"""
self.validate()
kwdict = self._serialize()
# in case of DocumentDraft, we want to transmit data as form
# this is kind of dirty, but should do its job in this case
# as_form = type(self).__name__ == "DocumentDraft"
# kwargs = {
# "form"
# if as_form
# else "json": {
# field.name: object_to_dict_value(getattr(self, field.name))
# for field in self._get_dataclass_fields()
# }
# }
res = await self._api.request_json("post", self._api_path, **kwdict)

if type(self).__name__ == "DocumentNoteDraft":
Expand All @@ -56,8 +45,12 @@ def _serialize(self) -> dict[str, Any]:
"json": {
field.name: object_to_dict_value(getattr(self, field.name))
for field in self._get_dataclass_fields()
}
},
}
# check for empty permissions as they will raise if None
if "set_permissions" in data["json"] and data["json"]["set_permissions"] is None:
del data["json"]["set_permissions"]

return data

def validate(self) -> None:
Expand All @@ -67,5 +60,5 @@ def validate(self) -> None:
if len(missing) == 0:
return
raise DraftFieldRequired(
f"Missing fields for saving a `{self.__class__.__name__}`: {', '.join(missing)}."
f"Missing fields for saving a `{type(self).__name__}`: {', '.join(missing)}."
)
Loading

0 comments on commit 6c8110f

Please sign in to comment.