Compare commits

..

1 Commits

Author SHA1 Message Date
2a927ebdd5 Added enumerable order & added array & removed collection
Some checks failed
Test before pr merge / test-lint (pull_request) Failing after 6s
Build on push / prepare (push) Successful in 10s
Build on push / core (push) Successful in 18s
Build on push / query (push) Successful in 19s
Build on push / dependency (push) Successful in 18s
Build on push / application (push) Successful in 16s
Build on push / database (push) Successful in 19s
Build on push / mail (push) Successful in 19s
Build on push / translation (push) Successful in 20s
Build on push / auth (push) Successful in 15s
Build on push / api (push) Has been cancelled
2025-09-24 19:39:28 +02:00
486 changed files with 1744 additions and 7791 deletions

View File

@@ -16,68 +16,61 @@ jobs:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, application, auth, core, dependency ] needs: [ prepare, application, auth, core, dependency ]
with: with:
working_directory: src/api working_directory: src/cpl-api
secrets: inherit secrets: inherit
application: application:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core, dependency ] needs: [ prepare, core, dependency ]
with: with:
working_directory: src/application working_directory: src/cpl-application
secrets: inherit secrets: inherit
auth: auth:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core, dependency, database ] needs: [ prepare, core, dependency, database ]
with: with:
working_directory: src/auth working_directory: src/cpl-auth
secrets: inherit
cli:
uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ]
with:
working_directory: src/cli
secrets: inherit secrets: inherit
core: core:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [prepare] needs: [prepare]
with: with:
working_directory: src/core working_directory: src/cpl-core
secrets: inherit secrets: inherit
database: database:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core, dependency ] needs: [ prepare, core, dependency ]
with: with:
working_directory: src/database working_directory: src/cpl-database
secrets: inherit secrets: inherit
dependency: dependency:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core ] needs: [ prepare, core ]
with: with:
working_directory: src/dependency working_directory: src/cpl-dependency
secrets: inherit secrets: inherit
mail: mail:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core, dependency ] needs: [ prepare, core, dependency ]
with: with:
working_directory: src/mail working_directory: src/cpl-mail
secrets: inherit secrets: inherit
query: query:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [prepare] needs: [prepare]
with: with:
working_directory: src/query working_directory: src/cpl-query
secrets: inherit secrets: inherit
translation: translation:
uses: ./.gitea/workflows/package.yaml uses: ./.gitea/workflows/package.yaml
needs: [ prepare, core, dependency ] needs: [ prepare, core, dependency ]
with: with:
working_directory: src/translation working_directory: src/cpl-translation
secrets: inherit secrets: inherit

View File

@@ -36,12 +36,6 @@ jobs:
echo "Set version to $(cat /workspace/sh-edraft.de/cpl/version.txt)" echo "Set version to $(cat /workspace/sh-edraft.de/cpl/version.txt)"
cat pyproject.toml cat pyproject.toml
- name: Set package version
run: |
sed -i -E "s/^__version__ = \".*\"/__version__ = \"$(cat /workspace/sh-edraft.de/cpl/version.txt)\"/" cpl/*/__init__.py
echo "Set version to $(cat /workspace/sh-edraft.de/cpl/version.txt)"
cat cpl/*/__init__.py
- name: Set pip conf - name: Set pip conf
run: | run: |
cat > .pip.conf <<'EOF' cat > .pip.conf <<'EOF'

View File

@@ -25,11 +25,7 @@ jobs:
git tag git tag
DATE=$(date +'%Y.%m.%d') DATE=$(date +'%Y.%m.%d')
TAG_COUNT=$(git tag -l "${DATE}.*" | wc -l) TAG_COUNT=$(git tag -l "${DATE}.*" | wc -l)
if [ "$TAG_COUNT" -eq 0 ]; then BUILD_NUMBER=$(($TAG_COUNT + 1))
BUILD_NUMBER=0
else
BUILD_NUMBER=$(($TAG_COUNT + 1))
fi
VERSION_SUFFIX=${{ inputs.version_suffix }} VERSION_SUFFIX=${{ inputs.version_suffix }}
if [ -n "$VERSION_SUFFIX" ] && [ "$VERSION_SUFFIX" = "dev" ]; then if [ -n "$VERSION_SUFFIX" ] && [ "$VERSION_SUFFIX" = "dev" ]; then

View File

@@ -1,22 +0,0 @@
## Prepare for development
After cloning the repository, run the following commands to set up your development environment:
```bash
python -m venv .venv
source .venv/bin/activate
# On Windows use `.venv\Scripts\activate`
# On Windows with git bash use `source .venv/Scripts/activate`
bash install.sh
```
Install cpl-cli as a development package:
```bash
pip install -e src/core
pip install -e src/cli
# test with:
cpl v
```
When using Pycharm, mark all directories under `src/` as "Sources Root" and `exa` to ensure proper module resolution.

View File

@@ -1,12 +0,0 @@
{
"name": "cpl",
"projects": [
"src/cli/cpl.project.json",
"src/core/cpl.project.json",
"test/cpl.project.json"
],
"defaultProject": "cpl-cli",
"scripts": {
"format": "black src"
}
}

View File

