feat: add native table for Animal Types; import from farmOS API
This commit is contained in:
parent
09042747a0
commit
4a517bf7bf
23 changed files with 786 additions and 12 deletions
6
docs/api/wuttafarm.cli.base.rst
Normal file
6
docs/api/wuttafarm.cli.base.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttafarm.cli.base``
|
||||
======================
|
||||
|
||||
.. automodule:: wuttafarm.cli.base
|
||||
:members:
|
||||
6
docs/api/wuttafarm.cli.import_farmos.rst
Normal file
6
docs/api/wuttafarm.cli.import_farmos.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttafarm.cli.import_farmos``
|
||||
===============================
|
||||
|
||||
.. automodule:: wuttafarm.cli.import_farmos
|
||||
:members:
|
||||
6
docs/api/wuttafarm.cli.install.rst
Normal file
6
docs/api/wuttafarm.cli.install.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttafarm.cli.install``
|
||||
=========================
|
||||
|
||||
.. automodule:: wuttafarm.cli.install
|
||||
:members:
|
||||
6
docs/api/wuttafarm.importing.farmos.rst
Normal file
6
docs/api/wuttafarm.importing.farmos.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttafarm.importing.farmos``
|
||||
==============================
|
||||
|
||||
.. automodule:: wuttafarm.importing.farmos
|
||||
:members:
|
||||
6
docs/api/wuttafarm.importing.rst
Normal file
6
docs/api/wuttafarm.importing.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
``wuttafarm.importing``
|
||||
=======================
|
||||
|
||||
.. automodule:: wuttafarm.importing
|
||||
:members:
|
||||
|
|
@ -8,9 +8,6 @@ and extend `farmOS`_.
|
|||
.. _WuttaWeb: https://wuttaproject.org
|
||||
.. _farmOS: https://farmos.org
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
|
||||
It is just an experiment so far; the ideas I hope to play with
|
||||
include:
|
||||
|
||||
|
|
@ -19,6 +16,9 @@ include:
|
|||
- possibly add more schema / extra features
|
||||
- possibly sync data back to farmOS
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
|
@ -37,11 +37,16 @@ include:
|
|||
api/wuttafarm.app
|
||||
api/wuttafarm.auth
|
||||
api/wuttafarm.cli
|
||||
api/wuttafarm.cli.base
|
||||
api/wuttafarm.cli.import_farmos
|
||||
api/wuttafarm.cli.install
|
||||
api/wuttafarm.config
|
||||
api/wuttafarm.db
|
||||
api/wuttafarm.db.model
|
||||
api/wuttafarm.farmos
|
||||
api/wuttafarm.farmos.handler
|
||||
api/wuttafarm.importing
|
||||
api/wuttafarm.importing.farmos
|
||||
api/wuttafarm.install
|
||||
api/wuttafarm.web
|
||||
api/wuttafarm.web.app
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ dependencies = [
|
|||
"psycopg2",
|
||||
"pyramid_exclog",
|
||||
"uvicorn[standard]",
|
||||
"WuttaSync",
|
||||
"WuttaWeb[continuum]>=0.27.4",
|
||||
]
|
||||
|
||||
|
|
@ -47,12 +48,18 @@ docs = ["Sphinx", "furo"]
|
|||
[project.entry-points."paste.app_factory"]
|
||||
"main" = "wuttafarm.web.app:main"
|
||||
|
||||
[project.entry-points."wutta.app.providers"]
|
||||
wuttafarm = "wuttafarm.app:WuttaFarmAppProvider"
|
||||
|
||||
[project.entry-points."wutta.config.extensions"]
|
||||
"wuttafarm" = "wuttafarm.config:WuttaFarmConfig"
|
||||
|
||||
[project.entry-points."wutta.web.menus"]
|
||||
"wuttafarm" = "wuttafarm.web.menus:WuttaFarmMenuHandler"
|
||||
|
||||
[project.entry-points."wuttasync.importing"]
|
||||
"import.to_wuttafarm.from_farmos" = "wuttafarm.importing.farmos:FromFarmOSToWuttaFarm"
|
||||
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://forgejo.wuttaproject.org/wutta/wuttafarm"
|
||||
|
|
|
|||
|
|
@ -64,3 +64,11 @@ class WuttaFarmAppHandler(base.AppHandler):
|
|||
"""
|
||||
handler = self.get_farmos_handler()
|
||||
return handler.get_farmos_client(*args, **kwargs)
|
||||
|
||||
|
||||
class WuttaFarmAppProvider(base.AppProvider):
|
||||
"""
|
||||
The :term:`app provider` for WuttaFarm.
|
||||
"""
|
||||
|
||||
email_modules = ["wuttafarm.emails"]
|
||||
|
|
|
|||
30
src/wuttafarm/cli/__init__.py
Normal file
30
src/wuttafarm/cli/__init__.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
WuttaFarm CLI
|
||||
"""
|
||||
|
||||
from .base import wuttafarm_typer
|
||||
|
||||
# nb. must bring in all modules for discovery to work
|
||||
from . import import_farmos
|
||||
from . import install
|
||||
31
src/wuttafarm/cli/base.py
Normal file
31
src/wuttafarm/cli/base.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
WuttaFarm CLI - base Typer instance
|
||||
"""
|
||||
|
||||
from wuttjamaican.cli import make_typer
|
||||
|
||||
|
||||
wuttafarm_typer = make_typer(
|
||||
name="wuttafarm", help="WuttaFarm -- Web app to integrate with and extend farmOS"
|
||||
)
|
||||
41
src/wuttafarm/cli/import_farmos.py
Normal file
41
src/wuttafarm/cli/import_farmos.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
See also: :ref:`wuttafarm-import-farmos`
|
||||
"""
|
||||
|
||||
import typer
|
||||
|
||||
from wuttasync.cli import import_command, ImportCommandHandler
|
||||
|
||||
from wuttafarm.cli import wuttafarm_typer
|
||||
|
||||
|
||||
@wuttafarm_typer.command()
|
||||
@import_command
|
||||
def import_farmos(ctx: typer.Context, **kwargs):
|
||||
"""
|
||||
Import data from farmOS API to WuttaFarm
|
||||
"""
|
||||
config = ctx.parent.wutta_config
|
||||
handler = ImportCommandHandler(config, key="import.to_wuttafarm.from_farmos")
|
||||
handler.run(ctx)
|
||||
|
|
@ -25,12 +25,7 @@ WuttaFarm CLI
|
|||
|
||||
import typer
|
||||
|
||||
from wuttjamaican.cli import make_typer
|
||||
|
||||
|
||||
wuttafarm_typer = make_typer(
|
||||
name="wuttafarm", help="WuttaFarm -- Web app to integrate with and extend farmOS"
|
||||
)
|
||||
from wuttafarm.cli import wuttafarm_typer
|
||||
|
||||
|
||||
@wuttafarm_typer.command()
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
"""add Animal Types
|
||||
|
||||
Revision ID: 2b6385d0fa17
|
||||
Revises:
|
||||
Create Date: 2026-02-08 14:55:42.236918
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import wuttjamaican.db.util
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "2b6385d0fa17"
|
||||
down_revision: Union[str, None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = ("wuttafarm",)
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
||||
# animal_type
|
||||
op.create_table(
|
||||
"animal_type",
|
||||
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
|
||||
sa.Column("name", sa.String(length=100), nullable=False),
|
||||
sa.Column("description", sa.String(length=255), nullable=True),
|
||||
sa.Column("changed", sa.DateTime(), nullable=True),
|
||||
sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
|
||||
sa.Column("drupal_internal_id", sa.Integer(), nullable=True),
|
||||
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_animal_type")),
|
||||
sa.UniqueConstraint(
|
||||
"drupal_internal_id", name=op.f("uq_animal_type_drupal_internal_id")
|
||||
),
|
||||
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_animal_type_farmos_uuid")),
|
||||
sa.UniqueConstraint("name", name=op.f("uq_animal_type_name")),
|
||||
)
|
||||
op.create_table(
|
||||
"animal_type_version",
|
||||
sa.Column(
|
||||
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
|
||||
sa.Column(
|
||||
"description", sa.String(length=255), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"farmos_uuid",
|
||||
wuttjamaican.db.util.UUID(),
|
||||
autoincrement=False,
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"drupal_internal_id", sa.Integer(), autoincrement=False, nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
|
||||
),
|
||||
sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("operation_type", sa.SmallInteger(), nullable=False),
|
||||
sa.PrimaryKeyConstraint(
|
||||
"uuid", "transaction_id", name=op.f("pk_animal_type_version")
|
||||
),
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_animal_type_version_end_transaction_id"),
|
||||
"animal_type_version",
|
||||
["end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_animal_type_version_operation_type"),
|
||||
"animal_type_version",
|
||||
["operation_type"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
"ix_animal_type_version_pk_transaction_id",
|
||||
"animal_type_version",
|
||||
["uuid", sa.literal_column("transaction_id DESC")],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
"ix_animal_type_version_pk_validity",
|
||||
"animal_type_version",
|
||||
["uuid", "transaction_id", "end_transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.create_index(
|
||||
op.f("ix_animal_type_version_transaction_id"),
|
||||
"animal_type_version",
|
||||
["transaction_id"],
|
||||
unique=False,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
# animal_type
|
||||
op.drop_index(
|
||||
op.f("ix_animal_type_version_transaction_id"), table_name="animal_type_version"
|
||||
)
|
||||
op.drop_index(
|
||||
"ix_animal_type_version_pk_validity", table_name="animal_type_version"
|
||||
)
|
||||
op.drop_index(
|
||||
"ix_animal_type_version_pk_transaction_id", table_name="animal_type_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_animal_type_version_operation_type"), table_name="animal_type_version"
|
||||
)
|
||||
op.drop_index(
|
||||
op.f("ix_animal_type_version_end_transaction_id"),
|
||||
table_name="animal_type_version",
|
||||
)
|
||||
op.drop_table("animal_type_version")
|
||||
op.drop_table("animal_type")
|
||||
|
|
@ -26,4 +26,5 @@ WuttaFarm data models
|
|||
# bring in all of wutta
|
||||
from wuttjamaican.db.model import *
|
||||
|
||||
# TODO: import other/custom models here...
|
||||
# wuttafarm models
|
||||
from .animals import AnimalType
|
||||
|
|
|
|||
94
src/wuttafarm/db/model/animals.py
Normal file
94
src/wuttafarm/db/model/animals.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Model definition for Animal Types
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from wuttjamaican.db import model
|
||||
|
||||
|
||||
class AnimalType(model.Base):
|
||||
"""
|
||||
Represents an "animal type" (taxonomy term) from farmOS
|
||||
"""
|
||||
|
||||
__tablename__ = "animal_type"
|
||||
__versioned__ = {
|
||||
"exclude": [
|
||||
"changed",
|
||||
],
|
||||
}
|
||||
__wutta_hint__ = {
|
||||
"model_title": "Animal Type",
|
||||
"model_title_plural": "Animal Types",
|
||||
}
|
||||
|
||||
uuid = model.uuid_column()
|
||||
|
||||
name = sa.Column(
|
||||
sa.String(length=100),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
doc="""
|
||||
Name of the animal type.
|
||||
""",
|
||||
)
|
||||
|
||||
description = sa.Column(
|
||||
sa.String(length=255),
|
||||
nullable=True,
|
||||
doc="""
|
||||
Optional description for the animal type.
|
||||
""",
|
||||
)
|
||||
|
||||
changed = sa.Column(
|
||||
sa.DateTime(),
|
||||
nullable=True,
|
||||
doc="""
|
||||
When the animal type was last changed, according to farmOS.
|
||||
""",
|
||||
)
|
||||
|
||||
farmos_uuid = sa.Column(
|
||||
model.UUID(),
|
||||
nullable=True,
|
||||
unique=True,
|
||||
doc="""
|
||||
UUID for the animal type within farmOS.
|
||||
""",
|
||||
)
|
||||
|
||||
drupal_internal_id = sa.Column(
|
||||
sa.Integer(),
|
||||
nullable=True,
|
||||
unique=True,
|
||||
doc="""
|
||||
Drupal internal ID for the animal type.
|
||||
""",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name or ""
|
||||
32
src/wuttafarm/emails.py
Normal file
32
src/wuttafarm/emails.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Email sending config for WuttaFarm
|
||||
"""
|
||||
|
||||
from wuttasync.emails import ImportExportWarning
|
||||
|
||||
|
||||
class import_to_wuttafarm_from_farmos_warning(ImportExportWarning):
|
||||
"""
|
||||
Diff warning for farmOS → WuttaFarm import.
|
||||
"""
|
||||
24
src/wuttafarm/importing/__init__.py
Normal file
24
src/wuttafarm/importing/__init__.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Importing data to WuttaFarm
|
||||
"""
|
||||
154
src/wuttafarm/importing/farmos.py
Normal file
154
src/wuttafarm/importing/farmos.py
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Data import for farmOS -> WuttaFarm
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from oauthlib.oauth2 import BackendApplicationClient
|
||||
from requests_oauthlib import OAuth2Session
|
||||
|
||||
from wuttasync.importing import ImportHandler, ToWuttaHandler, Importer, ToWutta
|
||||
|
||||
from wuttafarm.db import model
|
||||
|
||||
|
||||
class FromFarmOSHandler(ImportHandler):
|
||||
"""
|
||||
Base class for import handler using farmOS API as data source.
|
||||
"""
|
||||
|
||||
source_key = "farmos"
|
||||
generic_source_title = "farmOS"
|
||||
|
||||
def begin_source_transaction(self):
|
||||
"""
|
||||
Establish the farmOS API client.
|
||||
"""
|
||||
token = self.get_farmos_oauth2_token()
|
||||
self.farmos_client = self.app.get_farmos_client(token=token)
|
||||
|
||||
def get_farmos_oauth2_token(self):
|
||||
|
||||
client_id = self.config.get(
|
||||
"farmos.oauth2.importing.client_id", default="wuttafarm"
|
||||
)
|
||||
client_secret = self.config.require("farmos.oauth2.importing.client_secret")
|
||||
scope = self.config.get("farmos.oauth2.importing.scope", default="farm_manager")
|
||||
|
||||
client = BackendApplicationClient(client_id=client_id)
|
||||
oauth = OAuth2Session(client=client)
|
||||
|
||||
return oauth.fetch_token(
|
||||
token_url=self.app.get_farmos_url("/oauth/token"),
|
||||
include_client_id=True,
|
||||
client_secret=client_secret,
|
||||
scope=scope,
|
||||
)
|
||||
|
||||
def get_importer_kwargs(self, key, **kwargs):
|
||||
kwargs = super().get_importer_kwargs(key, **kwargs)
|
||||
kwargs["farmos_client"] = self.farmos_client
|
||||
return kwargs
|
||||
|
||||
|
||||
class ToWuttaFarmHandler(ToWuttaHandler):
|
||||
"""
|
||||
Base class for import handler targeting WuttaFarm
|
||||
"""
|
||||
|
||||
target_key = "wuttafarm"
|
||||
|
||||
|
||||
class FromFarmOSToWuttaFarm(FromFarmOSHandler, ToWuttaFarmHandler):
|
||||
"""
|
||||
Handler for farmOS → WuttaFarm import.
|
||||
"""
|
||||
|
||||
def define_importers(self):
|
||||
""" """
|
||||
importers = super().define_importers()
|
||||
importers["AnimalType"] = AnimalTypeImporter
|
||||
return importers
|
||||
|
||||
|
||||
class FromFarmOS(Importer):
|
||||
"""
|
||||
Base class for importers using farmOS API as data source.
|
||||
"""
|
||||
|
||||
key = "farmos_uuid"
|
||||
|
||||
def get_supported_fields(self):
|
||||
"""
|
||||
Auto-remove the ``uuid`` field, since we use ``farmos_uuid``
|
||||
instead for the importer key.
|
||||
"""
|
||||
fields = list(super().get_supported_fields())
|
||||
if "uuid" in fields:
|
||||
fields.remove("uuid")
|
||||
return fields
|
||||
|
||||
def normalize_datetime(self, dt):
|
||||
"""
|
||||
Convert a farmOS datetime value to naive UTC used by
|
||||
WuttaFarm.
|
||||
|
||||
:param dt: Date/time string value "as-is" from the farmOS API.
|
||||
|
||||
:returns: Equivalent naive UTC ``datetime``
|
||||
"""
|
||||
dt = datetime.datetime.fromisoformat(dt)
|
||||
return self.app.make_utc(dt)
|
||||
|
||||
|
||||
class AnimalTypeImporter(FromFarmOS, ToWutta):
|
||||
"""
|
||||
farmOS API → WuttaFarm importer for Animal Types
|
||||
"""
|
||||
|
||||
model_class = model.AnimalType
|
||||
|
||||
supported_fields = [
|
||||
"farmos_uuid",
|
||||
"drupal_internal_id",
|
||||
"name",
|
||||
"description",
|
||||
"changed",
|
||||
]
|
||||
|
||||
def get_source_objects(self):
|
||||
""" """
|
||||
animal_types = self.farmos_client.resource.get("taxonomy_term", "animal_type")
|
||||
return animal_types["data"]
|
||||
|
||||
def normalize_source_object(self, animal_type):
|
||||
""" """
|
||||
return {
|
||||
"farmos_uuid": UUID(animal_type["id"]),
|
||||
"drupal_internal_id": animal_type["attributes"]["drupal_internal__tid"],
|
||||
"name": animal_type["attributes"]["name"],
|
||||
"description": animal_type["attributes"]["description"],
|
||||
"changed": self.normalize_datetime(animal_type["attributes"]["changed"]),
|
||||
}
|
||||
|
|
@ -33,10 +33,24 @@ class WuttaFarmMenuHandler(base.MenuHandler):
|
|||
|
||||
def make_menus(self, request, **kwargs):
|
||||
return [
|
||||
self.make_asset_menu(request),
|
||||
self.make_farmos_menu(request),
|
||||
self.make_admin_menu(request, include_people=True),
|
||||
]
|
||||
|
||||
def make_asset_menu(self, request):
|
||||
return {
|
||||
"title": "Assets",
|
||||
"type": "menu",
|
||||
"items": [
|
||||
{
|
||||
"title": "Animal Types",
|
||||
"route": "animal_types",
|
||||
"perm": "animal_types.list",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
def make_farmos_menu(self, request):
|
||||
config = request.wutta_config
|
||||
app = config.get_app()
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ WuttaFarm Views
|
|||
|
||||
from wuttaweb.views import essential
|
||||
|
||||
from .master import WuttaFarmMasterView
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
|
|
@ -37,5 +39,8 @@ def includeme(config):
|
|||
}
|
||||
)
|
||||
|
||||
# native table views
|
||||
config.include("wuttafarm.web.views.animal_types")
|
||||
|
||||
# views for farmOS
|
||||
config.include("wuttafarm.web.views.farmos")
|
||||
|
|
|
|||
99
src/wuttafarm/web/views/animal_types.py
Normal file
99
src/wuttafarm/web/views/animal_types.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Master view for Animal Types
|
||||
"""
|
||||
|
||||
from wuttafarm.db.model.animals import AnimalType
|
||||
from wuttafarm.web.views import WuttaFarmMasterView
|
||||
|
||||
|
||||
class AnimalTypeView(WuttaFarmMasterView):
|
||||
"""
|
||||
Master view for Animal Types
|
||||
"""
|
||||
|
||||
model_class = AnimalType
|
||||
route_prefix = "animal_types"
|
||||
url_prefix = "/animal-types"
|
||||
|
||||
farmos_refurl_path = "/admin/structure/taxonomy/manage/animal_type/overview"
|
||||
|
||||
grid_columns = [
|
||||
"name",
|
||||
"description",
|
||||
"changed",
|
||||
]
|
||||
|
||||
sort_defaults = "name"
|
||||
|
||||
filter_defaults = {
|
||||
"name": {"active": True, "verb": "contains"},
|
||||
}
|
||||
|
||||
form_fields = [
|
||||
"name",
|
||||
"description",
|
||||
"changed",
|
||||
"farmos_uuid",
|
||||
"drupal_internal_id",
|
||||
]
|
||||
|
||||
def configure_grid(self, grid):
|
||||
g = grid
|
||||
super().configure_grid(g)
|
||||
|
||||
# name
|
||||
g.set_link("name")
|
||||
|
||||
def get_farmos_url(self, animal_type):
|
||||
return self.app.get_farmos_url(
|
||||
f"/taxonomy/term/{animal_type.drupal_internal_id}"
|
||||
)
|
||||
|
||||
def get_xref_buttons(self, animal_type):
|
||||
buttons = super().get_xref_buttons(animal_type)
|
||||
|
||||
if animal_type.farmos_uuid:
|
||||
buttons.append(
|
||||
self.make_button(
|
||||
"View farmOS record",
|
||||
primary=True,
|
||||
url=self.request.route_url(
|
||||
"farmos_animal_types.view", uuid=animal_type.farmos_uuid
|
||||
),
|
||||
icon_left="eye",
|
||||
)
|
||||
)
|
||||
|
||||
return buttons
|
||||
|
||||
|
||||
def defaults(config, **kwargs):
|
||||
base = globals()
|
||||
|
||||
AnimalTypeView = kwargs.get("AnimalTypeView", base["AnimalTypeView"])
|
||||
AnimalTypeView.defaults(config)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
defaults(config)
|
||||
|
|
@ -113,7 +113,10 @@ class AnimalTypeView(FarmOSMasterView):
|
|||
f.set_node("changed", WuttaDateTime())
|
||||
|
||||
def get_xref_buttons(self, animal_type):
|
||||
return [
|
||||
model = self.app.model
|
||||
session = self.Session()
|
||||
|
||||
buttons = [
|
||||
self.make_button(
|
||||
"View in farmOS",
|
||||
primary=True,
|
||||
|
|
@ -122,9 +125,27 @@ class AnimalTypeView(FarmOSMasterView):
|
|||
),
|
||||
target="_blank",
|
||||
icon_left="external-link-alt",
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
if wf_animal_type := (
|
||||
session.query(model.AnimalType)
|
||||
.filter(model.AnimalType.farmos_uuid == animal_type["uuid"])
|
||||
.first()
|
||||
):
|
||||
buttons.append(
|
||||
self.make_button(
|
||||
f"View {self.app.get_title()} record",
|
||||
primary=True,
|
||||
url=self.request.route_url(
|
||||
"animal_types.view", uuid=wf_animal_type.uuid
|
||||
),
|
||||
icon_left="eye",
|
||||
)
|
||||
)
|
||||
|
||||
return buttons
|
||||
|
||||
|
||||
def defaults(config, **kwargs):
|
||||
base = globals()
|
||||
|
|
|
|||
63
src/wuttafarm/web/views/master.py
Normal file
63
src/wuttafarm/web/views/master.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttaFarm --Web app to integrate with and extend farmOS
|
||||
# Copyright © 2026 Lance Edgar
|
||||
#
|
||||
# This file is part of WuttaFarm.
|
||||
#
|
||||
# WuttaFarm is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# WuttaFarm. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Base class for WuttaFarm master views
|
||||
"""
|
||||
|
||||
from wuttaweb.views import MasterView
|
||||
|
||||
|
||||
class WuttaFarmMasterView(MasterView):
|
||||
"""
|
||||
Base class for WuttaFarm master views
|
||||
"""
|
||||
|
||||
farmos_refurl_path = None
|
||||
|
||||
labels = {
|
||||
"farmos_uuid": "farmOS UUID",
|
||||
"drupal_internal_id": "Drupal Internal ID",
|
||||
}
|
||||
|
||||
def get_farmos_url(self, obj):
|
||||
return None
|
||||
|
||||
def get_template_context(self, context):
|
||||
|
||||
if self.listing and self.farmos_refurl_path:
|
||||
context["farmos_refurl"] = self.app.get_farmos_url(self.farmos_refurl_path)
|
||||
|
||||
return context
|
||||
|
||||
def get_xref_buttons(self, obj):
|
||||
url = self.get_farmos_url(obj)
|
||||
if url:
|
||||
return [
|
||||
self.make_button(
|
||||
"View in farmOS",
|
||||
primary=True,
|
||||
url=url,
|
||||
target="_blank",
|
||||
icon_left="external-link-alt",
|
||||
)
|
||||
]
|
||||
return []
|
||||
Loading…
Add table
Add a link
Reference in a new issue