Mirror of https://github.com/roostorg/osprey github.com/roostorg/osprey
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: all engine module tests (#22)

authored by

Caidan and committed by
GitHub
7c379c1d 5e9e5773

+398 -384
+3
.pre-commit-config.yaml
··· 8 8 rev: v5.0.0 9 9 hooks: 10 10 - id: trailing-whitespace 11 + exclude: .*/tests?/.*\.txt 11 12 - id: end-of-file-fixer 13 + exclude: .*/tests?/.*\.txt 12 14 - id: check-yaml 13 15 - id: check-case-conflict 14 16 - id: check-merge-conflict ··· 17 19 - id: check-toml 18 20 - id: mixed-line-ending 19 21 args: ["--fix=lf"] 22 + exclude: .*/tests?/.*\.txt 20 23 21 24 - repo: https://github.com/astral-sh/ruff-pre-commit 22 25 rev: v0.12.9
+1 -1
osprey_worker/src/osprey/engine/ast_validator/tests/test_validation_context/test_validation_transforms_osprey_py_ast_error.txt
··· 2 2 --> main.sml:1:0 3 3 | 4 4 1 | Foo(1) 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/tests/test_validation_context/test_validation_transforms_osprey_py_ast_error_2.txt
··· 3 3 | 4 4 2 | def foo(): 5 5 | ^ the Osprey rule language is a simplified subset of python 6 - | not all Python is valid osprey rule syntax 6 + | not all Python is valid osprey rule syntax
+1 -1
osprey_worker/src/osprey/engine/ast_validator/tests/test_validation_context/test_validation_transforms_osprey_py_ast_python_errors.txt
··· 2 2 --> main.sml:1:3 3 3 | 4 4 1 | foo( 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/tests/test_validation_context_warnings/test_validation_fails_if_warning_is_emitted_and_warning_as_error_is_true.txt
··· 2 2 --> main.sml:1:6 3 3 | 4 4 1 | Foo = 'jake is suspicious' 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/tests/test_validation_context_warnings/test_validation_succeeds_if_warning_is_emitted_and_warning_as_error_is_false.txt
··· 2 2 --> main.sml:1:6 3 3 | 4 4 1 | Foo = 'jake is suspicious' 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_imports_must_not_have_cycles/test_import_has_cycles.txt
··· 11 11 --> (2) foo.sml:2:14 12 12 | 13 13 2 | Import(rules=["bar.sml"]) 14 - | ^ 14 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_no_unused_locals/test_no_unused_locals.txt
··· 8 8 --> main.sml:3:0 9 9 | 10 10 3 | _Bar = 2 11 - | ^ this variable is not used anywhere, and thus has no effect. either delete or comment it out 11 + | ^ this variable is not used anywhere, and thus has no effect. either delete or comment it out
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_unique_stored_names/test_unique_stored_names_fails_disallows_duplicate_locals_in_same_file.txt
··· 7 7 --> (1) main.sml:3:0 8 8 | 9 9 3 | _Foo = 2 10 - | ^ 10 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_unique_stored_names/test_unique_stored_names_fails_with_dupe_names_in_different_file.txt
··· 7 7 --> (1) foo.sml:1:0 8 8 | 9 9 1 | Foo = 1 10 - | ^ 10 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_unique_stored_names/test_unique_stored_names_fails_with_dupe_names_in_same_file.txt
··· 11 11 --> (2) main.sml:4:0 12 12 | 13 13 4 | Foo = 3 14 - | ^ 14 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_allow_unexpected_respects_type[extra_arguments0].txt
··· 2 2 --> main.sml:1:60 3 3 | 4 4 1 | Ret = ValidatingUnexpectedArgsUdf(required='hi', unexpected=7) 5 - | ^ has type `int`, expected `str` 5 + | ^ has type `int`, expected `str`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_allow_unexpected_respects_type[extra_arguments1].txt
··· 2 2 --> main.sml:1:60 3 3 | 4 4 1 | Ret = ValidatingUnexpectedArgsUdf(required='hi', unexpected=None) 5 - | ^ has type `None`, expected `str` 5 + | ^ has type `None`, expected `str`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_allow_unexpected_respects_type[extra_arguments2].txt
··· 2 2 --> main.sml:1:60 3 3 | 4 4 1 | Ret = ValidatingUnexpectedArgsUdf(required='hi', unexpected=3.7) 5 - | ^ has type `float`, expected `str` 5 + | ^ has type `float`, expected `str`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_allow_unexpected_respects_type[extra_arguments3].txt
··· 2 2 --> main.sml:1:60 3 3 | 4 4 1 | Ret = ValidatingUnexpectedArgsUdf(required='hi', unexpected=['hello']) 5 - | ^ has type `List[str]`, expected `str` 5 + | ^ has type `List[str]`, expected `str`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_missing_keyword_argument.txt
··· 2 2 --> main.sml:1:11 3 3 | 4 4 1 | Foo: str = JsonData() 5 - | ^ the following keyword arguments were not provided: [`path`] 5 + | ^ the following keyword arguments were not provided: [`path`]
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_missing_kwarg.txt
··· 2 2 --> main.sml:1:11 3 3 | 4 4 1 | Foo: str = JsonData() 5 - | ^ the following keyword arguments were not provided: [`path`] 5 + | ^ the following keyword arguments were not provided: [`path`]
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_unknown_keyword_argument.txt
··· 8 8 --> main.sml:1:32 9 9 | 10 10 1 | Foo: str = JsonData(path=1, bad=1) 11 - | ^ valid keyword arguments are: [`coerce_type`, `path`, `required`] 11 + | ^ valid keyword arguments are: [`coerce_type`, `path`, `required`]
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_validate_call_kwargs_with_unary_ops_error.txt
··· 10 10 --> main.sml:2:30 11 11 | 12 12 2 | UserId: str = UDFWithUSub(foo=-'s') 13 - | ^ expected type `Number` 13 + | ^ expected type `Number`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_kwargs/test_validate_unknown_function.txt
··· 2 2 --> main.sml:1:6 3 3 | 4 4 1 | Foo = Bar() 5 - | ^ called here 5 + | ^ called here
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_rvalue/test_has_result_and_result_unused.txt
··· 5 5 | ^ this must must not be used as a statement within the source root, e.g.: 6 6 | - `Foo = HasResult(...)` is OK 7 7 | - `SomeOtherFunction(argument=HasResult(...))` is OK 8 - | - `HasResult(...)` is not OK 8 + | - `HasResult(...)` is not OK
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_rvalue/test_not_has_result_and_result_used_as_function_argument.txt
··· 4 4 1 | Qux = HasNoResult() 5 5 | ^ this cannot appear to the right of a `=`, e.g.: 6 6 | - `HasNoResult(...)` is OK 7 - | - `Qux = HasNoResult(...)` is not OK 7 + | - `Qux = HasNoResult(...)` is not OK
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_call_rvalue/test_not_has_result_and_result_used_in_list_literal.txt
··· 5 5 | ^ this function has no result, and thus its result cannot be used: 6 6 | - `HasNoResult(...)` is OK, however: 7 7 | - `Foo = Bar + HasNoResult(...)` and 8 - | - `Bar(qux=HasNoResult(...))` are not OK 8 + | - `Bar(qux=HasNoResult(...))` are not OK
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_dynamic_fn_must_be_assigned.txt
··· 4 4 1 | Foo = Entity(type='User', id=JsonData(path='$.foo')) 5 5 | ^ assign it to a variable before using it: 6 6 | `SomeVariable: str = JsonData(path='$.foo')` 7 - | `Foo = Entity(type='User', id=SomeVariable)` 7 + | `Foo = Entity(type='User', id=SomeVariable)`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_generic_fn_must_be_assigned.txt
··· 4 4 1 | Foo = [EntityJson(type='User', path='$.foo')] 5 5 | ^ assign it to a variable before using it: 6 6 | `SomeVariable: Entity[str] = EntityJson(type='User', path='$.foo')` 7 - | `Foo = [SomeVariable]` 7 + | `Foo = [SomeVariable]`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_generic_fn_must_have_compatible_type.txt
··· 2 2 --> main.sml:1:3 3 3 | 4 4 1 | A: str = EntityJson(type='User', path='$.foo') 5 - | ^ annotation is incompatible with `EntityJson` return type `Entity[~_T]` 5 + | ^ annotation is incompatible with `EntityJson` return type `Entity[~_T]`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[List[str, int, float]].txt
··· 7 7 --> (1) main.sml:1:20 8 8 | 9 9 1 | Foo: List[str, int, float] = JsonData(path='$.foo') 10 - | ^ 10 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[List[str, str]].txt
··· 2 2 --> main.sml:1:15 3 3 | 4 4 1 | Foo: List[str, str] = JsonData(path='$.foo') 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[List[wut]].txt
··· 2 2 --> main.sml:1:10 3 3 | 4 4 1 | Foo: List[wut] = JsonData(path='$.foo') 5 - | ^ got unknown non-generic type `wut` 5 + | ^ got unknown non-generic type `wut`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[List].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: List = JsonData(path='$.foo') 5 - | ^ `List` is generic, try `List[T]` where `T` is a type like `str` or `int` 5 + | ^ `List` is generic, try `List[T]` where `T` is a type like `str` or `int`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Optional[str, int, float]].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: Optional[str, int, float] = JsonData(path='$.foo') 5 - | ^ got 3 arguments 5 + | ^ got 3 arguments
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Optional[str, str]].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: Optional[str, str] = JsonData(path='$.foo') 5 - | ^ got 2 arguments 5 + | ^ got 2 arguments
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Optional[wut]].txt
··· 2 2 --> main.sml:1:14 3 3 | 4 4 1 | Foo: Optional[wut] = JsonData(path='$.foo') 5 - | ^ got unknown non-generic type `wut` 5 + | ^ got unknown non-generic type `wut`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Optional].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: Optional = JsonData(path='$.foo') 5 - | ^ `Optional` is generic, try `Optional[T]` where `T` is a type like `str` or `int` 5 + | ^ `Optional` is generic, try `Optional[T]` where `T` is a type like `str` or `int`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Union[str, str]].txt
··· 7 7 --> (1) main.sml:1:11 8 8 | 9 9 1 | Foo: Union[str, str] = JsonData(path='$.foo') 10 - | ^ 10 + | ^
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Union[str, wut]].txt
··· 2 2 --> main.sml:1:16 3 3 | 4 4 1 | Foo: Union[str, wut] = JsonData(path='$.foo') 5 - | ^ got unknown non-generic type `wut` 5 + | ^ got unknown non-generic type `wut`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[Union].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: Union = JsonData(path='$.foo') 5 - | ^ `Union` is generic, try `Union[T]` where `T` is a type like `str` or `int` 5 + | ^ `Union` is generic, try `Union[T]` where `T` is a type like `str` or `int`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_invalid_annotation[wut].txt
··· 2 2 --> main.sml:1:5 3 3 | 4 4 1 | Foo: wut = JsonData(path='$.foo') 5 - | ^ got unknown non-generic type `wut` 5 + | ^ got unknown non-generic type `wut`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_missing_annotation.txt
··· 2 2 --> main.sml:1:0 3 3 | 4 4 1 | Foo = JsonData(path='$.foo') 5 - | ^ add a type annotation, like: `Foo: str = JsonData(...)` 5 + | ^ add a type annotation, like: `Foo: str = JsonData(...)`
+1 -1
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_dynamic_calls_have_annotated_rvalue/test_missing_annotation_and_argument.txt
··· 2 2 --> main.sml:1:6 3 3 | 4 4 1 | Foo = JsonData() 5 - | ^ the following keyword arguments were not provided: [`path`] 5 + | ^ the following keyword arguments were not provided: [`path`]
+6 -4
osprey_worker/src/osprey/engine/ast_validator/validators/tests/test_validate_experiments.py
··· 28 28 experiment = f""" 29 29 E1 = Entity(type='MyEntity', id='entity 1') 30 30 A = Experiment( 31 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[2.5, 2.5], version=1, 32 - revision=1, local_bucketing=True 31 + entity=E1, 32 + buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[2.5, 2.5], 33 + version=1, revision=1 33 34 ) 34 35 """ 35 36 data = execute_with_result(experiment) ··· 40 41 experiment = f""" 41 42 E1 = Entity(type='MyEntity', id='entity 1') 42 43 A = Experiment( 43 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[2.5, 2.5], version=1, 44 - revision=1, local_bucketing=True 44 + entity=E1, 45 + buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[2.5, 2.5], 46 + version=1, revision=1 45 47 ) 46 48 """ 47 49 data = execute_with_result(experiment)
+1 -1
osprey_worker/src/osprey/engine/config/tests/test_config/test_config_registry_validator_has_full_path_in_separate_messages.txt
··· 8 8 --> config.yaml:4:15 9 9 | 10 10 4 | int_field: hello 11 - | ^ value is not a valid integer (type=type_error.integer) 11 + | ^ value is not a valid integer (type=type_error.integer)
+1 -1
osprey_worker/src/osprey/engine/config/tests/test_config/test_config_rejects_extra_keys.txt
··· 8 8 --> config.yaml:4:0 9 9 | 10 10 4 | unknown_top_level_key: "hello" 11 - | ^ make sure there is a config model registered for the `unknown_top_level_key` key 11 + | ^ make sure there is a config model registered for the `unknown_top_level_key` key
+46 -3
osprey_worker/src/osprey/engine/conftest.py
··· 5 5 from contextlib import contextmanager 6 6 from datetime import datetime 7 7 from textwrap import dedent 8 - from typing import TYPE_CHECKING, Callable, ContextManager, Dict, Iterator, Optional, Set, Type, TypeVar, Union 8 + from typing import ( 9 + TYPE_CHECKING, 10 + Any, 11 + Callable, 12 + ContextManager, 13 + Dict, 14 + Generator, 15 + Iterator, 16 + Optional, 17 + Set, 18 + Type, 19 + TypeVar, 20 + Union, 21 + ) 9 22 10 23 import gevent.pool 11 24 import pytest ··· 21 34 from osprey.engine.executor.udf_execution_helpers import UDFHelpers 22 35 from osprey.engine.stdlib import get_config_registry 23 36 from osprey.engine.udf.registry import UDFRegistry 37 + from osprey.worker.lib.singletons import CONFIG 24 38 from typing_extensions import Protocol 25 39 26 40 if TYPE_CHECKING: 27 41 from _pytest.config import Config 42 + from _pytest.config.argparsing import Parser 28 43 from _pytest.fixtures import FixtureRequest 29 44 45 + 46 + @pytest.fixture(autouse=True) # autouse = True means automatically use for each test 47 + def config_setup() -> Generator[Any, None, None]: 48 + CONFIG.instance().configure_from_env() 49 + # yield is used here to basically split this function into two parts: 50 + # all code before `yield` is the setup code (run before each test), and 51 + # all code after `yield` is the teardown code (run after each test) 52 + yield # this line is where the testing happens 53 + # teardown code 54 + CONFIG.instance().unconfigure_for_tests() 55 + 56 + 30 57 SourcesDict = Union[Sources, str, Dict[str, str]] 31 58 CheckOutputFunction = Callable[[str], bool] 32 59 ··· 98 125 raise Exception('Cannot call check_output more than once per test run.') 99 126 100 127 did_call = True 101 - if request.config.option.write_outputs: 128 + if getattr(request.config.option, 'write_outputs', False): 102 129 put_file_contents(output) 103 130 return True 104 131 else: ··· 108 135 f'\n\tExpected test output: {get_output_file()}' 109 136 ) 110 137 except AssertionError as e: 111 - if request.config.option.write_first_failed_output: 138 + if getattr(request.config.option, 'write_first_failed_output', False): 112 139 request.config.option.write_first_failed_output = False 113 140 put_file_contents(output) 114 141 raise AssertionError( ··· 266 293 action_time: Optional[datetime] = None, 267 294 ) -> ExecutionResult: 268 295 sources = into_sources(sources_dict) 296 + 297 + # Ensure standard AST validators are registered before validation/execution 298 + try: 299 + from osprey.worker.adaptor.plugin_manager import bootstrap_ast_validators 300 + 301 + bootstrap_ast_validators() 302 + except Exception: 303 + # If plugin bootstrap is unavailable in this context, continue; tests using run_validation will supply validators 304 + pass 305 + 269 306 config_validator = get_config_registry().get_validator() 270 307 validator_registry = ValidatorRegistry.get_instance().instance_with_additional_validators(config_validator) 271 308 try: ··· 368 405 assert check_output(e.value.rendered()) 369 406 370 407 return check_failure 408 + 409 + 410 + def pytest_addoption(parser: 'Parser') -> None: 411 + parser.addoption( 412 + '--write-outputs', action='store_true', help='write checked validator outputs instead of checking them' 413 + ) 371 414 372 415 373 416 def pytest_configure(config: 'Config') -> None:
+1 -1
osprey_worker/src/osprey/engine/executor/tests/test_literals/test_export_fails_on_non_literal.txt
··· 2 2 --> main.sml:4:27 3 3 | 4 4 4 | Foo: ExtractLiteral[int] = IntA + IntB 5 - | ^ `ExtractLiteral` assignment expects an rvalue of type `Union[Literal, FormatString]` 5 + | ^ `ExtractLiteral` assignment expects an rvalue of type `Union[Literal, FormatString]`
+13 -2
osprey_worker/src/osprey/engine/executor/tests/test_udf_execution_helpers.py
··· 29 29 def execute(self, execution_context: ExecutionContext, arguments: Arguments) -> int: 30 30 return self.accessor_get(execution_context, arguments) 31 31 32 + @classmethod 33 + def create_provider(cls) -> CountingService: 34 + return CountingService() 35 + 32 36 33 37 class CountingCallsUDF2(HasHelper[CountingService], UDFBase[Arguments, int]): 34 38 def execute(self, execution_context: ExecutionContext, arguments: Arguments) -> int: 35 39 return self.accessor_get(execution_context, arguments) 40 + 41 + @classmethod 42 + def create_provider(cls) -> CountingService: 43 + return CountingService() 36 44 37 45 38 46 @pytest.fixture ··· 41 49 42 50 43 51 def test_helper_reuses_service_with_complex_key(execute: ExecuteFunction) -> None: 44 - helper = CountingService() 45 - helpers = UDFHelpers().set_udf_helper(CountingCallsUDF1, helper).set_udf_helper(CountingCallsUDF2, helper) 52 + helpers = ( 53 + UDFHelpers() 54 + .set_udf_helper(CountingCallsUDF1, CountingCallsUDF1.create_provider()) 55 + .set_udf_helper(CountingCallsUDF2, CountingCallsUDF2.create_provider()) 56 + ) 46 57 data = execute( 47 58 """ 48 59 _MessageContent = 'this is weird'
+19
osprey_worker/src/osprey/engine/query_language/tests/conftest.py
··· 2 2 3 3 import pytest 4 4 from osprey.engine.ast_validator.validation_context import ValidatedSources 5 + from osprey.engine.ast_validator.validators.imports_must_not_have_cycles import ImportsMustNotHaveCycles 6 + from osprey.engine.ast_validator.validators.unique_stored_names import UniqueStoredNames 7 + from osprey.engine.ast_validator.validators.validate_call_kwargs import ValidateCallKwargs 8 + from osprey.engine.ast_validator.validators.validate_dynamic_calls_have_annotated_rvalue import ( 9 + ValidateDynamicCallsHaveAnnotatedRValue, 10 + ) 11 + from osprey.engine.ast_validator.validators.validate_static_types import ValidateStaticTypes 12 + from osprey.engine.ast_validator.validators.variables_must_be_defined import VariablesMustBeDefined 5 13 from osprey.engine.conftest import RunValidationFunction 14 + from osprey.engine.query_language.ast_validator import REGISTRY 6 15 from typing_extensions import Protocol 7 16 8 17 ··· 24 33 return run_validation('\n'.join(source_lines)) 25 34 26 35 return _make_rules_sources 36 + 37 + 38 + @pytest.fixture(autouse=True) 39 + def register_ast_validators(): 40 + REGISTRY.register(UniqueStoredNames) 41 + REGISTRY.register(ValidateCallKwargs) 42 + REGISTRY.register(ValidateStaticTypes) 43 + REGISTRY.register(VariablesMustBeDefined) 44 + REGISTRY.register(ImportsMustNotHaveCycles) 45 + REGISTRY.register(ValidateDynamicCallsHaveAnnotatedRValue)
+21 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator.py
··· 1 1 import json 2 2 3 3 import pytest 4 + from osprey.engine.ast_validator.validators.imports_must_not_have_cycles import ImportsMustNotHaveCycles 5 + from osprey.engine.ast_validator.validators.unique_stored_names import UniqueStoredNames 6 + from osprey.engine.ast_validator.validators.validate_call_kwargs import ValidateCallKwargs 7 + from osprey.engine.ast_validator.validators.validate_dynamic_calls_have_annotated_rvalue import ( 8 + ValidateDynamicCallsHaveAnnotatedRValue, 9 + ) 10 + from osprey.engine.ast_validator.validators.validate_static_types import ValidateStaticTypes 11 + from osprey.engine.ast_validator.validators.variables_must_be_defined import VariablesMustBeDefined 4 12 from osprey.engine.conftest import CheckJsonOutputFunction, RunValidationFunction 5 13 from osprey.engine.query_language import parse_query_to_validated_ast 6 14 from osprey.engine.query_language.ast_druid_translator import DruidQueryTransformer 7 15 from osprey.engine.query_language.tests.conftest import MakeRulesSourcesFunction 8 16 9 17 # The validators that the rules source validation should use, *not* the query source validation. 10 - pytestmark = pytest.mark.use_standard_rules_validators() 18 + pytestmark = [ 19 + pytest.mark.use_standard_rules_validators(), 20 + pytest.mark.use_validators( 21 + [ 22 + UniqueStoredNames, 23 + ValidateStaticTypes, 24 + ValidateCallKwargs, 25 + ImportsMustNotHaveCycles, 26 + ValidateDynamicCallsHaveAnnotatedRValue, 27 + VariablesMustBeDefined, 28 + ] 29 + ), 30 + ] 11 31 12 32 13 33 def test_parses_simple_query(
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_negation.txt
··· 59 59 ], 60 60 "type": "and" 61 61 } 62 - } 62 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_null_value.txt
··· 16 16 ], 17 17 "type": "and" 18 18 } 19 - } 19 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_singular_negation.txt
··· 10 10 }, 11 11 "type": "not" 12 12 } 13 - } 13 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[-10.0 [gt] A].txt
··· 19 19 ], 20 20 "type": "and" 21 21 } 22 - } 22 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[A != B].txt
··· 9 9 }, 10 10 "type": "not" 11 11 } 12 - } 12 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[A == -1].txt
··· 4 4 "type": "selector", 5 5 "value": -1 6 6 } 7 - } 7 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[not A == -1].txt
··· 7 7 }, 8 8 "type": "not" 9 9 } 10 - } 10 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[not A == 1].txt
··· 7 7 }, 8 8 "type": "not" 9 9 } 10 - } 10 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_query_with_unary_operator[not A == B or (C == D and F [gt]= 2)].txt
··· 45 45 ], 46 46 "type": "or" 47 47 } 48 - } 48 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_simple_query.txt
··· 42 42 ], 43 43 "type": "or" 44 44 } 45 - } 45 + }
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_ast_druid_translator/test_parses_string_in_query_as_search.txt
··· 7 7 }, 8 8 "type": "search" 9 9 } 10 - } 10 + }
+19
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast.py
··· 1 1 from typing import Any, Callable, List 2 2 3 3 import pytest 4 + from osprey.engine.ast_validator.validators.imports_must_not_have_cycles import ImportsMustNotHaveCycles 5 + from osprey.engine.ast_validator.validators.unique_stored_names import UniqueStoredNames 6 + from osprey.engine.ast_validator.validators.validate_call_kwargs import ValidateCallKwargs 7 + from osprey.engine.ast_validator.validators.validate_dynamic_calls_have_annotated_rvalue import ( 8 + ValidateDynamicCallsHaveAnnotatedRValue, 9 + ) 10 + from osprey.engine.ast_validator.validators.validate_static_types import ValidateStaticTypes 11 + from osprey.engine.ast_validator.validators.variables_must_be_defined import VariablesMustBeDefined 4 12 from osprey.engine.conftest import CheckFailureFunction, RunValidationFunction 5 13 from osprey.engine.query_language import parse_query_to_validated_ast 6 14 from osprey.engine.query_language.tests.conftest import MakeRulesSourcesFunction 7 15 8 16 # The validators and UDFs that the rules source validation should use, *not* the query source validation. 17 + # We need to include the specific validators that parse_query_to_validated_ast expects. 9 18 pytestmark: List[Callable[[Any], Any]] = [ 10 19 pytest.mark.use_standard_rules_validators(), 20 + pytest.mark.use_validators( 21 + [ 22 + UniqueStoredNames, 23 + ValidateStaticTypes, 24 + ValidateCallKwargs, 25 + ImportsMustNotHaveCycles, 26 + ValidateDynamicCallsHaveAnnotatedRValue, 27 + VariablesMustBeDefined, 28 + ] 29 + ), 11 30 pytest.mark.use_osprey_stdlib(), 12 31 ] 13 32
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_binary_comparison_must_contain_identifier['thing1' == 'thing2'].txt
··· 10 10 --> (2) main.sml:1:20 11 11 | 12 12 1 | Query = "thing1" == "thing2" 13 - | ^ this is a literal value 13 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_binary_comparison_must_contain_identifier[1 == 2].txt
··· 10 10 --> (2) main.sml:1:13 11 11 | 12 12 1 | Query = 1 == 2 13 - | ^ this is a literal value 13 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_binary_comparison_must_contain_identifier[True == False].txt
··· 10 10 --> (2) main.sml:1:16 11 11 | 12 12 1 | Query = True == False 13 - | ^ this is a literal value 13 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_binary_comparison_must_contain_identifier[True and False and True].txt
··· 14 14 --> (3) main.sml:1:27 15 15 | 16 16 1 | Query = True and False and True 17 - | ^ this is a literal value 17 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_binary_comparison_must_contain_identifier[True and True].txt
··· 10 10 --> (2) main.sml:1:17 11 11 | 12 12 1 | Query = True and True 13 - | ^ this is a literal value 13 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_disallows_nodes_not_explicitly_allowed.txt
··· 2 2 --> main.sml:1:13 3 3 | 4 4 1 | Query = A == f'{B}' 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_disallows_unknown_call_nodes.txt
··· 2 2 --> main.sml:1:8 3 3 | 4 4 1 | Query = Foo() 5 - | ^ called here 5 + | ^ called here
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_only_one_statement.txt
··· 8 8 --> main.sml:1:45 9 9 | 10 10 1 | Query = A == B or (C == D and F >= 2); Foo = Bar 11 - | ^ `Bar` does not exist in any rule files. typo, perhaps? 11 + | ^ `Bar` does not exist in any rule files. typo, perhaps?
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_query_contains_more_than_literal_or_name.txt
··· 2 2 --> main.sml:1:8 3 3 | 4 4 1 | Query = 1 5 - | ^ you have provided a `Number`, try something like `ActionName != True` 5 + | ^ you have provided a `Number`, try something like `ActionName != True`
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_static_types_are_converted_post_execution.txt
··· 18 18 --> (4) main.sml:3:0 19 19 | 20 20 3 | Bar = Entity(type="User", id=123) 21 - | ^ variable `Bar` with incompatible type `int` originally defined here 21 + | ^ variable `Bar` with incompatible type `int` originally defined here
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_unary_operator_query_validation_failure[UserName == 1 and not 2].txt
··· 16 16 --> (1) main.sml:1:30 17 17 | 18 18 1 | Query = UserName == 1 and not 2 19 - | ^ this is a literal value 19 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_unary_operator_query_validation_failure[not 1].txt
··· 16 16 --> (1) main.sml:1:12 17 17 | 18 18 1 | Query = not 1 19 - | ^ this is a literal value 19 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_unary_operator_query_validation_failure[not False].txt
··· 6 6 --> (1) main.sml:1:12 7 7 | 8 8 1 | Query = not False 9 - | ^ this is a literal value 9 + | ^ this is a literal value
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_validates_names_suggests_valid_name.txt
··· 2 2 --> main.sml:1:8 3 3 | 4 4 1 | Query = UserNaem == 'jake' 5 - | ^ unknown name `UserNaem`, did you mean `UserName`? 5 + | ^ unknown name `UserNaem`, did you mean `UserName`?
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_validates_names_with_wildly_invalid_name.txt
··· 2 2 --> main.sml:1:8 3 3 | 4 4 1 | Query = KLJHaflLasfkL == 'jake' 5 - | ^ `KLJHaflLasfkL` does not exist in any rule files. typo, perhaps? 5 + | ^ `KLJHaflLasfkL` does not exist in any rule files. typo, perhaps?
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_parse_query_to_validated_ast/test_validates_static_types.txt
··· 55 55 --> main.sml:1:29 56 56 | 57 57 1 | Query = (Foo > Bar) in (1 or 2) 58 - | ^ has type `int`, expected `bool` 58 + | ^ has type `int`, expected `bool`
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_regex_match/test_regex_match_fails_with_invalid_item_node.txt
··· 2 2 --> main.sml:1:16 3 3 | 4 4 1 | RegexMatch(item='Jake', regex='^foo$') 5 - | ^ argument `item` must be a variable 5 + | ^ argument `item` must be a variable
+1 -1
osprey_worker/src/osprey/engine/query_language/tests/test_regex_match/test_regex_match_fails_with_invalid_regex.txt
··· 2 2 --> main.sml:1:25 3 3 | 4 4 1 | RegexMatch(item=A, regex='[') 5 - | ^ error: unterminated character set at position 0 5 + | ^ error: unterminated character set at position 0
+6 -6
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_email_domain.py
··· 52 52 ({'email': 'a'}, None), 53 53 ({'email': 'b@'}, None), 54 54 ({'email': 'b@test@example.org'}, 'example.org'), 55 - ({'email': 'd@eXaMpLe.gov'}, 'example.gov'), 55 + ({'email': 'd@test.eXaMpLe.gov'}, 'example.gov'), 56 56 ({'email': 'e@me.example.co.uk'}, 'example.co.uk'), 57 57 ({'email': '@example'}, 'example'), 58 58 ({'email': 'blah@test.notarealtld'}, 'test.notarealtld'), ··· 71 71 [ 72 72 ({'email': 'a'}, None), 73 73 ({'email': 'b@'}, None), 74 - ({'email': 'b@test@example.org'}, 'example.org'), 75 - ({'email': 'd@eXaMpLe.gov'}, 'example.gov'), 76 - ({'email': 'e@me.example.co.uk'}, 'example.co.uk'), 77 - ({'email': '@example'}, 'example'), 78 - ({'email': 'blah@test.notarealtld'}, 'test.notarealtld'), 74 + ({'email': 'b@test@wow.example.org'}, 'wow.example.org'), 75 + ({'email': 'd@wow.eXaMpLe.gov'}, 'wow.example.gov'), 76 + ({'email': 'e@me.example.co.uk'}, 'me.example.co.uk'), 77 + ({'email': '@user.example'}, 'user.example'), 78 + ({'email': 'blah@beep.test.notarealtld'}, 'beep.test.notarealtld'), 79 79 ], 80 80 ) 81 81 def test_invalid_email_subdomain_addresses(
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_entity/test_entity_json_requires_valid_type_and_path_literals.txt
··· 8 8 --> main.sml:7:37 9 9 | 10 10 7 | EntityJson(type='ExampleType2', path="invalid path") 11 - | ^ error: Parse error at 1:8 near token path (ID) 11 + | ^ error: Parse error at 1:8 near token path (ID)
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_entity/test_entity_literal_only_one_level_deep_name_resolution.txt
··· 8 8 --> main.sml:5:8 9 9 | 10 10 5 | Type2 = Type 11 - | ^ expected type `String` 11 + | ^ expected type `String`
+49 -128
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments.py
··· 7 7 from osprey.engine.conftest import CheckFailureFunction, ExecuteFunction, RunValidationFunction 8 8 from osprey.engine.language_types.experiments import NOT_IN_EXPERIMENT_BUCKET, NOT_IN_EXPERIMENT_BUCKET_INDEX 9 9 from osprey.engine.stdlib.udfs.entity import Entity 10 - from osprey.engine.stdlib.udfs.experiments import ( 11 - CONTROL_BUCKET, 12 - EXPERIMENT_GRANULARITY, 13 - Experiment, 14 - # ExperimentsProvider, # TODO: figure out why this class no longer exists... 15 - ExperimentWhen, 16 - ) 10 + from osprey.engine.stdlib.udfs.experiments import CONTROL_BUCKET, EXPERIMENT_GRANULARITY, Experiment, ExperimentWhen 17 11 from osprey.engine.stdlib.udfs.rules import Rule 18 12 from osprey.engine.udf.registry import UDFRegistry 19 13 ··· 47 41 def test_experiment_bucketing(execute: ExecuteFunction) -> None: 48 42 experiment = f""" 49 43 E1 = Entity(type='MyEntity', id='entity 1') 50 - A = Experiment( 51 - entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, 52 - revision=1, local_bucketing=True 53 - ) 44 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, revision=1) 54 45 """ 55 46 data = execute(experiment) 56 47 assert data['A'] == [ ··· 61 52 str(0), 62 53 str(1), 63 54 str(1), 64 - str(True), 65 55 ] 66 56 67 57 68 - # TODO: related to ExperimentsProvider import issue above, re-enable when that is resolved 58 + def test_experiment_bucketing_nonlocal_with_missing_type(execute: ExecuteFunction) -> None: 59 + experiment = f""" 60 + E1 = Entity(type='MyEntity', id='entity 1') 61 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, revision=1) 62 + """ 63 + data = execute(experiment) 64 + assert data['A'] == [ 65 + 'A', 66 + 'entity 1', 67 + 'MyEntity', 68 + CONTROL_BUCKET, 69 + str(0), 70 + str(1), 71 + str(1), 72 + ] 73 + 69 74 70 - # @mock.patch.object(ExperimentsProvider, 'get_bucket_assignment_request') 71 - # def test_experiment_bucketing_nonlocal_with_missing_type( 72 - # get_bucket_assignment_request_mock: mock.MagicMock, execute: ExecuteFunction 73 - # ) -> None: 74 - # get_bucket_assignment_request_mock.return_value = '0' 75 - # experiment = f""" 76 - # E1 = Entity(type='MyEntity', id='entity 1') 77 - # A = Experiment( 78 - # entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, 79 - # revision=1, local_bucketing=False 80 - # ) 81 - # """ 82 - # data = execute(experiment, udf_helpers=UDFHelpers().set_udf_helper(Experiment, ExperimentsProvider())) 83 - # assert data['A'] == [ 84 - # 'A', 85 - # 'entity 1', 86 - # 'MyEntity', 87 - # CONTROL_BUCKET, 88 - # str(0), 89 - # str(1), 90 - # str(1), 91 - # str(False), 92 - # ] 93 - # 94 - # 95 - # @mock.patch.object(ExperimentsProvider, 'get_bucket_assignment_request') 96 - # def test_experiment_bucketing_nonlocal_type_user( 97 - # get_bucket_assignment_request_mock: mock.MagicMock, execute: ExecuteFunction 98 - # ) -> None: 99 - # get_bucket_assignment_request_mock.return_value = '0' 100 - # experiment = f""" 101 - # E1 = Entity(type='user', id='entity 1') 102 - # A = Experiment( 103 - # entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, 104 - # revision=1, local_bucketing=False 105 - # ) 106 - # """ 107 - # data = execute(experiment, udf_helpers=UDFHelpers().set_udf_helper(Experiment, ExperimentsProvider())) 108 - # assert data['A'] == [ 109 - # 'A', 110 - # 'entity 1', 111 - # 'user', 112 - # CONTROL_BUCKET, 113 - # str(0), 114 - # str(1), 115 - # str(1), 116 - # str(False), 117 - # ] 75 + def test_experiment_bucketing_nonlocal_type_user(execute: ExecuteFunction) -> None: 76 + experiment = f""" 77 + E1 = Entity(type='user', id='entity 1') 78 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=1, revision=1) 79 + """ 80 + data = execute(experiment) 81 + assert data['A'] == [ 82 + 'A', 83 + 'entity 1', 84 + 'user', 85 + CONTROL_BUCKET, 86 + str(0), 87 + str(1), 88 + str(1), 89 + ] 118 90 119 91 120 92 def test_consistent_bucketing_with_rollout(execute: ExecuteFunction) -> None: 121 93 experiment = f""" 122 94 E1 = Entity(type='MyEntity', id='1089') 123 - A = Experiment( 124 - entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[1.0, 1.0], version=1, 125 - revision=1, local_bucketing=True 126 - ) 95 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[1.0, 1.0], version=1, revision=1) 127 96 """ 128 97 data = execute(experiment) 129 98 assert data['A'] == [ ··· 134 103 str(0), 135 104 str(1), 136 105 str(1), 137 - str(True), 138 106 ] 139 107 140 108 experiment = f""" 141 109 E1 = Entity(type='MyEntity', id='1089') 142 - A = Experiment( 143 - entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[2.0, 2.0], version=2, 144 - revision=1, local_bucketing=True 145 - ) 110 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[2.0, 2.0], version=2, revision=1) 146 111 """ 147 112 data = execute(experiment) 148 113 assert data['A'] == [ ··· 153 118 str(0), 154 119 str(2), 155 120 str(1), 156 - str(True), 157 121 ] 158 122 159 123 experiment = f""" 160 124 E1 = Entity(type='MyEntity', id='1089') 161 - A = Experiment( 162 - entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=3, 163 - revision=1, local_bucketing=True 164 - ) 125 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'treatment'], bucket_sizes=[50.0, 50.0], version=3, revision=1) 165 126 """ 166 127 data = execute(experiment) 167 128 assert data['A'] == [ ··· 172 133 str(0), 173 134 str(3), 174 135 str(1), 175 - str(True), 176 136 ] 177 137 178 138 ··· 194 154 run_validation( 195 155 f""" 196 156 E1 = Entity(type='MyEntity', id='entity 1') 197 - A = Experiment( 198 - entity=E1, buckets={str(buckets)}, bucket_sizes={bucket_sizes}, version=1, 199 - revision=1, local_bucketing=True 200 - ) 157 + A = Experiment(entity=E1, buckets={str(buckets)}, bucket_sizes={bucket_sizes}, version=1, revision=1) 201 158 """ 202 159 ) 203 160 ··· 209 166 run_validation( 210 167 """ 211 168 E1 = Entity(type='MyEntity', id='entity 1') 212 - A = Experiment( 213 - entity=E1, buckets=['a', 'b'], bucket_sizes=[15, 20], version=1, 214 - revision=1, local_bucketing=True 215 - ) 169 + A = Experiment(entity=E1, buckets=['a', 'b'], bucket_sizes=[15, 20], version=1, revision=1) 216 170 """ 217 171 ) 218 172 ··· 224 178 run_validation( 225 179 """ 226 180 E1 = Entity(type='MyEntity', id='entity 1') 227 - A = Experiment( 228 - entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[15, 20], version=1, 229 - revision=1, local_bucketing=True 230 - ) 181 + A = Experiment(entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[15, 20], version=1, revision=1) 231 182 """ 232 183 ) 233 184 ··· 239 190 run_validation( 240 191 f""" 241 192 E1 = Entity(type='MyEntity', id='entity 1') 242 - A = Experiment( 243 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 2.512], version=2, 244 - revision=0, local_bucketing=True 245 - ) 193 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 2.512], version=2, revision=0) 246 194 """ 247 195 ) 248 196 ··· 252 200 run_validation( 253 201 f""" 254 202 E1 = Entity(type='MyEntity', id='entity 1') 255 - A = Experiment( 256 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 10], version=-1, 257 - revision=1, local_bucketing=True 258 - ) 203 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 10], version=-1, revision=1) 259 204 """ 260 205 ) 261 206 ··· 265 210 run_validation( 266 211 f""" 267 212 E1 = Entity(type='MyEntity', id='entity 1') 268 - A = Experiment( 269 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 10], version=1, 270 - revision=-1, local_bucketing=True 271 - ) 213 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[10, 10], version=1, revision=-1) 272 214 """ 273 215 ) 274 216 ··· 337 279 hash_mod_mock.return_value = mock_hash_value 338 280 experiment = f""" 339 281 E1 = Entity(type='MyEntity', id='entity 1') 340 - A = Experiment( 341 - entity=E1, buckets={str(buckets)}, bucket_sizes={str(bucket_sizes)}, version=1, 342 - revision=1, local_bucketing=True 343 - ) 282 + A = Experiment(entity=E1, buckets={str(buckets)}, bucket_sizes={str(bucket_sizes)}, version=1, revision=1) 344 283 """ 345 284 data = execute(experiment) 346 285 assert data['A'] == [ ··· 351 290 str(expected_bucket_index), 352 291 str(1), 353 292 str(1), 354 - str(True), 355 293 ] 356 294 357 295 ··· 375 313 run_validation( 376 314 f""" 377 315 E1 = Entity(type='MyEntity', id='entity 1') 378 - A = Experiment( 379 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[5, 5], version=1, 380 - revision=1, local_bucketing=True 381 - ) 316 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[5, 5], version=1, revision=1) 382 317 EW = ExperimentWhen({CONTROL_BUCKET}=[True, True, True], b=[True, True], c=[True], experiment=A) 383 318 R = Rule(when_all=[EW], description='') 384 319 """ ··· 392 327 run_validation( 393 328 f""" 394 329 E1 = Entity(type='MyEntity', id='entity 1') 395 - A = Experiment( 396 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[5, 5], version=1, 397 - revision=1, local_bucketing=True 398 - ) 330 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b'], bucket_sizes=[5, 5], version=1, revision=1) 399 331 EW = ExperimentWhen({CONTROL_BUCKET}=[True, True, True], experiment=A) 400 332 R = Rule(when_all=EW, description='') 401 333 """ ··· 409 341 hash_mod_mock.return_value = 9999 410 342 experiment = f""" 411 343 E1 = Entity(type='MyEntity', id='entity 1') 412 - A = Experiment( 413 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'], bucket_sizes=[33.3, 33.3, 33.3], 414 - version=1, revision=1, local_bucketing=True 415 - ) 344 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'], bucket_sizes=[33.3, 33.3, 33.3], version=1, revision=1) 416 345 B = ExperimentWhen({CONTROL_BUCKET}=[True, True, True], b=[True, False, True], c=[False], experiment=A) 417 346 """ 418 347 data = execute(experiment) ··· 433 362 hash_mod_mock.return_value = mock_hash_value 434 363 experiment = f""" 435 364 E1 = Entity(type='MyEntity', id='entity 1') 436 - A = Experiment( 437 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'], bucket_sizes=[10.1, 10.1, 10.1], 438 - version=1, revision=1, local_bucketing=True 439 - ) 365 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'], bucket_sizes=[10.1, 10.1, 10.1], version=1, revision=1) 440 366 B = ExperimentWhen({CONTROL_BUCKET}=[True, True, True], b=[False, False], c=[False, True], experiment=A) 441 367 """ 442 368 data = execute(experiment) ··· 451 377 hash_mod_mock.return_value = 3500 452 378 experiment = f""" 453 379 E1 = Entity(type='MyEntity', id='entity 1') 454 - A = Experiment( 455 - entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'],bucket_sizes=[5.0, 5.0, 5.0], 456 - version=1, revision=1, local_bucketing=True 457 - ) 458 - R = Rule( 459 - when_all=ExperimentWhen({CONTROL_BUCKET}=[True, False], b=[True], c=[False], experiment=A), description='' 460 - ) 380 + A = Experiment(entity=E1, buckets=['{CONTROL_BUCKET}', 'b', 'c'],bucket_sizes=[5.0, 5.0, 5.0], version=1, revision=1) 381 + R = Rule(when_all=ExperimentWhen({CONTROL_BUCKET}=[True, False], b=[True], c=[False], experiment=A), description='') 461 382 """ 462 383 data = execute(experiment) 463 384 assert data['R'] is True
+5 -5
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_bucket_size_precision_too_high.txt
··· 1 - error: 1 + error: 2 2 experiment bucket size precision is too high, 3 3 the precision can be at most to the hundredth decimal place 4 - 5 - --> main.sml:4:54 4 + 5 + --> main.sml:3:65 6 6 | 7 - 4 | entity=E1, buckets=['control', 'b'], bucket_sizes=[10, 2.512], version=2, 8 - | ^ 7 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[10, 2.512], version=2, revision=0) 8 + | ^
+8 -8
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_bucket_size_too_large[buckets0-bucket_sizes0].txt
··· 1 - error: 1 + error: 2 2 75 is over the 3 3 current max of 50. 4 4 Either reduce the bucket size or reduce the number of buckets 5 - 6 - --> main.sml:4:54 5 + 6 + --> main.sml:3:65 7 7 | 8 - 4 | entity=E1, buckets=['control', 'b'], bucket_sizes=[75, 25], version=1, 9 - | ^ 10 - | max percentage size of each bucket is 100/(# of buckets) rounded 11 - | down to the nearest hundreth decimal place 12 - | 8 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[75, 25], version=1, revision=1) 9 + | ^ 10 + | max percentage size of each bucket is 100/(# of buckets) rounded 11 + | down to the nearest hundreth decimal place 12 + |
+8 -8
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_bucket_size_too_large[buckets1-bucket_sizes1].txt
··· 1 - error: 1 + error: 2 2 33.34 is over the 3 3 current max of 33.33. 4 4 Either reduce the bucket size or reduce the number of buckets 5 - 6 - --> main.sml:4:59 5 + 6 + --> main.sml:3:70 7 7 | 8 - 4 | entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[33.34, 33.33, 33.33], version=1, 9 - | ^ 10 - | max percentage size of each bucket is 100/(# of buckets) rounded 11 - | down to the nearest hundreth decimal place 12 - | 8 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[33.34, 33.33, 33.33], version=1, revision=1) 9 + | ^ 10 + | max percentage size of each bucket is 100/(# of buckets) rounded 11 + | down to the nearest hundreth decimal place 12 + |
+32 -32
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_bucket_size_too_large[buckets2-bucket_sizes2].txt
··· 1 1 4 errors occurred while validating: 2 - [1/4] error: 2 + [1/4] error: 3 3 16.67 is over the 4 4 current max of 16.66. 5 5 Either reduce the bucket size or reduce the number of buckets 6 - 7 - --> main.sml:4:74 6 + 7 + --> main.sml:3:85 8 8 | 9 - 4 | entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, 10 - | ^ 11 - | max percentage size of each bucket is 100/(# of buckets) rounded 12 - | down to the nearest hundreth decimal place 13 - | 14 - [2/4] error: 9 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, revision=1) 10 + | ^ 11 + | max percentage size of each bucket is 100/(# of buckets) rounded 12 + | down to the nearest hundreth decimal place 13 + | 14 + [2/4] error: 15 15 16.67 is over the 16 16 current max of 16.66. 17 17 Either reduce the bucket size or reduce the number of buckets 18 - 19 - --> main.sml:4:74 18 + 19 + --> main.sml:3:85 20 20 | 21 - 4 | entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, 22 - | ^ 23 - | max percentage size of each bucket is 100/(# of buckets) rounded 24 - | down to the nearest hundreth decimal place 25 - | 26 - [3/4] error: 21 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, revision=1) 22 + | ^ 23 + | max percentage size of each bucket is 100/(# of buckets) rounded 24 + | down to the nearest hundreth decimal place 25 + | 26 + [3/4] error: 27 27 16.67 is over the 28 28 current max of 16.66. 29 29 Either reduce the bucket size or reduce the number of buckets 30 - 31 - --> main.sml:4:74 30 + 31 + --> main.sml:3:85 32 32 | 33 - 4 | entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, 34 - | ^ 35 - | max percentage size of each bucket is 100/(# of buckets) rounded 36 - | down to the nearest hundreth decimal place 37 - | 38 - [4/4] error: 33 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, revision=1) 34 + | ^ 35 + | max percentage size of each bucket is 100/(# of buckets) rounded 36 + | down to the nearest hundreth decimal place 37 + | 38 + [4/4] error: 39 39 16.67 is over the 40 40 current max of 16.66. 41 41 Either reduce the bucket size or reduce the number of buckets 42 - 43 - --> main.sml:4:74 42 + 43 + --> main.sml:3:85 44 44 | 45 - 4 | entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, 46 - | ^ 47 - | max percentage size of each bucket is 100/(# of buckets) rounded 48 - | down to the nearest hundreth decimal place 49 - | 45 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c', 'd', 'e', 'f'], bucket_sizes=[16.66, 16.67, 16.67, 16.67, 16.66, 16.67], version=1, revision=1) 46 + | ^ 47 + | max percentage size of each bucket is 100/(# of buckets) rounded 48 + | down to the nearest hundreth decimal place 49 + |
+3 -3
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_control_bucket_exists.txt
··· 1 1 error: 'control' must be one of the buckets 2 - --> main.sml:4:23 2 + --> main.sml:3:34 3 3 | 4 - 4 | entity=E1, buckets=['a', 'b'], bucket_sizes=[15, 20], version=1, 5 - | ^ 4 + 3 | A = Experiment(entity=E1, buckets=['a', 'b'], bucket_sizes=[15, 20], version=1, revision=1) 5 + | ^
+3 -3
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_revision_error.txt
··· 1 1 error: experiment revision must be zero or greater 2 - --> main.sml:5:14 2 + --> main.sml:3:96 3 3 | 4 - 5 | revision=-1, local_bucketing=True 5 - | ^ 4 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[10, 10], version=1, revision=-1) 5 + | ^
+3 -3
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_same_number_of_buckets_and_sizes.txt
··· 1 1 error: buckets and bucket_sizes must have the same number of elements 2 - --> main.sml:4:59 2 + --> main.sml:3:70 3 3 | 4 - 4 | entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[15, 20], version=1, 5 - | ^ 4 + 3 | A = Experiment(entity=E1, buckets=['control', 'b', 'c'], bucket_sizes=[15, 20], version=1, revision=1) 5 + | ^
+3 -3
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experiment_version_error.txt
··· 1 1 error: experiment version must be zero or greater 2 - --> main.sml:4:73 2 + --> main.sml:3:84 3 3 | 4 - 4 | entity=E1, buckets=['control', 'b'], bucket_sizes=[10, 10], version=-1, 5 - | ^ 4 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[10, 10], version=-1, revision=1) 5 + | ^
+5 -5
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experimentwhen_too_few_buckets.txt
··· 1 1 error: missing bucket 'b' required from experiment 'A' 2 - --> main.sml:7:5 2 + --> main.sml:4:5 3 3 | 4 - 7 | EW = ExperimentWhen(control=[True, True, True], experiment=A) 4 + 4 | EW = ExperimentWhen(control=[True, True, True], experiment=A) 5 5 | ^ 6 - --> (1) main.sml:4:23 6 + --> (1) main.sml:3:34 7 7 | 8 - 4 | entity=E1, buckets=['control', 'b'], bucket_sizes=[5, 5], version=1, 9 - | ^ 8 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[5, 5], version=1, revision=1) 9 + | ^
+5 -5
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experimentwhen_too_many_buckets.txt
··· 1 1 error: unexpected bucket 'c', this bucket must match a bucket defined in experiment 'A' 2 - --> main.sml:7:66 2 + --> main.sml:4:66 3 3 | 4 - 7 | EW = ExperimentWhen(control=[True, True, True], b=[True, True], c=[True], experiment=A) 4 + 4 | EW = ExperimentWhen(control=[True, True, True], b=[True, True], c=[True], experiment=A) 5 5 | ^ 6 - --> (1) main.sml:4:23 6 + --> (1) main.sml:3:34 7 7 | 8 - 4 | entity=E1, buckets=['control', 'b'], bucket_sizes=[5, 5], version=1, 9 - | ^ 8 + 3 | A = Experiment(entity=E1, buckets=['control', 'b'], bucket_sizes=[5, 5], version=1, revision=1) 9 + | ^
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_experiments/test_experimentwhen_uses_valid_experiment.txt
··· 2 2 --> main.sml:4:78 3 3 | 4 4 4 | EW = ExperimentWhen(control=[True, True], branch_b=[False, False], experiment=A) 5 - | ^ 5 + | ^
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_dupe_items_fails.txt
··· 11 11 --> (2) main.sml:1:32 12 12 | 13 13 1 | Import(rules=['a.sml', 'a.sml', 'a.sml']) 14 - | ^ 14 + | ^
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_invalid_list_item_type_fails.txt
··· 2 2 --> main.sml:1:14 3 3 | 4 4 1 | Import(rules=[11, 12, 13]) 5 - | ^ expected type `String` 5 + | ^ expected type `String`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_invalid_type_fails.txt
··· 2 2 --> main.sml:1:13 3 3 | 4 4 1 | Import(rules=11) 5 - | ^ expected type `List` 5 + | ^ expected type `List`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_of_nonexistent_file_fails.txt
··· 2 2 --> main.sml:1:13 3 3 | 4 4 1 | Import(rules='foo.sml') 5 - | ^ expected type `List` 5 + | ^ expected type `List`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_of_nonexistent_file_in_list_fails.txt
··· 2 2 --> main.sml:1:14 3 3 | 4 4 1 | Import(rules=['foo.sml']) 5 - | ^ import attempted here 5 + | ^ import attempted here
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_of_nonexistent_file_in_list_of_many_fails.txt
··· 2 2 --> main.sml:1:14 3 3 | 4 4 1 | Import(rules=['bar.sml', 'foo.sml']) 5 - | ^ import attempted here 5 + | ^ import attempted here
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_import/test_import_unsorted_items_fails.txt
··· 3 3 | 4 4 1 | Import(rules=['c.sml', 'b.sml', 'a.sml']) 5 5 | ^ sort imports lexicographically: 6 - | `Import(rules=['a.sml', 'b.sml', 'c.sml'])` 6 + | `Import(rules=['a.sml', 'b.sml', 'c.sml'])`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_json_data/test_rejects_invalid_json_data_path.txt
··· 2 2 --> main.sml:1:25 3 3 | 4 4 1 | Foo: str = JsonData(path='$..') 5 - | ^ error: invalid json-path supplied 5 + | ^ error: invalid json-path supplied
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_labels/test_checks_for_valid_label.txt
··· 8 8 --> main.sml:8:30 9 9 | 10 10 8 | L4 = HasLabel(entity=E, label='not_a_label_aoeuaouaoeu', status='added') 11 - | ^ unknown label `not_a_label_aoeuaouaoeu` 11 + | ^ unknown label `not_a_label_aoeuaouaoeu`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_labels/test_checks_for_valid_status.txt
··· 20 20 --> main.sml:6:49 21 21 | 22 22 6 | L4 = HasLabel(entity=E, label='my_label', status='ADDED') 23 - | ^ expected `added` or `removed`, got `ADDED` 23 + | ^ expected `added` or `removed`, got `ADDED`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_labels/test_suggests_similar_labels.txt
··· 6 6 --> (1) config.yaml:1:1 7 7 | 8 8 1 | {"labels": {"my_label": {"valid_for": ["MyEntity"]}}} 9 - | ^ add the label to the config here 9 + | ^ add the label to the config here
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_labels/test_validates_labels_are_valid_for_entity.txt
··· 70 70 --> (1) config.yaml:1:1 71 71 | 72 72 1 | {"labels": {"for_a": {"valid_for": ["TypeA", "Other"]}, "for_b": {"valid_for": ["TypeB", "Other"]}, "for_both": {"valid_for": ["TypeA", "TypeB"]}}} 73 - | ^ add the label to the config here 73 + | ^ add the label to the config here
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_phone_country.py
··· 14 14 15 15 @pytest.mark.parametrize( 16 16 'phone_number,country', 17 - [('+15555555555', 'US'), ('+65555555555', 'AU'), ('+5545555555555', 'BR')], 17 + [('+12125555555', 'US'), ('+61555555555', 'AU'), ('+5545555555555', 'BR')], 18 18 ) 19 19 def test_accepts_valid_country_code(execute: ExecuteFunction, phone_number: str, country: str) -> None: 20 20 result = execute(f'PhoneCountryStr = PhoneCountry(phone_number="{phone_number}")')
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_random_bool/test_random_bool_validation.txt
··· 2 2 --> main.sml:1:26 3 3 | 4 4 1 | r = RandomBool(percentage=1.1) 5 - | ^ this must be between 0.0 and 1.0 5 + | ^ this must be between 0.0 and 1.0
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_random_bool/test_random_bool_validation_0.txt
··· 2 2 --> main.sml:1:26 3 3 | 4 4 1 | r = RandomBool(percentage=0.0) 5 - | ^ this will always be `False` 5 + | ^ this will always be `False`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_random_bool/test_random_bool_validation_1.txt
··· 2 2 --> main.sml:1:26 3 3 | 4 4 1 | r = RandomBool(percentage=1.0) 5 - | ^ this will always be `True` 5 + | ^ this will always be `True`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_random_int/test_random_int_validation.txt
··· 2 2 --> main.sml:1:20 3 3 | 4 4 1 | r = RandomInt(start=10,end=0) 5 - | ^ the `start` value must be less than the `end` value 5 + | ^ the `start` value must be less than the `end` value
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_random_int/test_random_int_validation_0.txt
··· 2 2 --> main.sml:1:20 3 3 | 4 4 1 | r = RandomInt(start=0,end=0) 5 - | ^ the `start` value must be less than the `end` value 5 + | ^ the `start` value must be less than the `end` value
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_regex_match/test_rejects_invalid_regex.txt
··· 2 2 --> main.sml:1:25 3 3 | 4 4 1 | Foo = RegexMatch(pattern="(", target="") 5 - | ^ error: missing ), unterminated subpattern at position 0 5 + | ^ error: missing ), unterminated subpattern at position 0
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_require/test_validates_for_invalid_rule_ast_node.txt
··· 3 3 | 4 4 3 | Require(rule=Foo) 5 5 | ^ you can only use literal strings, for example: 6 - | `Require(rule="hello.sml")` or `Require(rule=f"actions/{ActionName}.sml")` 6 + | `Require(rule="hello.sml")` or `Require(rule=f"actions/{ActionName}.sml")`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_require/test_validates_for_nonexistent_rule_fstring.txt
··· 2 2 --> main.sml:3:13 3 3 | 4 4 3 | Require(rule=f'actions/{ActionName}.sml') 5 - | ^ require attempted here, glob: `actions/*.sml` matches no sources 5 + | ^ require attempted here, glob: `actions/*.sml` matches no sources
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_require/test_validates_for_nonexistent_rule_string.txt
··· 2 2 --> main.sml:2:13 3 3 | 4 4 2 | Require(rule='actions/foo.sml') 5 - | ^ require attempted here 5 + | ^ require attempted here
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_resolve_optional/test_resolve_optional_invalid_default_value_type.txt
··· 18 18 --> (1) main.sml:5:51 19 19 | 20 20 5 | BarUnwrapper: int = ResolveOptional(optional_value=Bar, default_value='test') 21 - | ^ 21 + | ^
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_resolve_optional/test_resolve_optional_invalid_optional_value_type.txt
··· 6 6 --> (1) main.sml:3:14 7 7 | 8 8 3 | FooUnwrapped: str = ResolveOptional(optional_value=Foo) 9 - | ^ expected `str` due to this 9 + | ^ expected `str` due to this
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_rules/test_rule_will_error_if_variable_interpolation_attempted_in_non_fstring.txt
··· 4 4 3 | R1 = Rule(when_all=[True], description='Interpolated: {X}') 5 5 | ^ this string contains what looks like variable interpolation, but is not an f-string 6 6 | found: `X` 7 - | consider prefixing with `f` 7 + | consider prefixing with `f`
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_rules/test_rules_must_be_stored_in_variables.txt
··· 17 17 | 18 18 8 | _Local = Rule(when_all=[True], description='') 19 19 | ^ this rule is being stored in the local variable `_Local` 20 - | rules must be in non-local features (eg that don't start with `_`) 20 + | rules must be in non-local features (eg that don't start with `_`)
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_rules/test_rules_must_have_str_or_f_str_descriptions.txt
··· 2 2 --> main.sml:3:38 3 3 | 4 4 3 | R = Rule(when_all=[True], description=description) 5 - | ^ got `Name` node, expected `String` or `FormatString` literal 5 + | ^ got `Name` node, expected `String` or `FormatString` literal
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_call[with-regular].txt
··· 2 2 --> main.sml:3:0 3 3 | 4 4 3 | CallFoo = StringClean(s=Foo) 5 - | ^ name 'CallFoo' is not marked as non-extractable 5 + | ^ name 'CallFoo' is not marked as non-extractable
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_call[with-secret].txt
··· 2 2 --> main.sml:3:0 3 3 | 4 4 3 | CallFoo = StringClean(s=Foo) 5 - | ^ name 'CallFoo' is not marked as non-extractable 5 + | ^ name 'CallFoo' is not marked as non-extractable
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_format_string[with-regular].txt
··· 8 8 --> main.sml:3:18 9 9 | 10 10 3 | FormattedFoo = f'{Foo}' 11 - | ^ name 'Foo' is marked as non-extractable 11 + | ^ name 'Foo' is marked as non-extractable
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_format_string[with-secret].txt
··· 8 8 --> main.sml:3:18 9 9 | 10 10 3 | FormattedFoo = f'{Foo}' 11 - | ^ name 'Foo' is marked as non-extractable 11 + | ^ name 'Foo' is marked as non-extractable
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_list[with-regular].txt
··· 2 2 --> main.sml:3:0 3 3 | 4 4 3 | ListFoo = [Foo] 5 - | ^ name 'ListFoo' is not marked as non-extractable 5 + | ^ name 'ListFoo' is not marked as non-extractable
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_secret_data/test_secret_type_fails_list[with-secret].txt
··· 2 2 --> main.sml:3:0 3 3 | 4 4 3 | ListFoo = [Foo] 5 - | ^ name 'ListFoo' is not marked as non-extractable 5 + | ^ name 'ListFoo' is not marked as non-extractable
+6 -6
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_strings.py
··· 182 182 Scenario('🔞t3xt'), 183 183 Scenario('ΠOPQ 100-', ['nop', '100']), 184 184 Scenario('Te.xt'), 185 - Scenario('∏opq'), 185 + Scenario('∏opq', 'nopq'), 186 186 Scenario('dat@ 2334', ['data', '2334']), 187 187 Scenario('t3xt |00-', ['100']), 188 188 Scenario('𝐓𝐄𝐗𝐓'), 189 189 Scenario('𝚃𝙴𝚇𝚃'), 190 - Scenario('tex刀'), 190 + Scenario('tex刀', 'texn'), 191 191 Scenario('te×ts'), 192 - Scenario('∏opq'), 193 - Scenario('nopq'), 194 - Scenario('t3x∩'), 195 - Scenario('texη'), 192 + Scenario('∏opq', 'nopq'), 193 + Scenario('nopq', 'nopq'), 194 + Scenario('t3x∩', 'texn'), 195 + Scenario('texη', 'texn'), 196 196 Scenario('Ç', ['c']), 197 197 Scenario('⒜,⒝,⒞,⒟,⒠,⒡,⒢,⒣,⒤,⒥,⒦,⒧,⒨,⒩,⒪,⒫,⒬,⒭,⒮,⒯,⒰,⒱,⒲,⒳,⒴,⒵', string.ascii_lowercase), 198 198 Scenario('Ⓐ,Ⓑ,Ⓒ,Ⓓ,Ⓔ,Ⓕ,Ⓖ,Ⓗ,Ⓘ,Ⓙ,Ⓚ,Ⓛ,Ⓜ,Ⓝ,Ⓞ,Ⓟ,Ⓠ,Ⓡ,Ⓢ,Ⓣ,Ⓤ,Ⓥ,Ⓦ,Ⓧ,Ⓨ,Ⓩ', string.ascii_lowercase),
+15 -7
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_time_bucket.py
··· 7 7 from osprey.engine.stdlib.udfs.time_bucket import GetSnowflakeBucket, GetTimedeltaBucket, GetTimestampBucket 8 8 from osprey.engine.stdlib.udfs.time_delta import TimeDelta 9 9 from osprey.engine.udf.registry import UDFRegistry 10 + from osprey.worker.lib.snowflake import Snowflake 10 11 11 12 pytestmark: List[Callable[[Any], Any]] = [ 12 13 pytest.mark.use_validators([ValidateCallKwargs, UniqueStoredNames]), ··· 17 18 18 19 19 20 def test_get_snowflake_bucket(execute: ExecuteFunction) -> None: 21 + snowflake = Snowflake(119144447702335491) 22 + timestamp = int(snowflake.to_timestamp()) # Convert to integer seconds 23 + 24 + week_granularity = 604800 25 + day_granularity = 86400 26 + hour_granularity = 3600 27 + 20 28 data = execute( 21 - """ 22 - Week_bucket = GetSnowflakeBucket(snowflake=119144447702335491,granularity_seconds=604800) 23 - Day_Bucket = GetSnowflakeBucket(snowflake=119144447702335491,granularity_seconds=86400) 24 - Hour_Bucket = GetSnowflakeBucket(snowflake=119144447702335491,granularity_seconds=3600) 29 + f""" 30 + Week_bucket = GetSnowflakeBucket(snowflake={snowflake},granularity_seconds={week_granularity}) 31 + Day_Bucket = GetSnowflakeBucket(snowflake={snowflake},granularity_seconds={day_granularity}) 32 + Hour_Bucket = GetSnowflakeBucket(snowflake={snowflake},granularity_seconds={hour_granularity}) 25 33 """ 26 34 ) 27 35 assert data == { 28 - 'Week_bucket': 1447891200, # 11/19/2015 0:00:00 29 - 'Day_Bucket': 1448409600, # 11/25/2015 0:00:00 30 - 'Hour_Bucket': 1448474400, # 11/25/2015 18:00:00 36 + 'Week_bucket': (timestamp // week_granularity) * week_granularity, 37 + 'Day_Bucket': (timestamp // day_granularity) * day_granularity, 38 + 'Hour_Bucket': (timestamp // hour_granularity) * hour_granularity, 31 39 } 32 40 33 41
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_time_bucket/test_get_snowflake_bucket_invalid_granularity.txt
··· 2 2 --> main.sml:1:68 3 3 | 4 4 1 | GetSnowflakeBucket(snowflake=119144447702335491,granularity_seconds=0) 5 - | ^ granularity_seconds can not be less than 3600 (1 hour) 5 + | ^ granularity_seconds can not be less than 3600 (1 hour)
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_time_bucket/test_get_timedelta_bucket_invalid_granularity.txt
··· 2 2 --> main.sml:1:76 3 3 | 4 4 1 | GetTimedeltaBucket(timedelta=TimeDelta(seconds=1136715),granularity_seconds=0) 5 - | ^ granularity_seconds can not be less than 3600 (1 hour) 5 + | ^ granularity_seconds can not be less than 3600 (1 hour)
+1 -1
osprey_worker/src/osprey/engine/stdlib/udfs/tests/test_time_bucket/test_get_timestamp_bucket_invalid_granularity.txt
··· 2 2 --> main.sml:1:60 3 3 | 4 4 1 | GetTimestampBucket(timestamp=1448476649,granularity_seconds=0) 5 - | ^ granularity_seconds can not be less than 3600 (1 hour) 5 + | ^ granularity_seconds can not be less than 3600 (1 hour)
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ArgumentDoesNotUseTypeUdf].txt
··· 1 - generic arguments type must have at least one generic item: UDF `ArgumentDoesNotUseTypeUdf` generic arguments type `ArgumentDoesNotUseTypeArgs[~A]` has no generic items 1 + generic arguments type must have at least one generic item: UDF `ArgumentDoesNotUseTypeUdf` generic arguments type `ArgumentDoesNotUseTypeArgs[~A]` has no generic items
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ArgumentGenericWhenUdfIsNotUdf].txt
··· 1 - Osprey generics must inherit from `OspreyInvariantGeneric`: generic UDF type `ArgumentGenericWhenUdfIsNotUdf` does not inherit from `OspreyInvariantGeneric` 1 + Osprey generics must inherit from `OspreyInvariantGeneric`: generic UDF type `ArgumentGenericWhenUdfIsNotUdf` does not inherit from `OspreyInvariantGeneric`
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ArgumentHasDifferentTypeVarUdf].txt
··· 1 - Osprey generics must have exactly one parameter: generic UDF type `ArgumentHasDifferentTypeVarUdf` has 2 parameters 1 + Osprey generics must have exactly one parameter: generic UDF type `ArgumentHasDifferentTypeVarUdf` has 2 parameters
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ArgumentInheritsWrongGenericUdf].txt
··· 1 - Osprey generics must inherit from `OspreyInvariantGeneric`: generic arguments type `ArgumentInheritsWrongGenericArgs` does not inherit from `OspreyInvariantGeneric` 1 + Osprey generics must inherit from `OspreyInvariantGeneric`: generic arguments type `ArgumentInheritsWrongGenericArgs` does not inherit from `OspreyInvariantGeneric`
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ComplexParamUdf].txt
··· 1 - cannot get type candidates for `Tuple[str, ...]`, is an unknown generic 1 + cannot get type candidates for `Tuple[str, ...]`, is an unknown generic
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ComplexReturnUdf].txt
··· 1 - cannot get type candidates for `Tuple[str, ...]`, is an unknown generic 1 + cannot get type candidates for `Tuple[str, ...]`, is an unknown generic
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[DoesNotReturnGenericUdf].txt
··· 1 - generic UDF return type must have exactly one type parameter: UDF `DoesNotReturnGenericUdf` return type `None` is not generic 1 + generic UDF return type must have exactly one type parameter: UDF `DoesNotReturnGenericUdf` return type `None` is not generic
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[InheritsWrongGenericsUdf].txt
··· 1 - Osprey generics must inherit from `OspreyInvariantGeneric`: generic UDF type `InheritsWrongGenericsUdf` does not inherit from `OspreyInvariantGeneric` 1 + Osprey generics must inherit from `OspreyInvariantGeneric`: generic UDF type `InheritsWrongGenericsUdf` does not inherit from `OspreyInvariantGeneric`
+1 -1
osprey_worker/src/osprey/engine/udf/tests/test_udf_registry/test_cannot_register_invalid_types[ReturnsDifferentTypeVarDirectUdf].txt
··· 1 - Osprey generics must have exactly one parameter: generic UDF type `ReturnsDifferentTypeVarDirectUdf` has 2 parameters 1 + Osprey generics must have exactly one parameter: generic UDF type `ReturnsDifferentTypeVarDirectUdf` has 2 parameters
-14
osprey_worker/src/osprey/worker/sinks/__init__.py
··· 1 - # ruff: noqa: E402 2 - """TODO: move logic to another file 3 - 4 - __init__.py often gets imported and run before other modules, 5 - so it's dangerous to import other modules here, potentially prior to gevent patching 6 - 7 - Therefore we patch at the top of this file -- it's generally fine to double patch 8 - but not ideal as clients should be responsible for patching 9 - """ 10 - 11 - from osprey.worker.lib.patcher import patch_all 12 - 13 - patch_all() 14 - 15 1 from enum import StrEnum, auto 16 2 17 3
+1 -19
osprey_worker/src/osprey/worker/ui_api/osprey/lib/tests/test_users.py
··· 1 1 import json 2 - from typing import Any, Generator, Type 2 + from typing import Any, Type 3 3 4 4 import pytest 5 - from cachetools.keys import hashkey 6 5 from flask import Flask 7 6 from osprey.worker.ui_api.osprey.lib.abilities import ( 8 7 Ability, ··· 11 10 CanViewLabelsForEntity, 12 11 HashableEntityKey, 13 12 ) 14 - from osprey.worker.ui_api.osprey.lib.auth import _okta_profile_request_cache 15 13 from osprey.worker.ui_api.osprey.lib.users import User 16 14 17 15 _super_user_test_ability = 'CAN_CREATE_AND_EDIT_SAVED_QUERIES' ··· 186 184 def test_user_ability_list_match(app: 'Flask', user_email: str, expected_ability: Ability[Any, Any]) -> None: 187 185 user = User(email=user_email) 188 186 assert user.get_ability(type(expected_ability)) == expected_ability 189 - 190 - 191 - @pytest.fixture() 192 - def okta_profile_cache(user_email: str, is_super: bool) -> Generator[None, None, None]: 193 - key = hashkey(user_email) 194 - if is_super: 195 - _okta_profile_request_cache[key] = { 196 - 'id': 'someid', 197 - 'name': 'Bob Ross', 198 - 'email': user_email, 199 - 'groups': ['App-Osprey-Super-User'], 200 - 'amr': ['pwd'], 201 - 'idp': {'id': 'someid', 'type': 'okta'}, 202 - } 203 - yield 204 - _okta_profile_request_cache.pop(key, None) 205 187 206 188 207 189 @pytest.mark.use_rules_sources(config)