Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable VSCode Testing to scan tests successfully #435

Merged
merged 3 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ output/*/index.html
.testmondata
*.rdb

# VS Code
.vscode

# Sphinx
docs-sphinx/.doctrees

Expand Down
147 changes: 147 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Protean CLI",
"type": "debugpy",
"request": "launch",
"module": "protean",
"console": "integratedTerminal",
"justMyCode": false,
"args": [
"new",
"-o",
"/Users/subhashb/wspace/proteanhq/test-scaffolding",
"-d",
"author_name=Subhash Bhushan",
"-d",
"[email protected]",
]
},
{
"name": "Python: Debug Tests",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "Python: Pytest",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"justMyCode": false,
"args": [
"tests/test_aggregates.py::TestAggregateIdentity::test_that_abstract_aggregates_do_not_have_id_field",
]
},
{
"name": "Python: Sqlite - Specific test case",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"justMyCode": false,
"args": [
"tests/adapters/repository/sqlalchemy_repo/sqlite/test_provider.py::TestProviders::test_provider_raw",
"--sqlite"
]
},
{
"name": "Python: Postgres - Specific test case",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"justMyCode": false,
"args": [
"tests/adapters/model/sqlalchemy_model/postgresql/test_array_datatype.py::test_array_data_type_association",
"--postgresql"
]
},
{
"name": "Python: Redis - Specific test case",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": [
"tests/adapters/broker/redis_broker/tests.py::TestPublishingToRedis::test_event_message_structure",
"--redis"
]
},
{
"name": "Python: MessageDB - Specific test case",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": [
"tests/adapters/event_store/message_db_event_store/tests.py::TestMessageDBEventStore::test_error_on_message_db_initialization",
"--message_db"
]
},
{
"name": "Python: Elasticsearch Generic",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"justMyCode": false,
"args": [
"tests/adapters/repository/test_generic.py::TestConcurrency::test_expected_version_error_on_version_mismatch",
"--db=ELASTICSEARCH"
]
},
{
"name": "Python: Elasticsearch",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"justMyCode": false,
"args": [
"tests/adapters/model/elasticsearch_model/tests.py::TestModelOptions::TestModelSettings::test_settings_override_in_custom_model",
"--elasticsearch"
]
},
{
"name": "Python: All Postgresql",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": ["--postgresql"]
},
{
"name": "Generic Tests - Postgresql",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": [
"tests/adapters/repository/test_generic.py::TestPersistenceViaRepository::test_that_aggregate_can_be_persisted_with_repository",
"-m",
"database",
"--db=POSTGRESQL",
"-sv"
]
},
{
"name": "Generic Tests - Elasticsearch",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": [
"tests/adapters/repository/test_generic.py::TestPersistenceViaRepository::test_that_aggregate_can_be_persisted_with_repository",
"--db=elasticsearch",
"-sv"
]
}
]
}
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"python.testing.pytestArgs": [
"tests",
"--ignore=tests/support"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
3 changes: 0 additions & 3 deletions src/protean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from .core.value_object import BaseValueObject
from .core.view import BaseView
from .domain import Domain
from .globals import current_domain, current_uow
from .server import Engine
from .utils import get_version
from .utils.mixins import handle
Expand Down Expand Up @@ -47,8 +46,6 @@
"QuerySet",
"UnitOfWork",
"apply",
"current_domain",
"current_uow",
"get_version",
"handle",
"invariant",
Expand Down
27 changes: 12 additions & 15 deletions src/protean/adapters/repository/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from protean.exceptions import (
ConfigurationError,
ObjectNotFoundError,
OutOfContextError,
)
from protean.fields import (
Auto,
Expand Down Expand Up @@ -95,22 +94,20 @@

If `current_domain` is not yet available, it simply means that Protean is still being loaded.
Default to `Identity.STRING`

Raises:
OutOfContextError: If the method is called outside the context of a domain
"""
try:
if current_domain.config["identity_type"] == IdentityType.INTEGER.value:
return sa_types.Integer
elif current_domain.config["identity_type"] == IdentityType.STRING.value:
return sa_types.String
elif current_domain.config["identity_type"] == IdentityType.UUID.value:
return GUID
else:
raise ConfigurationError(
f'Unknown Identity Type {current_domain.config["identity_type"]}'
)
except OutOfContextError:
# This happens only when the module is being imported the first time.
# All further calls will have `current_domain` available.
if current_domain.config["identity_type"] == IdentityType.INTEGER.value:
return sa_types.Integer

Check warning on line 102 in src/protean/adapters/repository/sqlalchemy.py

View check run for this annotation

Codecov / codecov/patch

src/protean/adapters/repository/sqlalchemy.py#L102

Added line #L102 was not covered by tests
elif current_domain.config["identity_type"] == IdentityType.STRING.value:
return sa_types.String
elif current_domain.config["identity_type"] == IdentityType.UUID.value:
return GUID
else:
raise ConfigurationError(

Check warning on line 108 in src/protean/adapters/repository/sqlalchemy.py

View check run for this annotation

Codecov / codecov/patch

src/protean/adapters/repository/sqlalchemy.py#L108

Added line #L108 was not covered by tests
f'Unknown Identity Type {current_domain.config["identity_type"]}'
)


def _default(value):
Expand Down
4 changes: 2 additions & 2 deletions src/protean/core/event_sourced_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
NotSupportedError,
)
from protean.fields import Identifier
from protean.globals import current_domain, current_uow
from protean.globals import current_uow
from protean.utils import DomainObjects, derive_element_class

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -54,7 +54,7 @@ def get(self, identifier: Identifier) -> BaseEventSourcedAggregate:
if current_uow and identifier in current_uow._identity_map:
return current_uow._identity_map[identifier]

aggregate = current_domain.event_store.store.load_aggregate(
aggregate = self._domain.event_store.store.load_aggregate(
self.meta_.part_of, identifier
)

Expand Down
11 changes: 5 additions & 6 deletions src/protean/core/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from protean.container import Element, OptionsMixin
from protean.exceptions import IncorrectUsageError, NotSupportedError
from protean.fields import HasMany, HasOne
from protean.globals import current_domain
from protean.reflection import association_fields, has_association_fields
from protean.utils import (
Database,
Expand Down Expand Up @@ -147,23 +146,23 @@ def _sync_children(self, entity):
# If the item was changed directly AND added via `add`, then
# we give preference to the object in the cache
if item not in entity._temp_cache[field_name]["updated"]:
current_domain.repository_for(field.to_cls)._dao.save(item)
self._domain.repository_for(field.to_cls)._dao.save(item)

for _, item in entity._temp_cache[field_name]["removed"].items():
current_domain.repository_for(field.to_cls)._dao.delete(item)
self._domain.repository_for(field.to_cls)._dao.delete(item)
entity._temp_cache[field_name][
"removed"
] = {} # Empty contents of `removed` cache

for _, item in entity._temp_cache[field_name]["updated"].items():
current_domain.repository_for(field.to_cls)._dao.save(item)
self._domain.repository_for(field.to_cls)._dao.save(item)
entity._temp_cache[field_name][
"updated"
] = {} # Empty contents of `updated` cache

for _, item in entity._temp_cache[field_name]["added"].items():
item.state_.mark_new()
current_domain.repository_for(field.to_cls)._dao.save(item)
self._domain.repository_for(field.to_cls)._dao.save(item)
entity._temp_cache[field_name][
"added"
] = {} # Empty contents of `added` cache
Expand All @@ -173,7 +172,7 @@ def _sync_children(self, entity):
# These are ones whose attributes have been changed directly
# instead of being routed via `add`/`remove`
item = getattr(entity, field_name)
to_cls_repo = current_domain.repository_for(field.to_cls)
to_cls_repo = self._domain.repository_for(field.to_cls)
if item is not None and item.state_.is_changed:
to_cls_repo._dao.save(item)
# Or a new instance has been assigned
Expand Down
5 changes: 2 additions & 3 deletions src/protean/domain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from protean.domain.registry import _DomainRegistry
from protean.exceptions import ConfigurationError, IncorrectUsageError
from protean.fields import HasMany, HasOne, Reference, ValueObject
from protean.globals import current_domain
from protean.reflection import declared_fields, has_fields
from protean.utils import (
CommandProcessing,
Expand Down Expand Up @@ -815,9 +814,9 @@ def publish(self, event: BaseEvent) -> None:

self.brokers.publish(event)

if current_domain.config["event_processing"] == EventProcessing.SYNC.value:
if self.config["event_processing"] == EventProcessing.SYNC.value:
# Consume events right-away
handler_classes = current_domain.handlers_for(event)
handler_classes = self.handlers_for(event)
for handler_cls in handler_classes:
handler_methods = (
handler_cls._handlers[fqn(event.__class__)]
Expand Down
7 changes: 5 additions & 2 deletions src/protean/fields/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def __init__(
messages.update(error_messages or {})
self.error_messages = messages

def _generic_param_values_for_repr(self):
def _generic_param_values_for_repr(self) -> list[str]:
"""Return the generic parameter values for the Field's repr"""
values = []
if self.description:
Expand All @@ -117,7 +117,10 @@ def _generic_param_values_for_repr(self):
if callable(self.default):
values.append(f"default={self.default.__name__}")
else:
values.append(f"default='{self.default}'")
if isinstance(self.default, str):
values.append(f"default='{self.default}'")
else:
values.append(f"default={self.default}")
return values

def __repr__(self):
Expand Down
Loading
Loading