Skip to content

Commit

Permalink
removal: remove ApiListData because of its unreliable total property
Browse files Browse the repository at this point in the history
  • Loading branch information
smotornyuk committed Jul 20, 2024
1 parent cc0544a commit 5fb1bbd
Show file tree
Hide file tree
Showing 34 changed files with 578 additions and 241 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ jobs:
test:
strategy:
matrix:
ckan-version: ["2.11", "2.10", 2.9]
ckan-version: ["2.11", "2.10"]
fail-fast: false

runs-on: ubuntu-latest
container:
# The CKAN version tag of the Solr and Postgres containers should match
# the one of the container the tests run on.
# You can switch this base image with a custom image tailored to your project
image: openknowledge/ckan-dev:${{ matrix.ckan-version }}
image: ckan/ckan-dev:${{ matrix.ckan-version }}
services:
solr:
image: ckan/ckan-solr:${{ matrix.ckan-version }}-solr9
Expand Down
19 changes: 4 additions & 15 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,14 @@ repos:
stages: [pre-commit]
- id: debug-statements
stages: [pre-push]

## Isort
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort
stages: [pre-commit]

## Black
- repo: https://github.com/psf/black
rev: 24.4.0
hooks:
- id: black
stages: [pre-commit]

## Ruff
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.4.1
rev: v0.5.0
hooks:
- id: ruff
args: [--fix]
stages: [pre-commit]
- id: ruff-format
stages: [pre-commit]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Tools for building interfaces for data collections using declarative style.

This extension simplifies describing series of items, such as datasets from
search page, users registered on portal, rows of CSV file, tables in DB,
etc. Once you defined the way items are obtained from data source, you'll get
etc. Once you defined the way of fetching items from data source, you'll get
generic interface for pagination, search and displaying data in any format:
HTML page, CSV document, JSON list, or any other custom format that you can
describe.
Expand Down
20 changes: 4 additions & 16 deletions ckanext/collection/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,27 @@


def anonymous_collections() -> list[str]:
"""Names of registered collections that are viewable by any visitor,
including anonymous.
"""

"""Names of registered public collections."""
return tk.config[CONFIG_ANNONYMOUS]


def authenticated_collections() -> list[str]:
"""Names of registered collections that are viewable by any authenticated
user.
"""
"""Names of registered collections available to registered users."""
return tk.config[CONFIG_AUTHENTICATED]


def include_htmx_asset() -> bool:
"""Add HTMX asset to pages. Enable this option if you are using CKAN
v2.10.
"""

"""Add HTMX asset to pages."""
return tk.config[CONFIG_INCLUDE_ASSET]


def htmx_init_modules() -> bool:
"""Initialize CKAN JS modules every time HTMX fetches HTML from the
server.
"""

"""Initialize CKAN JS modules when HTMX fetches HTML from the server."""
return tk.config[CONFIG_INIT_MODULES]


def serializer(format: str) -> type[types.BaseSerializer] | None:
"""Import path for serializer used by `format` export endpoint."""

