def __init__(self, postal_code: str): """ Constructor / Instantiate the class Parameters ---------- postal_code : str postal code to be searched """ try: super().__init__() Assertor.assert_data_types([postal_code], [str]) self._postal_code = postal_code self.validate_postal_code() LOGGER.success("created '{}', with id: [{}]".format( self.__class__.__name__, self.id_)) except Exception as posten_exception: LOGGER.exception(posten_exception) raise posten_exception
def __add__(self, other): """ addition helper method Parameters ---------- other : Amount other Amount object Returns ------- out : str sum of amount in object and amount in other object """ Assertor.assert_data_types([other], [type(self)]) return self.format_amount( str( Decimal(self.amount.replace(" ", "")) + Decimal(other.amount.replace(" ", ""))))
def __init__(self, data: dict): """ Constructor / Instantiate the class. Parameters ---------- data : dict information about the family, i.e. arguments to be passed to Family object """ self.start_process() super().__init__(name=__class__.__name__) Assertor.assert_data_types([data], [dict]) self.input_operation({"data": data}) self.validate_family() self._base_expenses = self.scrape_sifo_base_expenses() self.extract() self._expenses_shares = self.divide() self.output_operation() self.end_process()
def __init__(self, numerator: dict, denominator: dict, desc: str): """ Constructor / Instantiate the class. Parameters ---------- numerator : dict quantity denominator : dict divisor assumed to be of length one desc : str description """ self.name = self.__class__.__name__ Assertor.assert_data_types([numerator, denominator, desc], [dict, dict, str]) super().__init__(name=self.name, desc="id: {}".format(desc)) self.numerator = numerator self.denominator = denominator
def set_combo_box(self, combo_box_name: str, common_key: str = None, key_name: str = None): """ method for setting value in single combo_box Parameters ---------- combo_box_name : str name of combo_box common_key : str, None common data key to append all values key_name : str, None customized name of key """ try: Assertor.assert_data_types([combo_box_name, common_key, key_name], [str, (type(None), str), (type(None), str)]) combo_box_text = str( getattr(self.parent.ui, "combo_box_" + combo_box_name).currentText()) values = {key_name if key_name else combo_box_name: combo_box_text} if common_key and common_key not in self.data.keys(): self.data.update({common_key: values}) elif common_key and common_key in self.data.keys(): self.data[common_key].update(values) else: self.data.update(values) for key, val in self.data.copy().items(): if isinstance(val, dict): self.data.update({key: dict(sorted(val.items()))}) for key, val in self.data.copy().items(): if isinstance(val, dict): for k, v in val.copy().items(): if not v: self.data[key].pop(k) if not val: self.data.pop(key) except Exception as set_combo_box_error: self.parent.error_view.show_error(set_combo_box_error)
def __init__(self, sex: str = 'm', age: Union[int, float, str] = 0, kinder_garden: str = '0', sfo: str = '0'): """ Constructor / Instantiate the class Parameters ---------- sex : str sex of the person, male ('m') or female ('f') age : int, float, str age of person kinder_garden : str kids in kinder_garden, '1' true or '0' false sfo : str after school programme, '0' no, '1' half-day or '2' full-day """ super().__init__() Assertor.assert_data_types([sex, age, kinder_garden, sfo], [str, (int, float, str), str, str]) Assertor.assert_arguments({ kinder_garden: ['kinder_garden:', ('0', '1')], sfo: ['sfo:', ('0', '1', '2')] }) if self.sifo_age(age) not in ('1', '2', '3', '5') and kinder_garden == '1': raise ValueError( "only persons between 1-5 years can attend kinder_garden") if self.sifo_age(age) not in ('9', '13') and sfo == '1': raise ValueError("only persons between 6-13 years can attend sfo") self._kjonn = sex self._alder = self.sifo_age(age) self._barnehage = kinder_garden self._sfo = sfo
def __init__(self, finn_code: str): """ Constructor / Instantiate the class Parameters ---------- finn_code : str Finn-code to be searched for """ try: super().__init__() Assertor.assert_data_types([finn_code], [str]) self._finn_code = finn_code self.validate_finn_code() self._browser = None LOGGER.success("created '{}', with id: [{}]".format( self.__class__.__name__, self.id_)) except Exception as finn_exception: LOGGER.exception(finn_exception) raise finn_exception
def add_statistics_label(self, key: str, postfix: str): """ method for adding statistics specific labels Parameters ---------- key : str name of label to change postfix : str index if used in naming of line_edits """ Assertor.assert_data_types([key, postfix], [str, str]) if key in ["city_area", "municipality"]: getattr(self.parent.ui, "label_" + key + "_sqm_price").setText( "KMP ({})".format(self.data[key + postfix])) getattr(self.parent.ui, "label_sales_" + key).setText( "Salg ({})".format(self.data[key + postfix])) else: getattr(self.parent.ui, "line_edit_" + key).setText(self.data[key + postfix])
def __init__(self, date_1: Union[dict, None], date_2: Union[dict, None], desc: str): """ Constructor / Instantiate the class. Parameters ---------- date_1 : dict dictionary with first date date_2 : dict dictionary with second date desc : str Description of operation """ Assertor.assert_data_types([date_1, date_2], [(dict, type(None)), (dict, type(None))]) self.name = self.__class__.__name__ super().__init__(name=self.name, desc="id: {}".format(desc)) self.date_1 = list(date_1.values())[0] if date_1 else None self.date_2 = list(date_2.values())[0] if date_2 else None
def __init__(self, parent: QWidget): """ Constructor / Instantiation of class Parameters ---------- parent : QWidget parent view of the metaview """ Assertor.assert_data_types([parent], [QWidget]) super().__init__(parent) self.ui = loadUi(os.path.join(os.path.dirname(__file__), "forms/images_form.ui"), self) self.ui.setWindowFlag(Qt.WindowMinimizeButtonHint, True) self.ui.setWindowFlag(Qt.WindowMaximizeButtonHint, True) self.ui.setWindowFlag(Qt.WindowContextHelpButtonHint, False) self._parent = parent self._images_model = ImagesModel(self) self.ui.push_button_forward.clicked.connect(self.next_image) self.ui.push_button_back.clicked.connect(self.previous_image)
def clear_finn_history(self, postfix: str): """ method for clearing finn ownership history from line_edit and graphics Parameters ---------- postfix : str index if used in naming of line_edits """ Assertor.assert_data_types([postfix], [str]) for key in self._finn_history_keys: full_key = key + postfix if key == "historikk": self.clear_finn_data(full_key) BarChartWithLine.clear_graphics( self.parent.ui.graphics_view_historikk, self.parent.ui.table_view_historikk) else: self.clear_finn_data(full_key) getattr(self.parent.ui, "line_edit_" + key).clear()
def __init__(self, parent: QObject): """ Constructor / Instantiation Parameters ---------- parent : QObject parent view for which the SifoModel resides """ Assertor.assert_data_types([parent], [QObject]) super(SifoModel, self).__init__(parent) self.parent.ui.combo_box_select_year.addItems(self._select_year) for num in range(1, 8): getattr(self.parent.ui, "combo_box_kjonn_" + str(num)).addItems(self._kjonn) getattr(self.parent.ui, "combo_box_alder_" + str(num)).addItems(self._alder) self.parent.ui.combo_box_antall_biler.addItems(self._antall_biler) self._sifo_process = None self._extra_info = None
def sifo_age(self, age: Union[int, float, str]): """ Converts age into SIFO compatible str Parameters ---------- age : int, float, str age to be converted Returns ------- Out : str SIFO compatible age str """ try: age = float(age) except Exception as exp: raise TypeError("invalid numeric str, got '{}'".format(exp)) Assertor.assert_non_negative([age]) sifo_yrs = [0.41, 0.91, 1, 2, 3, 5, 9, 13, 17, 19, 30, 50, 60, 66, 74, 999] return str(sifo_yrs[bisect_left(sifo_yrs, age)]) if age <= 999 else str(999)
def __init__(self, name: str, desc: str, label: str = None): """ Constructor / Instantiating class Parameters ---------- name : str name of operation desc : str description of operation """ self.name = name Assertor.assert_data_types([name, desc], [str, str]) self.desc = desc self.label = "\\<{}\\> \\n {}".format( self.name, self.desc) if not label else label super().__init__(name=str(uuid4()), style="filled", fillcolor="gray", shape="record", label=self.label)
def calculate_yearly_income(self, monthly_income: str): """ method for calculating / setting / formatting yearly gross income Parameters ---------- monthly_income : str """ Assertor.assert_data_types([monthly_income], [str]) yearly_income = self.parent.ui.line_edit_brutto_arsinntekt.text() if monthly_income and not yearly_income: yearly_income_from_monthly = Money( str( Decimal( monthly_income.replace(" kr", "").replace(" ", "")) * 12)) self.data.update( {"brutto_arsinntekt": yearly_income_from_monthly.value()}) return yearly_income_from_monthly.value() else: return yearly_income
def show_extra_info(self, name: str, postfix: str, values: list): """ method for showing the extra info if chosen to be displayed Parameters ---------- name : str name of extra info, i.e. barnehage, sfo or gravid postfix : str postfix matching naming convention values : list values for combobox dropdown """ Assertor.assert_data_types([name, postfix, values], [str, str, list]) ui = self.parent.ui name = name.capitalize() if name != "sfo" else name.upper() getattr(ui, "label_tillegg" + postfix).setText(name + "?") getattr(ui, "combo_box_tillegg" + postfix).show() getattr(ui, "combo_box_tillegg" + postfix).setEnabled(True) getattr(ui, "combo_box_tillegg" + postfix).clear() getattr(ui, "combo_box_tillegg" + postfix).addItems(values)
def __init__(self, finn_code: str): """ Constructor / Instantiate the class Parameters ---------- finn_code : str Finn-code to be search finn-advert information """ self.start_process() super().__init__(name=self.__class__.__name__) Assertor.assert_data_types([finn_code], [str]) self.input_operation({"finn_code": finn_code}) self.validate_finn_code() self.run_parallel([ self.scrape_finn_statistics_info, self.scrape_finn_community_statistics, self.scrape_finn_advert_info, self.scrape_finn_ownership_history ]) self._multiplex_info_1 = self.multiplex_1() self.run_parallel( [self.extract_1, self.extract_2, self.extract_3, self.extract_4]) self.run_parallel([ self.extract_first_row, self.add_to_dataframe_1, self.finn_community_process ]) self.check_newest_date() self.run_parallel([self.add_to_dataframe_2]) self.rate_of_change_2() self._multiplex_info_2 = self.multiplex_2() self.output_operation() self.end_process()
def __init__(self, row: Union[dict, None], dataframe: Union[dict, None], desc: str): """ Constructor / Instantiating class Parameters ---------- row : dict row to be added as dictionary dataframe : dict dataframe as a dictionary to add the row desc : str description of operation """ self.name = self.__class__.__name__ Assertor.assert_data_types([row, dataframe, desc], [(dict, type(None)), (dict, type(None)), str]) super().__init__(name=self.name, desc="id: {}".format(desc)) self.row = row if row else None self.dataframe = dataframe if dataframe else None
def add_finn_info(self, postfix: str): """ method for adding finn_info to line_edits Parameters ---------- postfix : str index if used in naming of line_edits """ try: Assertor.assert_data_types([postfix], [str]) finn_code = getattr(self.parent.ui, "line_edit_finnkode" + postfix).text().strip() if finn_code and finn_code not in self.data.values(): getattr(self.parent.ui, "progress_bar" + postfix).setValue(randint(5, 25)) getattr(self.parent.ui, "progress_bar" + postfix).setTextVisible(False) self.process_finn_data(finn_code, postfix) getattr(self.parent.ui, "progress_bar" + postfix).setValue(30) elif finn_code and finn_code in self.data.values(): if ("finnkode" + postfix) not in self.data.keys(): getattr(self.parent.ui, "progress_bar" + postfix).setValue(0) getattr(self.parent.ui, "progress_bar" + postfix).setTextVisible(True) getattr(self.parent.ui, "progress_bar" + postfix).setAlignment(Qt.AlignCenter) getattr(self.parent.ui, "progress_bar" + postfix).setFormat("Duplikat!") else: self.clear_finn_info(postfix) except Exception as finn_processing_error: self.parent.error_view.show_error(finn_processing_error, self.data) self.parent.error_view.exec_() self.clear_finn_info(postfix, force=True) getattr(self.parent.ui, "progress_bar" + postfix).setValue(0) getattr(self.parent.ui, "line_edit_finnkode" + postfix).setFocus()
def __init__(self, age: Union[int, float, str] = 0, kinder_garden: str = '0', sfo: str = '0', pregnant: str = '0', student: str = '0'): """ Constructor / Instantiate the class Parameters ---------- age : int, float, str age of person kinder_garden : str kids in kinder garden, '1' true or '0' false sfo : str After school programme, '1' true or '0' false pregnant : str Pregnant female, '1' true or '0' false student : str Student classification, '1' true or '0' false """ try: super().__init__('k', age, kinder_garden, sfo) Assertor.assert_data_types([age, kinder_garden, sfo, student], [(float, int, str), str, str, str]) Assertor.assert_arguments([pregnant], [{"pregnant": ('0', '1')}]) if self.sifo_age(age) not in ('17', '19', '30', '50') and pregnant == '1': raise ValueError( "[{}] pregnancy at this age is not possible".format( self.__class__.__name__)) self._gravid = pregnant except Exception as female_exception: raise female_exception
def __init__(self, parent: QObject): """ Constructor / Instantiation of class Parameters ---------- parent : QObject Parent view for which the model in to be linked """ Assertor.assert_data_types([parent], [QObject]) super().__init__(parent) self.sales_plot = None self.ration_plot = None self.age_dist_city_area_plot = None self.age_dist_city_plot = None self.civil_status_city_area_plot = None self.civil_status_city_plot = None self.education_city_area_plot = None self.education_city_plot = None self.income_city_area_plot = None self.income_city_plot = None self.family_composition_city_area_plot = None self.family_composition_city_plot = None self.age_dist_children_city_area_plot = None self.age_dist_children_city_plot = None self.families_with_children_city_area_plot = None self.families_with_children_city_plot = None self.housing_stock_city_area_plot = None self.housing_stock_city_plot = None self.housing_ownership_city_area_plot = None self.housing_ownership_city_plot = None self.housing_area_city_area_plot = None self.housing_area_city_plot = None self.housing_age_city_area_plot = None self.housing_age_city_plot = None self.housing_prices_city_area_plot = None self.housing_prices_city_plot = None
def save_json(file_dict: dict, file_dir: str = "report/json", file_prefix: str = "Info"): """ save information in object to JSON file Parameters ---------- file_dict : dict retrieve information from this object and save to file file_dir : str file directory to save JSON files file_prefix : str title of file """ try: Assertor.assert_data_types([file_dir, file_prefix], [str, str]) try: if not os.path.exists(file_dir): os.makedirs(file_dir) except Exception as exception: raise OSError("creation of dir " + file_dir + " failed with: " + str(exception)) _json = json.dumps(file_dict, indent=2, separators=(',', ': '), ensure_ascii=False) local_time = datetime.datetime.now().isoformat().replace( ":", "-").replace(".", "-") file = open( os.path.join(file_dir, file_prefix + local_time + ".json"), "w") file.write(_json) file.close() except Exception as json_exception: LOGGER.exception(json) raise json_exception
def update_line_edits(self, line_edit_name: str, line_edits: list, obj: object = None, method: str = None, postfix: str = None, data: dict = None): """ method for updating the value of multiple line_edits Parameters ---------- line_edit_name : str name of line_edit to get values from line_edits : list all line_edits to update values for based on input, see line_edit_name obj : object name of object to get values to update line_edits method : str name of method in obj to use to get values to update line_edits postfix : str index if used in naming of line_edits data : dict dictionary with data to set if no object or method used """ postfix = postfix if postfix else "" line_edit = getattr(self.parent.ui, "line_edit_" + line_edit_name + postfix) try: Assertor.assert_data_types([line_edit_name, line_edits, obj, method, postfix], [str, list, (type(None), object), (type(None), str), (type(None), str), (type(None), str)]) line_edit_text = line_edit.text().strip() if line_edit_text and line_edit_text not in self.data.values(): self.set_line_edits(line_edit_text, line_edits, obj, method, postfix, data) elif line_edit_text and line_edit_text in self.data.values(): self.get_line_edits(line_edits, postfix) else: self.clear_line_edits(line_edits, postfix) except Exception as update_error: self.clear_line_edits(line_edits, postfix) self.parent.error_view.show_error(update_error, self.data) line_edit.setFocus()
def calculate_sqm_price_areas(self, info: dict): """ method for calculating sqm price in city area and municipality Parameters ---------- info : dict dictionary to store results """ Assertor.assert_data_types([info], [dict]) if all(name in info.keys() for name in ["hist_data_city_area", "hist_data_municipality"]): info.update({ "city_area_sqm_price": self.calculate_average(info["hist_data_city_area"]) + " kr/m²" }) info.update({ "municipality_sqm_price": self.calculate_average(info["hist_data_municipality"]) + " kr/m²" }) return info
def input_operation(self, data: object): """ initial operation in process Parameters ---------- data : dict postal_code sent in to process Returns ------- out : dict postal_code saved as signal """ Assertor.assert_data_types([data], [dict]) input_operation = InputOperation("Postal Code") self.add_node(input_operation) input_signal = Signal(data, desc="Postal Code") self.add_signal(input_signal, "input_signal") self.add_transition(input_operation, input_signal)
def show_error(self, exception: Exception, meta: dict, trace_back=None): """ method for shows an error form with exception, traceback and log information Parameters ---------- exception : Exception exception to be added to form meta : dict metadata trace_back : str, optional Optional trace_back string """ time.sleep(0.2) if os.path.exists(self.log_dir): shutil.rmtree(self.log_dir) Assertor.assert_data_types([exception, meta], [Exception, dict]) self.ui.tab_widget_error.setCurrentIndex(0) error_list = str(exception).split("->") error = error_list[-1].strip() tracking = [] for i, element in enumerate(error_list): if i == 0: tracking.append(element + "\n") else: tracking.append("|\n") tracking.append("|" + "__" * i * 2 + element + "\n") self.ui.label_error_text.setText(error) self.ui.plain_text_edit_tracking.setPlainText("".join(tracking)) self.ui.plain_text_edit_traceback.setPlainText( traceback.format_exc() if not trace_back else trace_back) self.ui.plain_text_edit_log.setPlainText(self.read_log(exception)) self.ui.plain_text_edit_error_meta_data.setPlainText( json.dumps(meta, indent=4, ensure_ascii=False)) self.show()
def set_line_edits(self, line_edit_text: str, line_edits: list, obj: object = None, method: str = None, postfix: str = None, data: dict = None): """ method for setting values of multiple line_edits Parameters ---------- line_edit_text : str value of inputted line_edit line_edits : list list of line_edit names to update values obj : object object with method for extracting values to update line_edits method : str name of method to call in object postfix : str index if used in naming of line_edits data : dict dictionary with data to set if no object or method used """ model_info = getattr(obj(line_edit_text), method)() if obj and method else data try: Assertor.assert_data_types([line_edit_text, line_edits, obj, method, postfix, data], [str, list, (object, type(None)), (str, type(None)), (str, type(None)), (dict, type(None))]) if not model_info: return for line_edit in line_edits: if line_edit in model_info.keys(): info = model_info[line_edit] line_edit_name = line_edit + postfix if postfix else line_edit self.set_line_edit(line_edit_name, data=info) except Exception as set_line_edits_error: self.clear_line_edits(line_edits, postfix) self.parent.error_view.show_error(set_line_edits_error, self.data)
def clear_finn_info(self, postfix, force=False): """ method for clearing finn info Parameters ---------- postfix : str index if used in naming of line_edits force : bool boolean to indicate if one wants to force a clear """ Assertor.assert_data_types([postfix, force], [str, bool]) finn_code = getattr(self.parent.ui, "line_edit_finnkode" + postfix).text().strip() if not finn_code or force: self.clear_line_edits(["finnkode" + postfix]) self.clear_line_edits(self._finn_keys, postfix) self.parent.history_view.history_model.clear_finn_history(postfix) self.parent.statistics_view.statistics_model.clear_statistics_info( postfix) getattr(self.parent.ui, "progress_bar" + postfix).setTextVisible(False) getattr(self.parent.ui, "progress_bar" + postfix).setValue(0)
def extract_area_sales_statistics(self, areal_sales_statistics: dict, info: dict): """ method for extracting the detail view statistics Parameters ---------- areal_sales_statistics : dict dictionary with area sales statistics info : dict dictionary to store results Returns ------- out : dict dictionary with results """ Assertor.assert_data_types([areal_sales_statistics, info], [dict, dict]) historical_data_names = [ "hist_data_city_area", "hist_data_municipality" ] location_name = ["city_area", "municipality"] for prop, value in areal_sales_statistics.items(): if prop.lower() == 'props': for pro, val in value.items(): if pro.lower() == 'pageprops': for pr_name, vl_name in val.items(): if pr_name.lower() == 'locationhistory': for i, data in enumerate(vl_name): if len(areal_sales_statistics) == 3: if i == 0: continue i -= 1 for prop_val, value_name in data.items(): if prop_val.lower( ) == "locationdetails": if value_name: if "name" in value_name[0]: info.update({ location_name[i]: value_name[0]["name"] }) elif prop_val.lower() == "histdata": historical_values = {} for ke_val, va_name in value_name.items( ): historical_values.update({ int(ke_val): int(va_name) }) info.update({ historical_data_names[i]: historical_values }) info.update({ historical_data_names[i] + "_count": Amount( str( sum(historical_values. values()))).amount }) if all(name in info.keys() for name in historical_data_names): self.harmonize_data_sets(info) return info
def add_dist_chart(self, prefix: str, postfix: str, key: str, plot_name_1: str, plot_name_2: str, table_name: str, dist_name: str, dist_var_1: str, dist_var_2: str, ignore_total: bool = True): """ method for adding distribution chart to the statistics model Parameters ---------- prefix : str name of prefix, i.e. "graphics" postfix : str index if used in naming of line_edits key : str name of label to change plot_name_1 : str name of first plot plot_name_2 : str name of second plot table_name : str name of table dist_name : str name of distribution variable dist_var_1 : str name of instance variable for distribution dist_var_2 : str name of second instance variable for distribution ignore_total: str boolean for handling total values """ Assertor.assert_data_types([ prefix, postfix, key, plot_name_1, plot_name_2, table_name, dist_name, dist_var_1, dist_var_2, ignore_total ], [str, str, str, str, str, str, str, str, str, bool]) BarChart.clear_graphics(getattr(self.parent.ui, prefix + plot_name_1)) BarChart.clear_graphics(getattr(self.parent.ui, prefix + plot_name_2)) if key + postfix in self.data.keys() and self.data[key + postfix]: dist = self.data[key + postfix] city_area_dist = dist["Nabolag"][:-2] if ignore_total else dist[ "Nabolag"] city_dist = dist["By"][:-2] if ignore_total else dist["By"] dist_range = list(range(len(city_area_dist))) if "info" + postfix in self.data.keys(): if self.data["info" + postfix]["neighborhood"]: neighbourhood = self.data["info" + postfix]["neighborhood"]["name"] \ .replace("-", " - ") city = self.data["info" + postfix]["neighborhood"]["city"] else: neighbourhood = self.data["info" + postfix]["census"].replace( "-", " - ") city = self.data["info" + postfix]["city"].replace( "-", " - ") else: neighbourhood = "" city = "" if "city_area" + postfix in self.data.keys(): city_area = self.data["city_area" + postfix] else: city_area = "" if sum(city_area_dist) != 0: dist_df = {"Gruppe": [], "Nabolag": [], "By": []} for keys, values in dist.items(): if keys == "Gruppe": dist_df[keys] = values else: if ignore_total: dist_df[keys] = [ Percent(str(val / 100)).value if i not in (len(values) - 1, len(values) - 2) else Amount(str(val)).amount for i, val in enumerate(values) ] else: dist_df[keys] = [ Percent(str(val / 100)).value for i, val in enumerate(values) ] table_model = TableModel(DataFrame(dist_df)) getattr(self.parent.ui, table_name).setModel(table_model) getattr(self.parent.ui, table_name).horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) setattr( self, dist_var_1, BarChartWithLine( dist_range, city_area_dist, getattr(self.parent.ui, prefix + plot_name_1), getattr(self.parent.ui, table_name), width=0.5, reverse=False, legend='<div style="text-align: center">' '<span style="font-size: 10pt">{}:</span><br>' '<span style="font-size: 10pt">{}</span><br>' '<span style="font-size: 10pt">({})</span><br>' '</div>'.format(dist_name, neighbourhood, city_area))) setattr( self, dist_var_2, BarChartWithLine( dist_range, city_dist, getattr(self.parent.ui, prefix + plot_name_2), getattr(self.parent.ui, table_name), width=0.5, reverse=False, legend='<div style="text-align: center">' '<span style="font-size: 10pt">{}:</span><br>' '<span style="font-size: 10pt">{}</span><br>' '</div>'.format(dist_name, city))) getattr(self, dist_var_1).table_view_mapping() getattr(self, dist_var_2).table_view_mapping()