@@ -1,147 +0,0 @@
from starlette.responses import JSONResponse
from cpl.dependency.event_bus import EventBusABC
from cpl.graphql.event_bus.memory import InMemoryEventBus
from queries.cities import CityGraphType, CityFilter, CitySort
from queries.hello import UserGraphType # , UserFilter, UserSort, UserGraphType
from queries.user import UserFilter, UserSort
from cpl.api.api_module import ApiModule
from cpl.application.application_builder import ApplicationBuilder
from cpl.auth.schema import User, Role
from cpl.core.configuration import Configuration
from cpl.core.console import Console
from cpl.core.environment import Environment
from cpl.core.utils.cache import Cache
from cpl.database.mysql.mysql_module import MySQLModule
from cpl.graphql.application.graphql_app import GraphQLApp
from cpl.graphql.auth.graphql_auth_module import GraphQLAuthModule
from cpl.graphql.graphql_module import GraphQLModule
from model.author_dao import AuthorDao
from model.author_query import AuthorGraphType, AuthorFilter, AuthorSort
from model.post_dao import PostDao
from model.post_query import PostFilter, PostSort, PostGraphType, PostMutation, PostSubscription
from permissions import PostPermissions
from queries.hello import HelloQuery
from scoped_service import ScopedService
from service import PingService
from test_data_seeder import TestDataSeeder
def main():
builder = ApplicationBuilder[GraphQLApp](GraphQLApp)
Configuration.add_json_file(f"appsettings.json")
Configuration.add_json_file(f"appsettings.{Environment.get_environment()}.json")
Configuration.add_json_file(f"appsettings.{Environment.get_host_name()}.json", optional=True)
# builder.services.add_logging()
(
builder.services.add_structured_logging()
.add_transient(PingService)
.add_module(MySQLModule)
.add_module(ApiModule)
.add_module(GraphQLModule)
.add_module(GraphQLAuthModule)
.add_scoped(ScopedService)
.add_singleton(EventBusABC, InMemoryEventBus)
.add_cache(User)
.add_cache(Role)
.add_transient(CityGraphType)
.add_transient(CityFilter)
.add_transient(CitySort)
.add_transient(UserGraphType)
.add_transient(UserFilter)
.add_transient(UserSort)
# .add_transient(UserGraphType)
# .add_transient(UserFilter)
# .add_transient(UserSort)
.add_transient(HelloQuery)
# test data
.add_singleton(TestDataSeeder)
# authors
.add_transient(AuthorDao)
.add_transient(AuthorGraphType)
.add_transient(AuthorFilter)
.add_transient(AuthorSort)
# posts
.add_transient(PostDao)
.add_transient(PostGraphType)
.add_transient(PostFilter)
.add_transient(PostSort)
.add_transient(PostMutation)
.add_transient(PostSubscription)
)
app = builder.build()
app.with_logging()
app.with_migrations("./scripts")
app.with_authentication()
app.with_authorization()
app.with_route(
path="/route1",
fn=lambda r: JSONResponse("route1"),
method="GET",
# authentication=True,
# permissions=[Permissions.administrator],
)
app.with_routes_directory("routes")
schema = app.with_graphql()
schema.query.string_field("ping", resolver=lambda: "pong")
schema.query.with_query("hello", HelloQuery)
schema.query.dao_collection_field(AuthorGraphType, AuthorDao, "authors", AuthorFilter, AuthorSort)
(
schema.query.dao_collection_field(PostGraphType, PostDao, "posts", PostFilter, PostSort)
# .with_require_any_permission(PostPermissions.read)
.with_public()
)
schema.mutation.with_mutation("post", PostMutation).with_public()
schema.subscription.with_subscription(PostSubscription)
app.with_auth_root_queries(True)
app.with_auth_root_mutations(True)
app.with_playground()
app.with_graphiql()
app.with_permissions(PostPermissions)
provider = builder.service_provider
user_cache = provider.get_service(Cache[User])
role_cache = provider.get_service(Cache[Role])
if role_cache == user_cache:
raise Exception("Cache service is not working")
s1 = provider.get_service(ScopedService)
s2 = provider.get_service(ScopedService)
if s1.name == s2.name:
raise Exception("Scoped service is not working")
with provider.create_scope() as scope:
s3 = scope.get_service(ScopedService)
s4 = scope.get_service(ScopedService)
if s3.name != s4.name:
raise Exception("Scoped service is not working")
if s1.name == s3.name:
raise Exception("Scoped service is not working")
Console.write_line(
s1.name,
s2.name,
s3.name,
s4.name,
)
app.run()
if __name__ == "__main__":
main()

View File

