aignostics 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aignostics/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ """Python SDK providing access to Aignostics AI services."""
2
+
3
+ from .constants import (
4
+ __project_name__,
5
+ __project_path__,
6
+ __version__,
7
+ )
8
+ from .service import Service
9
+
10
+ __all__ = [
11
+ "Service",
12
+ "__project_name__",
13
+ "__project_path__",
14
+ "__version__",
15
+ ]
aignostics/api.py ADDED
@@ -0,0 +1,239 @@
1
+ """Webservice API of Aignostics Python SDK.
2
+
3
+ This module provides a webservice API with several endpoints:
4
+ - A health/healthz endpoint that returns the health status of the service
5
+ - A hello-world endpoint that returns a greeting message
6
+ - An echo endpoint that echoes back the provided text
7
+
8
+ The endpoints use Pydantic models for request and response validation.
9
+ """
10
+
11
+ import os
12
+ from collections.abc import Generator
13
+ from enum import StrEnum
14
+ from typing import Annotated
15
+
16
+ from fastapi import Depends, FastAPI, Response, status
17
+ from pydantic import BaseModel, Field
18
+
19
+ from aignostics import Service
20
+
21
+ TITLE = "Aignostics Python SDK"
22
+ HELLO_WORLD_EXAMPLE = "Hello, world!"
23
+ UVICORN_HOST = os.environ.get("UVICORN_HOST", "127.0.0.1")
24
+ UVICORN_PORT = os.environ.get("UVICORN_PORT", "8000")
25
+ CONTACT_NAME = "Aignostics GmbH"
26
+ CONTACT_EMAIL = "support@aignostics.com"
27
+ CONTACT_URL = "https://github.com/aignostics"
28
+ TERMS_OF_SERVICE_URL = "https://aignostics.readthedocs.io/en/latest/"
29
+
30
+
31
+ def get_service() -> Generator[Service, None, None]:
32
+ """Get the service instance.
33
+
34
+ Yields:
35
+ Service: The service instance.
36
+ """
37
+ service = Service()
38
+ try:
39
+ yield service
40
+ finally:
41
+ # Cleanup code if needed
42
+ pass
43
+
44
+
45
+ api = FastAPI(
46
+ root_path="/api",
47
+ title=TITLE,
48
+ contact={
49
+ "name": CONTACT_NAME,
50
+ "email": CONTACT_EMAIL,
51
+ "url": CONTACT_URL,
52
+ },
53
+ terms_of_service=TERMS_OF_SERVICE_URL,
54
+ openapi_tags=[
55
+ {
56
+ "name": "v1",
57
+ "description": "API version 1, check link on the right",
58
+ "externalDocs": {
59
+ "description": "sub-docs",
60
+ "url": f"http://{UVICORN_HOST}:{UVICORN_PORT}/api/v1/docs",
61
+ },
62
+ },
63
+ {
64
+ "name": "v2",
65
+ "description": "API version 2, check link on the right",
66
+ "externalDocs": {
67
+ "description": "sub-docs",
68
+ "url": f"http://{UVICORN_HOST}:{UVICORN_PORT}/api/v2/docs",
69
+ },
70
+ },
71
+ ],
72
+ )
73
+
74
+ api_v1 = FastAPI(
75
+ version="1.0.0",
76
+ title=TITLE,
77
+ contact={
78
+ "name": CONTACT_NAME,
79
+ "email": CONTACT_EMAIL,
80
+ "url": CONTACT_URL,
81
+ },
82
+ terms_of_service=TERMS_OF_SERVICE_URL,
83
+ )
84
+
85
+ api_v2 = FastAPI(
86
+ version="2.0.0",
87
+ title=TITLE,
88
+ contact={
89
+ "name": CONTACT_NAME,
90
+ "email": CONTACT_EMAIL,
91
+ "url": CONTACT_URL,
92
+ },
93
+ terms_of_service=TERMS_OF_SERVICE_URL,
94
+ )
95
+
96
+
97
+ class _HealthStatus(StrEnum):
98
+ """Health status enumeration."""
99
+
100
+ UP = "UP"
101
+ DOWN = "DOWN"
102
+
103
+
104
+ class Health(BaseModel):
105
+ """Health status model."""
106
+
107
+ status: _HealthStatus
108
+ reason: str | None = None
109
+
110
+
111
+ class HealthResponse(BaseModel):
112
+ """Response model for health endpoint."""
113
+
114
+ health: str = Field(
115
+ ...,
116
+ description="The hello world message",
117
+ examples=[HELLO_WORLD_EXAMPLE],
118
+ )
119
+
120
+
121
+ @api_v1.get("/healthz", tags=["Observability"])
122
+ @api_v1.get("/health", tags=["Observability"])
123
+ @api_v2.get("/healthz", tags=["Observability"])
124
+ @api_v2.get("/health", tags=["Observability"])
125
+ async def health(service: Annotated[Service, Depends(get_service)], response: Response) -> Health:
126
+ """Check the health of the service.
127
+
128
+ This endpoint returns the health status of the service.
129
+ The health status can be either UP or DOWN.
130
+ If the service is healthy, the status will be UP.
131
+ If the service is unhealthy, the status will be DOWN and a reason will be provided.
132
+ The response will have a 200 OK status code if the service is healthy,
133
+ and a 500 Internal Server Error status code if the service is unhealthy.
134
+
135
+ Returns:
136
+ Health: The health status of the service.
137
+ """
138
+ if service.healthy():
139
+ health_result = Health(status=_HealthStatus.UP)
140
+ else:
141
+ health_result = Health(status=_HealthStatus.DOWN, reason="Service is unhealthy")
142
+
143
+ if health_result.status == _HealthStatus.DOWN:
144
+ response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
145
+
146
+ return health_result
147
+
148
+
149
+ class HelloWorldResponse(BaseModel):
150
+ """Response model for hello-world endpoint."""
151
+
152
+ message: str = Field(
153
+ ...,
154
+ description="The hello world message",
155
+ examples=[HELLO_WORLD_EXAMPLE],
156
+ )
157
+
158
+
159
+ @api_v1.get("/hello-world", tags=["Basics"])
160
+ @api_v2.get("/hello-world", tags=["Basics"])
161
+ async def hello_world() -> HelloWorldResponse:
162
+ """
163
+ Return a hello world message.
164
+
165
+ Returns:
166
+ HelloWorldResponse: A response containing the hello world message.
167
+ """
168
+ return HelloWorldResponse(message=Service.get_hello_world())
169
+
170
+
171
+ class EchoResponse(BaseModel):
172
+ """Response model for echo endpoint."""
173
+
174
+ message: str = Field(
175
+ ...,
176
+ min_length=1,
177
+ description="The message content",
178
+ examples=[HELLO_WORLD_EXAMPLE],
179
+ )
180
+
181
+
182
+ class EchoRequest(BaseModel):
183
+ """Request model for echo endpoint."""
184
+
185
+ text: str = Field(
186
+ ...,
187
+ min_length=1,
188
+ description="The text to echo back",
189
+ examples=[HELLO_WORLD_EXAMPLE],
190
+ )
191
+
192
+
193
+ @api_v1.post("/echo", tags=["Basics"])
194
+ async def echo(request: EchoRequest) -> EchoResponse:
195
+ """
196
+ Echo back the provided text.
197
+
198
+ Args:
199
+ request (EchoRequest): The request containing the text to echo back.
200
+
201
+ Returns:
202
+ EchoResponse: A response containing the echoed text.
203
+
204
+ Raises:
205
+ 422 Unprocessable Entity: If text is not provided or empty.
206
+ """
207
+ return EchoResponse(message=request.text)
208
+
209
+
210
+ class Utterance(BaseModel):
211
+ """Request model for echo endpoint."""
212
+
213
+ utterance: str = Field(
214
+ ...,
215
+ min_length=1,
216
+ description="The utterance to echo back",
217
+ examples=[HELLO_WORLD_EXAMPLE],
218
+ )
219
+
220
+
221
+ @api_v2.post("/echo", tags=["Basics"])
222
+ async def echo_v2(request: Utterance) -> EchoResponse:
223
+ """
224
+ Echo back the provided utterance.
225
+
226
+ Args:
227
+ request (Utterance): The request containing the utterance to echo back.
228
+
229
+ Returns:
230
+ EchoResponse: A response containing the echoed utterance.
231
+
232
+ Raises:
233
+ 422 Unprocessable Entity: If utterance is not provided or empty.
234
+ """
235
+ return EchoResponse(message=request.utterance)
236
+
237
+
238
+ api.mount("/v1", api_v1)
239
+ api.mount("/v2", api_v2)
aignostics/cli.py ADDED
@@ -0,0 +1,133 @@
1
+ """CLI (Command Line Interface) of Aignostics Python SDK."""
2
+
3
+ import os
4
+ from enum import StrEnum
5
+ from typing import Annotated
6
+
7
+ import typer
8
+ import uvicorn
9
+ import yaml
10
+ from rich.console import Console
11
+
12
+ from aignostics import Service, __version__
13
+ from aignostics.api import api_v1, api_v2
14
+
15
+ console = Console()
16
+
17
+ cli = typer.Typer(name="Command Line Interface of Aignostics Python SDK")
18
+
19
+
20
+ @cli.command()
21
+ def echo(
22
+ text: Annotated[
23
+ str, typer.Argument(help="The text to echo")
24
+ ] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
25
+ json: Annotated[
26
+ bool,
27
+ typer.Option(
28
+ help=("Print as JSON"),
29
+ ),
30
+ ] = False,
31
+ ) -> None:
32
+ """Echo the text."""
33
+ if json:
34
+ console.print_json(data={"text": text})
35
+ else:
36
+ console.print(text)
37
+
38
+
39
+ @cli.command()
40
+ def hello_world() -> None:
41
+ """Print hello world message and what's in the environment variable THE_VAR."""
42
+ console.print(Service.get_hello_world())
43
+
44
+
45
+ @cli.command()
46
+ def serve(
47
+ host: Annotated[str, typer.Option(help="Host to bind the server to")] = "127.0.0.1",
48
+ port: Annotated[int, typer.Option(help="Port to bind the server to")] = 8000,
49
+ watch: Annotated[bool, typer.Option(help="Enable auto-reload")] = True,
50
+ ) -> None:
51
+ """Start the API server."""
52
+ console.print(f"Starting API server at http://{host}:{port}")
53
+ os.environ["UVICORN_HOST"] = host
54
+ os.environ["UVICORN_PORT"] = str(port)
55
+ uvicorn.run(
56
+ "aignostics.api:api",
57
+ host=host,
58
+ port=port,
59
+ reload=watch,
60
+ )
61
+
62
+
63
+ class APIVersion(StrEnum):
64
+ """
65
+ Enum representing the API versions.
66
+
67
+ This enum defines the supported API verions:
68
+ - V1: Output doc for v1 API
69
+ - V2: Output doc for v2 API
70
+
71
+ Usage:
72
+ version = APIVersion.V1
73
+ print(f"Using {version} version")
74
+
75
+ """
76
+
77
+ V1 = "v1"
78
+ V2 = "v2"
79
+
80
+
81
+ class OutputFormat(StrEnum):
82
+ """
83
+ Enum representing the supported output formats.
84
+
85
+ This enum defines the possible formats for output data:
86
+ - YAML: Output data in YAML format
87
+ - JSON: Output data in JSON format
88
+
89
+ Usage:
90
+ format = OutputFormat.YAML
91
+ print(f"Using {format} format")
92
+ """
93
+
94
+ YAML = "yaml"
95
+ JSON = "json"
96
+
97
+
98
+ @cli.command()
99
+ def openapi(
100
+ api_version: Annotated[APIVersion, typer.Option(help="API Version", case_sensitive=False)] = APIVersion.V1,
101
+ output_format: Annotated[
102
+ OutputFormat, typer.Option(help="Output format", case_sensitive=False)
103
+ ] = OutputFormat.YAML,
104
+ ) -> None:
105
+ """Dump the OpenAPI specification to stdout (YAML by default)."""
106
+ match api_version:
107
+ case APIVersion.V1:
108
+ schema = api_v1.openapi()
109
+ case APIVersion.V2:
110
+ schema = api_v2.openapi()
111
+ match output_format:
112
+ case OutputFormat.JSON:
113
+ console.print_json(data=schema)
114
+ case OutputFormat.YAML:
115
+ console.print(yaml.dump(schema, default_flow_style=False), end="")
116
+
117
+
118
+ def _apply_cli_settings(cli: typer.Typer, epilog: str) -> None:
119
+ """Add epilog to all typers in the tree and configure default behavior."""
120
+ cli.info.epilog = epilog
121
+ cli.info.no_args_is_help = True
122
+ for command in cli.registered_commands:
123
+ command.epilog = cli.info.epilog
124
+
125
+
126
+ _apply_cli_settings(
127
+ cli,
128
+ f"🔬 Aignostics Python SDK v{__version__} - built with love in Berlin 🐻",
129
+ )
130
+
131
+
132
+ if __name__ == "__main__":
133
+ cli()
@@ -0,0 +1,10 @@
1
+ """Constants used throughout Aignostics Python SDK's codebase ."""
2
+
3
+ import importlib.metadata
4
+ import pathlib
5
+
6
+ __project_name__ = __name__.split(".")[0]
7
+ __project_path__ = str(pathlib.Path(__file__).parent.parent.parent)
8
+ __version__ = importlib.metadata.version(__project_name__)
9
+
10
+ LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
aignostics/service.py ADDED
@@ -0,0 +1,35 @@
1
+ """Service of Aignostics Python SDK."""
2
+
3
+ import os
4
+
5
+ from dotenv import load_dotenv
6
+
7
+ load_dotenv()
8
+ THE_VAR = os.getenv("THE_VAR", "not defined")
9
+
10
+
11
+ class Service:
12
+ """Service of Aignostics Python SDK."""
13
+
14
+ def __init__(self) -> None:
15
+ """Initialize service."""
16
+ self.is_healthy = True
17
+
18
+ @staticmethod
19
+ def get_hello_world() -> str:
20
+ """
21
+ Get a hello world message.
22
+
23
+ Returns:
24
+ str: Hello world message.
25
+ """
26
+ return f"Hello, world! The value of THE_VAR is {THE_VAR}"
27
+
28
+ def healthy(self) -> bool:
29
+ """
30
+ Check if the service is healthy.
31
+
32
+ Returns:
33
+ bool: True if the service is healthy, False otherwise.
34
+ """
35
+ return self.is_healthy
@@ -0,0 +1,428 @@
1
+ Metadata-Version: 2.4
2
+ Name: aignostics
3
+ Version: 0.0.1
4
+ Summary: 🔬 Python SDK providing access to Aignostics AI services.
5
+ Project-URL: Homepage, https://aignostics.readthedocs.io/en/latest/
6
+ Project-URL: Documentation, https://aignostics.readthedocs.io/en/latest/
7
+ Project-URL: Source, https://github.com/aignostics/python-sdk
8
+ Project-URL: Changelog, https://github.com/aignostics/python-sdk/releases
9
+ Project-URL: Issues, https://github.com/aignostics/python-sdk/issues
10
+ Author-email: Helmut Hoffer von Ankershoffen <helmut@aignostics.com>
11
+ License: MIT License
12
+
13
+ Copyright (c) [2025] [Aignostics GmbH (support@aignostics.com)]
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: act,aignostics,codecov,copier,cyclonedx,detect-secrets,devcontainer,docker,git-cliff,jupyter,marimo,mypy,nox,oe-python-template,pip-audit,pip-licenses,pre-commit,pydantic,pypi,pytest,python,readthedocs,ruff,sonarcloud,sonarqube,sphinx,streamlit,typer,uv
34
+ Classifier: Development Status :: 2 - Pre-Alpha
35
+ Classifier: Framework :: Pydantic
36
+ Classifier: Framework :: Pytest
37
+ Classifier: Intended Audience :: Developers
38
+ Classifier: Intended Audience :: End Users/Desktop
39
+ Classifier: License :: OSI Approved :: MIT License
40
+ Classifier: Natural Language :: English
41
+ Classifier: Operating System :: MacOS :: MacOS X
42
+ Classifier: Operating System :: Microsoft :: Windows
43
+ Classifier: Operating System :: POSIX :: Linux
44
+ Classifier: Programming Language :: Python
45
+ Classifier: Programming Language :: Python :: 3
46
+ Classifier: Programming Language :: Python :: 3.11
47
+ Classifier: Programming Language :: Python :: 3.12
48
+ Classifier: Programming Language :: Python :: 3.13
49
+ Classifier: Typing :: Typed
50
+ Requires-Python: <4.0,>=3.11
51
+ Requires-Dist: fastapi[all,standard]>=0.115.11
52
+ Requires-Dist: pydantic>=2.10.6
53
+ Requires-Dist: python-dotenv>=1.0.1
54
+ Requires-Dist: typer>=0.15.1
55
+ Provides-Extra: examples
56
+ Requires-Dist: jinja2>=3.1.6; extra == 'examples'
57
+ Requires-Dist: jupyter>=1.1.1; extra == 'examples'
58
+ Requires-Dist: marimo>=0.11.19; extra == 'examples'
59
+ Requires-Dist: streamlit>=1.43.2; extra == 'examples'
60
+ Description-Content-Type: text/markdown
61
+
62
+
63
+ [//]: # (README.md generated from docs/partials/README_*.md)
64
+
65
+ # 🔬 Aignostics Python SDK
66
+
67
+ [![License](https://img.shields.io/github/license/aignostics/python-sdk?logo=opensourceinitiative&logoColor=3DA639&labelColor=414042&color=A41831)
68
+ ](https://github.com/aignostics/python-sdk/blob/main/LICENSE)
69
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aignostics.svg?logo=python&color=204361&labelColor=1E2933)](https://github.com/aignostics/python-sdk/blob/main/noxfile.py)
70
+ [![CI](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml/badge.svg)](https://github.com/aignostics/python-sdk/actions/workflows/test-and-report.yml)
71
+ [![Read the Docs](https://img.shields.io/readthedocs/aignostics)](https://aignostics.readthedocs.io/en/latest/)
72
+ [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk)
73
+ [![Security](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk)
74
+ [![Maintainability](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk)
75
+ [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk)
76
+ [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=aignostics_python-sdk&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk)
77
+ [![CodeQL](https://github.com/aignostics/python-sdk/actions/workflows/codeql.yml/badge.svg)](https://github.com/aignostics/python-sdk/security/code-scanning)
78
+ [![Dependabot](https://img.shields.io/badge/dependabot-active-brightgreen?style=flat-square&logo=dependabot)](https://github.com/aignostics/python-sdk/security/dependabot)
79
+ [![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/aignostics/python-sdk/issues?q=is%3Aissue%20state%3Aopen%20Dependency%20Dashboard)
80
+ [![Coverage](https://codecov.io/gh/aignostics/python-sdk/graph/badge.svg?token=SX34YRP30E)](https://codecov.io/gh/aignostics/python-sdk)
81
+ [![Ruff](https://img.shields.io/badge/style-Ruff-blue?color=D6FF65)](https://github.com/aignostics/python-sdk/blob/main/noxfile.py)
82
+ [![MyPy](https://img.shields.io/badge/mypy-checked-blue)](https://github.com/aignostics/python-sdk/blob/main/noxfile.py)
83
+ [![GitHub - Version](https://img.shields.io/github/v/release/aignostics/python-sdk?label=GitHub&style=flat&labelColor=1C2C2E&color=blue&logo=GitHub&logoColor=white)](https://github.com/aignostics/python-sdk/releases)
84
+ [![GitHub - Commits](https://img.shields.io/github/commit-activity/m/aignostics/python-sdk/main?label=commits&style=flat&labelColor=1C2C2E&color=blue&logo=GitHub&logoColor=white)](https://github.com/aignostics/python-sdk/commits/main/)
85
+ [![PyPI - Version](https://img.shields.io/pypi/v/aignostics.svg?label=PyPI&logo=pypi&logoColor=%23FFD243&labelColor=%230073B7&color=FDFDFD)](https://pypi.python.org/pypi/aignostics)
86
+ [![PyPI - Status](https://img.shields.io/pypi/status/aignostics?logo=pypi&logoColor=%23FFD243&labelColor=%230073B7&color=FDFDFD)](https://pypi.python.org/pypi/aignostics)
87
+ [![Docker - Version](https://img.shields.io/docker/v/helmuthva/aignostics-python-sdk?sort=semver&label=Docker&logo=docker&logoColor=white&labelColor=1354D4&color=10151B)](https://hub.docker.com/r/helmuthva/aignostics-python-sdk/tags)
88
+ [![Docker - Size](https://img.shields.io/docker/image-size/helmuthva/aignostics-python-sdk?sort=semver&arch=arm64&label=image&logo=docker&logoColor=white&labelColor=1354D4&color=10151B)](https://hub.docker.com/r/helmuthva/aignostics-python-sdk/)
89
+ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template)
90
+ [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE3IDE2VjdsLTYgNU0yIDlWOGwxLTFoMWw0IDMgOC04aDFsNCAyIDEgMXYxNGwtMSAxLTQgMmgtMWwtOC04LTQgM0gzbC0xLTF2LTFsMy0zIi8+PC9zdmc+)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/aignostics/python-sdk)
91
+ [![Open in GitHub Codespaces](https://img.shields.io/static/v1?label=GitHub%20Codespaces&message=Open&color=blue&logo=github)](https://github.com/codespaces/new/aignostics/python-sdk)
92
+
93
+ <!---
94
+ [![ghcr.io - Version](https://ghcr-badge.egpl.dev/aignostics/python-sdk/tags?color=%2344cc11&ignore=0.0%2C0%2Clatest&n=3&label=ghcr.io&trim=)](https://github.com/aignostics/python-sdk/pkgs/container/python-sdk)
95
+ [![ghcr.io - Sze](https://ghcr-badge.egpl.dev/aignostics/python-sdk/size?color=%2344cc11&tag=latest&label=size&trim=)](https://github.com/aignostics/python-sdk/pkgs/container/python-sdk)
96
+ -->
97
+
98
+ > [!TIP]
99
+ > 📚 [Online documentation](https://aignostics.readthedocs.io/en/latest/) - 📖 [PDF Manual](https://aignostics.readthedocs.io/_/downloads/en/latest/pdf/)
100
+
101
+ > [!NOTE]
102
+ > 🧠 This project was scaffolded using the template [oe-python-template](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template) with [copier](https://copier.readthedocs.io/).
103
+
104
+ ---
105
+
106
+
107
+ Python SDK providing access to Aignostics AI services.
108
+
109
+ This [Copier](https://copier.readthedocs.io/en/stable/) template enables you to quickly generate a Python package with fully functioning build and test automation.
110
+ Projects generated from this template can be [easily updated](https://copier.readthedocs.io/en/stable/updating/) to benefit from improvements and new features of the template.
111
+
112
+ Features:
113
+ 1. Package management with [uv](https://github.com/astral-sh/uv)
114
+ 2. Code formatting with [Ruff](https://github.com/astral-sh/ruff)
115
+ 3. Linting with [Ruff](https://github.com/astral-sh/ruff)
116
+ 4. Static type checking with [mypy](https://mypy.readthedocs.io/en/stable/)
117
+ 5. Complete set of [pre-commit](https://pre-commit.com/) hooks including [detect-secrets](https://github.com/Yelp/detect-secrets) and [pygrep](https://github.com/pre-commit/pygrep-hooks)
118
+ 6. Unit and E2E testing with [pytest](https://docs.pytest.org/en/stable/) including parallel test execution
119
+ 7. Matrix testing in multiple environments with [nox](https://nox.thea.codes/en/stable/)
120
+ 8. Test coverage reported with [Codecov](https://codecov.io/) and published as release artifact
121
+ 9. CI/CD pipeline automated with [GitHub Actions](https://github.com/features/actions)
122
+ 10. CI/CD pipeline can be run locally with [act](https://github.com/nektos/act)
123
+ 11. Code quality and security checks with [SonarQube](https://www.sonarsource.com/products/sonarcloud) and [GitHub CodeQL](https://codeql.github.com/)
124
+ 12. Dependency monitoring with [pip-audit](https://pypi.org/project/pip-audit/), [Renovate](https://github.com/renovatebot/renovate), and [GitHub Dependabot](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide)
125
+ 13. Licenses of dependencies extracted with [pip-licenses](https://pypi.org/project/pip-licenses/) and published as release artifacts in CSV and JSON format for compliance checks
126
+ 14. Software Bill of Materials (SBOM) generated with [cyclonedx-python](https://github.com/CycloneDX/cyclonedx-python) and published as release artifact
127
+ 15. Version and release management with [bump-my-version](https://callowayproject.github.io/bump-my-version/)
128
+ 16. Changelog and release notes generated with [git-cliff](https://git-cliff.org/)
129
+ 17. Documentation generated with [Sphinx](https://www.sphinx-doc.org/en/master/) including reference documentation and PDF export
130
+ 18. Documentation published to [Read The Docs](https://readthedocs.org/)
131
+ 19. Interactive OpenAPI specification with [Swagger](https://swagger.io/)
132
+ 20. Python package published to [PyPI](https://pypi.org/)
133
+ 21. Docker images published to [Docker.io](https://hub.docker.com/) and [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) with [artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds)
134
+ 22. One-click development environments with [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) and [GitHub Codespaces](https://github.com/features/codespaces)
135
+ 23. Settings for use with [VSCode](https://code.visualstudio.com/)
136
+ 24. Settings and custom instructions for use with [GitHub Copilot](https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot)
137
+
138
+ The generated project includes code, documentation and configuration of a fully functioning demo-application and service, which can be used as a starting point for your own project.
139
+ 1. Service architecture suitable for use as shared library
140
+ 2. Validation with [pydantic](https://docs.pydantic.dev/)
141
+ 3. Command-line interface (CLI) with [Typer](https://typer.tiangolo.com/)
142
+ 4. Versioned Web API with [FastAPI](https://fastapi.tiangolo.com/)
143
+ 5. [Interactive Jupyter notebook](https://jupyter.org/) and [reactive Marimo notebook](https://marimo.io/)
144
+ 6. Simple Web UI with [Streamlit](https://streamlit.io/)
145
+ 7. Configuration to run the CLI and API in a Docker container including setup for [Docker Compose](https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-docker-compose/)
146
+ 8. Documentation including badges, setup instructions, contribution guide and security policy
147
+
148
+ Explore [here](https://github.com/helmut-hoffer-von-ankershoffen/oe-python-template-example) for what's generated out of the box.
149
+
150
+ ## Generate a new project
151
+
152
+ This template is designed to be used with the [copier](https://copier.readthedocs.io/en/stable/) project generator. It allows you to create a new project based on this template and customize it according to your needs.
153
+ To generate a new project, follow these steps:
154
+
155
+ **Step 1**: Install uv package manager and copier. Copy the following code into your terminal and execute it.
156
+ ```shell
157
+ if [[ "$OSTYPE" == "darwin"* ]]; then # Install dependencies for macOS X
158
+ if ! command -v brew &> /dev/null; then ## Install Homebrew if not present
159
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
160
+ fi
161
+ elif [[ "$OSTYPE" == "linux-gnu"* ]]; then # Install dependencies for Linux
162
+ sudo apt-get update -y && sudo apt-get install curl -y # Install curl
163
+ fi
164
+ if ! command -v uvx &> /dev/null; then # Install uv package manager if not present
165
+ curl -LsSf https://astral.sh/uv/install.sh | sh
166
+ source $HOME/.local/bin/env
167
+ fi
168
+ uv tool install copier # Install copier as global tool
169
+ ```
170
+
171
+ **Step 2**: [Create an empty repository on GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository), clone to your local machine, and change into it's directory.
172
+
173
+ **Step 3**: Generate the project. Copy
174
+ ```shell
175
+ copier copy --trust gh:helmut-hoffer-von-ankershoffen/oe-python-template .
176
+ ```
177
+
178
+ **Step 4**: Perform initial commit and push. Copy the following code into your terminal and execute it.
179
+ ```shell
180
+ git add .
181
+ git commit -m "feat: Initial commit"
182
+ git push
183
+ ```
184
+
185
+ Visit your GitHub repository and check the Actions tab. The CI workflow should already be running! The workflow will fail at the SonarQube step, as this external service is not yet configured for our new repository.
186
+
187
+ **Step 5**: Follow the [instructions](SERVICE_CONNECTIONS.md) to wire up
188
+ external services such as CloudCov, SonarQube Cloud, Read The Docs, Docker.io, and Streamlit Community Cloud.
189
+
190
+ **Step 6**: Release the first versions
191
+ ```shell
192
+ ./n bump
193
+ ```
194
+ Notes:
195
+ 1. You can remove this section post having successfully generated your project.
196
+ 2. The following sections refer to the dummy application and service provided by this template.
197
+ Use them as inspiration and adapt them to your own project.
198
+
199
+ ## Overview
200
+
201
+ Adding Aignostics Python SDK to your project as a dependency is easy. See below for usage examples.
202
+
203
+ ```shell
204
+ uv add aignostics # add dependency to your project
205
+ ```
206
+
207
+ If you don't have uv installed follow [these instructions](https://docs.astral.sh/uv/getting-started/installation/). If you still prefer pip over the modern and fast package manager [uv](https://github.com/astral-sh/uv), you can install the library like this:
208
+
209
+
210
+ ```shell
211
+ pip install aignostics # add dependency to your project
212
+ ```
213
+
214
+ Executing the command line interface (CLI) in an isolated Python environment is just as easy:
215
+
216
+ ```shell
217
+ uvx aignostics hello-world # prints "Hello, world! [..]"
218
+ uvx aignostics serve # serves web API
219
+ uvx aignostics serve --port=4711 # serves web API on port 4711
220
+ ```
221
+
222
+ Notes:
223
+ 1. The API is versioned, mounted at `/api/v1` resp. `/api/v2`
224
+ 2. While serving the web API go to [http://127.0.0.1:8000/api/v1/hello-world](http://127.0.0.1:8000/api/v1/hello-world) to see the respons of the `hello-world` operation.
225
+ 3. Interactive documentation is provided at [http://127.0.0.1:8000/api/docs](http://127.0.0.1:8000/api/docs)
226
+
227
+
228
+ The CLI provides extensive help:
229
+
230
+ ```shell
231
+ uvx aignostics --help # all CLI commands
232
+ uvx aignostics hello-world --help # help for specific command
233
+ uvx aignostics echo --help
234
+ uvx aignostics openapi --help
235
+ uvx aignostics serve --help
236
+ ```
237
+
238
+
239
+ ## Operational Excellence
240
+
241
+ This project is designed with operational excellence in mind, using modern Python tooling and practices. It includes:
242
+
243
+ 1. Various examples demonstrating usage:
244
+ a. [Simple Python script](https://github.com/aignostics/python-sdk/blob/main/examples/script.py)
245
+ b. [Streamlit web application](https://aignostics.streamlit.app/) deployed on [Streamlit Community Cloud](https://streamlit.io/cloud)
246
+ c. [Jupyter](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb) and [Marimo](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py) notebook
247
+ 2. [Complete reference documentation](https://aignostics.readthedocs.io/en/latest/reference.html) on Read the Docs
248
+ 3. [Transparent test coverage](https://app.codecov.io/gh/aignostics/python-sdk) including unit and E2E tests (reported on Codecov)
249
+ 4. Matrix tested with [multiple python versions](https://github.com/aignostics/python-sdk/blob/main/noxfile.py) to ensure compatibility (powered by [Nox](https://nox.thea.codes/en/stable/))
250
+ 5. Compliant with modern linting and formatting standards (powered by [Ruff](https://github.com/astral-sh/ruff))
251
+ 6. Up-to-date dependencies (monitored by [Renovate](https://github.com/renovatebot/renovate) and [Dependabot](https://github.com/aignostics/python-sdk/security/dependabot))
252
+ 7. [A-grade code quality](https://sonarcloud.io/summary/new_code?id=aignostics_python-sdk) in security, maintainability, and reliability with low technical debt and codesmell (verified by SonarQube)
253
+ 8. Additional code security checks using [CodeQL](https://github.com/aignostics/python-sdk/security/code-scanning)
254
+ 9. [Security Policy](SECURITY.md)
255
+ 10. [License](LICENSE) compliant with the Open Source Initiative (OSI)
256
+ 11. 1-liner for installation and execution of command line interface (CLI) via [uv(x)](https://github.com/astral-sh/uv) or [Docker](https://hub.docker.com/r/helmuthva/aignostics-python-sdk/tags)
257
+ 12. Setup for developing inside a [devcontainer](https://code.visualstudio.com/docs/devcontainers/containers) included (supports VSCode and GitHub Codespaces)
258
+
259
+
260
+ ## Usage Examples
261
+
262
+ The following examples run from source - clone this repository using
263
+ `git clone git@github.com:aignostics/python-sdk.git`.
264
+
265
+ ### Minimal Python Script:
266
+
267
+ ```python
268
+ """Example script demonstrating the usage of the service provided by Aignostics Python SDK."""
269
+
270
+ from dotenv import load_dotenv
271
+ from rich.console import Console
272
+
273
+ from aignostics import Service
274
+
275
+ console = Console()
276
+
277
+ load_dotenv()
278
+
279
+ message = Service.get_hello_world()
280
+ console.print(f"[blue]{message}[/blue]")
281
+ ```
282
+
283
+ [Show script code](https://github.com/aignostics/python-sdk/blob/main/examples/script.py) - [Read the reference documentation](https://aignostics.readthedocs.io/en/latest/reference.html)
284
+
285
+ ### Streamlit App
286
+
287
+ Serve the functionality provided by Aignostics Python SDK in the web by easily integrating the service into a Streamlit application.
288
+
289
+ [Try it out!](https://aignostics.streamlit.app) - [Show the code](https://github.com/aignostics/python-sdk/blob/main/examples/streamlit.py)
290
+
291
+ ... or serve the app locally
292
+ ```shell
293
+ uv sync --all-extras # Install streamlit dependency part of the examples extra, see pyproject.toml
294
+ uv run streamlit run examples/streamlit.py # Serve on localhost:8501, opens browser
295
+ ```
296
+
297
+ ## Notebooks
298
+
299
+ ### Jupyter
300
+
301
+ [Show the Jupyter code](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.ipynb)
302
+
303
+ ... or run within VSCode
304
+
305
+ ```shell
306
+ uv sync --all-extras # Install dependencies required for examples such as Juypyter kernel, see pyproject.toml
307
+ ```
308
+ Install the [Jupyter extension for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter)
309
+
310
+ Click on `examples/notebook.ipynb` in VSCode and run it.
311
+
312
+ ### Marimo
313
+
314
+ [Show the marimo code](https://github.com/aignostics/python-sdk/blob/main/examples/notebook.py)
315
+
316
+ Execute the notebook as a WASM based web app
317
+
318
+ ```shell
319
+ uv sync --all-extras # Install ipykernel dependency part of the examples extra, see pyproject.toml
320
+ uv run marimo run examples/notebook.py --watch # Serve on localhost:2718, opens browser
321
+ ```
322
+
323
+ or edit interactively in your browser
324
+
325
+ ```shell
326
+ uv sync --all-extras # Install ipykernel dependency part of the examples extra, see pyproject.toml
327
+ uv run marimo edit examples/notebook.py --watch # Edit on localhost:2718, opens browser
328
+ ```
329
+
330
+ ... or edit interactively within VSCode
331
+
332
+ Install the [Marimo extension for VSCode](https://marketplace.visualstudio.com/items?itemName=marimo-team.vscode-marimo)
333
+
334
+ Click on `examples/notebook.py` in VSCode and click on the caret next to the Run icon above the code (looks like a pencil) > "Start in marimo editor" (edit).
335
+
336
+ ## Command Line Interface (CLI)
337
+
338
+ ### Run with [uvx](https://docs.astral.sh/uv/guides/tools/)
339
+
340
+ Show available commands:
341
+
342
+ ```shell
343
+ uvx aignostics --help
344
+ ```
345
+
346
+ Execute commands:
347
+
348
+ ```shell
349
+ uvx aignostics hello-world
350
+ uvx aignostics echo --help
351
+ uvx aignostics echo "Lorem"
352
+ uvx aignostics echo "Lorem" --json
353
+ uvx aignostics openapi
354
+ uvx aignostics openapi --output-format=json
355
+ uvx aignostics serve
356
+ ```
357
+
358
+ ### Environment
359
+
360
+ The service loads environment variables including support for .env files.
361
+
362
+ ```shell
363
+ cp .env.example .env # copy example file
364
+ echo "THE_VAR=MY_VALUE" > .env # overwrite with your values
365
+ ```
366
+
367
+ Now run the usage examples again.
368
+
369
+ ### Run with Docker
370
+
371
+ You can as well run the CLI within Docker.
372
+
373
+ ```shell
374
+ docker run helmuthva/aignostics-python-sdk --help
375
+ docker run helmuthva/aignostics-python-sdk hello-world
376
+ docker run helmuthva/aignostics-python-sdk echo --help
377
+ docker run helmuthva/aignostics-python-sdk echo "Lorem"
378
+ docker run helmuthva/aignostics-python-sdk echo "Lorem" --json
379
+ docker run helmuthva/aignostics-python-sdk openapi
380
+ docker run helmuthva/aignostics-python-sdk openapi --output-format=json
381
+ docker run helmuthva/aignostics-python-sdk serve
382
+ ```
383
+
384
+ Execute command:
385
+
386
+ ```shell
387
+ docker run --env THE_VAR=MY_VALUE helmuthva/aignostics-python-sdk echo "Lorem Ipsum"
388
+ ```
389
+
390
+ Or use docker compose
391
+
392
+ The .env is passed through from the host to the Docker container.
393
+
394
+ ```shell
395
+ docker compose run aignostics --help
396
+ docker compose run aignostics hello-world
397
+ docker compose run aignostics echo --help
398
+ docker compose run aignostics echo "Lorem"
399
+ docker compose run aignostics echo "Lorem" --json
400
+ docker compose run aignostics openapi
401
+ docker compose run aignostics openapi --output-format=json
402
+ docker compose up
403
+ curl http://127.0.0.1:8000/api/v1/hello-world
404
+ curl http://127.0.0.1:8000/api/v1/docs
405
+ curl http://127.0.0.1:8000/api/v2/hello-world
406
+ curl http://127.0.0.1:8000/api/v2/docs
407
+ ```
408
+
409
+ ## Extra: Lorem Ipsum
410
+
411
+ Dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam.
412
+
413
+
414
+ ## Further Reading
415
+
416
+ * Check out the [reference](https://aignostics.readthedocs.io/en/latest/reference.html) with detailed documentation of public classes and functions.
417
+ * Our [release notes](https://aignostics.readthedocs.io/en/latest/release-notes.html) provide a complete log of recent improvements and changes.
418
+ * In case you want to help us improve 🔬 Aignostics Python SDK: The [contribution guidelines](https://aignostics.readthedocs.io/en/latest/contributing.html) explain how to setup your development environment and create pull requests.
419
+
420
+ ## Star History
421
+
422
+ <a href="https://star-history.com/#aignostics/python-sdk">
423
+ <picture>
424
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=aignostics/python-sdk&type=Date&theme=dark" />
425
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=aignostics/python-sdk&type=Date" />
426
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=aignostics/python-sdk&type=Date" />
427
+ </picture>
428
+ </a>
@@ -0,0 +1,10 @@
1
+ aignostics/__init__.py,sha256=iAqIfmcFS5DkiQyJQCSkLqSlglrIDB2t-_2gAkHlqbs,276
2
+ aignostics/api.py,sha256=_eoVpxfH6WPudnCad21IgdE-7zThJ6fNjtbSU3hSMMM,6217
3
+ aignostics/cli.py,sha256=ex4ywnJG-YtQjEFj1keqXEsfaPSgm70wiFad0NutIMw,3411
4
+ aignostics/constants.py,sha256=7kqUdabmtRqxal_ZIx_0wVhzVHI4dicOVoHQ9h4P3qk,353
5
+ aignostics/service.py,sha256=vF9TeIMGeOrOdPYoMzaEFlFUlRV1_TXtCJOSMUwErkk,750
6
+ aignostics-0.0.1.dist-info/METADATA,sha256=0WLqG0B2LbvYbKw5HRES9Mj_BB9TiSgobDX-BEtfDEY,24969
7
+ aignostics-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ aignostics-0.0.1.dist-info/entry_points.txt,sha256=wjAm-SIqSt9_1YU6UodhOpduT0OGvohSEJp5FbuUMqk,50
9
+ aignostics-0.0.1.dist-info/licenses/LICENSE,sha256=-M3GfV1uL55s46W22-zcZMDRT5SRGij3RDbn4xDp0gQ,1101
10
+ aignostics-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ aignostics = aignostics.cli:cli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [Aignostics GmbH (support@aignostics.com)]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.