Skip to content

Commit

Permalink
fix(dummy): Simulatus Config is no Longer a Subset of Captura Config.
Browse files Browse the repository at this point in the history
Fixed mypy errors.
  • Loading branch information
acederberg committed Sep 5, 2024
1 parent 57d00b8 commit 47af15d
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 51 deletions.
23 changes: 6 additions & 17 deletions src/captura/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,10 @@ class Event(Base):
__tablename__ = "events"
__kind__ = KindObject.event

timestamp: Mapped[int] = mapped_column(
timestamp: Mapped[str] = mapped_column(
default=(_now := lambda: datetime.timestamp(datetime.now())),
)

# id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
uuid: Mapped[MappedColumnUUIDUnique] = mapped_column(primary_key=True)
uuid_parent: Mapped[str] = mapped_column(
ForeignKey("events.uuid", ondelete="CASCADE"),
Expand Down Expand Up @@ -707,15 +706,15 @@ class AssocCollectionDocument(Base):
# NOTE: Since this object supports soft deletion (for the deletion grace
# period that will later be implemented) deleted is included.
# deleted: Mapped[MappedColumnDeleted]
uuid_document: Mapped[int] = mapped_column(
uuid_document: Mapped[str] = mapped_column(
ForeignKey(
"documents.uuid",
ondelete="CASCADE",
),
primary_key=True,
)

uuid_collection: Mapped[int] = mapped_column(
uuid_collection: Mapped[str] = mapped_column(
ForeignKey(
"collections.uuid",
ondelete="CASCADE",
Expand Down Expand Up @@ -796,14 +795,14 @@ class AssocUserDocument(Base):
cascade="all, delete",
)

uuid_user: Mapped[int] = mapped_column(
uuid_user: Mapped[str] = mapped_column(
ForeignKey(
"users.uuid",
ondelete="CASCADE",
),
key="a",
)
uuid_document: Mapped[int] = mapped_column(
uuid_document: Mapped[str] = mapped_column(
ForeignKey(
"documents.uuid",
ondelete="CASCADE",
Expand All @@ -819,16 +818,6 @@ class AssocUserDocument(Base):
__table_args__ = (UniqueConstraint("a", "b", name="_grant_vector"),)


@property
def uuid_user_granter(self) -> str:
session = self.get_session()
res = session.execute(
select(User.uuid).where(User.uuid == self.uuid_user_granter) # type: ignore
).scalar()
if res is None:
raise ValueError("Inconcievable!")
return res

@classmethod
def resolve_from_target(
cls, session: Session, source: "User | Document", uuid_target: Set[str]
Expand Down Expand Up @@ -1231,7 +1220,7 @@ class Collection(SearchableTableMixins, Base):
__tablename__ = "collections"
__kind__ = KindObject.collection

uuid_user: Mapped[int] = mapped_column(
uuid_user: Mapped[str] = mapped_column(
ForeignKey("users.uuid", ondelete="CASCADE"),
nullable=False,
)
Expand Down
4 changes: 4 additions & 0 deletions src/captura/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ def from_env(v: str, default: str | None = None, *, prefix: bool = True):
"CONFIG_CLIENT",
Path.config("client.yaml"),
)
PATH_CONFIG_DUMMY = from_env(
"CONFIG_DUMMY",
Path.config("dummy.yaml"),
)
PATH_CONFIG_TEST_APP = from_env(
"CONFIG_APP_TEST",
Path.config("app.test.yaml"),
Expand Down
31 changes: 21 additions & 10 deletions src/simulatus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
# --------------------------------------------------------------------------- #
from captura import util
from captura.auth import Auth, Token, TokenPermissionTier
from captura.config import Config
from captura.controllers.access import Access
from captura.controllers.base import (
BaseResolved,
Expand Down Expand Up @@ -111,15 +112,17 @@ class BaseDummyProvider:
}

client_config_cls: Type
config: ConfigSimulatus
config: Config
config_dummy: ConfigSimulatus
dummy: DummyConfig
session: Session
user: User
auth: Auth

def __init__(
self,
config: ConfigSimulatus,
config: Config,
config_dummy: ConfigSimulatus,
session: Session,
*,
user: User,
Expand All @@ -128,7 +131,8 @@ def __init__(
):
self.client_config_cls = client_config_cls or ClientConfig
self.config = config
self.dummy = config.dummy
self.config_dummy = config_dummy
self.dummy = config_dummy.dummy
self.auth = auth if auth is not None else Auth.forPyTest(config)
self.session = session
self.user = user
Expand Down Expand Up @@ -1173,15 +1177,17 @@ def q_select_suitable(self):

def __init__(
self,
config: ConfigSimulatus,
config: Config,
config_dummy: ConfigSimulatus,
session: Session,
*,
auth: Auth | None = None,
use_existing: bool | User = True,
client_config_cls: Type | None = None,
):
self.config = config
self.dummy = config.dummy
self.config_dummy = config_dummy
self.dummy = config_dummy.dummy

self.auth = auth if auth is not None else Auth.forPyTest(config)
self.session = session
Expand Down Expand Up @@ -1259,21 +1265,25 @@ def info_is_tainted(self, maximum_use_count: int | None = None) -> bool | None:

class DummyHandler:
dummy: DummyConfig
config: ConfigSimulatus
config: Config
config_dummy: ConfigSimulatus
sessionmaker: sqa_sessionmaker[Session]
auth: Auth
# user_uuids: List[str]

def __init__(
self,
sessionmaker: sqa_sessionmaker,
config: ConfigSimulatus,
config: Config,
config_dummy: ConfigSimulatus,
# user_uuids: List[str],
*,
auth: Auth | None = None,
):
self.dummy = config.dummy
self.config_dummy = config_dummy
self.dummy = self.config_dummy.dummy
self.config = config

self.sessionmaker = sessionmaker
self.auth = auth or Auth.forPyTest(config)
# self.user_uuids = user_uuids
Expand Down Expand Up @@ -1373,8 +1383,9 @@ def restore(
logger.info("Generating `%s` dummies.", n_generate)
for count in range(n_generate):
dd = DummyProvider(
self.config,
session,
config=self.config,
config_dummy=self.config_dummy,
session=session,
auth=self.auth,
use_existing=False,
)
Expand Down
60 changes: 44 additions & 16 deletions src/simulatus/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

# --------------------------------------------------------------------------- #
from captura import User
from captura.config import Config
from captura.fields import KindObject
from captura.models import Base, Document
from captura.schemas import TimespanLimitParams, UserExtraSchema, mwargs
Expand Down Expand Up @@ -85,21 +86,22 @@
class ContextDataDummy(BaseModel):
# NOTE: Global options for flags do not exist. Instead, create a manifest.
quiet: bool = True
config: ConfigSimulatus
config: Config
config_dummy: ConfigSimulatus
config_output: OutputConfig

def register_manifest(self, manifest_path: str | None) -> DummyConfig | None:
def register_manifest(self, manifest_path: str | None) -> ConfigSimulatus | None:
if manifest_path is None:
return None

manifest = DummyConfig.load(manifest_path)
self.config.dummy = manifest
manifest = ConfigSimulatus(dummy=DummyConfig.load(manifest_path))
self.config_dummy = manifest

return manifest

def preview_manifest(self):
data = HandlerData(
data=self.config.dummy.model_dump(),
data=self.config_dummy.model_dump(),
output_config=self.config_output,
)
data.print()
Expand All @@ -109,25 +111,39 @@ def dummy_handler(self) -> DummyHandler:
engine = self.config.engine()
sm = _sessionmaker(engine)

return DummyHandler(sm, self.config)
return DummyHandler(sm, self.config, self.config_dummy)

@classmethod
def for_typer(
cls,
context: typer.Context,
quiet: Annotated[bool, typer.Option("--quiet/--loud")] = True,
path_config: Annotated[Optional[str], typer.Option("--config")] = None,
path_config_dummy: Annotated[Optional[str], typer.Option("--config")] = None,
) -> None:
if path_config_dummy is None:
config_dummy = mwargs(ConfigSimulatus)
else:
with open(path_config_dummy, "r") as file:
config_dummy = ConfigSimulatus.model_validate(
yaml.safe_load(file),
)

if path_config is None:
config = mwargs(ConfigSimulatus)
config = mwargs(Config)
else:
with open(path_config, "r") as file:
config = ConfigSimulatus.model_validate(
config = Config.model_validate(
yaml.safe_load(file),
)

config_output = mwargs(OutputConfig, output=Output.yaml)
context.obj = cls(config=config, quiet=quiet, config_output=config_output)
context.obj = cls(
config=config,
config_dummy=config_dummy,
quiet=quiet,
config_output=config_output,
)


# --------------------------------------------------------------------------- #
Expand Down Expand Up @@ -302,8 +318,9 @@ def user(
raise typer.Exit(1)
else:
dummy_provider = DummyProvider(
context.dummy_handler.config,
session,
config=context.config,
config_dummy=context.dummy_handler.config_dummy,
session=session,
use_existing=False,
)
user = dummy_provider.user
Expand Down Expand Up @@ -354,7 +371,12 @@ def new(cls, _context: typer.Context, count: FlagCount = 1):
handler = context.dummy_handler
with handler.sessionmaker() as session:
for _ in range(count):
DummyProvider(handler.config, session, use_existing=False)
DummyProvider(
config=handler.config,
config_dummy=handler.config_dummy,
session=session,
use_existing=False,
)

@classmethod
def get(cls, _context: typer.Context, count: FlagCount = 1):
Expand All @@ -367,7 +389,12 @@ def get(cls, _context: typer.Context, count: FlagCount = 1):
q_existing = select(User).order_by(func.random()).limit(count)
existing = session.scalars(q_existing)
for ee in existing:
DummyProvider(handler.config, session, use_existing=ee)
DummyProvider(
config=handler.config,
config_dummy=handler.config_dummy,
session=session,
use_existing=ee,
)

@classmethod
def search(
Expand Down Expand Up @@ -408,8 +435,9 @@ def taint(
users = tuple(session.scalars(q))
for user in users:
DummyProvider(
context.config,
session,
config=context.config,
config_dummy=context.config_dummy,
session=session,
use_existing=user,
).info_mark_tainted()

Expand Down Expand Up @@ -460,7 +488,7 @@ def dispose(
CONSOLE.print("[red]Maximum uses too small to prune.")
raise typer.Exit()

context.config.dummy.users.maximum_uses = prune
context.config_dummy.dummy.users.maximum_uses = prune
if preview:
context.preview_manifest()
return
Expand Down
24 changes: 22 additions & 2 deletions src/simulatus/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@

import yaml
from pydantic import Field
from yaml_settings_pydantic import (
BaseYamlSettings,
YamlFileConfigDict,
YamlSettingsConfigDict,
)

# --------------------------------------------------------------------------- #
from captura import util
from captura.config import BaseHashable
from captura.config import Config as ConfigCaptura
from captura.schemas import mwargs


Expand Down Expand Up @@ -106,5 +111,20 @@ def load(cls, manifest_path: str) -> Self:
return cls.model_validate(raw)


class ConfigSimulatus(ConfigCaptura):
class ConfigSimulatus(BaseYamlSettings):
model_config = YamlSettingsConfigDict(
# NOTE: Yes, this field is labeled by the constant value computed at
# the initial runtime. This can be overwritten with environment
# changes (e.g. mocks in tests) where getting this value from the
# environment.
yaml_files={
util.PATH_CONFIG_DUMMY: YamlFileConfigDict(
envvar=util.prefix_env("DUMMY_CONFIG")
)
},
yaml_reload=False,
env_prefix=util.ENV_PREFIX,
env_nested_delimiter="__",
extra="allow",
)
dummy: DummyConfig
4 changes: 2 additions & 2 deletions src/simulatus/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ def q_content_data_count(cls, user: User | None = None):
q_assignment = select(func.count(Assignment.uuid))

if user is not None:
q_document = select(Grant.uuid_document).where(
_q_document = select(Grant.uuid_document).where(
Grant.pending_from == fields.PendingFrom.created,
Grant.uuid_user == user.uuid,
)
q_document = select(func.count()).select_from(q_document.subquery())
q_document = select(func.count()).select_from(_q_document.subquery())
q_collection = q_collection.join(User).where(User.uuid == user.uuid)
q_assignment = q_assignment.join(Collection).where(
Collection.uuid_user == user.uuid
Expand Down
Loading

0 comments on commit 47af15d

Please sign in to comment.