@@ -1,30 +0,0 @@
from datetime import datetime
from typing import Self
from cpl.core.typing import SerialId
from cpl.database.abc import DbModelABC
class Author(DbModelABC[Self]):
def __init__(
self,
id: int,
first_name: str,
last_name: str,
deleted: bool = False,
editor_id: SerialId | None = None,
created: datetime | None = None,
updated: datetime | None = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._first_name = first_name
self._last_name = last_name
@property
def first_name(self) -> str:
return self._first_name
@property
def last_name(self) -> str:
return self._last_name

View File

@@ -1,11 +0,0 @@
from cpl.database.abc import DbModelDaoABC
from model.author import Author
class AuthorDao(DbModelDaoABC):
def __init__(self):
DbModelDaoABC.__init__(self, Author, "authors")
self.attribute(Author.first_name, str, db_name="firstname")
self.attribute(Author.last_name, str, db_name="lastname")

View File

@@ -1,37 +0,0 @@
from cpl.graphql.schema.db_model_graph_type import DbModelGraphType
from cpl.graphql.schema.filter.db_model_filter import DbModelFilter
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
from model.author import Author
class AuthorFilter(DbModelFilter[Author]):
def __init__(self):
DbModelFilter.__init__(self, public=True)
self.int_field("id")
self.string_field("firstName")
self.string_field("lastName")
class AuthorSort(Sort[Author]):
def __init__(self):
Sort.__init__(self)
self.field("id", SortOrder)
self.field("firstName", SortOrder)
self.field("lastName", SortOrder)
class AuthorGraphType(DbModelGraphType[Author]):
def __init__(self):
DbModelGraphType.__init__(self, public=True)
self.int_field(
"id",
resolver=lambda root: root.id,
).with_public(True)
self.string_field(
"firstName",
resolver=lambda root: root.first_name,
).with_public(True)
self.string_field(
"lastName",
resolver=lambda root: root.last_name,
).with_public(True)

View File

@@ -1,44 +0,0 @@
from datetime import datetime
from typing import Self
from cpl.core.typing import SerialId
from cpl.database.abc import DbModelABC
class Post(DbModelABC[Self]):
def __init__(
self,
id: int,
author_id: SerialId,
title: str,
content: str,
deleted: bool = False,
editor_id: SerialId | None = None,
created: datetime | None = None,
updated: datetime | None = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._author_id = author_id
self._title = title
self._content = content
@property
def author_id(self) -> SerialId:
return self._author_id
@property
def title(self) -> str:
return self._title
@title.setter
def title(self, value: str):
self._title = value
@property
def content(self) -> str:
return self._content
@content.setter
def content(self, value: str):
self._content = value

View File

@@ -1,15 +0,0 @@
from cpl.database.abc import DbModelDaoABC
from model.author_dao import AuthorDao
from model.post import Post
class PostDao(DbModelDaoABC[Post]):
def __init__(self, authors: AuthorDao):
DbModelDaoABC.__init__(self, Post, "posts")
self.attribute(Post.author_id, int, db_name="authorId")
self.reference("author", "id", Post.author_id, "authors", authors)
self.attribute(Post.title, str)
self.attribute(Post.content, str)

View File

@@ -1,148 +0,0 @@
from cpl.dependency.event_bus import EventBusABC
from cpl.graphql.query_context import QueryContext
from cpl.graphql.schema.db_model_graph_type import DbModelGraphType
from cpl.graphql.schema.filter.db_model_filter import DbModelFilter
from cpl.graphql.schema.input import Input
from cpl.graphql.schema.mutation import Mutation
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
from cpl.graphql.schema.subscription import Subscription
from model.author_dao import AuthorDao
from model.author_query import AuthorGraphType, AuthorFilter
from model.post import Post
from model.post_dao import PostDao
class PostFilter(DbModelFilter[Post]):
def __init__(self):
DbModelFilter.__init__(self, public=True)
self.int_field("id")
self.filter_field("author", AuthorFilter)
self.string_field("title")
self.string_field("content")
class PostSort(Sort[Post]):
def __init__(self):
Sort.__init__(self)
self.field("id", SortOrder)
self.field("title", SortOrder)
self.field("content", SortOrder)
class PostGraphType(DbModelGraphType[Post]):
def __init__(self, authors: AuthorDao):
DbModelGraphType.__init__(self, public=True)
self.int_field(
"id",
resolver=lambda root: root.id,
).with_optional().with_public(True)
async def _a(root: Post):
return await authors.get_by_id(root.author_id)
def r_name(ctx: QueryContext):
return ctx.user.username == "admin"
self.object_field("author", AuthorGraphType, resolver=_a).with_public(True) # .with_require_any([], [r_name]))
self.string_field(
"title",
resolver=lambda root: root.title,
).with_public(True)
self.string_field(
"content",
resolver=lambda root: root.content,
).with_public(True)
class PostCreateInput(Input[Post]):
title: str
content: str
author_id: int
def __init__(self):
Input.__init__(self)
self.string_field("title").with_required()
self.string_field("content").with_required()
self.int_field("author_id").with_required()
class PostUpdateInput(Input[Post]):
title: str
content: str
author_id: int
def __init__(self):
Input.__init__(self)
self.int_field("id").with_required()
self.string_field("title").with_required(False)
self.string_field("content").with_required(False)
class PostSubscription(Subscription):
def __init__(self, bus: EventBusABC):
Subscription.__init__(self)
self._bus = bus
def selector(event: Post, info) -> bool:
return event.id == 101
self.subscription_field("postChange", PostGraphType, selector).with_public()
class PostMutation(Mutation):
def __init__(self, posts: PostDao, authors: AuthorDao, bus: EventBusABC):
Mutation.__init__(self)
self._posts = posts
self._authors = authors
self._bus = bus
self.field("create", int, resolver=self.create_post).with_public().with_required().with_argument(
"input",
PostCreateInput,
).with_required()
self.field("update", bool, resolver=self.update_post).with_public().with_required().with_argument(
"input",
PostUpdateInput,
).with_required()
self.field("delete", bool, resolver=self.delete_post).with_public().with_required().with_argument(
"id",
int,
).with_required()
self.field("restore", bool, resolver=self.restore_post).with_public().with_required().with_argument(
"id",
int,
).with_required()
async def create_post(self, input: PostCreateInput) -> int:
return await self._posts.create(Post(0, input.author_id, input.title, input.content))
async def update_post(self, input: PostUpdateInput) -> bool:
post = await self._posts.get_by_id(input.id)
if post is None:
return False
post.title = input.title if input.title is not None else post.title
post.content = input.content if input.content is not None else post.content
await self._posts.update(post)
await self._bus.publish("postChange", post)
return True
async def delete_post(self, id: int) -> bool:
post = await self._posts.get_by_id(id)
if post is None:
return False
await self._posts.delete(post)
return True
async def restore_post(self, id: int) -> bool:
post = await self._posts.get_by_id(id)
if post is None:
return False
await self._posts.restore(post)
return True

View File

@@ -1,8 +0,0 @@
from enum import Enum
class PostPermissions(Enum):
read = "post.read"
write = "post.write"
delete = "post.delete"

View File

@@ -1,39 +0,0 @@
from cpl.graphql.schema.filter.filter import Filter
from cpl.graphql.schema.graph_type import GraphType
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
class City:
def __init__(self, id: int, name: str):
self.id = id
self.name = name
class CityFilter(Filter[City]):
def __init__(self):
Filter.__init__(self)
self.field("id", int)
self.field("name", str)
class CitySort(Sort[City]):
def __init__(self):
Sort.__init__(self)
self.field("id", SortOrder)
self.field("name", SortOrder)
class CityGraphType(GraphType[City]):
def __init__(self):
GraphType.__init__(self)
self.int_field(
"id",
resolver=lambda root: root.id,
)
self.string_field(
"name",
resolver=lambda root: root.name,
)

View File

@@ -1,70 +0,0 @@
from queries.cities import CityFilter, CitySort, CityGraphType, City
from queries.user import User, UserFilter, UserSort, UserGraphType
from cpl.api.middleware.request import get_request
from cpl.auth.schema import UserDao, User
from cpl.graphql.schema.filter.filter import Filter
from cpl.graphql.schema.graph_type import GraphType
from cpl.graphql.schema.query import Query
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
users = [User(i, f"User {i}") for i in range(1, 101)]
cities = [City(i, f"City {i}") for i in range(1, 101)]
# class UserFilter(Filter[User]):
# def __init__(self):
# Filter.__init__(self)
# self.field("id", int)
# self.field("username", str)
#
#
# class UserSort(Sort[User]):
# def __init__(self):
# Sort.__init__(self)
# self.field("id", SortOrder)
# self.field("username", SortOrder)
#
# class UserGraphType(GraphType[User]):
#
# def __init__(self):
# GraphType.__init__(self)
#
# self.int_field(
# "id",
# resolver=lambda root: root.id,
# )
# self.string_field(
# "username",
# resolver=lambda root: root.username,
# )
class HelloQuery(Query):
def __init__(self):
Query.__init__(self)
self.string_field(
"message",
resolver=lambda name: f"Hello {name} {get_request().state.request_id}",
).with_argument("name", str, "Name to greet", "world")
self.collection_field(
UserGraphType,
"users",
UserFilter,
UserSort,
resolver=lambda: users,
)
self.collection_field(
CityGraphType,
"cities",
CityFilter,
CitySort,
resolver=lambda: cities,
)
# self.dao_collection_field(
# UserGraphType,
# UserDao,
# "Users",
# UserFilter,
# UserSort,
# )

View File

@@ -1,39 +0,0 @@
from cpl.graphql.schema.filter.filter import Filter
from cpl.graphql.schema.graph_type import GraphType
from cpl.graphql.schema.sort.sort import Sort
from cpl.graphql.schema.sort.sort_order import SortOrder
class User:
def __init__(self, id: int, name: str):
self.id = id
self.name = name
class UserFilter(Filter[User]):
def __init__(self):
Filter.__init__(self)
self.field("id", int)
self.field("name", str)
class UserSort(Sort[User]):
def __init__(self):
Sort.__init__(self)
self.field("id", SortOrder)
self.field("name", SortOrder)
class UserGraphType(GraphType[User]):
def __init__(self):
GraphType.__init__(self)
self.int_field(
"id",
resolver=lambda root: root.id,
)
self.string_field(
"name",
resolver=lambda root: root.name,
)

View File

@@ -1,14 +0,0 @@
from cpl.core.console.console import Console
from cpl.core.utils.string import String
class ScopedService:
def __init__(self):
self._name = String.random(8)
@property
def name(self) -> str:
return self._name
def run(self):
Console.write_line(f"Im {self._name}")

View File

@@ -1,22 +0,0 @@
CREATE TABLE IF NOT EXISTS `authors` (
`id` INT(30) NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(64) NOT NULL,
`lastname` VARCHAR(64) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
editorId INT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`id`)
);
CREATE TABLE IF NOT EXISTS `posts` (
`id` INT(30) NOT NULL AUTO_INCREMENT,
`authorId` INT(30) NOT NULL REFERENCES `authors`(`id`) ON DELETE CASCADE,
`title` TEXT NOT NULL,
`content` TEXT NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
editorId INT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`id`)
);

View File

@@ -1,48 +0,0 @@
from faker import Faker
from cpl.database.abc import DataSeederABC
from cpl.query import Enumerable
from model.author import Author
from model.author_dao import AuthorDao
from model.post import Post
from model.post_dao import PostDao
fake = Faker()
class TestDataSeeder(DataSeederABC):
def __init__(self, authors: AuthorDao, posts: PostDao):
DataSeederABC.__init__(self)
self._authors = authors
self._posts = posts
async def seed(self):
if await self._authors.count() == 0:
await self._seed_authors()
if await self._posts.count() == 0:
await self._seed_posts()
async def _seed_authors(self):
authors = Enumerable.range(0, 35).select(
lambda x: Author(
0,
fake.first_name(),
fake.last_name(),
)
).to_list()
await self._authors.create_many(authors, skip_editor=True)
async def _seed_posts(self):
posts = Enumerable.range(0, 100).select(
lambda x: Post(
id=0,
author_id=fake.random_int(min=1, max=35),
title=fake.sentence(nb_words=6),
content=fake.paragraph(nb_sentences=6),
)
).to_list()
await self._posts.create_many(posts, skip_editor=True)

View File

@@ -0,0 +1,47 @@
from starlette.responses import JSONResponse
from cpl import api
from cpl.api.application.web_app import WebApp
from cpl.application import ApplicationBuilder
from cpl.auth.permission.permissions import Permissions
from cpl.auth.schema import AuthUser, Role
from cpl.core.configuration import Configuration
from cpl.core.environment import Environment
from cpl.core.utils.cache import Cache
from service import PingService
def main():
builder = ApplicationBuilder[WebApp](WebApp)
Configuration.add_json_file(f"appsettings.json")
Configuration.add_json_file(f"appsettings.{Environment.get_environment()}.json")
Configuration.add_json_file(f"appsettings.{Environment.get_host_name()}.json", optional=True)
# builder.services.add_logging()
builder.services.add_structured_logging()
builder.services.add_transient(PingService)
builder.services.add_module(api)
builder.services.add_cache(AuthUser)
builder.services.add_cache(Role)
app = builder.build()
app.with_logging()
app.with_database()
app.with_authentication()
app.with_authorization()
app.with_route(path="/route1", fn=lambda r: JSONResponse("route1"), method="GET", authentication=True, permissions=[Permissions.administrator])
app.with_routes_directory("routes")
provider = builder.service_provider
user_cache = provider.get_service(Cache[AuthUser])
role_cache = provider.get_service(Cache[Role])
app.run()
if __name__ == "__main__":
main()

View File

@@ -5,17 +5,12 @@ from starlette.responses import JSONResponse
from cpl.api import APILogger from cpl.api import APILogger
from cpl.api.router import Router from cpl.api.router import Router
from cpl.core.console import Console
from cpl.dependency import ServiceProvider
from scoped_service import ScopedService
@Router.authenticate() @Router.authenticate()
# @Router.authorize(permissions=[Permissions.administrator]) # @Router.authorize(permissions=[Permissions.administrator])
# @Router.authorize(policies=["test"]) # @Router.authorize(policies=["test"])
@Router.get(f"/ping") @Router.get(f"/ping")
async def ping(r: Request, ping: PingService, logger: APILogger, provider: ServiceProvider, scoped: ScopedService): async def ping(r: Request, ping: PingService, logger: APILogger):
logger.info(f"Ping: {ping}") logger.info(f"Ping: {ping}")
Console.write_line(scoped.name)
return JSONResponse(ping.ping(r)) return JSONResponse(ping.ping(r))

