Skip to content
Merged
8 changes: 2 additions & 6 deletions spp_cel_vocabulary/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ OpenSPP CEL Vocabulary Integration
!! source digest: sha256:187208d6a52a5dda86e67b1024f417772f64d60f710b523e275e30c8adbdeb0c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
Expand Down Expand Up @@ -124,10 +124,6 @@ Dependencies

``spp_cel_domain``, ``spp_vocabulary``

.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.

**Table of contents**

.. contents::
Expand Down
20 changes: 10 additions & 10 deletions spp_cel_vocabulary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def _ensure_concept_groups(env):
standard_groups = [
{
"name": "feminine_gender",
"display_name": "Feminine Gender",
"label": "Feminine Gender",
"cel_function": "is_female",
"target_field": "gender_id",
"description": (
Expand All @@ -40,7 +40,7 @@ def _ensure_concept_groups(env):
},
{
"name": "masculine_gender",
"display_name": "Masculine Gender",
"label": "Masculine Gender",
"cel_function": "is_male",
"target_field": "gender_id",
"description": (
Expand All @@ -51,7 +51,7 @@ def _ensure_concept_groups(env):
},
{
"name": "head_of_household",
"display_name": "Head of Household",
"label": "Head of Household",
"cel_function": "is_head",
"description": (
"Relationship types indicating head of household role. "
Expand All @@ -61,7 +61,7 @@ def _ensure_concept_groups(env):
},
{
"name": "pregnant_eligible",
"display_name": "Pregnant/Eligible",
"label": "Pregnant/Eligible",
"cel_function": "is_pregnant",
"target_field": "pregnancy_status_id",
"description": (
Expand All @@ -72,7 +72,7 @@ def _ensure_concept_groups(env):
},
{
"name": "climate_hazards",
"display_name": "Climate-related Hazards",
"label": "Climate-related Hazards",
"cel_function": None,
"description": (
"Hazard types related to climate and weather events "
Expand All @@ -82,7 +82,7 @@ def _ensure_concept_groups(env):
},
{
"name": "geophysical_hazards",
"display_name": "Geophysical Hazards",
"label": "Geophysical Hazards",
"cel_function": None,
"description": (
"Hazard types related to earth processes "
Expand All @@ -92,7 +92,7 @@ def _ensure_concept_groups(env):
},
{
"name": "children",
"display_name": "Children",
"label": "Children",
"cel_function": None,
"description": (
"Age group codes representing children (typically under 18 years). "
Expand All @@ -101,15 +101,15 @@ def _ensure_concept_groups(env):
},
{
"name": "adults",
"display_name": "Adults",
"label": "Adults",
"cel_function": None,
"description": (
"Age group codes representing adults. Add codes from your age group vocabulary if applicable."
),
},
{
"name": "elderly",
"display_name": "Elderly/Senior Citizens",
"label": "Elderly/Senior Citizens",
"cel_function": None,
"description": (
"Age group codes representing elderly or senior citizens. "
Expand All @@ -118,7 +118,7 @@ def _ensure_concept_groups(env):
},
{
"name": "persons_with_disability",
"display_name": "Persons with Disability",
"label": "Persons with Disability",
"cel_function": None,
"description": (
"Disability type codes. "
Expand Down
2 changes: 1 addition & 1 deletion spp_cel_vocabulary/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
"license": "LGPL-3",
"development_status": "Alpha",
"development_status": "Beta",
"depends": [
"spp_cel_domain",
"spp_vocabulary",
Expand Down
8 changes: 4 additions & 4 deletions spp_cel_vocabulary/models/cel_vocabulary_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ def register_vocabulary_functions(self):
# Register with CEL function registry
if registry.register(name, marked):
count += 1
_logger.debug(f"[CEL Vocabulary] Registered function '{name}'")
_logger.debug("[CEL Vocabulary] Registered function '%s'", name)

_logger.info(f"[CEL Vocabulary] Registered {count} vocabulary function(s)")
_logger.info("[CEL Vocabulary] Registered %d vocabulary function(s)", count)

return count

Expand All @@ -110,9 +110,9 @@ def unregister_vocabulary_functions(self):
for name in vocab_funcs.VOCABULARY_FUNCTIONS.keys():
if registry.unregister(name):
count += 1
_logger.debug(f"[CEL Vocabulary] Unregistered function '{name}'")
_logger.debug("[CEL Vocabulary] Unregistered function '%s'", name)

_logger.info(f"[CEL Vocabulary] Unregistered {count} vocabulary function(s)")
_logger.info("[CEL Vocabulary] Unregistered %d vocabulary function(s)", count)

return count

Expand Down
38 changes: 19 additions & 19 deletions spp_cel_vocabulary/models/cel_vocabulary_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ class CelVocabularyTranslator(models.AbstractModel):
"is_male": "masculine_gender",
"is_head": "head_of_household",
"is_pregnant": "pregnant_eligible",
"is_caregiver": "caregiver",
"is_mother": "mother",
"is_father": "father",
}

def _to_plan(self, model: str, node: Any, cfg: dict[str, Any], ctx: dict[str, Any]): # noqa: C901
Expand All @@ -61,7 +58,7 @@ def _to_plan(self, model: str, node: Any, cfg: dict[str, Any], ctx: dict[str, An

# Handle semantic helpers: is_female(field), is_male(field), etc.
if func_name in self.SEMANTIC_HELPERS and len(node.args) >= 1:
_logger.debug(f"[CEL Vocabulary] Handling semantic helper {func_name} for model {model}")
_logger.debug("[CEL Vocabulary] Handling semantic helper %s for model %s", func_name, model)
return self._handle_semantic_helper(model, node, cfg, ctx, func_name)

# Handle comparisons with code() calls
Expand Down Expand Up @@ -105,7 +102,7 @@ def _handle_in_group(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: d
field_name, field_model = self._resolve_field(model, field_node, cfg, ctx)
field_name = self._normalize_field_name(field_model or model, field_name)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to resolve field in in_group(): {e}")
_logger.warning("[CEL Vocabulary] Failed to resolve field in in_group(): %s", e)
return (
LeafDomain(model, [("id", "=", 0)]),
"in_group() [FIELD RESOLUTION ERROR]",
Expand All @@ -115,7 +112,7 @@ def _handle_in_group(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: d
try:
group_name = self._eval_literal(node.args[1], ctx)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to evaluate group name in in_group(): {e}")
_logger.warning("[CEL Vocabulary] Failed to evaluate group name in in_group(): %s", e)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
f"in_group({field_name}, ?) [EVAL ERROR]",
Expand All @@ -132,7 +129,7 @@ def _handle_in_group(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: d
group = self.env["spp.vocabulary.concept.group"].search([("name", "=", group_name)], limit=1)

if not group:
_logger.warning(f"[CEL Vocabulary] Concept group '{group_name}' not found, returning empty domain")
_logger.warning("[CEL Vocabulary] Concept group '%s' not found, returning empty domain", group_name)
# Return domain that matches nothing
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
Expand All @@ -143,7 +140,7 @@ def _handle_in_group(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: d
uri_list = group.get_code_uris()

if not uri_list:
_logger.warning(f"[CEL Vocabulary] Concept group '{group_name}' has no codes")
_logger.warning("[CEL Vocabulary] Concept group '%s' has no codes", group_name)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
f"in_group({field_name}, '{group_name}') [EMPTY GROUP]",
Expand Down Expand Up @@ -188,7 +185,7 @@ def _handle_semantic_helper(
"""
group_name = self.SEMANTIC_HELPERS.get(func_name)
if not group_name:
_logger.warning(f"[CEL Vocabulary] Unknown semantic helper: {func_name}")
_logger.warning("[CEL Vocabulary] Unknown semantic helper: %s", func_name)
return (
LeafDomain(model, [("id", "=", 0)]),
f"{func_name}() [UNKNOWN HELPER]",
Expand All @@ -200,7 +197,7 @@ def _handle_semantic_helper(
field_name, field_model = self._resolve_field(model, field_node, cfg, ctx)
field_name = self._normalize_field_name(field_model or model, field_name)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to resolve field in {func_name}(): {e}")
_logger.warning("[CEL Vocabulary] Failed to resolve field in %s(): %s", func_name, e)
return (
LeafDomain(model, [("id", "=", 0)]),
f"{func_name}() [FIELD RESOLUTION ERROR]",
Expand All @@ -211,7 +208,9 @@ def _handle_semantic_helper(

if not group:
_logger.warning(
f"[CEL Vocabulary] Concept group '{group_name}' not found for {func_name}(), returning empty domain"
"[CEL Vocabulary] Concept group '%s' not found for %s(), returning empty domain",
group_name,
func_name,
)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
Expand All @@ -222,7 +221,7 @@ def _handle_semantic_helper(
uri_list = group.get_code_uris()

if not uri_list:
_logger.warning(f"[CEL Vocabulary] Concept group '{group_name}' has no codes for {func_name}()")
_logger.warning("[CEL Vocabulary] Concept group '%s' has no codes for %s()", group_name, func_name)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
f"{func_name}({field_name}) [GROUP EMPTY]",
Expand Down Expand Up @@ -264,7 +263,7 @@ def _handle_code_eq(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: di
field_name, field_model = self._resolve_field(model, field_node, cfg, ctx)
field_name = self._normalize_field_name(field_model or model, field_name)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to resolve field in code_eq(): {e}")
_logger.warning("[CEL Vocabulary] Failed to resolve field in code_eq(): %s", e)
return (
LeafDomain(model, [("id", "=", 0)]),
"code_eq() [FIELD RESOLUTION ERROR]",
Expand All @@ -274,7 +273,7 @@ def _handle_code_eq(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: di
try:
identifier = self._eval_literal(node.args[1], ctx)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to evaluate identifier in code_eq(): {e}")
_logger.warning("[CEL Vocabulary] Failed to evaluate identifier in code_eq(): %s", e)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
f"code_eq({field_name}, ?) [EVAL ERROR]",
Expand All @@ -290,7 +289,8 @@ def _handle_code_eq(self, model: str, node: P.Call, cfg: dict[str, Any], ctx: di

if not target_code:
_logger.warning(
f"[CEL Vocabulary] Could not resolve code identifier '{identifier}', returning empty domain"
"[CEL Vocabulary] Could not resolve code identifier '%s', returning empty domain",
identifier,
)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
Expand Down Expand Up @@ -351,15 +351,15 @@ def _handle_code_comparison(

# Only support equality/inequality for code comparisons
if op not in ("=", "!="):
_logger.warning(f"[CEL Vocabulary] code() comparisons only support == and !=, got {node.op}")
_logger.warning("[CEL Vocabulary] code() comparisons only support == and !=, got %s", node.op)
return super()._to_plan(model, node, cfg, ctx)

# Resolve the field
try:
field_name, field_model = self._resolve_field(model, field_node, cfg, ctx)
field_name = self._normalize_field_name(field_model or model, field_name)
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to resolve field in code comparison: {e}")
_logger.warning("[CEL Vocabulary] Failed to resolve field in code comparison: %s", e)
return (
LeafDomain(model, [("id", "=", 0)]),
"code() comparison [FIELD RESOLUTION ERROR]",
Expand All @@ -369,7 +369,7 @@ def _handle_code_comparison(
try:
identifier = self._eval_literal(code_node.args[0], ctx) if code_node.args else None
except Exception as e:
_logger.warning(f"[CEL Vocabulary] Failed to evaluate code identifier: {e}")
_logger.warning("[CEL Vocabulary] Failed to evaluate code identifier: %s", e)
identifier = None

if not identifier:
Expand All @@ -386,7 +386,7 @@ def _handle_code_comparison(
target_code = self.env["spp.vocabulary.code"].resolve_alias(identifier)

if not target_code:
_logger.warning(f"[CEL Vocabulary] Could not resolve code '{identifier}'")
_logger.warning("[CEL Vocabulary] Could not resolve code '%s'", identifier)
return (
LeafDomain(field_model or model, [("id", "=", 0)]),
f"{field_name} {op} code('{identifier}') [NOT FOUND]",
Expand Down
2 changes: 1 addition & 1 deletion spp_cel_vocabulary/services/cel_vocabulary_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def in_group(env, code_value, group_name):
uri_set = ConceptGroup._get_group_uris_cached(group_name)

if uri_set is None:
_logger.warning(f"[CEL Vocabulary] Concept group '{group_name}' not found")
_logger.warning("[CEL Vocabulary] Concept group '%s' not found", group_name)
return False

if not uri_set:
Expand Down
7 changes: 1 addition & 6 deletions spp_cel_vocabulary/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ <h1 class="title">OpenSPP CEL Vocabulary Integration</h1>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:187208d6a52a5dda86e67b1024f417772f64d60f710b523e275e30c8adbdeb0c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/license-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_cel_vocabulary"><img alt="OpenSPP/OpenSPP2" src="https://img.shields.io/badge/github-OpenSPP%2FOpenSPP2-lightgray.png?logo=github" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/license-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_cel_vocabulary"><img alt="OpenSPP/OpenSPP2" src="https://img.shields.io/badge/github-OpenSPP%2FOpenSPP2-lightgray.png?logo=github" /></a></p>
<p>Integrates vocabulary-aware functions into the CEL (Common Expression
Language) expression engine for eligibility rules. Extends the CEL
translator to resolve vocabulary codes by URI or alias and translate
Expand Down Expand Up @@ -490,11 +490,6 @@ <h1>Extension Points</h1>
<div class="section" id="dependencies">
<h1>Dependencies</h1>
<p><tt class="docutils literal">spp_cel_domain</tt>, <tt class="docutils literal">spp_vocabulary</tt></p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.</p>
</div>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
Expand Down
1 change: 1 addition & 0 deletions spp_cel_vocabulary/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.

from . import test_cel_vocabulary
from . import test_init_and_coverage
from . import test_vocabulary_cache
from . import test_vocabulary_in_exists
Loading
Loading