diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..0e831a9 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,45 @@ + +volumes: + pip-dir: + +services: + build: + image: python:3.10-buster + volumes: + - pip-dir:/pip_dir + - .:/open-needs-server + working_dir: /open-needs-server + healthcheck: + test: test -f /pip_dir/bin/ons || exit 1 + interval: 5s + timeout: 10s + retries: 6 + environment: + PYTHONUSERBASE: /pip_dir + command: + - /bin/bash + - -c + - | + python3 -m pip install --user . --upgrade + while true; + do sleep 30 + done + backend: + image: python:3.10-buster + ports: + - 9595:9595 + network_mode: "host" + networks: [] + configs: [] + volumes: + - pip-dir:/pip_dir + - .:/open-needs-server # still need the settings.toml file at runtime + working_dir: /open-needs-server + depends_on: + build: + condition: service_healthy + environment: + PYTHONPATH: /pip_dir/lib/python3.10/site-packages:$PYTHONPATH + PATH: /pip_dir/bin:$PATH + command: ons + diff --git a/docs/contributing.rst b/docs/contributing.rst index b192238..5395d78 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -11,6 +11,6 @@ Documentation build .. code-block:: bash - pip install -r requirements/docs.txt + python3 -m pip install .[docs] cd docs make html \ No newline at end of file diff --git a/docs/installation.rst b/docs/installation.rst index 3518e6f..15eae53 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -18,8 +18,5 @@ From source git clone git@github.com:open-needs/open-needs-server.git cd open-needs-server - pip install -e . + python3 -m pip install . ons - - - diff --git a/open_needs_server/extensions/domain/api.py b/open_needs_server/extensions/domain/api.py index 4b5bca1..e7dd5fc 100644 --- a/open_needs_server/extensions/domain/api.py +++ b/open_needs_server/extensions/domain/api.py @@ -25,9 +25,9 @@ async def get_domains(db: AsyncSession, skip: int = 0, limit: int = 100): async def create_domain(db: AsyncSession, domain: DomainSchema): - cursor = await db.execute(insert(DomainModel), domain) + cursor = await db.execute(insert(DomainModel).values(**domain).returning(DomainModel.id)) await db.commit() - domain_id = cursor.inserted_primary_key[0] + domain_id = cursor.fetchone()[0] return {**domain, "id": domain_id} diff --git a/open_needs_server/extensions/need/api.py b/open_needs_server/extensions/need/api.py index a1ac7f9..17c2ee4 100644 --- a/open_needs_server/extensions/need/api.py +++ b/open_needs_server/extensions/need/api.py @@ -35,9 +35,9 @@ async def create_need(ext: ONSExtension, db: AsyncSession, need: NeedReturnSchem data = ext.fire_event("need_create", {"need": need, "project": db_project}) need = data["need"] - cursor = await db.execute(insert(NeedModel), need) + cursor = await db.execute(insert(NeedModel).values(**need).returning(NeedModel.id)) await db.commit() - need_id = cursor.inserted_primary_key[0] + need_id = cursor.fetchone()[0] need = ext.fire_event("need_create_done", need) diff --git a/open_needs_server/extensions/ons_admin/__init__.py b/open_needs_server/extensions/ons_admin/__init__.py index 3779733..19fba41 100644 --- a/open_needs_server/extensions/ons_admin/__init__.py +++ b/open_needs_server/extensions/ons_admin/__init__.py @@ -1,6 +1,6 @@ import importlib import logging -from sqladmin import Admin, ModelAdmin +from sqladmin import Admin, ModelView from open_needs_server.extensions.base import ONSExtension from open_needs_server.database import engine @@ -24,7 +24,7 @@ def __init__(self, *args, **kwargs): self.admin = Admin(self.ons_app, engine) for admin_model in self._get_models(): - self.admin.register_model(admin_model) + self.admin.add_view(admin_model) def _get_models(self): models = [] @@ -49,7 +49,7 @@ def _get_models(self): new_class = types.new_class( name=f"{class_str}Admin", - bases=(ModelAdmin,), + bases=(ModelView,), kwds={"model": clazz}, exec_body=lambda ns: ns.update( { diff --git a/open_needs_server/extensions/organization/api.py b/open_needs_server/extensions/organization/api.py index 56888ea..1ece3ff 100644 --- a/open_needs_server/extensions/organization/api.py +++ b/open_needs_server/extensions/organization/api.py @@ -51,9 +51,9 @@ async def create_organization( ext: ONSExtension, db: AsyncSession, organization: OrganizationCreateSchema ): organization = ext.fire_event("org_create", organization) - cursor = await db.execute(insert(OrganizationModel), organization) + cursor = await db.execute(insert(OrganizationModel).values(**organization).returning(OrganizationModel.id)) await db.commit() - organization_id = cursor.inserted_primary_key[0] + organization_id = cursor.fetchone()[0] new_organization = {**organization, "id": organization_id} new_organization = ext.fire_event("org_create_done", new_organization) return new_organization diff --git a/open_needs_server/extensions/project/api.py b/open_needs_server/extensions/project/api.py index 1675071..40d9999 100644 --- a/open_needs_server/extensions/project/api.py +++ b/open_needs_server/extensions/project/api.py @@ -37,9 +37,14 @@ async def create_project(db: AsyncSession, project: ProjectSchema): raise HTTPException(404, detail=f"Unknown domain id: {domain_id}") domains_db.append(domain_db) - cursor = await db.execute(insert(ProjectModel), project) + + project = { + "title": project["title"], + "organization_id": project["organization_id"] + } + cursor = await db.execute(insert(ProjectModel).values(**project).returning(ProjectModel.id)) await db.commit() - project_id = cursor.inserted_primary_key[0] + project_id = cursor.fetchone()[0] project_db = await get_project(db, project_id) project_db.domains = domains_db await db.commit() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c7e0202 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,33 @@ +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "open_needs_server" +version = "0.1.0" +authors = [ + { name="Open-Needs community", email="daniel@useblocks.com" }, +] +description = "Open-Needs Server" +readme = "README.md" +requires-python = ">=3.10" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dynamic = ["dependencies", "optional-dependencies"] + +[tool.setuptools.packages.find] +where = ["."] +include = ["open_needs_server"] +namespaces = false + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements/server.txt"]} +optional-dependencies.docs = {file = ["requirements/docs.txt"] } +optional-dependencies.data = {file = ["requirements/data.txt"] } + + +[project.scripts] +ons = "open_needs_server.main:start" diff --git a/requirements/docs.txt b/requirements/docs.txt index a3f5052..17b5d84 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,9 +1,9 @@ -sphinx +sphinx>=5.0.0 jinja2<3.1 sphinx-immaterial # The theme sphinxcontrib-plantuml # Used for all architecture and mockup images sphinxcontrib-httpdomain # Used REST-API documentation -sphinxcontrib-needs # need objects and filtering +sphinxcontrib-needs>=0.7.9 # need objects and filtering sphinx-panels # tabs, dropdonws, cards and more sphinx-disqus # comment field integration sphinx-preview # iframe-preview for links diff --git a/requirements/server.txt b/requirements/server.txt index 17633d6..5b3b8ab 100644 --- a/requirements/server.txt +++ b/requirements/server.txt @@ -1,9 +1,9 @@ -rich -uvicorn -pydantic -fastapi -fastapi-users[sqlalchemy]>=10.0.0 -aiosqlite -dynaconf -sqladmin -jsonschema \ No newline at end of file +rich==13.7.0 +uvicorn==0.30.1 +pydantic==2.5.3 +fastapi==0.111.0 +fastapi-users[sqlalchemy]==13.0.0 +aiosqlite==0.20.0 +dynaconf==3.2.5 +sqladmin==0.17.0 +jsonschema>=3.2.0 \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 48d9589..0000000 --- a/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -from distutils.core import setup -import os -import os.path - - -with open(os.path.join("requirements", "server.txt"), encoding="utf-8") as reqs: - REQUIREMENTS = [reqs.readlines()] - -setup( - name="Open-Needs Server", - version="1.0", - description="Open-Needs Server", - author="Open-Needs community", - url="https://www.open-needs.org", - packages=["open_needs_server"], - python_requires=">=3.10", - install_requires=REQUIREMENTS, - entry_points={"console_scripts": ["ons = open_needs_server.main:start"]}, -)