View File

@@ -0,0 +1,40 @@
{
"Project": {
"Name": "database",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl==2021.4.2.dev1"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {},
"Classifiers": []
},
"Build": {
"ProjectType": "console",
"SourcePath": "src",
"OutputPath": "dist",
"Main": "main",
"EntryPoint": "database",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {}
}
}

View File

@@ -3,8 +3,7 @@ from cpl.auth.keycloak import KeycloakAdmin
from cpl.core.console import Console from cpl.core.console import Console
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.log import LoggerABC from cpl.core.log import LoggerABC
from cpl.dependency import ServiceProvider from cpl.dependency import ServiceProviderABC
from cpl.dependency.typing import Modules
from model.city import City from model.city import City
from model.city_dao import CityDao from model.city_dao import CityDao
from model.user import User from model.user import User
@@ -12,8 +11,8 @@ from model.user_dao import UserDao
class Application(ApplicationABC): class Application(ApplicationABC):
def __init__(self, services: ServiceProvider, modules: Modules): def __init__(self, services: ServiceProviderABC):
ApplicationABC.__init__(self, services, modules) ApplicationABC.__init__(self, services)
self._logger = services.get_service(LoggerABC) self._logger = services.get_service(LoggerABC)

View File

@@ -3,7 +3,6 @@ from cpl.application import ApplicationBuilder
from cpl.auth.permission.permissions_registry import PermissionsRegistry from cpl.auth.permission.permissions_registry import PermissionsRegistry
from cpl.core.console import Console from cpl.core.console import Console
from cpl.core.log import LogLevel from cpl.core.log import LogLevel
from cpl.database import DatabaseModule
from custom_permissions import CustomPermissions from custom_permissions import CustomPermissions
from startup import Startup from startup import Startup
@@ -11,12 +10,13 @@ from startup import Startup
def main(): def main():
builder = ApplicationBuilder(Application).with_startup(Startup) builder = ApplicationBuilder(Application).with_startup(Startup)
builder.services.add_logging() builder.services.add_logging()
app = builder.build() app = builder.build()
app.with_logging(LogLevel.trace) app.with_logging(LogLevel.trace)
app.with_permissions(CustomPermissions) app.with_permissions(CustomPermissions)
app.with_migrations("./scripts") app.with_migrations("./scripts")
# app.with_seeders() app.with_seeders()
Console.write_line(CustomPermissions.test.value in PermissionsRegistry.get()) Console.write_line(CustomPermissions.test.value in PermissionsRegistry.get())
app.run() app.run()

View File

@@ -5,16 +5,16 @@ from cpl.core.typing import SerialId
from cpl.database.abc.db_model_abc import DbModelABC from cpl.database.abc.db_model_abc import DbModelABC
class City(DbModelABC[Self]): class City(DbModelABC):
def __init__( def __init__(
self, self,
id: int, id: int,
name: str, name: str,
zip: str, zip: str,
deleted: bool = False, deleted: bool = False,
editor_id: SerialId | None = None, editor_id: Optional[SerialId] = None,
created: datetime | None= None, created: Optional[datetime] = None,
updated: datetime | None= None, updated: Optional[datetime] = None,
): ):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated) DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._name = name self._name = name

View File

@@ -5,7 +5,7 @@ from cpl.core.typing import SerialId
from cpl.database.abc.db_model_abc import DbModelABC from cpl.database.abc.db_model_abc import DbModelABC
class User(DbModelABC[Self]): class User(DbModelABC):
def __init__( def __init__(
self, self,
@@ -13,9 +13,9 @@ class User(DbModelABC[Self]):
name: str, name: str,
city_id: int = 0, city_id: int = 0,
deleted: bool = False, deleted: bool = False,
editor_id: SerialId | None = None, editor_id: Optional[SerialId] = None,
created: datetime | None= None, created: Optional[datetime] = None,
updated: datetime | None= None, updated: Optional[datetime] = None,
): ):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated) DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._name = name self._name = name

View File

@@ -1,14 +1,11 @@
from cpl import auth from cpl import auth
from cpl.application.abc.startup_abc import StartupABC from cpl.application.abc.startup_abc import StartupABC
from cpl.auth import permission from cpl.auth import permission
from cpl.auth.auth_module import AuthModule
from cpl.auth.permission.permission_module import PermissionsModule
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.log import Logger, LoggerABC from cpl.core.log import Logger, LoggerABC
from cpl.database import mysql, DatabaseModule from cpl.database import mysql
from cpl.database.abc.data_access_object_abc import DataAccessObjectABC from cpl.database.abc.data_access_object_abc import DataAccessObjectABC
from cpl.database.mysql.mysql_module import MySQLModule
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from model.city_dao import CityDao from model.city_dao import CityDao
from model.user_dao import UserDao from model.user_dao import UserDao
@@ -24,10 +21,9 @@ class Startup(StartupABC):
@staticmethod @staticmethod
async def configure_services(services: ServiceCollection): async def configure_services(services: ServiceCollection):
services.add_module(MySQLModule) services.add_module(mysql)
services.add_module(DatabaseModule) services.add_module(auth)
services.add_module(AuthModule) services.add_module(permission)
services.add_module(PermissionsModule)
services.add_transient(DataAccessObjectABC, UserDao) services.add_transient(DataAccessObjectABC, UserDao)
services.add_transient(DataAccessObjectABC, CityDao) services.add_transient(DataAccessObjectABC, CityDao)

View File

@@ -0,0 +1,9 @@
{
"Workspace": {
"DefaultProject": "di",
"Projects": {
"di": "src/di/di.json"
},
"Scripts": {}
}
}

