In [1]:
%cd "/opt/osmose-backend/"
Each plugin is a class inheriting from Plugin
. The class must define:
init(self, logger)
node
, way
or relation
. Method can call each other to factorize the code. But the method are optional.Should define the class of issue. It is meta-information about the produced issues. See general documentation for details.
The tags
argument is a dictionary of OSM tags.
The method should return a dictionary or an array of dictionary of Osmose-QA issues. See general documentation for details. But the returned dictionary must contain:
class
: the same id from the definitionsubclass
optional: to make issue unique if requiredtext
optional: detail about the issuefix
optional: fix suggestion
In [2]:
from plugins.Plugin import Plugin
class Fountain(Plugin):
def init(self, logger):
Plugin.init(self, logger)
# Define meta-information about the produced Osmose issues
self.errors[1] = self.def_class(item = 2020, level = 3, tags = ['tag', 'fix:survey'],
title = T_('Fountain here'),
detail = T_(
'''Nice report of Fountain.'''))
def node(self, data, tags):
if tags.get("amenity") == "fountain":
# When we found OSM object with tag amenity=fountain,
# return Osmose issue of class 1, with name tag issue subtitle
return {"class": 1, "text": T_f("Name: {0}", tags.get("name"))}
def way(self, data, tags, nds):
# Same check as node
return self.node(data, tags)
def relation(self, data, tags, members):
# Same check as node
return self.node(data, tags)
Each plugin should come with unitary test. It checks that the plugin done the expect job. You must call the plugin method with various OSM object definition. For each you must check if the plugin return an Osmose issue or not.
self.check_err(plugin_return, expect_issue)
assert the return of the plugin is valid and match the optional expect_issue
.assert not plugin_return
assert the plugin return nothing
In [3]:
from plugins.Plugin import TestPluginCommon
class Test(TestPluginCommon):
def test(self):
# Instantiate and initialize the Plugin
a = Fountain(None)
a.init(None)
# Assert the OSM object with tag amenity=fountain
# returns an Osmose issue of class 1
self.check_err(
a.node(None, {"amenity": "fountain"}),
{'class': 1}
)
# Assert the plugin return nothing for OSM object with tag natural=peak
assert not a.node(None, {"natural": "peak"})
# Run the test
Test().test() # Returns nothing where it is OK, else error.
To run the analyze we need a context of execution. Each country or area have a entry in the file osmose_config.py
. Parameters from the configuration can be used in the plugin, eg. self.father.config.options.get("phone_code")
.
In [4]:
import osmose_config as config
country_conf = config.config['monaco']
country_conf.init()
country_conf.analyser_options
Out[4]:
The plugins are run by the analyzer "sax". The result can be fetched by Jupyter and displayed. By default it is in Osmose-QA XML format. CSV en GeoJson format are for debug only and have partial content.
In [5]:
from analysers.analyser_sax import Analyser_Sax
from modules.jupyter import *
csv = run(country_conf, Analyser_Sax, plugin = Fountain, format = 'csv')
print_csv(csv)
Out[5]:
In [6]:
geojson = run(country_conf, Analyser_Sax, plugin = Fountain, format = 'geojson')
print_geojson(geojson)
In [ ]: