Skip to content

Commit

Permalink
chg: always produce entity forms with the offline entities spec version
Browse files Browse the repository at this point in the history
- removed the older create/update spec versions which are now unused.
- although it looks a bit useless now, the "entity_features" code in
  xls2json.py and survey.py was retained since it seems likely that
  this will be needed in the near future as the entities spec evolves.
  • Loading branch information
lindsay-stevens committed Dec 10, 2024
1 parent 95034d9 commit 80c323a
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 173 deletions.
3 changes: 0 additions & 3 deletions pyxform/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@
CURRENT_XFORMS_VERSION = "1.0.0"

# The ODK entities spec version that generated forms comply to
ENTITIES_CREATE_VERSION = "2022.1.0"
ENTITIES_UPDATE_VERSION = "2023.1.0"
ENTITIES_OFFLINE_VERSION = "2024.1.0"
ENTITY = "entity"
ENTITY_FEATURES = "entity_features"
Expand All @@ -127,7 +125,6 @@ class EntityColumns(StrEnum):
CREATE_IF = "create_if"
UPDATE_IF = "update_if"
LABEL = "label"
OFFLINE = "offline"


DEPRECATED_DEVICE_ID_METADATA_FIELDS = {"subscriberid", "simserial"}
Expand Down
3 changes: 0 additions & 3 deletions pyxform/entities/entities_parsing.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Any

from pyxform import constants as const
from pyxform.aliases import yes_no
from pyxform.errors import PyXFormError
from pyxform.parsing.expression import is_xml_tag
from pyxform.validators.pyxform.sheet_misspellings import find_sheet_misspellings
Expand Down Expand Up @@ -30,7 +29,6 @@ def get_entity_declaration(
create_condition = entity_row.get(EC.CREATE_IF, None)
update_condition = entity_row.get(EC.UPDATE_IF, None)
entity_label = entity_row.get(EC.LABEL, None)
offline = yes_no.get(entity_row.get(EC.OFFLINE, None), None)

if update_condition and not entity_id:
raise PyXFormError(
Expand All @@ -56,7 +54,6 @@ def get_entity_declaration(
EC.CREATE_IF: create_condition,
EC.UPDATE_IF: update_condition,
EC.LABEL: entity_label,
EC.OFFLINE: offline,
},
}

Expand Down
20 changes: 8 additions & 12 deletions pyxform/entities/entity_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ def xml_instance(self, **kwargs):
if entity_id_expression:
attributes["update"] = "1"
attributes["baseVersion"] = ""
if parameters.get(EC.OFFLINE, None):
attributes["trunkVersion"] = ""
attributes["branchId"] = ""
attributes["trunkVersion"] = ""
attributes["branchId"] = ""

if create_condition or (not update_condition and not entity_id_expression):
attributes["create"] = "1"
Expand Down Expand Up @@ -101,15 +100,12 @@ def xml_bindings(self, survey: "Survey"):
bind_nodes.append(
self._get_bind_node(survey, f"{entity}/__version", "/@baseVersion")
)
if parameters.get(EC.OFFLINE, None):
bind_nodes.append(
self._get_bind_node(
survey, f"{entity}/__trunkVersion", "/@trunkVersion"
)
)
bind_nodes.append(
self._get_bind_node(survey, f"{entity}/__branchId", "/@branchId")
)
bind_nodes.append(
self._get_bind_node(survey, f"{entity}/__trunkVersion", "/@trunkVersion")
)
bind_nodes.append(
self._get_bind_node(survey, f"{entity}/__branchId", "/@branchId")
)

if label_expression:
bind_nodes.append(self._get_bind_node(survey, label_expression, "/label"))
Expand Down
13 changes: 1 addition & 12 deletions pyxform/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,18 +724,7 @@ def xml_model(self):
model_kwargs = {"odk:xforms-version": constants.CURRENT_XFORMS_VERSION}

if self.entity_features:
if "offline" in self.entity_features:
model_kwargs["entities:entities-version"] = (
constants.ENTITIES_OFFLINE_VERSION
)
elif "update" in self.entity_features:
model_kwargs["entities:entities-version"] = (
constants.ENTITIES_UPDATE_VERSION
)
else:
model_kwargs["entities:entities-version"] = (
constants.ENTITIES_CREATE_VERSION
)
model_kwargs["entities:entities-version"] = constants.ENTITIES_OFFLINE_VERSION

model_children = []
if self._translations:
Expand Down
10 changes: 1 addition & 9 deletions pyxform/xls2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -1514,15 +1514,7 @@ def workbook_to_json(
)

if len(entity_declaration) > 0:
json_dict[constants.ENTITY_FEATURES] = ["create"]
entity_parameters = entity_declaration.get(constants.PARAMETERS, {})

if entity_parameters.get(constants.EntityColumns.ENTITY_ID, None):
json_dict[constants.ENTITY_FEATURES].append("update")

if entity_parameters.get(constants.EntityColumns.OFFLINE, None):
json_dict[constants.ENTITY_FEATURES].append("offline")

json_dict[constants.ENTITY_FEATURES] = ["create", "update", "offline"]
meta_children.append(entity_declaration)

if len(meta_children) > 0:
Expand Down
42 changes: 1 addition & 41 deletions tests/test_entities_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_basic_entity_creation_building_blocks(self):
'/h:html/h:head/x:model/x:setvalue[@event = "odk-instance-first-load" and @type = "string" and @ref = "/data/meta/entity/@id" and @value = "uuid()"]',
"/h:html/h:head/x:model/x:instance/x:data/x:meta/x:entity/x:label",
'/h:html/h:head/x:model/x:bind[@nodeset = "/data/meta/entity/label" and @type = "string" and @readonly = "true()" and @calculate = "a"]',
'/h:html/h:head/x:model[@entities:entities-version = "2022.1.0"]',
f"""/h:html/h:head/x:model[@entities:entities-version = '{co.ENTITIES_OFFLINE_VERSION}']""",
],
xml__xpath_count=[
("/h:html/h:head/x:model/x:instance/x:data/x:meta/x:entity/@update", 0),
Expand Down Expand Up @@ -440,43 +440,3 @@ def test_entities_columns__multiple_unexpected(self):
"'why'",
],
)