View File

@@ -0,0 +1,42 @@
from cpl.application.abc import ApplicationABC
from cpl.core.console.console import Console
from cpl.dependency import ServiceProviderABC
from cpl.dependency.scope import Scope
from di.static_test import StaticTest
from di.test_abc import TestABC
from di.test_service import TestService
from di.di_tester_service import DITesterService
from di.tester import Tester
class Application(ApplicationABC):
def __init__(self, services: ServiceProviderABC):
ApplicationABC.__init__(self, services)
def _part_of_scoped(self):
ts: TestService = self._services.get_service(TestService)
ts.run()
def configure(self): ...
def main(self):
with self._services.create_scope() as scope:
Console.write_line("Scope1")
ts: TestService = scope.service_provider.get_service(TestService)
ts.run()
dit: DITesterService = scope.service_provider.get_service(DITesterService)
dit.run()
with self._services.create_scope() as scope:
Console.write_line("Scope2")
ts: TestService = scope.service_provider.get_service(TestService)
ts.run()
dit: DITesterService = scope.service_provider.get_service(DITesterService)
dit.run()
Console.write_line("Global")
self._part_of_scoped()
StaticTest.test()
self._services.get_service(Tester)
Console.write_line(self._services.get_services(list[TestABC]))

View File

@@ -1,15 +1,11 @@
from cpl.core.console.console import Console from cpl.core.console.console import Console
from test_service import TestService from di.test_service import TestService
class DITesterService: class DITesterService:
def __init__(self, ts: TestService): def __init__(self, ts: TestService):
self._ts = ts self._ts = ts
@property
def name(self) -> str:
return self._ts.name
def run(self): def run(self):
Console.write_line("DIT: ") Console.write_line("DIT: ")
self._ts.run() self._ts.run()

View File

@@ -1,7 +1,7 @@
from cpl.application import ApplicationBuilder from cpl.application import ApplicationBuilder
from application import Application from di.application import Application
from startup import Startup from di.startup import Startup
def main(): def main():

View File

@@ -0,0 +1,25 @@
from cpl.application.abc import StartupABC
from cpl.dependency import ServiceProviderABC, ServiceCollection
from di.di_tester_service import DITesterService
from di.test1_service import Test1Service
from di.test2_service import Test2Service
from di.test_abc import TestABC
from di.test_service import TestService
from di.tester import Tester
class Startup(StartupABC):
def __init__(self):
StartupABC.__init__(self)
def configure_configuration(self): ...
def configure_services(self, services: ServiceCollection) -> ServiceProviderABC:
services.add_scoped(TestService)
services.add_scoped(DITesterService)
services.add_singleton(TestABC, Test1Service)
services.add_singleton(TestABC, Test2Service)
services.add_singleton(Tester)
return services.build()

View File

@@ -0,0 +1,9 @@
from cpl.dependency import ServiceProvider, ServiceProviderABC
from di.test_service import TestService
class StaticTest:
@staticmethod
@ServiceProvider.inject
def test(services: ServiceProviderABC, t1: TestService):
t1.run()

View File

@@ -1,12 +1,12 @@
import string import string
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.core.utils.string import String from cpl.core.utils.string import String
from test_abc import TestABC from di.test_abc import TestABC
class Test1Service(TestABC): class Test1Service(TestABC):
def __init__(self): def __init__(self):
TestABC.__init__(self, String.random(8)) TestABC.__init__(self, String.random_string(string.ascii_lowercase, 8))
def run(self): def run(self):
Console.write_line(f"Im {self._name}") Console.write_line(f"Im {self._name}")

View File

@@ -1,12 +1,12 @@
import string import string
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.core.utils.string import String from cpl.core.utils.string import String
from test_abc import TestABC from di.test_abc import TestABC
class Test2Service(TestABC): class Test2Service(TestABC):
def __init__(self): def __init__(self):
TestABC.__init__(self, String.random(8)) TestABC.__init__(self, String.random_string(string.ascii_lowercase, 8))
def run(self): def run(self):
Console.write_line(f"Im {self._name}") Console.write_line(f"Im {self._name}")

View File

@@ -1,3 +1,5 @@
import string
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.core.utils.string import String from cpl.core.utils.string import String
@@ -6,9 +8,5 @@ class TestService:
def __init__(self): def __init__(self):
self._name = String.random(8) self._name = String.random(8)
@property
def name(self) -> str:
return self._name
def run(self): def run(self):
Console.write_line(f"Im {self._name}") Console.write_line(f"Im {self._name}")

View File

@@ -0,0 +1,8 @@
from cpl.core.console.console import Console
from di.test_abc import TestABC
class Tester:
def __init__(self, t1: TestABC, t2: TestABC, t3: list[TestABC]):
Console.write_line("Tester:")
Console.write_line(t1, t2, t3)

View File

@@ -0,0 +1,8 @@
{
"Workspace": {
"DefaultProject": "general",
"Projects": {
"general": "src/general/general.json"
}
}
}

View File

