Skip to content

Commit

Permalink
Check if mapcss functions exist
Browse files Browse the repository at this point in the history
Check if mapcss functions exist and have the right number of arguments
  • Loading branch information
Famlam committed Jun 30, 2023
1 parent 4fc59bd commit 9f7cb4f
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
24 changes: 24 additions & 0 deletions mapcss/mapcss2osmose.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from .MapCSSListenerL import MapCSSListenerL
from typing import Dict, List, Set, Optional
from copy import deepcopy
from . import mapcss_lib
from inspect import signature, Parameter


# Clean
Expand Down Expand Up @@ -429,8 +431,30 @@ def functionExpression_runtime(t, c):
"mapcss.round_" if t['name'] == 'round' else
"mapcss." + t['name']
)

if not c.get('flags'):
checkValidFunction(t['name'], len(t['params']))
return t

def checkValidFunction(fn_name, num_params):
"""
Tests if mapcss.* functions actually exist, throws a compile error otherwise
"""
if fn_name[0:7] != "mapcss.":
return
if not fn_name[7:] in dir(mapcss_lib):
raise NotImplementedError("Undefined function '{0}'. Blacklist or implement to avoid runtime errors".format(fn_name))
else:
sig = signature(getattr(mapcss_lib, fn_name[7:]))
argcount = len(sig.parameters) # includes optional arguments
has_vararg = any(map(lambda p: p.kind == Parameter.VAR_POSITIONAL, sig.parameters.values()))
num_optional_arg = len(set(filter(lambda p: p.default != Parameter.empty, sig.parameters.values())))
if has_vararg:
argcount = argcount - 1 # *args can be zero-length
if num_params < argcount - num_optional_arg or (not has_vararg and num_params > argcount):
raise NotImplementedError("Undefined function '{0}' with {1} arguments. Blacklist or implement to avoid runtime errors".format(fn_name, num_params))


rewrite_rules_clean = [
('valueExpression', valueExpression_remove_null_op),
('primaryExpression', primaryExpression_remove_null_op),
Expand Down
16 changes: 16 additions & 0 deletions plugins/tests/test_mapcss_parsing_evalutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,18 @@ def node(self, data, tags):
# assertNoMatch:"node y=world"
err.append({'class': 11, 'subclass': 1778220616, 'text': mapcss.tr('test any {0} {1}', mapcss.any_(mapcss.tag(tags, 'b'), ''), mapcss.any_(mapcss.tag(tags, 'c'), mapcss.tag(tags, 'd'), ''))})

# node[x][substring(tag(x),1)=="bcde"][substring(tag(x),1,3)="bc"]
if ('x' in keys):
match = False
if not match:
capture_tags = {}
try: match = ((mapcss._tag_capture(capture_tags, 0, tags, 'x')) and (mapcss.substring(mapcss.tag(tags, 'x'), 1) == 'bcde') and (mapcss.substring(mapcss.tag(tags, 'x'), 1, 3) == 'bc'))
except mapcss.RuleAbort: pass
if match:
# throwWarning:"test"
# assertMatch:"node x=abcde"
err.append({'class': 6, 'subclass': 770828321, 'text': {'en': 'test'}})

return err

def way(self, data, tags, nds):
Expand Down Expand Up @@ -965,6 +977,9 @@ def relation(self, data, tags, members):
# assertMatch:"relation type=other z=yes"
err.append({'class': 10, 'subclass': 758090756, 'text': mapcss.tr('test closed rewrite {0}', mapcss._tag_uncapture(capture_tags, '{0.tag}'))})

# relation[tag(x)==parent_tag(x)]
# Part of rule not implemented

return err


Expand Down Expand Up @@ -1099,6 +1114,7 @@ class father:
self.check_not_err(n.node(data, {'x': 'hello', 'y': 'world'}), expected={'class': 11, 'subclass': 1778220616})
self.check_err(n.node(data, {'x': 'hello'}), expected={'class': 11, 'subclass': 1778220616})
self.check_not_err(n.node(data, {'y': 'world'}), expected={'class': 11, 'subclass': 1778220616})
self.check_err(n.node(data, {'x': 'abcde'}), expected={'class': 6, 'subclass': 770828321})
self.check_err(n.way(data, {'x': 'C00;C1;C22'}, [0]), expected={'class': 12, 'subclass': 1785050832})
self.check_err(n.way(data, {'x': 'C1'}, [0]), expected={'class': 12, 'subclass': 1785050832})
self.check_not_err(n.way(data, {'x': 'C12'}, [0]), expected={'class': 12, 'subclass': 1785050832})
Expand Down
10 changes: 10 additions & 0 deletions plugins/tests/test_mapcss_parsing_evalutation.validator.mapcss
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,13 @@ node[a] {
assertNoMatch: "node y=world";
assertNoMatch: "node unknownkey=yes";
}

relation[tag(x)==parent_tag(x)] { /*parent_tag not implemented, but blacklisted, should be skipped*/
throwWarning: "test";
assertMatch: "relation a=b c=d";
}

node[x][substring(tag(x), 1) == "bcde"][substring(tag(x), 1, 3) = "bc"] {
throwWarning: "test";
assertMatch: "node x=abcde";
}

0 comments on commit 9f7cb4f

Please sign in to comment.