def handle_main_filters_refmegye(relations: helpers.Relations, refmegye_id: str, refmegye: str) -> yattag.Doc: """Handles one refmegye in the filter part of the main wsgi page.""" doc = yattag.Doc() name = relations.refmegye_get_name(refmegye) if not name: return doc with doc.tag("a", href="/osm/filter-for/refmegye/" + refmegye): doc.text(name) if refmegye_id and refmegye == refmegye_id: reftelepules_ids = relations.refmegye_get_reftelepules_ids(refmegye_id) if reftelepules_ids: names = [] # type: List[yattag.Doc] for reftelepules_id in reftelepules_ids: name = relations.reftelepules_get_name(refmegye_id, reftelepules_id) if name: name_doc = yattag.Doc() href_format = "/osm/filter-for/refmegye/{}/reftelepules/{}" with name_doc.tag("a", href=href_format.format(refmegye, reftelepules_id)): name_doc.text(name) names.append(name_doc) if names: doc.text(" (") for index, item in enumerate(names): if index: doc.text(", ") doc.asis(item.getvalue()) doc.text(")") return doc
def update_missing_housenumbers(relations: helpers.Relations) -> None: """Update the relation's house number coverage stats.""" logging.info("update_missing_housenumbers: start") for relation_name in relations.get_active_names(): relation = relations.get_relation(relation_name) streets = relation.get_config().should_check_missing_streets() if streets == "only": continue relation.write_missing_housenumbers() logging.info("update_missing_housenumbers: end")
def update_street_housenumbers_ref(relations: helpers.Relations, config: configparser.ConfigParser) -> None: """Update the existing reference street housenumber list of all relations.""" for relation_name in relations.get_active_names(): logging.info("update_street_housenumbers_ref: start: %s", relation_name) relation = relations.get_relation(relation_name) reference = config.get('wsgi', 'reference_housenumbers').strip().split(' ') relation.write_ref_housenumbers(reference) logging.info("update_street_housenumbers_ref: end: %s", relation_name)
def missing_housenumbers_view_txt(relations: helpers.Relations, request_uri: str) -> str: """Expected request_uri: e.g. /osm/missing-housenumbers/ormezo/view-result.txt.""" tokens = request_uri.split("/") relation_name = tokens[-2] relation = relations.get_relation(relation_name) output = "" if not os.path.exists(relation.get_files().get_osm_streets_path()): output += _("No existing streets") elif not os.path.exists(relation.get_files().get_osm_housenumbers_path()): output += _("No existing house numbers") elif not os.path.exists(relation.get_files().get_ref_housenumbers_path()): output += _("No reference house numbers") else: ongoing_streets, _ignore = relation.get_missing_housenumbers() table = [] for result in ongoing_streets: if result[1]: result_strings = util.get_housenumber_ranges(result[1]) # Street name, only_in_reference items. if not relation.get_config().get_street_is_even_odd(result[0]): row = result[0] + "\t[" + ", ".join(result_strings) + "]" else: elements = util.format_even_odd(result_strings, doc=None) row = result[0] + "\t[" + "], [".join(elements) + "]" table.append(row) table.sort(key=locale.strxfrm) output += "\n".join(table) return output
def handle_main(request_uri: str, relations: helpers.Relations) -> yattag.Doc: """Handles the main wsgi page. Also handles /osm/filter-for/* which filters for a condition.""" filter_for, refmegye = setup_main_filter_for(request_uri) doc = yattag.Doc() doc.asis(get_toolbar(relations).getvalue()) doc.asis(handle_main_filters(relations, refmegye).getvalue()) table = [] table.append([util.html_escape(_("Area")), util.html_escape(_("House number coverage")), util.html_escape(_("Existing house numbers")), util.html_escape(_("Street coverage")), util.html_escape(_("Existing streets")), util.html_escape(_("Area boundary"))]) for relation_name in relations.get_names(): row = handle_main_relation(relations, filter_for, relation_name) if row: table.append(row) doc.asis(util.html_table_from_list(table).getvalue()) with doc.tag("p"): with doc.tag("a", href="https://github.com/vmiklos/osm-gimmisn/tree/master/doc"): doc.text(_("Add new area")) doc.asis(get_footer().getvalue()) return doc
def handle_street_housenumbers(relations: helpers.Relations, request_uri: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/street-housenumbers/ormezo/view-query.""" tokens = request_uri.split("/") relation_name = tokens[-2] action = tokens[-1] relation = relations.get_relation(relation_name) osmrelation = relation.get_config().get_osmrelation() doc = yattag.Doc() doc.asis(get_toolbar(relations, "street-housenumbers", relation_name, osmrelation).getvalue()) if action == "view-query": with doc.tag("pre"): doc.text(relation.get_osm_housenumbers_query()) elif action == "view-result": with relation.get_files().get_osm_housenumbers_stream(mode="r") as sock: table = util.tsv_to_list(sock) doc.asis(util.html_table_from_list(table).getvalue()) elif action == "update-result": query = relation.get_osm_housenumbers_query() try: relation.get_files().write_osm_housenumbers(overpass_query.overpass_query(query)) doc.text(_("Update successful: ")) link = "/osm/missing-housenumbers/" + relation_name + "/view-result" doc.asis(util.gen_link(link, _("View missing house numbers")).getvalue()) except urllib.error.HTTPError as http_error: doc.asis(util.handle_overpass_error(http_error).getvalue()) date = get_housenumbers_last_modified(relation) doc.asis(get_footer(date).getvalue()) return doc
def handle_missing_housenumbers(relations: helpers.Relations, request_uri: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-housenumbers/ormezo/view-[result|query].""" tokens = request_uri.split("/") relation_name = tokens[-2] action = tokens[-1] date = None relation = relations.get_relation(relation_name) osmrelation = relation.get_config().get_osmrelation() doc = yattag.Doc() doc.asis(get_toolbar(relations, "missing-housenumbers", relation_name, osmrelation).getvalue()) if action == "view-result": doc.asis(missing_housenumbers_view_res(relations, request_uri).getvalue()) elif action == "view-turbo": doc.asis(missing_housenumbers_view_turbo(relations, request_uri).getvalue()) elif action == "view-query": with doc.tag("pre"): with relation.get_files().get_ref_housenumbers_stream("r") as sock: doc.text(sock.read()) date = get_last_modified(relation.get_files().get_ref_housenumbers_path()) elif action == "update-result": doc.asis(missing_housenumbers_update(relations, relation_name).getvalue()) if not date: date = ref_housenumbers_last_modified(relations, relation_name) doc.asis(get_footer(date).getvalue()) return doc
def missing_relations_view_result(relations: helpers.Relations, request_uri: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-streets/budapest_11/view-result.""" tokens = request_uri.split("/") relation_name = tokens[-2] relation = relations.get_relation(relation_name) doc = yattag.Doc() if not os.path.exists(relation.get_files().get_osm_streets_path()): doc.text(_("No existing streets: ")) with doc.tag("a", href="/osm/streets/" + relation_name + "/update-result"): doc.text(_("Call Overpass to create")) elif not os.path.exists(relation.get_files().get_ref_streets_path()): doc.text(_("No street list: ")) with doc.tag("a", href="/osm/missing-streets/" + relation_name + "/update-result"): doc.text(_("Create from reference")) else: ret = relation.write_missing_streets() todo_count, done_count, percent, streets = ret streets.sort(key=locale.strxfrm) table = [[util.html_escape(_("Street name"))]] for street in streets: table.append([util.html_escape(street)]) with doc.tag("p"): doc.text(_("OpenStreetMap is possibly missing the below {0} streets.").format(str(todo_count))) doc.text(_(" (existing: {0}, ready: {1}%).").format(str(done_count), str(percent))) doc.asis(util.html_table_from_list(table).getvalue()) return doc
def handle_main_relation( relations: helpers.Relations, filter_for: Callable[[bool, helpers.Relation], bool], relation_name: str ) -> List[yattag.Doc]: """Handles one relation (one table row) on the main page.""" relation = relations.get_relation(relation_name) complete = True streets = relation.get_config().should_check_missing_streets() row = [] # List[yattag.Doc] row.append(util.html_escape(relation_name)) if streets != "only": cell, percent = handle_main_housenr_percent(relation) doc = yattag.Doc() doc.asis(cell.getvalue()) row.append(doc) if float(percent) < 100.0: complete = False date = get_housenumbers_last_modified(relation) doc = yattag.Doc() href = "/osm/street-housenumbers/" + relation_name + "/view-result" with doc.tag("a", href=href, title=_("updated") + " " + date): doc.text(_("existing house numbers")) row.append(doc) else: row.append(yattag.Doc()) row.append(yattag.Doc()) if streets != "no": cell, percent = handle_main_street_percent(relation) row.append(cell) if float(percent) < 100.0: complete = False else: row.append(yattag.Doc()) date = get_streets_last_modified(relation) doc = yattag.Doc() with doc.tag("a", href="/osm/streets/" + relation_name + "/view-result", title=_("updated") + " " + date): doc.text(_("existing streets")) row.append(doc) doc = yattag.Doc() with doc.tag("a", href="https://www.openstreetmap.org/relation/" + str(relation.get_config().get_osmrelation())): doc.text(_("area boundary")) row.append(doc) if not filter_for(complete, relation): row.clear() return row
def update_streets(relations: helpers.Relations) -> None: """Update the existing street list of all relations.""" for relation_name in relations.get_active_names(): logging.info("update_streets: start: %s", relation_name) relation = relations.get_relation(relation_name) retry = 0 while should_retry(retry): if retry > 0: logging.info("update_streets: try #%s", retry) retry += 1 try: overpass_sleep() query = relation.get_osm_streets_query() relation.get_files().write_osm_streets( overpass_query.overpass_query(query)) break except urllib.error.HTTPError as http_error: logging.info("update_streets: http error: %s", str(http_error)) logging.info("update_streets: end: %s", relation_name)
def missing_housenumbers_update(relations: helpers.Relations, relation_name: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-housenumbers/ormezo/update-result.""" reference = get_config().get('wsgi', 'reference_housenumbers').strip().split(' ') reference = [util.get_abspath(i) for i in reference] relation = relations.get_relation(relation_name) relation.write_ref_housenumbers(reference) doc = yattag.Doc() doc.text(_("Update successful: ")) link = "/osm/missing-housenumbers/" + relation_name + "/view-result" doc.asis(util.gen_link(link, _("View missing house numbers")).getvalue()) return doc
def missing_housenumbers_view_turbo(relations: helpers.Relations, request_uri: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-housenumbers/ormezo/view-turbo.""" tokens = request_uri.split("/") relation_name = tokens[-2] doc = yattag.Doc() relation = relations.get_relation(relation_name) ret = relation.write_missing_housenumbers() _todo_street_count, _todo_count, _done_count, _percent, table = ret query = helpers.make_turbo_query_for_streets(relation, table) with doc.tag("pre"): doc.text(query) return doc
def missing_streets_view_txt(relations: helpers.Relations, request_uri: str) -> str: """Expected request_uri: e.g. /osm/missing-streets/ujbuda/view-result.txt.""" tokens = request_uri.split("/") relation_name = tokens[-2] relation = relations.get_relation(relation_name) output = "" if not os.path.exists(relation.get_files().get_osm_streets_path()): output += _("No existing streets") elif not os.path.exists(relation.get_files().get_ref_streets_path()): output += _("No reference streets") else: todo_streets, _ignore = relation.get_missing_streets() todo_streets.sort(key=locale.strxfrm) output += "\n".join(todo_streets) return output
def handle_main_filters(relations: helpers.Relations, refmegye_id: str) -> yattag.Doc: """Handlers the filter part of the main wsgi page.""" items = [] # type: List[yattag.Doc] doc = yattag.Doc() with doc.tag("a", href="/osm/filter-for/incomplete"): doc.text(_("Hide complete areas")) items.append(doc) # Sorted set of refmegye values of all relations. for refmegye in sorted({relation.get_config().get_refmegye() for relation in relations.get_relations()}): items.append(handle_main_filters_refmegye(relations, refmegye_id, refmegye)) doc = yattag.Doc() with doc.tag("h1"): doc.text(_("Where to map?")) with doc.tag("p"): doc.text(_("Filters:") + " ") for index, item in enumerate(items): if index: doc.text(" ¦ ") doc.asis(item.getvalue()) return doc
def missing_housenumbers_view_res(relations: helpers.Relations, request_uri: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-housenumbers/ormezo/view-result.""" tokens = request_uri.split("/") relation_name = tokens[-2] doc = yattag.Doc() relation = relations.get_relation(relation_name) if not os.path.exists(relation.get_files().get_osm_streets_path()): doc.text(_("No existing streets: ")) link = "/osm/streets/" + relation_name + "/update-result" doc.asis(util.gen_link(link, _("Call Overpass to create")).getvalue()) elif not os.path.exists(relation.get_files().get_osm_housenumbers_path()): doc.text(_("No existing house numbers: ")) link = "/osm/street-housenumbers/" + relation_name + "/update-result" doc.asis(util.gen_link(link, _("Call Overpass to create")).getvalue()) elif not os.path.exists(relation.get_files().get_ref_housenumbers_path()): doc.text(_("No missing house numbers: ")) link = "/osm/missing-housenumbers/" + relation_name + "/update-result" doc.asis(util.gen_link(link, _("Create from reference")).getvalue()) else: ret = relation.write_missing_housenumbers() todo_street_count, todo_count, done_count, percent, table = ret with doc.tag("p"): doc.text(_("OpenStreetMap is possibly missing the below {0} house numbers for {1} streets.") .format(str(todo_count), str(todo_street_count))) doc.text(_(" (existing: {0}, ready: {1}%).").format(str(done_count), str(percent))) doc.stag("br") with doc.tag("a", href="https://github.com/vmiklos/osm-gimmisn/tree/master/doc"): doc.text(_("Filter incorrect information")) doc.text(".") doc.stag("br") with doc.tag("a", href="/osm/missing-housenumbers/{}/view-turbo".format(relation_name)): doc.text(_("Overpass turbo query for the below streets")) doc.text(".") doc.asis(util.html_table_from_list(table).getvalue()) return doc
def missing_streets_update(relations: helpers.Relations, relation_name: str) -> yattag.Doc: """Expected request_uri: e.g. /osm/missing-streets/ujbuda/update-result.""" reference = util.get_abspath(get_config().get('wsgi', 'reference_street').strip()) relation = relations.get_relation(relation_name) relation.write_ref_streets(reference) return util.html_escape(_("Update successful."))
def synonyms(): """QUERY""" word = request.args.get("word").lower() if word not in wordPath_list: wordPath_list.append(word) # To create word path original_word = wordPath_list[0] """GET SYNONYMS""" # Get result try: results = Word(word) except exceptions.MisspellingError as msplt: session.clear() # return render_template("errorRedirect.html", error=msplt) session['mspltError'] = str(msplt) return redirect(f'/related?word={word}') except exceptions.WordNotFoundError as wnf: session.clear() session['wnf'] = str(wnf) return redirect(f'/related?word={word}') results = Word(word) resultData = results.data # session['word'] = word # To reuse in "/result" # Constructing parameters: part of speech and definitions numberOfOptions = len(results) partsOfSpeech = [ item['partOfSpeech'].strip('.') for item in resultData ] #.strip because for example, in html, div id = "adj.1" will not function. it is supposed to be adj1 definitions = [item['meaning'] for item in resultData] # Constructing parameters: synonyms for each part of speech and definitions synList = results.synonyms('all') flat_synList = [ item for sublist in synList for item in sublist ] # Nothing to do with this part. This is for the next part GET RELATED WORDS! """GET RELATED WORDS""" # Result from helpers Related_words_data = RelatedWords(word) # Filter results: No overlapping with Synonyms, restricted to 10 words, with score rounded Related_words_data = [ item for item in Related_words_data if item['word'] not in flat_synList ] # Avoid overlap with Synonyms Related_words_data = Related_words_data[: 10] # Trimming to avoid irrelevant results # Rounding the 'score' values in the above dict results Related_words_data for item in Related_words_data: item['score'] = round(item['score'], 2) """GET RELATED CONCEPTS""" concepts = Relations("_".join( word.split())) # For example, "eat mice " becomes "eat_mice" # Process data: Get the lists of relations id and relations label relations_list_id = [] for item in concepts: if item['rel']['@id'] not in relations_list_id: relations_list_id.append(item['rel']['@id']) relations_list_label = [] for item in concepts: if item['rel']['label'] not in relations_list_label: relations_list_label.append(item['rel']['label']) # Rounding the 'weight' values to display better in html for item in concepts: item['weight'] = round(item['weight'], 2) # Change the labels to normal (eg. RelatedTo to "is related to") for easier printing out in html label_dict = { 'RelatedTo': 'is related to', 'ExternalURL': 'can be linked to other sites', 'FormOf': 'is a form of', 'IsA': 'is a', 'PartOf': 'is a part of', 'HasA': 'has', 'UsedFor': 'is used for', 'CapableOf': 'is capable of', 'AtLocation': 'can be found in', 'Causes': 'can lead to', 'HasSubevent': 'is followed by', 'HasFirstSubevent': 'starts with', 'HasLastSubevent': 'ends with', 'HasPrerequisite': 'requires', 'HasProperty': 'has property or can be described as', 'MotivatedByGoal': 'in order to', 'ObstructedBy': 'is prevented by', 'Desires': 'typically wants', 'CreatedBy': 'is created by', 'Synonym': 'has similar meaning with', 'Antonym': 'has opposite meaning with', 'DistinctFrom': 'is distinct from', 'SymbolOf': 'is a symbol of', 'DefinedAs': 'can be defined or explained as', 'Entails': 'entails', 'MannerOf': 'is a way of', 'LocatedNear': 'can be found near', 'HasContext': 'is often used in', 'SimilarTo': 'is similar to', 'EtymologicallyRelatedTo': 'has common origin with', 'EtymologicallyDerivedFrom': 'is derived from', 'CausesDesire': 'makes someone want', 'MadeOf': 'is made of', 'ReceivesAction': 'can be', 'InstanceOf': 'is an example of', 'NotDesires': 'typically not want', 'DerivedFrom': 'is derived from' } # Build a dictionary and use it to look up relation labels # Create a new list as a copy of label lists to store real relation list labels, eg 'RelatedTo' to 'is related to' real_relations_list_label_names = relations_list_label.copy() for i in range(len( relations_list_label)): # Populate the list of real relation names if relations_list_label[i] in label_dict.keys(): real_relations_list_label_names[i] = label_dict[ relations_list_label[i]] # List of start node start_node_list = [] for item in concepts: if item['start']['label'] not in start_node_list: start_node_list.append(item['start']['label']) # List for each relation concept_network = {} for item in relations_list_label: concept_network[item] = [ ] # Initiate a list as value for each key/relation for item in relations_list_label: for edge in concepts: if item == edge['rel']['label']: obj_to_append = dict( (i, edge[i]) for i in ('start', 'end', 'rel', 'weight')) # Only take the important stuff concept_network[item].append(obj_to_append) # Problem: sometimes the word queried is 'start', other times it is 'end' word_start_or_end = {} for i in range(len(relations_list_label)): for j in range(len(concept_network[relations_list_label[i]])): if word in concept_network[ relations_list_label[i]][j]['end']['label']: word_start_or_end[relations_list_label[i]] = 'end' else: word_start_or_end[relations_list_label[i]] = 'start' # Return return render_template("results.html", partsOfSpeech=partsOfSpeech, definitions=definitions, synList=synList, numberOfOptions=numberOfOptions, \ resultData=resultData, Related_words_data=Related_words_data, relations_list_label=relations_list_label, concept_network=concept_network, \ real_relations_list_label_names=real_relations_list_label_names, word_start_or_end=word_start_or_end, original_word=original_word, word=word, wordPath_list=wordPath_list)
def related(): """In case misspelling error of the queried word, which return no synonyms""" # Clear word path because it doesn't mean anything now """QUERY""" word = request.args.get("word").lower() if word not in wordPath_list: wordPath_list.append(word) # To create word path original_word = wordPath_list[0] """GET SYNONYMS""" for key in session: if key == 'mspltError': word_suggest = session['mspltError'].split("mean '")[1].split( "'?")[0] else: word_suggest = '' # This is the old way, when we didn't have Word not found error exception """ if session['mspltError'] != '': word_suggest = session['mspltError'].split("mean '")[1].split("'?")[0] # Get the word suggested after the error is shown else: word_suggest = '' """ """GET RELATED WORDS""" # Result from helpers Related_words_data = RelatedWords(word) # Filter results: No overlapping with Synonyms, restricted to 10 words, with score rounded Related_words_data = [item for item in Related_words_data ] # Avoid overlap with Synonyms Related_words_data = Related_words_data[: 10] # Trimming to avoid irrelevant results # Rounding the 'score' values in the above dict results Related_words_data for item in Related_words_data: item['score'] = round(item['score'], 2) """GET RELATIONS""" concepts = Relations("_".join(word.split())) # Process data: Get the lists of relations id and relations label relations_list_id = [] for item in concepts: if item['rel']['@id'] not in relations_list_id: relations_list_id.append(item['rel']['@id']) relations_list_label = [] for item in concepts: if item['rel']['label'] not in relations_list_label: relations_list_label.append(item['rel']['label']) # Rounding the 'weight' values to display better in html for item in concepts: item['weight'] = round(item['weight'], 2) # Change the labels to normal (eg. RelatedTo to "is related to") for easier printing out in html label_dict = { 'RelatedTo': 'is related to', 'ExternalURL': 'can be linked to other sites', 'FormOf': 'is a form of', 'IsA': 'is a', 'PartOf': 'is a part of', 'HasA': 'has', 'UsedFor': 'is used for', 'CapableOf': 'is capable of', 'NotCapableOf': 'is not capable of', 'AtLocation': 'can be found in', 'Causes': 'can lead to', 'HasSubevent': 'is followed by', 'HasFirstSubevent': 'starts with', 'HasLastSubevent': 'ends with', 'HasPrerequisite': 'requires', 'HasProperty': 'has property or can be described as', 'MotivatedByGoal': 'in order to', 'ObstructedBy': 'is prevented by', 'Desires': 'typically wants', 'CreatedBy': 'is created by', 'Synonym': 'has similar meaning with', 'Antonym': 'has opposite meaning with', 'DistinctFrom': 'is distinct from', 'SymbolOf': 'is a symbol of', 'DefinedAs': 'can be defined or explained as', 'Entails': 'entails', 'MannerOf': 'is a way of', 'LocatedNear': 'can be found near', 'HasContext': 'is often used in', 'SimilarTo': 'is similar to', 'EtymologicallyRelatedTo': 'has common origin with', 'EtymologicallyDerivedFrom': 'is derived from', 'CausesDesire': 'makes someone want', 'MadeOf': 'is made of', 'ReceivesAction': 'can be', 'InstanceOf': 'is an example of', 'NotDesires': 'typically not want', 'DerivedFrom': 'is derived from' } # Build a dictionary and use it to look up relation labels # Create a new list as a copy of label lists to store real relation list labels, eg 'RelatedTo' to 'is related to' real_relations_list_label_names = relations_list_label.copy() for i in range(len( relations_list_label)): # Populate the list of real relation names if relations_list_label[i] in label_dict.keys(): real_relations_list_label_names[i] = label_dict[ relations_list_label[i]] # List of start node start_node_list = [] for item in concepts: if item['start']['label'] not in start_node_list: start_node_list.append(item['start']['label']) # List for each relation concept_network = {} for item in relations_list_label: concept_network[item] = [ ] # Initiate a list as value for each key/relation for item in relations_list_label: for edge in concepts: if item == edge['rel']['label']: obj_to_append = dict( (i, edge[i]) for i in ('start', 'end', 'rel', 'weight')) # Only take the important stuff concept_network[item].append(obj_to_append) # Problem: sometimes the word queried is 'start', other times it is 'end' word_start_or_end = {} for i in range(len(relations_list_label)): for j in range(len(concept_network[relations_list_label[i]])): if word in concept_network[ relations_list_label[i]][j]['end']['label']: word_start_or_end[relations_list_label[i]] = 'end' else: word_start_or_end[relations_list_label[i]] = 'start' # Return return render_template("related.html", word_suggest=word_suggest, Related_words_data=Related_words_data, relations_list_label=relations_list_label, concept_network=concept_network, \ real_relations_list_label_names=real_relations_list_label_names, word_start_or_end=word_start_or_end, original_word=original_word, word=word, wordPath_list=wordPath_list)
def ref_housenumbers_last_modified(relations: helpers.Relations, name: str) -> str: """Gets the update date for missing house numbers.""" relation = relations.get_relation(name) t_ref = get_timestamp(relation.get_files().get_ref_housenumbers_path()) t_housenumbers = get_timestamp(relation.get_files().get_osm_housenumbers_path()) return format_timestamp(max(t_ref, t_housenumbers))