@@ -1,25 +1,23 @@
import asyncio
import time import time
from typing import Optional
from cpl.application.abc import ApplicationABC from cpl.application.abc import ApplicationABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.console import Console from cpl.core.console import Console
from cpl.dependency import ServiceProviderABC
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.log import LoggerABC from cpl.core.log import LoggerABC
from cpl.core.pipes import IPAddressPipe from cpl.core.pipes import IPAddressPipe
from cpl.dependency import ServiceProvider
from cpl.dependency.typing import Modules
from cpl.mail import EMail, EMailClientABC from cpl.mail import EMail, EMailClientABC
from cpl.query import List from cpl.query.extension.list import List
from scoped_service import ScopedService
from test_service import TestService from test_service import TestService
from test_settings import TestSettings from test_settings import TestSettings
class Application(ApplicationABC): class Application(ApplicationABC):
def __init__(self, services: ServiceProvider, modules: Modules): def __init__(self, services: ServiceProviderABC):
ApplicationABC.__init__(self, services, modules) ApplicationABC.__init__(self, services)
self._logger = self._services.get_service(LoggerABC) self._logger = self._services.get_service(LoggerABC)
self._mailer = self._services.get_service(EMailClientABC) self._mailer = self._services.get_service(EMailClientABC)
@@ -37,10 +35,10 @@ class Application(ApplicationABC):
def _wait(time_ms: int): def _wait(time_ms: int):
time.sleep(time_ms) time.sleep(time_ms)
async def main(self): def main(self):
self._logger.debug(f"Host: {Environment.get_host_name()}") self._logger.debug(f"Host: {Environment.get_host_name()}")
self._logger.debug(f"Environment: {Environment.get_environment()}") self._logger.debug(f"Environment: {Environment.get_environment()}")
Console.write_line(List(range(0, 10)).select(lambda x: f"x={x}").to_list()) Console.write_line(List(int, range(0, 10)).select(lambda x: f"x={x}").to_list())
Console.spinner("Test", self._wait, 2, spinner_foreground_color="red") Console.spinner("Test", self._wait, 2, spinner_foreground_color="red")
test: TestService = self._services.get_service(TestService) test: TestService = self._services.get_service(TestService)
ip_pipe: IPAddressPipe = self._services.get_service(IPAddressPipe) ip_pipe: IPAddressPipe = self._services.get_service(IPAddressPipe)
@@ -50,21 +48,10 @@ class Application(ApplicationABC):
Console.write_line(f"DI working: {test == test2 and ip_pipe != ip_pipe2}") Console.write_line(f"DI working: {test == test2 and ip_pipe != ip_pipe2}")
Console.write_line(self._services.get_service(LoggerABC)) Console.write_line(self._services.get_service(LoggerABC))
root_scoped_service = self._services.get_service(ScopedService) scope = self._services.create_scope()
with self._services.create_scope() as scope: Console.write_line("scope", scope)
s_srvc1 = scope.get_service(ScopedService) with self._services.create_scope() as s:
s_srvc2 = scope.get_service(ScopedService) Console.write_line("with scope", s)
Console.write_line(root_scoped_service)
Console.write_line(s_srvc1)
Console.write_line(s_srvc2)
if root_scoped_service == s_srvc1 or s_srvc1 != s_srvc2:
raise Exception("Root scoped service should not be equal to scoped service")
root_scoped_service2 = self._services.get_service(ScopedService)
Console.write_line(root_scoped_service2)
if root_scoped_service == root_scoped_service2:
raise Exception("Root scoped service should be equal to root scoped service 2")
test_settings = Configuration.get(TestSettings) test_settings = Configuration.get(TestSettings)
Console.write_line(test_settings.value) Console.write_line(test_settings.value)
@@ -75,9 +62,3 @@ class Application(ApplicationABC):
test_settings1 = Configuration.get(TestSettings) test_settings1 = Configuration.get(TestSettings)
Console.write_line(test_settings1.value) Console.write_line(test_settings1.value)
# self.test_send_mail() # self.test_send_mail()
x = 0
while x < 500:
Console.write_line("Running...")
x += 1
await asyncio.sleep(5)

View File