def test_entities_offline_opt_in__yes(self):
"""Should find offline spec version, if opted-in."""
self.assertPyxformXform(
md="""
| survey |
| | type | name | label |
| | text | a | A |
| entities |
| | dataset | label | offline |
| | trees | a | yes |
""",
xml__xpath_match=[
f"""
/h:html/h:head/x:model[
@entities:entities-version = "{co.ENTITIES_OFFLINE_VERSION}"
]
""",
],
)

def test_entities_offline_opt_in__no(self):
"""Should find create spec version, if not opted-in."""
self.assertPyxformXform(
md="""
| survey |
| | type | name | label |
| | text | a | A |
| entities |
| | dataset | label | offline |
| | trees | a | no |
""",
xml__xpath_match=[
f"""
/h:html/h:head/x:model[
@entities:entities-version = "{co.ENTITIES_CREATE_VERSION}"
]
""",
],
)
116 changes: 23 additions & 93 deletions tests/test_entities_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,29 @@ def test_basic_entity_update_building_blocks(self):
'/h:html/h:head/x:model/x:bind[@nodeset = "/data/meta/entity/@id" and @type = "string" and @readonly = "true()" and @calculate = " /data/id "]',
'/h:html/h:head/x:model/x:instance/x:data/x:meta/x:entity[@baseVersion = ""]',
'/h:html/h:head/x:model/x:bind[@nodeset = "/data/meta/entity/@baseVersion" and @type = "string" and @readonly = "true()" and @calculate = "instance(\'trees\')/root/item[name= /data/id ]/__version"]',
'/h:html/h:head/x:model[@entities:entities-version = "2023.1.0"]',
f"""/h:html/h:head/x:model[@entities:entities-version = '{co.ENTITIES_OFFLINE_VERSION}']""",
"""
/h:html/h:head/x:model/x:instance/x:data/x:meta/x:entity[
@trunkVersion = ''
and @branchId = ''
]
""",
"""
/h:html/h:head/x:model/x:bind[
@nodeset = '/data/meta/entity/@trunkVersion'
and @calculate = "instance('trees')/root/item[name= /data/id ]/__trunkVersion"
and @type = 'string'
and @readonly = 'true()'
]
""",
"""
/h:html/h:head/x:model/x:bind[
@nodeset = '/data/meta/entity/@branchId'
and @calculate = "instance('trees')/root/item[name= /data/id ]/__branchId"
and @type = 'string'
and @readonly = 'true()'
]
""",
],
xml__xpath_count=[
("/h:html/h:head/x:model/x:instance/x:data/x:meta/x:entity/x:label", 0),
Expand Down Expand Up @@ -176,95 +198,3 @@ def test_save_to_with_entity_id__puts_save_tos_on_bind(self):
'/h:html/h:head/x:model/x:bind[@nodeset = "/data/a" and @entities:saveto = "foo"]'
],
)