value = tk.config.get(f"ckanext.collection.export.{format}.serializer")
if value:
return import_string(value, silent=True)
Expand Down
4 changes: 3 additions & 1 deletion ckanext/collection/interfaces.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Interface."""

from __future__ import annotations

from ckan.plugins import Interface
Expand All @@ -6,7 +8,7 @@


class ICollection(Interface):
"""Extend functionality of ckanext-collections
"""Extend functionality of ckanext-collections.
Example:
```python
Expand Down
10 changes: 3 additions & 7 deletions ckanext/collection/internal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"""Logic used across collection utilities.
"""
"""Logic used across collection utilities."""

from __future__ import annotations

Expand Down Expand Up @@ -52,7 +50,6 @@ class AttachTrait(abc.ABC, Generic[types.TDataCollection]):
logic.
Example:
>>> class Impl(AttachTrait):
>>> def __init__(self, collection):
>>> self._attach(collection)
Expand Down Expand Up @@ -187,7 +184,6 @@ def configurable_attribute(
"""Declare configurable attribute.
Example:
>>> class DataFactory(Data):
>>> private = configurable_attribute(False)
>>>
Expand All @@ -198,9 +194,9 @@ def configurable_attribute(


class UserTrait(AttrSettingsTrait):
"""Add configurable `user` attribute, with default set to
`current_user.name`.
"""Add configurable `user` attribute.
Default value set to `tk.current_user.name`.
"""

user = configurable_attribute(
Expand Down
2 changes: 2 additions & 0 deletions ckanext/collection/plugin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""hehe."""

from __future__ import annotations

import operator
Expand Down
1 change: 0 additions & 1 deletion ckanext/collection/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@
@pytest.fixture()
def collection_registry():
"""Collection registry cleaned after each test."""

yield internal.collection_registry
internal.collection_registry.reset()
6 changes: 0 additions & 6 deletions ckanext/collection/tests/test_dive.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ def test_api_search(self):
for pkg in col:
assert isinstance(pkg, dict)

@pytest.mark.usefixtures("clean_db", "clean_index", "package")
def test_api_list(self):
col = ApiListCollection("", {}, data_settings={"action": "package_list"})
for pkg in col:
assert isinstance(pkg, str)

@pytest.mark.usefixtures("clean_db", "user")
def test_api(self):
col = ApiCollection("", {}, data_settings={"action": "user_list"})
Expand Down
27 changes: 0 additions & 27 deletions ckanext/collection/tests/utils/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,30 +234,3 @@ def test_base(self, package_factory: Any):

assert obj.total == 1
assert next(iter(obj))["id"] == ids[1]


@pytest.mark.usefixtures("clean_db")
class TestApiListData:
def test_base(self, organization_factory: Any):
ids = sorted([o["name"] for o in organization_factory.create_batch(3)])

collection = Collection("", {})
obj = data.ApiListData(collection, action="organization_list")

assert obj.total == 3
assert sorted(obj) == ids

def test_payload(self, organization_factory: Any):
organization_factory(type="custom")

collection = Collection("", {})

obj = data.ApiListData(collection, action="organization_list")
assert obj.total == 0

obj = data.ApiListData(
collection,
action="organization_list",
payload={"type": "custom"},
)
assert obj.total == 1
4 changes: 2 additions & 2 deletions ckanext/collection/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def service_name(self) -> str:


class BaseColumns(abc.ABC, Service):
"""Declaration of columns properties"""
"""Declaration of columns properties."""

names: list[str]
visible: set[str]
Expand Down Expand Up @@ -77,7 +77,7 @@ def service_name(self):


class BasePager(abc.ABC, Service):
"""Declaration of pager properties"""
"""Declaration of pager properties."""

params: dict[str, Any]

Expand Down
4 changes: 0 additions & 4 deletions ckanext/collection/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .collection import (
ApiCollection,
ApiListCollection,
ApiSearchCollection,
Collection,
CollectionExplorer,
Expand All @@ -12,7 +11,6 @@
from .columns import Columns, DbColumns, TableColumns
from .data import (
ApiData,
ApiListData,
ApiSearchData,
BaseModelData,
BaseSaData,
Expand Down Expand Up @@ -57,8 +55,6 @@
"UrlDbConnection",
"ApiCollection",
"ApiData",
"ApiListCollection",
"ApiListData",
"ApiSearchCollection",
"ApiSearchData",
"BaseModelData",
Expand Down
3 changes: 1 addition & 2 deletions ckanext/collection/utils/collection/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from ckanext.collection.utils.data import StaticData

from .api import ApiCollection, ApiListCollection, ApiSearchCollection
from .api import ApiCollection, ApiSearchCollection
from .base import Collection
from .db import DbCollection
from .explorer import CollectionExplorer, DbExplorer
Expand All @@ -13,7 +13,6 @@
"DbCollection",
"ApiCollection",
"ApiSearchCollection",
"ApiListCollection",
"ModelCollection",
"CollectionExplorer",
"DbExplorer",
Expand Down
6 changes: 1 addition & 5 deletions ckanext/collection/utils/collection/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from ckanext.collection.utils.data import ApiData, ApiListData, ApiSearchData
from ckanext.collection.utils.data import ApiData, ApiSearchData

from .base import Collection

Expand All @@ -11,7 +11,3 @@ class ApiCollection(Collection):

class ApiSearchCollection(ApiCollection):
DataFactory = ApiSearchData


class ApiListCollection(ApiCollection):
DataFactory = ApiListData
2 changes: 1 addition & 1 deletion ckanext/collection/utils/collection/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def replace_service(
) -> types.BaseDbConnection | None: ...

def replace_service(self, service: types.Service) -> types.Service | None:
"""Attach service to collection"""
"""Attach service to collection."""
old_service = getattr(self, service.service_name, None)
setattr(self, service.service_name, service)
return old_service
Expand Down
5 changes: 3 additions & 2 deletions ckanext/collection/utils/collection/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

class ExplorerSerializer(HtmlSerializer[types.TDataCollection]):
extend_page_template: bool = internal.configurable_attribute(
default_factory=lambda self: tk.request
and not tk.request.headers.get("hx-request"),
default_factory=lambda self: bool(
tk.request and not tk.request.headers.get("hx-request"),
),
)
main_template: str = internal.configurable_attribute(
"collection/serialize/explorer/main.html",
Expand Down
2 changes: 1 addition & 1 deletion ckanext/collection/utils/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def _compute_set(self, value: Default | set[str]):
return cast("set[str]", set())

if value is self.Default.ALL:
return {c for c in self.names}
return set(self.names)

if value is self.Default.NOT_HIDDEN:
return {c for c in self.names if c not in self.hidden}
Expand Down
25 changes: 21 additions & 4 deletions ckanext/collection/utils/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@

from ckanext.collection import internal, types

from .api import ApiData, ApiListData, ApiSearchData
from .api import ApiData, ApiSearchData
from .base import Data
from .db import DbData, TableData
from .misc import CsvFileData
from .model import BaseSaData, ModelData, StatementSaData, UnionSaData
from .stream import CsvFileData

__all__ = [
"Data",
"CsvFileData",
"TableData",
"ApiData",
"ApiListData",
"ApiSearchData",
"UnionSaData",
"UnionModelData",
Expand All @@ -38,7 +37,25 @@
class StaticData(Data[types.TData, types.TDataCollection]):
"""Static data source.
This class turns existing iterable into a data source.
This class produce items from its `data` attribute. Use any sequence as a
value for `data` during initialization.
Attributes:
data: sequence of items produced by the service
Example:
```python
NumericData = data.StaticData.with_attributes(data=range(1, 20))
UppercaseData = data.StaticData.with_attributes(
data="ABCDEFGHIJKLMNOPQRSTUVWXYZ",
)
```
```pycon
>>> col = collection.Collection(data_factory=NumericData)
>>> list(col)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```
"""

data: Iterable[types.TData] = internal.configurable_attribute(
Expand Down
Loading

0 comments on commit 5fb1bbd

Please sign in to comment.