Skip to content

Fix issue where rule.references is discarded during modification#374

Merged
himynamesdave merged 2 commits intomainfrom
fix-reference-omission-in-modification
Apr 9, 2026
Merged

Fix issue where rule.references is discarded during modification#374
himynamesdave merged 2 commits intomainfrom
fix-reference-omission-in-modification

Conversation

@fqrious
Copy link
Copy Markdown
Contributor

@fqrious fqrious commented Apr 9, 2026

closes #372
closes #373

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
301 1 300 0
View the full list of 1 ❄️ flaky test(s)
../../../../../opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/schemathesis/generation/hypothesis/builder.py::test_imports[POST /api/v1/identities/]

Flake rate in main: 42.31% (Passed 30 times, Failed 22 times)

Stack Traces | 90.4s run time
self = <siemrules.siemrules.identities.IdentityView object at 0x7f74405ae3d0>
request = <rest_framework.request.Request: POST '.../api/v1/identities/'>
args = (), kwargs = {}
handler = <bound method CreateModelMixin.create of <siemrules.siemrules.identities.IdentityView object at 0x7f74405ae3d0>>
response = <JsonResponse status_code=400, "application/json">

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
>           response = handler(request, *args, **kwargs)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/views.py:512: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11....../site-packages/drf_spectacular/drainage.py:207: in wrapped_method
    return method(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/mixins.py:19: in create
    self.perform_create(serializer)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/mixins.py:24: in perform_create
    serializer.save()
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/serializers.py:210: in save
    self.instance = self.create(validated_data)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/serializers.py:991: in create
    instance = ModelClass._default_manager.create(**validated_data)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/query.py:665: in create
    obj.save(force_insert=True, using=self.db)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../dogesec_commons/identity/models.py:37: in save
    return super().save(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/base.py:902: in save
    self.save_base(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/base.py:1008: in save_base
    updated = self._save_table(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/base.py:1169: in _save_table
    results = self._do_insert(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/base.py:1210: in _do_insert
    return manager._insert(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/query.py:1873: in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1881: in execute_sql
    for sql, params in self.as_sql():
                       ^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1804: in as_sql
    value_rows = [
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1805: in <listcomp>
    [
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1806: in <listcomp>
    self.prepare_value(field, self.pre_save_val(field, obj))
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1741: in prepare_value
    return field.get_db_prep_save(value, connection=self.connection)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/fields/__init__.py:1012: in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/fields/__init__.py:1683: in get_db_prep_value
    value = self.get_prep_value(value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/fields/__init__.py:1661: in get_prep_value
    value = super().get_prep_value(value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/fields/__init__.py:1537: in get_prep_value
    return self.to_python(value)
           ^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.DateTimeField: created>
value = '488-12-12T00:00:00.000Z'

    def to_python(self, value):
        if value is None:
            return value
        if isinstance(value, datetime.datetime):
            return value
        if isinstance(value, datetime.date):
            value = datetime.datetime(value.year, value.month, value.day)
            if settings.USE_TZ:
                # For backwards compatibility, interpret naive datetimes in
                # local time. This won't work during DST change, but we can't
                # do much about it, so we let the exceptions percolate up the
                # call stack.
                try:
                    name = f"{self.model.__name__}.{self.name}"
                except AttributeError:
                    name = "(unbound)"
                warnings.warn(
                    f"DateTimeField {name} received a naive datetime ({value}) while "
                    "time zone support is active.",
                    RuntimeWarning,
                )
                default_timezone = timezone.get_default_timezone()
                value = timezone.make_aware(value, default_timezone)
            return value
    
        try:
            parsed = parse_datetime(value)
            if parsed is not None:
                return parsed
        except ValueError:
            raise exceptions.ValidationError(
                self.error_messages["invalid_datetime"],
                code="invalid_datetime",
                params={"value": value},
            )
    
        try:
            parsed = parse_date(value)
            if parsed is not None:
                return datetime.datetime(parsed.year, parsed.month, parsed.day)
        except ValueError:
            raise exceptions.ValidationError(
                self.error_messages["invalid_date"],
                code="invalid_date",
                params={"value": value},
            )
    
>       raise exceptions.ValidationError(
            self.error_messages["invalid"],
            code="invalid",
            params={"value": value},
        )
E       django.core.exceptions.ValidationError: ['“488-12-12T00:00:00.000Z” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.']

.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/fields/__init__.py:1643: ValidationError

The above exception was the direct cause of the following exception:

args = (), keywargs = {}

    @wraps(test_function)
>   def test_wrapper(*args: Any, **kwargs: Any) -> Any:
               ^^^^^^^^^^^^^^^^^^^^

.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../generation/hypothesis/builder.py:207: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11/unittest/mock.py:1378: in patched
    return func(*newargs, **newkeywargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/st/test_schemathesis.py:143: in test_imports
    case.call_and_validate(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../schemathesis/generation/case.py:211: in call
    response = transport_.send(
tests/utils.py:55: in send
    response: DRFResponse = client.generic(**serialized_request)
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../django/test/client.py:671: in generic
    return self.request(**r)
           ^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../django/test/client.py:1090: in request
    self.check_exception(response)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../django/test/client.py:805: in check_exception
    raise exc_value
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../core/handlers/exception.py:55: in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../core/handlers/base.py:197: in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../views/decorators/csrf.py:65: in _view_wrapper
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../site-packages/rest_framework/viewsets.py:125: in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/views.py:515: in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/views.py:475: in handle_exception
    self.raise_uncaught_exception(exc)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/views.py:486: in raise_uncaught_exception
    raise exc
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/views.py:512: in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11....../site-packages/drf_spectacular/drainage.py:207: in wrapped_method
    return method(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/mixins.py:18: in create
    serializer.is_valid(raise_exception=True)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/serializers.py:225: in is_valid
    self._validated_data = self.run_validation(self.initial_data)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/serializers.py:444: in run_validation
    value = self.to_internal_value(data)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../dogesec_commons/identity/serializers.py:29: in to_internal_value
    super().to_internal_value(data)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.............../site-packages/rest_framework/serializers.py:501: in to_internal_value
    validated_value = field.run_validation(primitive_value)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/fields.py:757: in run_validation
    return super().run_validation(data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/fields.py:539: in run_validation
    self.run_validators(value)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11........./site-packages/rest_framework/fields.py:551: in run_validators
    validator(value, self)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11....../site-packages/rest_framework/validators.py:86: in __call__
    if qs_exists(queryset):
       ^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11....../site-packages/rest_framework/validators.py:23: in qs_exists
    return queryset.exists()
           ^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/models/query.py:1298: in exists
    return self.query.has_results(using=self.db)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/query.py:676: in has_results
    return compiler.has_results()
           ^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1591: in has_results
    return bool(self.execute_sql(SINGLE))
                ^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../models/sql/compiler.py:1623: in execute_sql
    cursor.execute(sql, params)
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../db/backends/utils.py:99: in _execute
    self.db.validate_no_broken_transaction()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <DatabaseWrapper vendor='postgresql' alias='default'>

    def validate_no_broken_transaction(self):
        if self.needs_rollback:
>           raise TransactionManagementError(
                "An error occurred in the current transaction. You can't "
                "execute queries until the end of the 'atomic' block."
            ) from self.rollback_exc
E           django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
E           
E           Reproduce with: 
E           
E               curl -X POST -H 'Content-Type: application/json' -d '{"created": "2000-01-01T00:00:00Z", "id": "identity--00000000-0000-1000-8000-000000000000", "identity_class": "", "modified": "2000-01-01T00:00:00Z", "name": "0", "spec_version": "2.1", "type": "identity"}' http://localhost:8008.../api/v1/identities/

.../hostedtoolcache/Python/3.11.15............................................................................................................................................................................../x64/lib/python3.11.../backends/base/base.py:521: TransactionManagementError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@himynamesdave himynamesdave marked this pull request as ready for review April 9, 2026 13:01
@himynamesdave himynamesdave merged commit c50cd2c into main Apr 9, 2026
1 check failed
@himynamesdave himynamesdave deleted the fix-reference-omission-in-modification branch April 9, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add test for reference url rule modification discards reference urls

2 participants