364 lines
11 KiB
Python
364 lines
11 KiB
Python
import unittest
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add `src` directory to the import paths
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / 'src'))
|
|
|
|
from mapcss import parseDeclaration, MapCSS
|
|
|
|
|
|
class MapCSSTest(unittest.TestCase):
|
|
def test_declarations(self):
|
|
decl = parseDeclaration(""" linejoin: round; """)
|
|
self.assertEqual(len(decl), 1)
|
|
self.assertEqual(decl[0], {"linejoin": "round"})
|
|
|
|
decl = parseDeclaration("""\tlinejoin :\nround ; """)
|
|
self.assertEqual(len(decl), 1)
|
|
self.assertEqual(decl[0], {"linejoin": "round"})
|
|
|
|
decl = parseDeclaration(""" icon-image: parking_private-s.svg; text: "name"; """)
|
|
self.assertEqual(len(decl), 1)
|
|
self.assertEqual(decl[0], {
|
|
"icon-image": "parking_private-s.svg",
|
|
"text": "name"
|
|
})
|
|
|
|
decl = parseDeclaration("""
|
|
pattern-offset: 90\t;
|
|
pattern-image:\tarrow-m.svg ;
|
|
pattern-spacing: @trunk0 ;""")
|
|
self.assertEqual(len(decl), 1)
|
|
self.assertEqual(decl[0], {
|
|
"pattern-offset": "90",
|
|
"pattern-image": "arrow-m.svg",
|
|
"pattern-spacing": "@trunk0",
|
|
})
|
|
|
|
def test_parse_variables(self):
|
|
parser = MapCSS()
|
|
parser.parse("""
|
|
@city_label: #999999;
|
|
@country_label: #444444;
|
|
@wave_length: 25;
|
|
""")
|
|
self.assertEqual(parser.variables, {
|
|
"city_label": "#999999",
|
|
"country_label": "#444444",
|
|
"wave_length": "25"
|
|
})
|
|
|
|
def test_parse_colors(self):
|
|
parser = MapCSS()
|
|
parser.parse("""
|
|
@city_label : #999999;
|
|
@country_label: #444444 ;
|
|
@wave_length: 25;
|
|
""")
|
|
self.assertEqual(parser.variables, {
|
|
"city_label": "#999999",
|
|
"country_label": "#444444",
|
|
"wave_length": "25"
|
|
})
|
|
|
|
def test_parse_import(self):
|
|
parser = MapCSS()
|
|
mapcssFile = Path(__file__).parent / 'assets' / 'case-1-import' / 'main.mapcss'
|
|
parser.parse(filename=str(mapcssFile))
|
|
|
|
colors = parser.get_colors()
|
|
self.assertEqual(colors, {
|
|
"GuiText-color": (1.0, 1.0, 1.0),
|
|
"GuiText-opacity": 0.7,
|
|
"Route-color": (0.0, 0.0, 1.0),
|
|
"Route-opacity": 0.5,
|
|
})
|
|
|
|
def test_parse_basic_chooser(self):
|
|
parser = MapCSS()
|
|
static_tags = {"tourism": True, "office": True,
|
|
"craft": True, "amenity": True}
|
|
parser.parse("""
|
|
node|z17-[tourism],
|
|
area|z17-[tourism],
|
|
node|z18-[office],
|
|
area|z18-[office],
|
|
node|z18-[craft],
|
|
area|z18-[craft],
|
|
node|z19-[amenity],
|
|
area|z19-[amenity],
|
|
{text: name; text-color: #000030; text-offset: 1;}
|
|
""", static_tags=static_tags)
|
|
|
|
self.assertEqual(len(parser.choosers), 1)
|
|
self.assertEqual(len(parser.choosers[0].ruleChains), 8)
|
|
|
|
def test_parse_basic_chooser_2(self):
|
|
parser = MapCSS()
|
|
static_tags = {"highway": True}
|
|
parser.parse("""
|
|
@trunk0: #FF7326;
|
|
|
|
line|z6[highway=trunk],
|
|
line|z6[highway=motorway],
|
|
{color: @trunk0; opacity: 0.3;}
|
|
line|z7-9[highway=trunk],
|
|
line|z7-9[highway=motorway],
|
|
{color: @trunk0; opacity: 0.7;}
|
|
""", static_tags=static_tags)
|
|
|
|
self.assertEqual(len(parser.choosers), 2)
|
|
self.assertEqual(len(parser.choosers[0].ruleChains), 2)
|
|
self.assertEqual(parser.choosers[0].ruleChains[0].subject, 'line')
|
|
self.assertEqual(parser.choosers[0].selzooms, [6, 6])
|
|
self.assertEqual(parser.choosers[1].selzooms, [7, 9])
|
|
|
|
rule, object_id = parser.choosers[0].testChains({"highway": "trunk"})
|
|
self.assertEqual(object_id, "::default")
|
|
|
|
def test_parse_basic_chooser_3(self):
|
|
parser = MapCSS()
|
|
static_tags = {"addr:housenumber": True, "addr:street": False}
|
|
parser.parse("""
|
|
/* Some Comment Here */
|
|
|
|
/*
|
|
This sample is borrowed from Organic Maps Basemap_label.mapcss file
|
|
*/
|
|
node|z18-[addr:housenumber][addr:street]::int_name
|
|
{text: int_name; text-color: #65655E; text-position: center;}
|
|
""", static_tags=static_tags)
|
|
|
|
building_tags = {"building": "yes", "addr:housenumber": "12", "addr:street": "Baker street"}
|
|
|
|
# Check that mapcss parsed correctly
|
|
self.assertEqual(len(parser.choosers), 1)
|
|
styleChooser = parser.choosers[0]
|
|
self.assertEqual(len(styleChooser.ruleChains), 1)
|
|
self.assertEqual(styleChooser.selzooms, [18, 19])
|
|
rule, object_id = styleChooser.testChains(building_tags)
|
|
self.assertEqual(object_id, "::int_name")
|
|
|
|
rule = styleChooser.ruleChains[0]
|
|
self.assertEqual(rule.subject, 'node')
|
|
self.assertEqual(rule.extract_tags(), {'addr:housenumber', 'addr:street'})
|
|
|
|
def test_parse_basic_chooser_class(self):
|
|
parser = MapCSS()
|
|
parser.parse("""
|
|
way|z-13::*
|
|
{
|
|
linejoin: round;
|
|
}
|
|
""")
|
|
|
|
# Check that mapcss parsed correctly
|
|
self.assertEqual(len(parser.choosers), 1)
|
|
styleChooser = parser.choosers[0]
|
|
self.assertEqual(len(styleChooser.ruleChains), 1)
|
|
self.assertEqual(styleChooser.selzooms, [0, 13])
|
|
rule, object_id = styleChooser.testChains({})
|
|
self.assertEqual(object_id, "::*")
|
|
|
|
rule = styleChooser.ruleChains[0]
|
|
self.assertEqual(rule.subject, 'way')
|
|
self.assertEqual(rule.extract_tags(), {'*'})
|
|
|
|
def test_parse_basic_chooser_class_2(self):
|
|
parser = MapCSS()
|
|
parser.parse("""
|
|
way|z10-::*
|
|
{
|
|
linejoin: round;
|
|
}
|
|
""")
|
|
|
|
# Check that mapcss parsed correctly
|
|
self.assertEqual(len(parser.choosers), 1)
|
|
styleChooser = parser.choosers[0]
|
|
self.assertEqual(len(styleChooser.ruleChains), 1)
|
|
self.assertEqual(styleChooser.selzooms, [10, 19])
|
|
rule, object_id = styleChooser.testChains({})
|
|
self.assertEqual(object_id, "::*")
|
|
|
|
rule = styleChooser.ruleChains[0]
|
|
self.assertEqual(rule.subject, 'way')
|
|
self.assertEqual(rule.extract_tags(), {'*'})
|
|
|
|
def test_parse_basic_chooser_colors(self):
|
|
parser = MapCSS()
|
|
parser.parse("""
|
|
way|z-6::*
|
|
{
|
|
linejoin: round;
|
|
}
|
|
|
|
colors {
|
|
GuiText-color: #FFFFFF;
|
|
GuiText-opacity: 0.7;
|
|
MyPositionAccuracy-color: #FFFFFF;
|
|
MyPositionAccuracy-opacity: 0.06;
|
|
Selection-color: #FFFFFF;
|
|
Selection-opacity: 0.64;
|
|
Route-color: #0000FF;
|
|
RouteOutline-color: #00FFFF;
|
|
}
|
|
""")
|
|
|
|
# Check that colors from mapcss parsed correctly
|
|
colors = parser.get_colors()
|
|
self.assertEqual(colors, {
|
|
"GuiText-color": (1.0, 1.0, 1.0),
|
|
"GuiText-opacity": 0.7,
|
|
"MyPositionAccuracy-color": (1.0, 1.0, 1.0),
|
|
"MyPositionAccuracy-opacity": 0.06,
|
|
"Selection-color": (1.0, 1.0, 1.0),
|
|
"Selection-opacity": 0.64,
|
|
"Route-color": (0.0, 0.0, 1.0),
|
|
"RouteOutline-color": (0.0, 1.0, 1.0)
|
|
})
|
|
|
|
def test_parser_choosers_tree(self):
|
|
parser = MapCSS()
|
|
static_tags = {"tourism": True, "office": True,
|
|
"craft": True, "amenity": True}
|
|
|
|
parser.parse("""
|
|
node|z17-[office=lawyer],
|
|
area|z17-[office=lawyer],
|
|
{text: name;text-color: #444444;text-offset: 1;font-size: 10;}
|
|
|
|
node|z17-[tourism],
|
|
area|z17-[tourism],
|
|
node|z18-[office],
|
|
area|z18-[office],
|
|
node|z18-[craft],
|
|
area|z18-[craft],
|
|
node|z19-[amenity],
|
|
area|z19-[amenity],
|
|
{text: name; text-color: #000030; text-offset: 1;}
|
|
|
|
node|z18-[office],
|
|
area|z18-[office],
|
|
node|z18-[craft],
|
|
area|z18-[craft],
|
|
{font-size: 11;}
|
|
|
|
node|z17-[office=lawyer],
|
|
area|z17-[office=lawyer]
|
|
{icon-image: lawyer-m.svg;}
|
|
""", static_tags=static_tags)
|
|
|
|
for obj_type in ["line", "area", "node"]:
|
|
parser.build_choosers_tree("tourism", obj_type, "tourism")
|
|
parser.build_choosers_tree("office", obj_type, "office")
|
|
parser.build_choosers_tree("craft", obj_type, "craft")
|
|
parser.build_choosers_tree("amenity", obj_type, "amenity")
|
|
|
|
parser.finalize_choosers_tree()
|
|
|
|
# Pick style for zoom = 17
|
|
styles18 = parser.get_style("office", "node", {"office": "lawyer"},
|
|
zoom=18, xscale=1, zscale=1, filter_by_runtime_conditions=False)
|
|
|
|
self.assertEqual(len(styles18), 1),
|
|
self.assertEqual(styles18[0], {'object-id': '::default',
|
|
'font-size': '11',
|
|
'text': 'name',
|
|
'text-color': (0, 0, 16*3/255),
|
|
'text-offset': 1.0,
|
|
'icon-image': 'lawyer-m.svg'})
|
|
|
|
# Pick style for zoom = 17
|
|
styles17 = parser.get_style("office", "node", {"office": "lawyer"},
|
|
zoom=17, xscale=1, zscale=1, filter_by_runtime_conditions=False)
|
|
|
|
self.assertEqual(len(styles17), 1),
|
|
self.assertEqual(styles17[0], {'object-id': '::default',
|
|
'font-size': '10',
|
|
'text': 'name',
|
|
'text-color': (68/255, 68/255, 68/255),
|
|
'text-offset': 1.0,
|
|
'icon-image': 'lawyer-m.svg'})
|
|
|
|
# Pick style for zoom = 15
|
|
styles15 = parser.get_style("office", "node", {"office": "lawyer"},
|
|
zoom=15, xscale=1, zscale=1, filter_by_runtime_conditions=False)
|
|
|
|
self.assertEqual(styles15, []),
|
|
|
|
def test_parser_choosers_tree_with_classes(self):
|
|
parser = MapCSS()
|
|
static_tags = {"highway": True}
|
|
|
|
parser.parse("""
|
|
line|z10-[highway=motorway]::shield,
|
|
line|z10-[highway=trunk]::shield,
|
|
line|z10-[highway=motorway_link]::shield,
|
|
line|z10-[highway=trunk_link]::shield,
|
|
line|z10-[highway=primary]::shield,
|
|
line|z11-[highway=primary_link]::shield,
|
|
line|z12-[highway=secondary]::shield,
|
|
line|z13-[highway=tertiary]::shield,
|
|
line|z15-[highway=residential]::shield,
|
|
{
|
|
shield-font-size: 9;
|
|
shield-text-color: #000000;
|
|
shield-text-halo-radius: 0;
|
|
shield-color: #FFFFFF;
|
|
shield-outline-radius: 1;
|
|
}
|
|
|
|
line|z12-[highway=residential],
|
|
line|z12-[highway=tertiary],
|
|
line|z18-[highway=tertiary_link]
|
|
{
|
|
text: name;
|
|
text-color: #333333;
|
|
text-halo-opacity: 0.8;
|
|
text-halo-radius: 1;
|
|
}
|
|
|
|
line|z12-13[highway=residential],
|
|
line|z12-13[highway=tertiary]
|
|
{
|
|
font-size: 12;
|
|
text-color: #444444;
|
|
}
|
|
""", static_tags=static_tags)
|
|
|
|
parser.build_choosers_tree("highway", "line", "highway")
|
|
parser.finalize_choosers_tree()
|
|
|
|
# Pick style for zoom = 10
|
|
styles10 = parser.get_style("highway", "line", {"highway": "primary"},
|
|
zoom=10, xscale=1, zscale=1, filter_by_runtime_conditions=False)
|
|
|
|
self.assertEqual(len(styles10), 1),
|
|
self.assertEqual(styles10[0], {'object-id': '::shield',
|
|
'shield-font-size': '9',
|
|
'shield-text-color': (0.0, 0.0, 0.0),
|
|
'shield-text-halo-radius': 0.0,
|
|
'shield-color': (1.0, 1.0, 1.0),
|
|
'shield-outline-radius': 1.0})
|
|
|
|
# Pick style for zoom = 15. Expecting two `object-id` values: '::shield' and '::default'
|
|
styles15 = parser.get_style("highway", "line", {"highway": "tertiary"},
|
|
zoom=15, xscale=1, zscale=1, filter_by_runtime_conditions=False)
|
|
|
|
self.assertEqual(len(styles15), 2),
|
|
self.assertEqual(styles15[0], {'object-id': '::shield',
|
|
'shield-font-size': '9',
|
|
'shield-text-color': (0.0, 0.0, 0.0),
|
|
'shield-text-halo-radius': 0.0,
|
|
'shield-color': (1.0, 1.0, 1.0),
|
|
'shield-outline-radius': 1.0})
|
|
self.assertEqual(styles15[1], {'object-id': '::default',
|
|
'text': 'name',
|
|
'text-color': (51/255, 51/255, 51/255),
|
|
'text-halo-opacity': 0.8,
|
|
'text-halo-radius': 1.0})
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|