@@ -0,0 +1,51 @@
{
"Project": {
"Name": "general",
"Version": {
"Major": "2021",
"Minor": "04",
"Micro": "01"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",
"Description": "sh-edraft Common Python library",
"LongDescription": "sh-edraft Common Python library",
"URL": "https://www.sh-edraft.de",
"CopyrightDate": "2020 - 2021",
"CopyrightName": "sh-edraft.de",
"LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [
"cpl-core==2022.10.0.post9",
"cpl-translation==2022.10.0.post2",
"cpl-query==2022.10.0.post2"
],
"DevDependencies": [
"cpl-cli==2022.10"
],
"PythonVersion": ">=3.10",
"PythonPath": {
"linux": "../../venv/bin/python",
"win32": ""
},
"Classifiers": []
},
"Build": {
"ProjectType": "console",
"SourcePath": "",
"OutputPath": "dist",
"Main": "main",
"EntryPoint": "",
"IncludePackageData": true,
"Included": [
"*/templates"
],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@@ -1,11 +1,9 @@
from cpl import mail
from cpl.application.abc import StartupABC from cpl.application.abc import StartupABC
from cpl.core.configuration import Configuration from cpl.core.configuration import Configuration
from cpl.core.environment import Environment from cpl.core.environment import Environment
from cpl.core.pipes import IPAddressPipe from cpl.core.pipes import IPAddressPipe
from cpl.dependency import ServiceCollection from cpl.dependency import ServiceCollection
from cpl.mail.mail_module import MailModule
from hosted_service import Hosted, MyCronJob
from scoped_service import ScopedService
from test_service import TestService from test_service import TestService
@@ -20,9 +18,6 @@ class Startup(StartupABC):
@staticmethod @staticmethod
def configure_services(services: ServiceCollection): def configure_services(services: ServiceCollection):
services.add_logging() services.add_logging()
services.add_module(MailModule) services.add_module(mail)
services.add_transient(IPAddressPipe) services.add_transient(IPAddressPipe)
services.add_singleton(TestService) services.add_singleton(TestService)
services.add_scoped(ScopedService)
services.add_hosted_service(Hosted)
services.add_hosted_service(MyCronJob)

View File

@@ -1,10 +1,10 @@
from cpl.application.abc import ApplicationExtensionABC from cpl.application.abc import ApplicationExtensionABC
from cpl.core.console import Console from cpl.core.console import Console
from cpl.dependency import ServiceProvider from cpl.dependency import ServiceProviderABC
class TestExtension(ApplicationExtensionABC): class TestExtension(ApplicationExtensionABC):
@staticmethod @staticmethod
def run(services: ServiceProvider): def run(services: ServiceProviderABC):
Console.write_line("Hello World from App Extension") Console.write_line("Hello World from App Extension")

View File

@@ -1,10 +1,10 @@
from cpl.core.console.console import Console from cpl.core.console.console import Console
from cpl.dependency import ServiceProvider from cpl.dependency import ServiceProviderABC
from cpl.core.pipes.ip_address_pipe import IPAddressPipe from cpl.core.pipes.ip_address_pipe import IPAddressPipe
class TestService: class TestService:
def __init__(self, provider: ServiceProvider): def __init__(self, provider: ServiceProviderABC):
self._provider = provider self._provider = provider
def run(self): def run(self):

View File

@@ -0,0 +1,3 @@
class Custom:
def __init__(self):
print("hello")

View File

@@ -48,9 +48,9 @@ def t_benchmark(data: list):
def main(): def main():
N = 1_000_000 N = 10_000_000
data = list(range(N)) data = list(range(N))
t_benchmark(data) #t_benchmark(data)
Console.write_line() Console.write_line()
_default() _default()

View File

@@ -1,14 +1,14 @@
from cpl.application import ApplicationABC from cpl.application import ApplicationABC
from cpl.core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl.core.console import Console from cpl.core.console import Console
from cpl.dependency import ServiceProvider from cpl.dependency import ServiceProviderABC
from cpl.translation.translate_pipe import TranslatePipe from cpl.translation.translate_pipe import TranslatePipe
from cpl.translation.translation_service_abc import TranslationServiceABC from cpl.translation.translation_service_abc import TranslationServiceABC
from cpl.translation.translation_settings import TranslationSettings from cpl.translation.translation_settings import TranslationSettings
class Application(ApplicationABC): class Application(ApplicationABC):
def __init__(self, config: ConfigurationABC, services: ServiceProvider): def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
ApplicationABC.__init__(self, config, services) ApplicationABC.__init__(self, config, services)
self._translate: TranslatePipe = services.get_service(TranslatePipe) self._translate: TranslatePipe = services.get_service(TranslatePipe)

View File

@@ -1,6 +1,6 @@
from cpl.application import StartupABC from cpl.application import StartupABC
from cpl.core.configuration import ConfigurationABC from cpl.core.configuration import ConfigurationABC
from cpl.dependency import ServiceProvider, ServiceCollection from cpl.dependency import ServiceProviderABC, ServiceCollection
from cpl.core.environment import Environment from cpl.core.environment import Environment
@@ -12,6 +12,6 @@ class Startup(StartupABC):
configuration.add_json_file("appsettings.json") configuration.add_json_file("appsettings.json")
return configuration return configuration
def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProvider: def configure_services(self, services: ServiceCollection, environment: Environment) -> ServiceProviderABC:
services.add_translation() services.add_translation()
return services.build() return services.build()

View File

@@ -1,45 +0,0 @@
from cpl.application.abc import ApplicationABC
from cpl.core.console.console import Console
from cpl.dependency import ServiceProvider
from test_abc import TestABC
from test_service import TestService
from di_tester_service import DITesterService
from tester import Tester
class Application(ApplicationABC):
def __init__(self, services: ServiceProvider):
ApplicationABC.__init__(self, services)
def _part_of_scoped(self):
ts: TestService = self._services.get_service(TestService)
ts.run()
def main(self):
with self._services.create_scope() as scope:
Console.write_line("Scope1")
ts: TestService = scope.get_service(TestService)
ts.run()
dit: DITesterService = scope.get_service(DITesterService)
dit.run()
if ts.name != dit.name:
raise Exception("DI is broken!")
with self._services.create_scope() as scope:
Console.write_line("Scope2")
ts: TestService = scope.get_service(TestService)
ts.run()
dit: DITesterService = scope.get_service(DITesterService)
dit.run()
if ts.name != dit.name:
raise Exception("DI is broken!")
Console.write_line("Global")
self._part_of_scoped()
#from static_test import StaticTest
#StaticTest.test()
self._services.get_service(Tester)
Console.write_line(self._services.get_services(TestABC))

View File

@@ -1,27 +0,0 @@
from cpl.application.abc import StartupABC
from cpl.dependency import ServiceProvider, ServiceCollection
from di_tester_service import DITesterService
from test1_service import Test1Service
from test2_service import Test2Service
from test_abc import TestABC
from test_service import TestService
from tester import Tester
class Startup(StartupABC):
def __init__(self):
StartupABC.__init__(self)
@staticmethod
def configure_configuration(): ...
@staticmethod
def configure_services(services: ServiceCollection) -> ServiceProvider:
services.add_scoped(TestService)
services.add_scoped(DITesterService)
services.add_singleton(TestABC, Test1Service)
services.add_singleton(TestABC, Test2Service)
services.add_singleton(Tester)
return services.build()

View File

@@ -1,10 +0,0 @@
from cpl.dependency import ServiceProvider, ServiceProvider
from cpl.dependency.inject import inject
from test_service import TestService
class StaticTest:
@staticmethod
@inject
def test(services: ServiceProvider, t1: TestService):
t1.run()

View File

@@ -1,7 +0,0 @@
from cpl.core.console.console import Console
from test_abc import TestABC
class Tester:
def __init__(self, t1: TestABC, t2: TestABC, t3: TestABC, t: list[TestABC]):
Console.write_line("Tester:", t, t1, t2, t3)

View File

@@ -1,30 +0,0 @@
import asyncio
from datetime import datetime
from cpl.core.console import Console
from cpl.core.time.cron import Cron
from cpl.core.service.cronjob import CronjobABC
from cpl.core.service.hosted_service import HostedService
class Hosted(HostedService):
def __init__(self):
self._stopped = False
async def start(self):
Console.write_line("Hosted Service Started")
while not self._stopped:
Console.write_line("Hosted Service Running")
await asyncio.sleep(5)
async def stop(self):
Console.write_line("Hosted Service Stopped")
self._stopped = True
class MyCronJob(CronjobABC):
def __init__(self):
CronjobABC.__init__(self, Cron("*/1 * * * *")) # Every minute
async def loop(self):
Console.write_line(f"[{datetime.now()}] Hello from Cronjob!")

View File

@@ -1,10 +0,0 @@
from cpl.core.console import Console
class ScopedService:
def __init__(self):
self.value = "I am a scoped service"
Console.write_line(self.value, self)
def get_value(self):
return self.value

Some files were not shown because too many files have changed in this diff Show More