test_evaluation_context.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from dataclasses import dataclass
  2. from typing import Any
  3. import pytest
  4. from flagpole.evaluation_context import ContextBuilder, EvaluationContextDict
  5. class TestEvaluationContext:
  6. pass
  7. @dataclass
  8. class ContextData:
  9. foo: str | None = None
  10. baz: int | None = None
  11. buzz: dict | set | None = None
  12. class TestContextBuilder:
  13. def test_empty_context_builder(self):
  14. context_builder = ContextBuilder[ContextData]()
  15. context = context_builder.build()
  16. assert context.size() == 0
  17. def test_static_transformer(self):
  18. def static_transformer(_data: ContextData) -> dict[str, Any]:
  19. return dict(foo="bar", baz=1)
  20. eval_context = (
  21. ContextBuilder[ContextData]()
  22. .add_context_transformer(static_transformer)
  23. .build(ContextData())
  24. )
  25. assert eval_context.size() == 2
  26. assert eval_context.get("foo") == "bar"
  27. assert eval_context.get("baz") == 1
  28. def test_transformer_with_data(self):
  29. def transformer_with_data(data: ContextData) -> dict[str, Any]:
  30. return dict(foo="bar", baz=getattr(data, "baz", None))
  31. eval_context = (
  32. ContextBuilder[ContextData]()
  33. .add_context_transformer(transformer_with_data)
  34. .build(ContextData(baz=2))
  35. )
  36. assert eval_context.size() == 2
  37. assert eval_context.get("foo") == "bar"
  38. assert eval_context.get("baz") == 2
  39. def test_multiple_context_transformers(self):
  40. def transformer_one(data: ContextData) -> dict[str, Any]:
  41. return dict(foo="overwrite_me", baz=2, buzz=getattr(data, "buzz"))
  42. def transformer_two(_data: ContextData) -> dict[str, Any]:
  43. return dict(foo="bar")
  44. eval_context = (
  45. ContextBuilder[ContextData]()
  46. .add_context_transformer(transformer_one)
  47. .add_context_transformer(transformer_two)
  48. .build(ContextData(foo="bar", buzz={1, 2, 3}))
  49. )
  50. assert eval_context.size() == 3
  51. assert eval_context.get("foo") == "bar"
  52. assert eval_context.get("baz") == 2
  53. assert eval_context.get("buzz") == {1, 2, 3}
  54. def test_with_exception_handler(self):
  55. exc_message = "oh noooooo"
  56. def broken_transformer(_data: ContextData) -> EvaluationContextDict:
  57. raise Exception(exc_message)
  58. context_builder = ContextBuilder[ContextData]().add_context_transformer(broken_transformer)
  59. with pytest.raises(Exception) as exc:
  60. context_builder.build(ContextData())
  61. assert exc.match(exc_message)
  62. # Ensure builder doesn't raise an exception
  63. context_builder.add_exception_handler(lambda _exc: None)
  64. context_builder.build(ContextData())
  65. with pytest.raises(Exception):
  66. context_builder.add_exception_handler(lambda _exc: None)