Skip to content

Commit

Permalink
fix datetime.utcnow() with datetime.now(timezone.utc), Message inheri…
Browse files Browse the repository at this point in the history
…ts from Model, WIP process actions & control flow, default install fractal-repositories package
  • Loading branch information
douwevandermeij committed Jun 7, 2023
1 parent b354d80 commit 42dd179
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ coverage: ## Run tests with coverage

deps: ## Install dependencies
python -m pip install --upgrade pip
python -m pip install autoflake black coverage django fastapi flake8 flit fractal-roles fractal-specifications fractal-tokens httpx isort mccabe mypy pre-commit pylint pytest pytest-cov pytest-asyncio pytest-lazy-fixture python-dotenv python-jose requests 'sqlalchemy<2.0' tox tox-gh-actions
python -m pip install autoflake black coverage django fastapi flake8 flit fractal-repositories fractal-roles fractal-specifications fractal-tokens httpx isort mccabe mypy pre-commit pylint pytest pytest-cov pytest-asyncio pytest-lazy-fixture python-dotenv python-jose requests 'sqlalchemy<2.0' tox tox-gh-actions
python -m pip install cryptography

lint: ## Lint and static-check
Expand Down
2 changes: 1 addition & 1 deletion fractal/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Fractal is a scaffolding toolkit for building SOLID logic for your Python applications."""

__version__ = "3.1.3"
__version__ = "3.1.4"

from abc import ABC

Expand Down
2 changes: 1 addition & 1 deletion fractal/contrib/fastapi/routers/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from fractal_roles.models import Role, TokenPayloadRolesMixin
from fractal_roles.services import RolesService as BaseRolesService
from fractal_tokens.services.dummy import DummyJsonTokenService
from fractal_tokens.services.generic import TokenPayload as BaseTokenPayload
from fractal_tokens.services.generic import TokenService
from fractal_tokens.services.jwt import TokenPayload as BaseTokenPayload
from fractal_tokens.services.jwt.automatic import AutomaticJwtTokenService

from fractal import ApplicationContext, Fractal
Expand Down
4 changes: 2 additions & 2 deletions fractal/contrib/gcp/pubsub/projectors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import logging
from dataclasses import asdict
from datetime import datetime
from datetime import datetime, timezone
from json import JSONEncoder
from typing import Optional, Type

Expand Down Expand Up @@ -47,7 +47,7 @@ def project(self, id: str, event: BasicSendingEvent):
# Wrap event in a message
message = Message(
id=id,
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=json.dumps(asdict(event), cls=self.json_encoder),
object_id=event.object_id,
Expand Down
5 changes: 3 additions & 2 deletions fractal/contrib/kafka/projectors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import logging
from dataclasses import asdict
from datetime import datetime
from datetime import datetime, timezone
from json import JSONEncoder
from typing import List, Type

Expand Down Expand Up @@ -38,10 +38,11 @@ def project(self, id: str, event: BasicSendingEvent):

message = Message(
id=id,
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=json.dumps(asdict(event), cls=self.json_encoder),
object_id=event.object_id,
aggregate_root_id=event.aggregate_root_id,
)

producer = KafkaProducer(bootstrap_servers=self.bootstrap_servers)
Expand Down
5 changes: 3 additions & 2 deletions fractal/contrib/rabbitmq/projectors.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import logging
from dataclasses import asdict
from datetime import datetime
from datetime import datetime, timezone
from json import JSONEncoder
from typing import List, Type

Expand Down Expand Up @@ -42,10 +42,11 @@ def __init__(
def project(self, id: str, event: BasicSendingEvent):
message = Message(
id=id,
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=json.dumps(asdict(event), cls=self.json_encoder),
object_id=event.object_id,
aggregate_root_id=event.aggregate_root_id,
)

self.channel.basic_publish(
Expand Down
10 changes: 5 additions & 5 deletions fractal/core/event_sourcing/event_store.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import uuid
from abc import ABC, abstractmethod
from dataclasses import asdict
from datetime import datetime
from datetime import datetime, timezone
from json import JSONEncoder
from typing import List, Optional, Type

Expand Down Expand Up @@ -64,7 +64,7 @@ def commit(self, event_stream: EventStream, aggregate: str, version: int):
self.event_store_repository.add(
Message(
id=str(uuid.uuid4()),
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=event,
object_id=event.object_id,
Expand Down Expand Up @@ -96,7 +96,7 @@ def commit(self, event_stream: EventStream, aggregate: str, version: int):
self.event_store_repository.add(
Message(
id=str(uuid.uuid4()),
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=asdict(event),
object_id=event.object_id,
Expand Down Expand Up @@ -134,7 +134,7 @@ def commit(self, event_stream: EventStream, aggregate: str, version: int):
self.event_store_repository.add(
Message(
id=str(uuid.uuid4()),
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=json.dumps(asdict(event), cls=self.json_encoder),
object_id=event.object_id,
Expand Down Expand Up @@ -172,7 +172,7 @@ def commit(self, event_stream: EventStream, aggregate: str, version: int):
self.event_store_repository.add(
Message(
id=str(uuid.uuid4()),
occurred_on=datetime.utcnow(),
occurred_on=datetime.now(timezone.utc),
event=event.__class__.__name__,
data=pickle.dumps(event),
object_id=event.object_id,
Expand Down
4 changes: 3 additions & 1 deletion fractal/core/event_sourcing/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
from datetime import datetime
from typing import Any

from fractal.core.models import Model


@dataclass
class Message:
class Message(Model):
id: str
occurred_on: datetime
event: str
Expand Down
85 changes: 51 additions & 34 deletions fractal/core/process/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional
from typing import Callable, Optional

from fractal_specifications.generic.specification import Specification

Expand All @@ -14,18 +14,28 @@ def execute(self, scope: ProcessScope) -> ProcessScope:
return scope.update(ProcessScope(self.kwargs))


class ApplyToValueAction(Action):
def __init__(self, *, field: str, function: Callable):
self.field = field
self.function = function

def execute(self, scope: ProcessScope) -> ProcessScope:
scope[self.field] = self.function(scope[self.field])
return scope


class IncreaseValueAction(Action):
def __init__(self, name, value):
self.name = name
def __init__(self, *, field: str, value):
self.field = field
self.value = value

def execute(self, scope: ProcessScope) -> ProcessScope:
scope[self.name] += self.value
scope[self.field] += self.value
return scope


class PrintAction(Action):
def __init__(self, text):
def __init__(self, *, text):
self.text = text

def execute(self, scope: ProcessScope) -> ProcessScope:
Expand All @@ -34,74 +44,81 @@ def execute(self, scope: ProcessScope) -> ProcessScope:


class PrintValueAction(Action):
def __init__(self, name):
self.name = name
def __init__(self, *, field: str):
self.field = field

def execute(self, scope: ProcessScope) -> ProcessScope:
print(scope[self.name])
print(scope[self.field])
return scope


class AddEntityAction(Action):
def __init__(self, repository_key: str = "repository", **entity_defaults):
self.repository_key = repository_key
self.entity_defaults = entity_defaults
def __init__(self, *, repository_name: str, entity: str = "entity"):
self.repository_name = repository_name
self.entity = entity

def execute(self, scope: ProcessScope) -> ProcessScope:
entity_class = scope[self.repository_key].entity
data = self.entity_defaults
if hasattr(scope, "contract"):
data.update(scope["contract"])
entity = entity_class(**data)
scope["entity"] = scope[self.repository_key].add(entity)
repository = getattr(scope.fractal.context, self.repository_name)
repository.add(getattr(scope, self.entity))
return scope


class UpdateEntityAction(Action):
def __init__(self, repository_key: str = "repository"):
self.repository_key = repository_key
def __init__(
self, *, repository_name: str, entity: str = "entity", upsert: bool = False
):
self.repository_name = repository_name
self.entity = entity
self.upsert = upsert

def execute(self, scope: ProcessScope) -> ProcessScope:
entity = scope["entity"].update(scope["contract"])
scope["entity"] = scope[self.repository_key].update(entity)
repository = getattr(scope.fractal.context, self.repository_name)
repository.update(getattr(scope, self.entity), self.upsert)
return scope


class FetchEntityAction(Action):
def __init__(
self, specification: Specification, repository_key: str = "repository"
self,
*,
repository_name: str,
specification: Specification,
entity: str = "entity",
):
self.repository_name = repository_name
self.specification = specification
self.repository_key = repository_key
self.entity = entity

def execute(self, scope: ProcessScope) -> ProcessScope:
scope["entity"] = scope[self.repository_key].find_one(self.specification)
repository = getattr(scope.fractal.context, self.repository_name)
scope[self.entity] = repository.find_one(self.specification)
return scope


class FindEntitiesAction(Action):
def __init__(
self,
*,
repository_name: str,
specification: Optional[Specification] = None,
repository_key: str = "repository",
entities: str = "entities",
):
self.repository_name = repository_name
self.specification = specification
self.repository_key = repository_key
self.entities = entities

def execute(self, scope: ProcessScope) -> ProcessScope:
scope["entities"] = scope["entity"] = scope[self.repository_key].find(
self.specification
)
repository = getattr(scope.fractal.context, self.repository_name)
scope[self.entities] = repository.find(self.specification)
return scope


class DeleteEntityAction(Action):
def __init__(
self, specification: Specification, repository_key: str = "repository"
):
def __init__(self, *, repository_name: str, specification: Specification):
self.repository_name = repository_name
self.specification = specification
self.repository_key = repository_key

def execute(self, scope: ProcessScope) -> ProcessScope:
scope[self.repository_key].remove_one(self.specification)
repository = getattr(scope.fractal.context, self.repository_name)
repository.remove_one(self.specification)
return scope
18 changes: 9 additions & 9 deletions fractal/core/process/actions/control_flow.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Iterable, Optional
from typing import Iterable, List, Optional

from fractal_specifications.generic.specification import Specification

Expand All @@ -11,12 +11,12 @@ class IfElseAction(Action):
def __init__(
self,
specification: Specification,
process_true: Process,
process_false: Optional[Process] = None,
actions_true: List[Action],
actions_false: Optional[List[Action]] = None,
):
self.specification = specification
self.process_true = process_true
self.process_false = process_false
self.process_true = Process(actions_true)
self.process_false = Process(actions_false) if actions_false else None

def execute(self, scope: ProcessScope) -> ProcessScope:
if self.specification.is_satisfied_by(scope):
Expand All @@ -27,9 +27,9 @@ def execute(self, scope: ProcessScope) -> ProcessScope:


class WhileAction(Action):
def __init__(self, specification: Specification, process: Process):
def __init__(self, specification: Specification, actions: List[Action]):
self.specification = specification
self.process = process
self.process = Process(actions)

def execute(self, scope: ProcessScope) -> ProcessScope:
while self.specification.is_satisfied_by(scope):
Expand All @@ -38,9 +38,9 @@ def execute(self, scope: ProcessScope) -> ProcessScope:


class ForEachAction(Action):
def __init__(self, iterable: Iterable, process: Process):
def __init__(self, iterable: Iterable, actions: List[Action]):
self.iterable = iterable
self.process = process
self.process = Process(actions)

def execute(self, scope: ProcessScope) -> ProcessScope:
for item in self.iterable:
Expand Down
1 change: 1 addition & 0 deletions fractal/py.typed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This file is used to indicate that this package supports type annotations.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "fractal-toolkit"
version = "3.1.3"
version = "3.1.4"
description = "Fractal is a scaffolding toolkit for building SOLID logic for your Python applications."
authors = ["Douwe van der Meij <douwe@karibu-online.nl>"]

Expand All @@ -25,6 +25,7 @@ classifiers = [
]
description-file = "README.md"
requires = [
"fractal-repositories",
"fractal-roles",
"fractal-specifications",
"fractal-tokens",
Expand Down
4 changes: 2 additions & 2 deletions tests/fixtures/core/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from datetime import datetime
from datetime import datetime, timezone

import pytest

Expand Down Expand Up @@ -63,4 +63,4 @@ class EmptyApplicationContext(ApplicationContext):

@pytest.fixture
def now():
return datetime.utcnow()
return datetime.now(timezone.utc)
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ deps =
django
fastapi
flake8
fractal-repositories
fractal-roles
fractal-specifications
fractal-tokens
Expand Down

0 comments on commit 42dd179

Please sign in to comment.