def test_entities_offline_opt_in__yes(self):
"""Should find offline spec version and trunk/branch props/binds, if opted-in."""
self.assertPyxformXform(
md="""
| survey |
| | type | name | label |
| | text | id | Tree id |
| | text | q1 | Q1 |
| entities |
| | dataset | entity_id | offline |
| | trees | ${id} | yes |
""",
xml__xpath_match=[
f"""
/h:html/h:head/x:model[
@entities:entities-version = "{co.ENTITIES_OFFLINE_VERSION}"
]
""",
"""
/h:html/h:head/x:model/x:instance/x:test_name/x:meta/x:entity[
@trunkVersion = ''
and @branchId = ''
]
""",
"""
/h:html/h:head/x:model/x:bind[
@nodeset = '/test_name/meta/entity/@trunkVersion'
and @calculate = "instance('trees')/root/item[name= /test_name/id ]/__trunkVersion"
and @type = 'string'
and @readonly = 'true()'
]
""",
"""
/h:html/h:head/x:model/x:bind[
@nodeset = '/test_name/meta/entity/@branchId'
and @calculate = "instance('trees')/root/item[name= /test_name/id ]/__branchId"
and @type = 'string'
and @readonly = 'true()'
]
""",
],
)

def test_entities_offline_opt_in__no(self):
"""Should not find update spec version and trunk/branch props/binds, if not opted-in."""
cases = (
"""
| entities |
| | dataset | entity_id |
| | trees | ${id} |
""",
"""
| entities |
| | dataset | entity_id | offline |
| | trees | ${id} | no |
""",
)
survey = """
| survey |
| | type | name | label |
| | text | id | Tree id |
| | text | q1 | Q1 |
"""
for i, case in enumerate(cases):
with self.subTest(msg=i):
self.assertPyxformXform(
md=survey + case,
xml__xpath_match=[
f"""
/h:html/h:head/x:model[
@entities:entities-version = "{co.ENTITIES_UPDATE_VERSION}"
]
""",
"""
/h:html/h:head/x:model/x:instance/x:test_name/x:meta/x:entity[
not(@trunkVersion)
and not(@branchId)
]
""",
"""
/h:html/h:head/x:model[
not(x:bind[@nodeset = '/test_name/meta/entity/@trunkVersion'])
]
""",
"""
/h:html/h:head/x:model[
not(x:bind[@nodeset = '/test_name/meta/entity/@branchId'])
]
""",
],
)

0 comments on commit 80c323a

Please sign in to comment.