#!/usr/bin/env python
# coding: utf-8

#importando librerias
import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from community import community_louvain

#leyendo backbone del grafo
G3=nx.read_graphml('/home/aleida/Documentos/Posgrado_Redes/repo/new_backbone.graphml')

#Detectando comunidades
comunidades=nx.community.louvain_communities(G3, weight='weight', resolution=1.5,seed=3)

#comunidades
#len(comunidades)

comunidades_map={}
for i in range(len(comunidades)):
    comunidades_map.update(dict.fromkeys(comunidades[i],i))
#comunidades_map

#cargando bd
bd=pd.read_csv('/home/aleida/Documentos/Posgrado_Redes/repo/bd_new.csv',index_col='country')

#bd

#df para la info de la frecuencia de los ingredientes por paises
new_df=pd.DataFrame(data=0,index=bd.index.unique(),columns=bd.columns)

#new_df

for i in bd.columns:
    distribucion=bd[i].groupby("country").sum()
    for index in distribucion.index:
        new_df.loc[index][i]=distribucion[index]

#new_df

tabla_resumen=pd.DataFrame(columns=['ingredient','comunidad','pais','category'])

#df resumen sobre info de las comunidades
for k in range(len(comunidades)):
    for ingredient in comunidades[k]:
        pais=new_df.index[0]
        x=new_df.loc[pais][ingredient]
        for i in new_df.index[1:]:
                if x<new_df.loc[i][ingredient]:
                    pais=i
                    x=new_df.loc[i][ingredient]
        tabla_resumen = tabla_resumen.append({'ingredient': ingredient,
                                              'comunidad': k,
                                              'pais': pais,
                                              'category': G3.nodes[ingredient]['category']}, ignore_index=True)

#tabla_resumen

#df resumen sobre la representacion de cada pais en las comunidades
tabla_resumen2=pd.DataFrame(columns=['comunidad','pais','aporte relativo'])

for i in range(len(comunidades)):
    df=tabla_resumen[tabla_resumen['comunidad'] == i]
    for k in df['pais'].value_counts().index:
        tabla_resumen2 = tabla_resumen2.append({'comunidad': i,
                                                'pais': k,
                                                'aporte relativo': df['pais'].value_counts(normalize=True)[k]}, ignore_index=True)

#tabla_resumen2

#df resumen sobre la representacion de cada categoria en las comunidades
tabla_resumen3=pd.DataFrame(columns=['comunidad','category','aporte'])

for i in range(len(comunidades)):
    df=tabla_resumen[tabla_resumen['comunidad'] == i]
    for k in df['category'].value_counts().index:
        tabla_resumen3 = tabla_resumen3.append({'comunidad': i,
                                                'category': k,
                                                'aporte': df['category'].value_counts(normalize=True)[k]}, ignore_index=True)

#tabla_resumen3

datos = open('/home/aleida/Documentos/Posgrado_Redes/repo/communities_stat_new.txt', 'wt')

for i in range(len(comunidades)):
    datos.write('\n')
    datos.write(".........comunidad.........."+str(i))
    datos.write('\n')
    datos.write(str(tabla_resumen2[tabla_resumen2['comunidad']==i].iloc[0:3]))
    datos.write('\n')
    datos.write(str(tabla_resumen3[tabla_resumen3['comunidad']==i].iloc[0:3]))

datos.close()

import matplotlib.colors as mcolors
paleta=list(mcolors.TABLEAU_COLORS.values())
paleta.append("darkslateblue")
color_pallet=paleta

color_nodos=[]
for node in G3:
    color_nodos.append(color_pallet[comunidades_map[node]])

"""nx.draw(G3,node_color=color_nodos, with_labels=True)
plt.show()

#Pintando el grafo con colores segun las comunidades y peso
weights = [a[2]["weight"] for a in G3.edges(data=True)]
weights = [(a-min(weights))/(max(weights)-min(weights))*100 for a in weights]

# Definir la posición de los nodos utilizando un layout
pos = nx.spring_layout(G3)

# Representar nodos y ejes
fig, ax = plt.subplots(figsize=(15,10))
nx.draw_networkx_nodes(
    G3,
    pos = pos,
    node_size=600,
    ax = ax,
    node_color=color_nodos,
)
nx.draw_networkx_edges(
    G3,
    pos = pos,
    edgelist = G3.edges,
    width = weights,
    alpha=0.3,
    ax = ax
)
nx.draw_networkx_labels(
    G3,
    pos = pos,
    horizontalalignment='right',
    verticalalignment='center',
    font_size = 8
)
("")

H = G3.subgraph(comunidades[2])

#Pintando algunas comunidades
# Definir la posición de los nodos utilizando un layout
pos = nx.random_layout(H)

# Representar nodos y ejes
fig, ax = plt.subplots(figsize=(15,10))
nx.draw_networkx_nodes(
    H,
    pos = pos,
    node_size=600,
    ax = ax,
    node_color=list(nx.get_node_attributes(H, "color").values()),
)
nx.draw_networkx_edges(
    H,
    pos = pos,
    edgelist = H.edges,
    width = weights,
    alpha=0.3,
    ax = ax
)
nx.draw_networkx_labels(
    H,
    pos = pos,
    horizontalalignment='right',
    verticalalignment='center',
    font_size = 8
)
("")"""

G6=nx.Graph()

k=0
for node in G3:
    G6.add_node(node,weight=nx.get_node_attributes(G3,'weight')[node],category=nx.get_node_attributes(G3,'category')[node],color=color_nodos[k])
    k+=1

for edge in G3.edges():
    G6.add_edge(edge[0],edge[1],weight=G3.get_edge_data(edge[0],edge[1])["weight"])

nx.write_graphml(G6,'/home/aleida/Documentos/Posgrado_Redes/repo/new_communities_graph.graphml')

central = open("/home/aleida/Documentos/Posgrado_Redes/repo/new_central.txt", "w")
for j, com in enumerate(comunidades):
    H = G3.subgraph(com)
    degree=nx.degree_centrality(H)
    betweennes=nx.betweenness_centrality(H)
    sor1 = sorted(degree.items(), key=lambda i: i[1], reverse=True)
    sor2 = sorted(betweennes.items(), key=lambda i: i[1], reverse=True)
    degree_com=0
    for z in sor1:
        degree_com+=z[1]
    degree_com=degree_com/len(sor1)
    betwennes_com=0
    for z in sor2:
        betwennes_com+=z[1]
    betwennes_com=betwennes_com/len(sor1)
    central.write(f"degree\n")
    for i in sor1[:3]:
        central.write(f"{j}: {i[0]}={i[1]}\n")
    central.write(f"degree_community....{degree_com}\n")
    central.write(f"beetwennes\n")
    for i in sor2[:3]:
        central.write(f"{j}: {i[0]}={i[1]}\n")
    central.write(f"beetwennes_community....{betwennes_com}\n")
central.close()


from django.urls import path
from .views import *

app_name = 'restopay'

urlpatterns = [
    path('', get_restopay, name='get_restopay'),
    path('tambah_saldo/', add_restopay, name='add_restopay'),
    path('tarik_saldo/', withdraw_restopay, name='withdraw_restopay'),

]


from django.urls import path
from . import views

urlpatterns = [
	path('signin/', views.signin_view, name="signin" ),
	path('signup/', views.signup_view, name="signup" ),
	path('logout/', views.logout_view, name="logout" ),
	path('profile/', views.profile,    name="profile"),
	path('pesan/', views.pesan, name="pesan"),
	path('perkembangan/', views.insert_perkembangan, name="perkembangan"),
]


from django.urls import path
from .views import *

urlpatterns = [
    # path('cobrar_tratamiento/<int:id_paciente>', cobrar_tratamiento, name="cobrar_tratamiento"),
    path('mostrar_tratamientos_cobrar/<int:id_paciente>', mostrar_tratamientos_cobrar, name="mostrar_tratamientos_cobrar"),
    path('registrar_cobro/<str:numero_documento>/', registrar_cobro, name="registrar_cobro"),
    path('listar_cobros/', listar_cobros, name="listar_cobros"),
    path('listar_cobros_pendientes/', listar_cobros_pendientes, name="listar_cobros_pendientes"),
    path('eliminar_tratamiento_confirmado/<id_tratamiento_confirmado>', eliminar_tratamiento_confirmado, name="eliminar_tratamiento_confirmado"),
    path('error_cobro/', ErrorCobro.as_view(), name="error_cobro"),
    # path('mensaje_confirmacion_cobro/', ConfirmacionCobro.as_view(), name="mensaje_confirmacion_cobro"),
    path('mensaje_confirmacion_cobro/<id_cobro>', mostrar_msj_confirmacion_cobro, name="mensaje_confirmacion_cobro"),
    path('ver_detalle_cobro/<int:id_cobro_contado>', ver_detalle_cobro, name="ver_detalle_cobro"),
    path('verificar_datos_cita/<numero_documento>/<menor_edad>', verificar_datos_cita, name="verificar_datos_cita"),
    # path('solicitar_razon_social/<numero_documento>', solicitar_razon_social, name="solicitar_razon_social"),
    path('registrar_cobro2/<numero_documento>/<numero_documento2>/<razon_social>', registrar_cobro2, name="registrar_cobro2"),
    path('confirmacion_de_cobro/<int:id_factura>', confirmacion_de_cobro, name="confirmacion_de_cobro"),

    # path('ingresar_datos_factura/<int:id_cobro>', ingresar_datos_factura, name="ingresar_datos_factura"),
    path('ingresar_datos_cobro/<int:id_paciente>', ingresar_datos_cobro, name="ingresar_datos_cobro"),
    path('visualizar_datos_factura/<int:id_factura>', visualizar_datos_factura, name="visualizar_datos_factura"),

    #Factura_html
    path('generar_factura_original/', generar_factura_original, name="generar_factura_original"),
    path('listar_facturas/', listar_facturas, name="listar_facturas"),
    path('cambiar_estado_factura/<id_factura>', cambiar_estado_factura, name="cambiar_estado_factura"),

    #PDF------------------------
    path('detalle_cobro_pdf/<int:id_paciente>', detalle_cobro_pdf ,name="detalle_cobro_pdf"),
    path('presupuesto_pdf/<int:id_paciente>',  presupuesto_pdf, name="presupuesto_pdf"),
    path('generar_factura/<int:id_factura>', generar_factura, name="generar_factura"),
    path('pdf_movimiento_caja/', pdf_movimiento_caja, name="pdf_movimiento_caja"),

    # Cobranza --------------------
    path('mostrar_caja/<str:numero_documento>', mostrar_caja, name="mostrar_caja"),
    path('datos_apertura_caja/<str:numero_documento>/<str:id_paciente>', guardar_datos_apertura_caja, name="datos_apertura_caja"),
    path('datos_apertura_caja2/<str:numero_documento>', guardar_datos_apertura_caja2, name="datos_apertura_caja2"),
    path('msj_caja_cerrada/<str:id_paciente>/<str:numero_documento>', msj_caja_cerrada, name="msj_caja_cerrada"),
    path('msj_caja_abierta2/', msj_caja_abierta2, name="msj_caja_abierta2"),
    path('cerrar_caja/', cerrar_caja, name="cerrar_caja"),

    # Gastos ----------------------------------
    path('registrar_gasto/', registrar_gasto, name="registrar_gasto"),
    path('agregar_detalle_comprobante/<int:id_comprobante>', agregar_detalle_comprobante, name="agregar_detalle_comprobante"),
    path('agregar_monto_total/<int:id_comprobante>', agregar_monto_total, name="agregar_monto_total"),
    path('listar_gastos/', listar_gastos, name="listar_gastos"),
    path('cerrar_caja/', cerrar_caja, name="cerrar_caja"),
    path('mostar_caja_previa/', mostar_caja_previa, name="mostar_caja_previa"),
    path('apertura_exitosa/', mostar_apertura_exitosa_caja, name="apertura_exitosa"),
    path('solicitar_monto_efectivo/<int:id_cobro>', solicitar_monto_efectivo, name="solicitar_monto_efectivo"),
    path('mostrar_montos/<int:id_cobro>', mostrar_vuelto, name="mostrar_montos"),
    path('visualizar_gasto/<int:id_comprobante>', visualizar_gasto, name="visualizar_gasto"),
]


import pymongo
import csv

def insertNama():
    client = pymongo.MongoClient("mongodb://localhost:27017/")
    db = client["testing"]
    col = db["pasien"]
    # names = [{'nama': 'jay', 'umur': 22, 'len': 3600},{'nama': 'john', 'umur': 40, 'len': 3600}]
    # for x in names:
    #     name = x['nama']
    #     umur = x['umur']
    col.insert_one({
        'nama':"dummy",
        'umur':999
    })

def insertData():
    # with open('100.csv', 'r') as csvFile:
    #     reader = csv.reader(csvFile)
    #     i = 0
    #     data = []

    #     for row in reader:
    #         if i > 0:
    #             data.append(float(row[0]))
    #         i = i+1
    iot = {
        "nama":"dummy",
        "data":"dummy",
        "len":999999
    }
    client = pymongo.MongoClient("mongodb://localhost:27017/")
    db = client["testing"]
    col = db["data"]
    col.insert_one(iot)
    # csvFile.close()

def insertHasil():
    pred = {
        'APC': [[1927, 2224]],
        'Normal': [[223, 517], [516, 805], [805, 1089], [1089, 1373], [1373, 1662], [1662, 1927], [2224, 2555], [2554, 2852], [2852, 3141], [3140, 3422]],
        'LBB': [],
        'PAB': [],
        'PVC': [],
        'RBB': [],
        'VEB': []}
    client = pymongo.MongoClient("mongodb://localhost:27017/")
    db = client["testing"]
    col = db["hasil"]
    print(pred["Normal"])
    col.insert_one(
        {
            "nama": "dummy",
            "hasil": {
                'APC': pred["APC"],
                'Normal': pred["Normal"],
                'LBB': pred["LBB"],
                'PAB': pred["PAB"],
                'PVC': pred["PVC"],
                'RBB': pred["RBB"],
                'VEB': pred["VEB"]
                }
        }
    )

def findData():
    client = pymongo.MongoClient("mongodb://localhost:27017/")
    db = client["test"]
    col = db["hasil"]
    x = col.find({ "nama": "" }).count()
    print(x)

insertNama()


from django.contrib import admin
from world.models import Image

def make_active(modeladmin, request, queryset):
    queryset.update(active=True)

make_active.short_description = "Опубликовать выбранные объявления"

class ImageAdmin(admin.ModelAdmin):
    list_display = ['active', 'image_file', 'type', 'date', 'description', 'contacts', 'email']
    fields = ['active', 'type', 'point', 'date', 'image_url', 'image_file', 'description', 'email', 'radius', 'contacts']
    actions = [make_active]

admin.site.register(Image, ImageAdmin)


"""
gatefilter.py
"""

# Load the needed packages
from functools import partial
import os
import numpy as np
import pyart
import time

from ..core import Component, Variable, common, QtWidgets, QtCore, componentsList
from ..components import RadarDisplay

class GateFilter(Component):
    '''
    Interface for executing :py:class:`pyart.filters.GateFilter`.
    '''

    Vradar = None  #: see :ref:`shared_variable`
    Vgatefilter = None  #: see :ref:`shared_variable`

    @classmethod
    def guiStart(self, parent=None):
        '''Graphical interface for starting this class.'''
        kwargs, independent = \
            common._SimplePluginStart("GateFilter").startDisplay()
        kwargs['parent'] = parent
        return self(**kwargs), independent

    def __init__(self, Vradar=None, Vgatefilter=None,
                 name="GateFilter", parent=None):
        '''Initialize the class to create the interface.

        Parameters
        ----------
        [Optional]
        Vradar : :py:class:`~artview.core.core.Variable` instance
            Radar signal variable.
            A value of None initializes an empty Variable.
        Vgatefilter : :py:class:`~artview.core.core.Variable` instance
            GateFilter signal variable.
            A value of None initializes an empty Variable.
        name : string
            GateFilter instance window name.
        parent : PyQt instance
            Parent instance to associate to this class.
            If None, then Qt owns, otherwise associated w/ parent PyQt instance
        '''
        super(GateFilter, self).__init__(name=name, parent=parent)
        self.central_widget = QtWidgets.QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QtWidgets.QGridLayout(self.central_widget)

        # Set up signal, so that DISPLAY can react to
        # changes in radar or gatefilter shared variables
        if Vradar is None:
            self.Vradar = Variable(None)
        else:
            self.Vradar = Vradar

        if Vgatefilter is None:
            self.Vgatefilter = Variable(None)
        else:
            self.Vgatefilter = Vgatefilter

        self.sharedVariables = {"Vradar": None,
                                "Vgatefilter": None, }
        # Connect the components
        self.connectAllVariables()
        self.field = None

        self.operators = {"=": "exclude_equal",
                          "!=": "exclude_not_equal",
                          "<": "exclude_below",
                          "<=": "exclude_below",
                          ">": "exclude_above",
                          ">=": "exclude_above",
                          "inside": "exclude_inside",
                          "outside": "exclude_outside",
                          }

        self.generalLayout = QtWidgets.QVBoxLayout()
        # Set the Variable layout
        self.generalLayout.addWidget(self.createVarUI())
        self.generalLayout.addWidget(self.createFilterBox())
        self.generalLayout.addWidget(self.createButtonUI())

        self.layout.addLayout(self.generalLayout, 0, 0, 1, 2)

        self.show()

    ######################
    #   Layout Methods   #
    ######################

    def createVarUI(self):
        '''
        Mount the Variable layout.
        User may select another Display
        '''
        groupBox = QtWidgets.QGroupBox("Variable Input")
        gBox_layout = QtWidgets.QGridLayout()

        self.dispCombo = QtWidgets.QComboBox()
        gBox_layout.addWidget(QtWidgets.QLabel("Select Display Link"), 0, 0)
        gBox_layout.addWidget(self.dispCombo, 0, 1, 1, 1)

        self.DispChoiceList = []
        self.components = componentsList
        for component in self.components:
            if "Vradar" in component.sharedVariables.keys():
                if "Vgatefilter" in component.sharedVariables.keys():
                    self.dispCombo.addItem(component.name)
                    self.DispChoiceList.append(component)
        self.dispCombo.setCurrentIndex(0)

        self.chooseDisplay()
        groupBox.setLayout(gBox_layout)

        return groupBox

    def createButtonUI(self):
        '''Mount the Action layout.'''
        groupBox = QtWidgets.QGroupBox("Select Action")
        gBox_layout = QtWidgets.QGridLayout()

        self.helpButton = QtWidgets.QPushButton("Help")
        self.helpButton.clicked.connect(self._displayHelp)
        gBox_layout.addWidget(self.helpButton, 0, 0, 1, 1)

        self.scriptButton = QtWidgets.QPushButton("Show Script")
        self.scriptButton.clicked.connect(self.showScript)
        self.scriptButton.setToolTip('Display relevant python script')
        gBox_layout.addWidget(self.scriptButton, 0, 1, 1, 1)

        self.saveButton = QtWidgets.QPushButton("Save File")
        self.saveButton.clicked.connect(self.saveRadar)
        self.saveButton.setToolTip('Save cfRadial data file')
        gBox_layout.addWidget(self.saveButton, 0, 2, 1, 1)

        self.restoreButton = QtWidgets.QPushButton("Restore to Original")
        self.restoreButton.clicked.connect(self.restoreRadar)
        self.restoreButton.setToolTip('Remove applied filters')
        gBox_layout.addWidget(self.restoreButton, 0, 3, 1, 1)

        self.filterButton = QtWidgets.QPushButton("Filter")
        self.filterButton.clicked.connect(self.apply_filters)
        self.filterButton.setToolTip('Make Filter')
        gBox_layout.addWidget(self.filterButton, 0, 4, 1, 1)

        groupBox.setLayout(gBox_layout)

        return groupBox

    def createFilterBox(self):
        '''Mount options layout.'''
        # Create lists for each column
        chkactive = []
        fldlab = []
        operator = []
        loval = []
        hival = []

        groupBox = QtWidgets.QGroupBox("Filter Design - Exclude gates "
                                   "via the following statements")
        # groupBox.setFlat(True)
        gBox_layout = QtWidgets.QGridLayout()

        gBox_layout.addWidget(QtWidgets.QLabel("Activate\nFilter"), 0, 0, 1, 1)
        gBox_layout.addWidget(QtWidgets.QLabel("Variable"), 0, 1, 1, 1)
        gBox_layout.addWidget(QtWidgets.QLabel("Operation"), 0, 2, 1, 1)
        gBox_layout.addWidget(QtWidgets.QLabel("Value 1"), 0, 3, 1, 1)
        gBox_layout.addWidget(QtWidgets.QLabel("Value 2\nFor outside/inside"),
                              0, 4, 1, 1)

        groupBox.setLayout(gBox_layout)

        self.fieldfilter = {}

        if self.Vradar.value is not None:
            for nn, field in enumerate(self.Vradar.value.fields.keys()):
                chkactive.append(QtWidgets.QCheckBox())
                chkactive[nn].setChecked(False)
                fldlab.append(QtWidgets.QLabel(field))
                loval.append(QtWidgets.QLineEdit(""))
                hival.append(QtWidgets.QLineEdit(""))
                operator.append(self.set_operator_menu())

                gBox_layout.addWidget(chkactive[nn], nn+1, 0, 1, 1)
                gBox_layout.addWidget(fldlab[nn], nn+1, 1, 1, 1)
                gBox_layout.addWidget(operator[nn], nn+1, 2, 1, 1)
                gBox_layout.addWidget(loval[nn], nn+1, 3, 1, 1)
                gBox_layout.addWidget(hival[nn], nn+1, 4, 1, 1)

            self.fieldfilter["check_active"] = chkactive
            self.fieldfilter["field"] = fldlab
            self.fieldfilter["operator"] = operator
            self.fieldfilter["low_value"] = loval
            self.fieldfilter["high_value"] = hival

#         for index, chk in enumerate(self.fieldfilter["check_active"]):
#             if chk.isChecked():
#                 if (self.fieldfilter["operator"] == 'outside' or
#                    self.fieldfilter["operator"] == 'inside'):
#                     self.fieldfilter["high_value"].setText(' ')
#                     self.fieldfilter["high_value"].setReadOnly(True)

        return groupBox

    #########################
    #   Selection Methods   #
    #########################

    def chooseDisplay(self):
        '''Get Display.'''
        selection = self.dispCombo.currentIndex()
        Vradar = getattr(self.DispChoiceList[selection], str("Vradar"))
        Vgatefilter = getattr(self.DispChoiceList[selection],
                              str("Vgatefilter"))

        self.dispCombo.setCurrentIndex(selection)

        self.disconnectAllVariables()
        self.Vradar = Vradar
        self.Vgatefilter = Vgatefilter
        self.connectAllVariables()

    def _displayHelp(self):
        '''Display Py-Art's docstring for help.'''
        text = (
            "Using the GateFilter window

"
            "Choose a filter:
"
            "  1. Select an operation and value(s) to exclude.
"
            "       Notes: 'outside' masks values less than 'Value 1' and "
            "greater than 'Value 2.'
"
            "              'inside' masks values greater than 'Value 1' and "
            "less than 'Value 2.'
"
            "              For other operations only 'Value 1 is used.
"
            "  2. Check the 'Activate Filter' box to apply the filter.
"
            "  3. Click the 'Filter' button.
"
            "  4. GateFilter needs to be activated in the Display to see the "
            "results. It is turned on by default. To check see "
            "'Display Options' dropdown menu on the Display of interest.
"
            "
"
            "Change Radar variables:
"
            "  Click the 'Find Variable', select variable.

"
            "Show Python script for batching:
"
            "  Click the 'Show Script' button.

"
            "The following information is from the Py-ART documentation.
"
            "
"
            "WARNING: By saving the file, the mask associated with "
            "the data "
            "values may be modfidied. The data itself does not change.
"
            "
"
            "GateFilter
" + pyart.filters.GateFilter.__doc__ +
            "

"
            "GateFilter.exclude_below
"
            "" + pyart.filters.GateFilter.exclude_below.__doc__ + ""
            )
        print(text)
        common.ShowLongText(text.replace("\n", "
"), set_html=True)

    def set_operator_menu(self):
        '''Set the field operators choice.'''
        opBox = QtWidgets.QComboBox()
        opBox.setFocusPolicy(QtCore.Qt.NoFocus)
        opBox.setToolTip("Select filter operator.\n")
        opBox_layout = QtWidgets.QVBoxLayout()
        for op in self.operators.keys():
            opBox.addItem(op)
        opBox.setLayout(opBox_layout)

        return opBox

    def showScript(self):
        '''Create the output script to reproduce filtering results.'''
        text = (
            "PyArt Script Commands

"
            "Warning: This generated script is not complete!
"
            "The commands below are intended to be integrated for use in "
            "batch scripting to achieve the same results seen in the Display."
            "

"
            "Just copy and paste the below commands into your script.

"
            "Commands:

"
            "gatefilter = pyart.filters.GateFilter(radar, exclude_based=True)"
            "
")

        try:
            for cmd in self.filterscript:
                text += cmd + "
"
        except:
            common.ShowWarning("Must apply filter first.")

        text += ("

"
                 "for field in Vradar.value.fields.keys():
"
                 "    Vradar.value.fields[field]['data'].mask = ("
                 "Vgatefilter.value._gate_excluded)
")
        common.ShowLongText(text)

    def saveRadar(self):
        '''Open a dialog box to save radar file.'''
        dirIn, fname = os.path.split(self.Vradar.value.filename)
        filename = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save Radar File', dirIn)
        filename = str(filename)
        if filename == '' or self.Vradar.value is None:
            return
        else:
            for field in self.Vradar.value.fields.keys():
                self.Vradar.value.fields[field]['data'] = np.ma.array(
                    self.Vradar.value.fields[field]['data'],
                    mask=self.Vgatefilter.value._gate_excluded)

                # **This section is a potential replacement for merging
                # if problems are found in mask later **
#               # combine the masks  (noting two Falses is a good point)
#               combine = np.ma.mask_or(
#                   self.Vradar.value.fields[field]['data'].mask,
#                   self.Vgatefilter.value._gate_excluded)
#               self.Vradar.value.fields[field]['data'].mask = np.ma.mask_or(
#                    combine,
#                    self.Vradar.value.fields[field]['data'].mask)
#               self.Vradar.value.fields[field].data[:]=np.where(combine,
#                     self.Vradar.value.fields[field]['_FillValue'],
#                     self.Vradar.value.fields[field]['data'].data)

            pyart.io.write_cfradial(filename, self.Vradar.value)
            print("Saved %s" % (filename))

    def restoreRadar(self):
        '''Remove applied filters by restoring original mask'''
        for field in self.Vradar.value.fields.keys():
            self.Vradar.value.fields[field]['data'] = np.ma.array(
                self.Vradar.value.fields[field]['data'],
                mask=self.original_masks[field])
        self.Vgatefilter.value._gate_excluded = self.original_masks[field]
        self.Vgatefilter.update(True)

    ######################
    #   Filter Methods   #
    ######################

    def apply_filters(self):
        '''Mount Options and execute
        :py:func:`~pyart.filters.GateFilter`.
        The resulting fields are added to Vradar.
        Vradar is updated, strong or weak depending on overwriting old fields.
        '''
        # Test radar
        if self.Vradar.value is None:
            common.ShowWarning("Radar is None, cannot perform filtering.")
            return

        # Retain the original masks
        self.original_masks = {}
        for field in self.Vradar.value.fields.keys():
            self.original_masks[field] = np.ma.getmaskarray(
                self.Vradar.value.fields[field]['data'])
            print(field)

        gatefilter = pyart.filters.GateFilter(self.Vradar.value,
                                              exclude_based=True)

        # Clear flags from previous filter application or instantiate if first
        args = {}
        self.filterscript = []

        # Create a list of possible filtering actions
        val2Cmds = ["inside", "outside"]
        valinc = [">=", "<="]

        # Initial point for timing
        t0 = time.time()

        # Get a list of field to apply the filters
        self.filt_flds = []

        pyarterr = "Py-ART fails with following error\n\n"
        # Execute chosen filters
        print("Applying filters ..")
        NoChecks = True
        for index, chk in enumerate(self.fieldfilter["check_active"]):
            if chk.isChecked():
                NoChecks = False
                field = str(self.fieldfilter["field"][index].text())
                operator = str(
                    self.fieldfilter["operator"][index].currentText())
                val1 = self.fieldfilter["low_value"][index].text()
                val2 = self.fieldfilter["high_value"][index].text()

                print("%s checked, %s, v1 = %s, v2 = %s" %
                      (field, self.operators[operator], val1, val2))

                # Create the command to be issued for filtering
                # Try that command and return error if fail

                # If the operator takes val1 and val2
                if operator in val2Cmds:
                    filtercmd = "gatefilter.%s(%s, %s, %s)" % (
                        self.operators[operator], field, val1, val2)
                    if operator == "inside":
                        try:
                            gatefilter.exclude_inside(
                                field, float(val1), float(val2))
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                    else:
                        try:
                            gatefilter.exclude_outside(
                                field, float(val1), float(val2))
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                # If the operators are inclusive of val1
                elif operator in valinc:
                    filtercmd = "gatefilter.%s(%s, %s, inclusive=True)" % (
                        self.operators[operator], field, val1)
                    if operator == "<=":
                        try:
                            gatefilter.exclude_below(
                                field, float(val1), inclusive=True)
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                    elif operator == ">=":
                        try:
                            gatefilter.exclude_above(
                                field, float(val1), inclusive=True)
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                # If the operators are exclusive of val1
                else:
                    filtercmd = "gatefilter.%s(%s, %s, inclusive=False)" % (
                        self.operators[operator], field, val1)
                    if operator == "=":
                        try:
                            gatefilter.exclude_equal(
                                field, float(val1))
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                    elif operator == "!=":
                        try:
                            gatefilter.exclude_not_equal(
                                field, float(val1))
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                    elif operator == "<":
                        try:
                            gatefilter.exclude_below(
                                field, float(val1), inclusive=False)
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)
                    elif operator == ">":
                        try:
                            gatefilter.exclude_above(
                                field, float(val1), inclusive=False)
                        except:
                            import traceback
                            error = traceback.format_exc()
                            common.ShowLongText(pyarterr + error)

                self.filterscript.append(filtercmd)

        print(("Filtering took %fs" % (time.time()-t0)))
        # If no filters were applied issue warning
        if NoChecks:
            common.ShowWarning("Please Activate Filter(s)")
            return

        # add fields and update
        self.Vgatefilter.change(gatefilter, True)

    def _clearLayout(self, layout):
        '''recursively remove items from layout.'''
        while layout.count():
            item = layout.takeAt(0)
            widget = item.widget()
            if widget is not None:
                widget.deleteLater()
            else:
                self._clearLayout(item.layout())

_plugins = [GateFilter]

class MyQCheckBox(QtWidgets.QCheckBox):

    def __init__(self, *args, **kwargs):
        QtWidgets.QCheckBox.__init__(self, *args, **kwargs)
        self.is_modifiable = True
        self.clicked.connect(self.value_change_slot)

    def value_change_slot(self):
        if self.isChecked():
            self.setChecked(self.is_modifiable)
        else:
            self.setChecked(not self.is_modifiable)

    def setModifiable(self, flag):
        self.is_modifiable = flag

    def isModifiable(self):
        return self.is_modifiable


import tensorflow.keras as keras
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras import backend as K

import pandas as pd
from nltk.tokenize import word_tokenize , sent_tokenize
import gensim
from sklearn import preprocessing , model_selection,metrics
from imblearn.over_sampling import SMOTE
import numpy as np

# LOAD BEST MODEL AND COMPARE FIT TO LAST EPOCH
def load_best_model(model_path=None, xtr=None, xte=None, ytr=None, yte=None,
                    custom_obs={'SeqSelfAttention':None}):
    model_path = model_path
    model_out = keras.models.load_model(model_path, custom_objects=custom_obs)

    # GET CONFUSION MATRIX FOR BEST MODEL
    y_preds = model_out.predict_classes(xtr)
    y_preds_test = model_out.predict_classes(xte)

    matrix = metrics.confusion_matrix(ytr, y_preds)
    matrix_test = metrics.confusion_matrix(yte, y_preds_test)

    print('Final Model Confusion Matrix')
    print(matrix)
    print('Final Model Confusion Matrix')
    print(matrix_test)

    return model_out, matrix, matrix_test

#####MODEL DATA PREPROCESSING FUNCTION
def make_df(datapath
            , max_features
            , EMBEDDING_DIM
            , stop_list
            , target
            , rebalance_data=False
            , test_size=.2
            , textcol='final_complaint_string'):
    '''
    Inputs:
    ##### datapath = path to dataframe of sentences and label ids
    ##### max_features = total number of features from text to consider when buildling embedding layer
    ##### EMBEDDING_DIM = total number of dimensions from embedding we want to use in embedding layer (Note: if using pymag you must use 300)
    ##### stop_lsit = list of stopwords to use for preprocessing
    ##### stemmer = stemming class to use to stem words in sentences
    ##### target = name of the target feild you are trying to predict in the dataset
    PROCESS STEPS:
    ##### 1. toeknize text
    ##### 2. Convert text to sequences
    ##### 3. Pad Sequences
    ##### 4. Split into Test and Train
    ##### 5. Return X_train , X_Test, Y, WordIndex
    '''

    # load data
    if isinstance(datapath, object):
        data = datapath
    else:
        data = pd.read_pickle(datapath)

    # clean original sentence level text
    # trainDF = orig_text_clean(data,target=target , txtfeild='Sentence',stopwords=stop_list,stemmer=stemmer)

    # specify X and Y (these standard columns are created in orig_text_clean)
    X = data[textcol]
    Y = data[target]

    # generate list of unique words based on total words specified to consider
    sentences = []
    lines = X.values.tolist()
    lines = [word_tokenize(sent) for sent in lines]
    model = gensim.models.Word2Vec(sentences=lines, size=EMBEDDING_DIM, window=5, workers=4, min_count=1)
    words = list(model.wv.vocab)

    # model process
    # fit tokenizer to words and turn to sequences
    tokenizer_obj = Tokenizer()
    tokenizer_obj.fit_on_texts(X)
    sequences = tokenizer_obj.texts_to_sequences(X)

    # define max length for padding and total vocab size
    max_length = max([len(s.split()) for s in X])
    vocab_size = len(tokenizer_obj.word_index) + 1

    # pad sequences
    word_index = tokenizer_obj.word_index
    review_pad = pad_sequences(sequences, maxlen=max_length)
    label = Y.values

    # split data
    x_train, x_test, y_train, y_test = model_selection.train_test_split(review_pad, label, shuffle=True, stratify=Y,
                                                                        test_size=test_size, random_state=10)

    if rebalance_data == True:
        sm = SMOTE(random_state=2)
        x_train, y_train = sm.fit_sample(x_train, y_train)

    return x_train, y_train, x_test, y_test, word_index, max_length, words

#pymagnitude vectors

def make_embeddings_pymag(wv, max_features,words, word_index, embed_size, nb_words):
    #embeddings using pymagnitude
    embeddings_index = {}
    for w in words:
        word =w
        coefs = wv.query(word) #np.asarray(values[1:])
        embeddings_index[word]=coefs

    embedding_matrix = np.zeros((nb_words, embed_size))
    for word, i in word_index.items():
        if i >= max_features:
            continue
        embedding_vector = embeddings_index.get(word)
        if embedding_vector is not None:
            embedding_matrix[i] = embedding_vector
    return embedding_matrix

#peformance metrics
def precision(y_true, y_pred):
    # Calculates the precision
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision

def recall(y_true, y_pred):
    # Calculates the recall
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def fbeta_score(y_true, y_pred, beta=1):
    # Calculates the F score, the weighted harmonic mean of precision and recall.

    if beta < 0:
        raise ValueError('The lowest choosable beta is zero (only precision).')

    # If there are no true positives, fix the F score at 0 like sklearn.
    if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
        return 0

    p = precision(y_true, y_pred)
    r = recall(y_true, y_pred)
    bb = beta ** 2
    fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
    return fbeta_score

def fmeasure(y_true, y_pred):
    # Calculates the f-measure, the harmonic mean of precision and recall.
    return fbeta_score(y_true, y_pred, beta=1)

def build_model( embedding_dim, embedding_vector, maxlen,nb_words,targ_levels=7, transfer_learn=True):
    model = keras.models.Sequential()

    # add embedding layer
    model.add(keras.layers.Embedding(input_dim=nb_words  # max_features
                                     , output_dim=embedding_dim  # embedding size
                                     , weights=[embedding_vector]
                                     , mask_zero=False
                                     , trainable=transfer_learn
                                     # if True transfer learning is enabled, the weights from the past epoch are used as starting points for the next epoch
                                     , input_length=maxlen
                                     # the max sequence length, this is the length that all sequences will be padded to (so all sequences will have same length)
                                     ))

    # ADD CNN LAYER WITH SELU ACTIVATION AND GAUSSIAN DROPOUT
    # NOTE:specify guassian dropout befire activation function has been specified
    # WARNING: if you specify guassian dropout after activation function  the resulting values may be out-of-range
    # from what the activation function may normally provide. For example, a value with added noise may be less than zero,
    # whereas the relu activation function will only ever output values 0 or larger.
    model.add(keras.layers.Conv1D(filters=164, kernel_size=10, padding='valid', strides=1))
    model.add(keras.layers.MaxPooling1D(pool_size=4))
    model.add(keras.layers.GaussianDropout(0.2))
    model.add(keras.layers.Activation('selu'))

    # ADD BILSTM WITH DROPOUT
    # DROPOUT VERY HIGH TO AVOID OVERFIT
    model.add(keras.layers.Bidirectional(keras.layers.LSTM(units=100,
                                                           return_sequences=True,
                                                           # dropout=.3, #dropout not applied here becase we apply it via the guassian dropout specificed below
                                                           recurrent_dropout=.2,
                                                           recurrent_regularizer=keras.regularizers.L1L2(l1=0.0,
                                                                                l2=0.01),
                                                           kernel_regularizer=keras.regularizers.L1L2(l1=0, l2=.01),
                                                           bias_regularizer=keras.regularizers.L1L2(l1=0, l2=.01),
                                                           )))
    # ADD NON RECURRENT DROPUT TO LSTM
    model.add(keras.layers.GaussianDropout(0.2))
    model.add(keras.layers.Activation('selu'))

    # FLATTENED LAYER (CONVERTS 2D tensor to 1D)
    # model.add(GlobalMaxPool1D())
    model.add(keras.layers.Flatten())

    # OUTPUT LAYER(units = # target labels, for binary this =1)
    model.add(keras.layers.Dense(units=targ_levels, activation='softmax'))

    # COMPILE MODEL WITH CUSTOM KERAS METRICS (functions defined at top of script)
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])#, recall, fmeasure, precision, fbeta_score

    return model


import warnings
import numpy as np
from PIL import Image
from anytree import NodeMixin, PostOrderIter, PreOrderIter

H_MIN = 0.5
H_MAX = 2.0

class BaseElement(NodeMixin):
    def __init__(self, d):
        self.name = d.name.split('/')[-1]
        self.image = Image.fromarray(d[:])
        self.attrs = dict(d.attrs)
        self.__H, self.__x, self.__y = [None] * 3
        for k, v in self.attrs.items():
            if type(v) == np.ndarray:
                self.attrs[k] = list(v)

    def _normalize(self):
        M = self.root.base_size
        x0, y0, x1, y1 = self.attrs['box']
        x0, x1 = x0 / M, x1 / M
        y0, y1 = y0 / M, y1 / M
        self.attrs['nbox'] = [x0, y0, x1, y1]
        self.__H_max = (y1 - y0) * H_MAX
        self.aspect_ratio = (x1 - x0) / (y1 - y0)

    @property
    def H(self):
        if self.__H is None:
            if np.isfinite(self.l_H):
                H_ub = min(self.parent.H, self.__H_max,
                           self.parent.W / self.aspect_ratio)
                self.__H = self.l_H * (H_ub - self.H_lb) + self.H_lb
            else:
                self.__H = self.parent.H
        return self.__H

    @property
    def x(self):
        if self.__x is None:
            if np.isfinite(self.l_x):
                x_ub = self.parent.x + self.parent.W - self.W
                self.__x = self.l_x * (x_ub - self.parent.x) + self.parent.x
            else:
                self.__x = self.parent.x
        return self.__x

    @property
    def y(self):
        if self.__y is None:
            if np.isfinite(self.l_y):
                y_ub = self.parent.y + self.parent.H - self.H
                self.__y = self.l_y * (y_ub - self.parent.y) + self.parent.y
            else:
                self.__y = self.parent.y
        return self.__y

    @property
    def W(self):
        return self.H * self.aspect_ratio

class RootElement(BaseElement):
    def __init__(self, d):
        super().__init__(d)
        x0, y0, x1, y1 = self.attrs['box']
        self.base_size = float(max(y1 - y0, x1 - x0))
        self._normalize()

    @property
    def H(self):
        _, y0, _, y1 = self.attrs['nbox']
        return y1 - y0

    @property
    def x(self):
        return self.attrs['nbox'][0]

    @property
    def y(self):
        return self.attrs['nbox'][1]

    def _pre_attach(self, parent):
        raise RuntimeError('Cannot set parent to RootElement')

class Element(BaseElement):
    def set_H_lb(self):
        _, y0, _, y1 = self.attrs['nbox']
        H_lb = (y1 - y0) * H_MIN
        for d in self.descendants:
            H_lb = max(d.H_lb, d.W_lb / self.aspect_ratio, H_lb)
        self.H_lb = H_lb
        self.W_lb = H_lb * self.aspect_ratio

class WebPageLayout():
    def __init__(self, g):
        self.root = RootElement(g['root'])
        self.elements = [Element(g[str(i)])
                         for i in range(len(g) - 1)]

        # tree construction
        for e in self.elements:
            if e.attrs['parent'] == 'root':
                e.parent = self.root
            else:
                e.parent = self.elements[e.attrs['parent']]

        def not_root(e):
            return not e.is_root

        # set H lower bound
        for e in PostOrderIter(self.root, filter_=not_root):
            e._normalize()
            e.set_H_lb()

        # set parameters
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore")
            for e in PreOrderIter(self.root, filter_=not_root):
                x0, y0, _, y1 = e.attrs['nbox']
                H_ub = min(e.parent.H, e.parent.W / e.aspect_ratio,
                           (y1 - y0) * H_MAX)
                e.l_H = (y1 - y0 - e.H_lb) / (H_ub - e.H_lb)
                e.l_x = (x0 - e.parent.x) / (e.parent.W - e.W)
                e.l_y = (y0 - e.parent.y) / (e.parent.H - e.H)


# Sums up the transactions in a Bankgiroinbetalning transaction file

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("bgfile", help="File from Bankgirot")
args = parser.parse_args()

with open(args.bgfile, 'r') as f:
    l = f.readline()
    sum = 0
    i = 0
    while l:
        if l[:2] == "20":
            i+=1
            sum += int(l[38:55])
        l = f.readline()
    print("Sum: %d Transactions: %d" % (sum, i))


import os
import json
import pandas as pd
from matplotlib import pyplot as plt

CHECKPOINT_ROOT = "D:/checkpoints/final_results"

if __name__ == '__main__':
    _, folders, _ = next(os.walk(CHECKPOINT_ROOT))

    full_csv_paths = [f"{CHECKPOINT_ROOT}/{f}/progress.csv" for f in folders]

    fig, ax = plt.subplots()

    ax.set_xlabel("epizoda")
    ax.set_ylabel(r"odměna $r$")
    ax.set_title("Vývoj odměn agentů 2b)")

    for i, pth in enumerate(full_csv_paths):
        with open(pth, "rb") as f:
            res = pd.read_csv(f)
            ax.plot(res["episode_reward_mean"])

    plt.legend([r"$r_0 ... 1-d$", "$r_1 ... $sigmoid", "$r_2 ... 1-d^{0.4}$", "$r_3 ... r_2 - p$", "$r_4 ... \mu r_2-p$"])
    plt.savefig(f"{CHECKPOINT_ROOT}/collective_reward_plot.png", dpi=200)
    plt.show()


# https://leetcode.com/problems/maximum-depth-of-binary-tree/
# 문제104번.Maximum Depth of Binary Tree

# 입력
'''
1. 이진 트리의 노드들
- 0 <= 노드 수 <= 10,000
- -100 <= Node.val <= 100
'''

# 출력
'''
1. 이진 트리의 최대 깊이 출력
'''

# 코드
import sys
from collections import deque

sys.stdin = open('input_text/104.txt')

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# print(root)의 결과
# ⇒ TreeNode{val: 3, left: TreeNode{val: 9, left: None, right: None}, right: TreeNode{val: 20, left: TreeNode{val: 15, left: None, right: None}, right: TreeNode{val: 7, left: None, right: None}}}

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0

        q = deque([root])
        depth = 0
        while q:
            depth += 1
            for _ in range(len(q)):
                cur_root = q.popleft()
                if cur_root.left:
                    q.append(cur_root.left)
                if cur_root.right:
                    q.append(cur_root.right)
        return depth

# 실행 결과: 성공(메모리:15.3 MB, 시간:48 ms)


# -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 :

__all__ = [
        'SpawnedProcessError',
        'dbg_exec_cmd',
        'do_exec_cmd',
        'suggest_exec_cmd',
        'dbg_system_cmd',
        'do_system_cmd',
        'dbg_popen_cmd',
        'do_popen_cmd',
        'dbg_spawn_cmd',
        'do_spawn_cmd',
        'clean_cmd_output',
        'Executable',
        'SystemExecutable',
        'PipedExecutable',
        'PipedScript',
        'PipedPortableScript',
        'XdgExecutable',
        'EDITOR',
        'DIFFTOOL',
        'edfile',
        'edvar',
        'eddiff',
        'eddiffvar',
        'xdg_open',
        'nice',
        'renice',
        'ionice',
        'list2cmdlist',
        'list2cmdline',
        'stdout_wrapper',
        'clean_file_name',
        ]

from pathlib import Path
import abc
import collections
import contextlib
import enum
import errno
import functools
import logging
import os
import pexpect
import pexpect.fdpexpect
import pexpect.popen_spawn
import pexpect.spawnbase
import pexpect.utils
import re
import shlex
import shutil
import signal
import subprocess
import sys
import threading
import time
import types
import unidecode
import xdg
import xml.etree.ElementTree as ET
log = logging.getLogger(__name__)

from qip.app import app  # Also setup log.verbose
from qip.utils import byte_decode, prettyxml
from qip.xdg import XdgResource

_mswindows = (sys.platform == "win32")

try:
    from queue import Queue, Empty  # Python 3
except ImportError:
    from Queue import Queue, Empty  # Python 2

def arg2cmdarg(arg):
    return (os.fspath(arg) if isinstance(arg, os.PathLike)
            else (
                str(arg)))

def list2cmdlist(cmd):
    return [arg2cmdarg(e) for e in cmd]

def list2cmdline(cmd):
    return subprocess.list2cmdline(
        list2cmdlist(cmd))

class SpawnedProcessError(subprocess.CalledProcessError):

    def __init__(self, returncode, cmd, output=None, stderr=None, spawn=None):
        self.spawn = spawn
        super().__init__(returncode=returncode, cmd=cmd, output=output, stderr=stderr)

class _SpawnMixin(pexpect.spawnbase.SpawnBase):

    def __init__(self, *args, errors=None, timeout=None, **kwargs):
        super().__init__(*args, codec_errors=errors, timeout=timeout, **kwargs)

    def communicate(self, pattern_dict,
                    timeout=-1, searchwindowsize=-1):
        pattern_kv_list = list(pattern_dict.items())
        pattern_list = [k for k, v in pattern_kv_list]
        compiled_pattern_list = self.compile_pattern_list(pattern_list)
        if timeout == -1:
            timeout = self.timeout
        from pexpect.expect import Expecter, searcher_re
        searcher = searcher_re(compiled_pattern_list)
        exp = Expecter(spawn=self, searcher=searcher, searchwindowsize=searchwindowsize)
        while True:
            idx = exp.expect_loop(timeout=timeout)
            if idx is None:
                break
            k, v = pattern_kv_list[idx]
            yield v

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.close(force=True)
        try:
            if not self.terminated:
                try:
                    self.wait()
                except pexpect.ExceptionPexpect as err:
                    if err.value != 'Cannot wait for dead child process.':
                        raise
        finally:
            self.close()

class spawn(_SpawnMixin, pexpect.spawn):

    def __init__(self, command, args=[],
                 **kwargs):
        if command is not None:
            command = os.fspath(command)
        args = list2cmdlist(args)
        super().__init__(command=command, args=args,
                         **kwargs)

class fdspawn(_SpawnMixin, pexpect.fdpexpect.fdspawn):

    def __init__(self, fd, command=None, args=None,
                 cwd=None,
                 **kwargs):
        assert cwd is None  # Not supported by pexpect.fdpexpect.fdspawn
        super().__init__(fd=fd, args=args, **kwargs)
        self.args = args  # pexpect.fdpexpect.fdspawn sets to None
        self.command = command  # pexpect.fdpexpect.fdspawn sets to None

    def close(self, *, force=None, **kwargs):
        return super().close(
            # force=force  # Not supported by pexpect.fdpexpect.fdspawn
            **kwargs)

class popen_spawn(_SpawnMixin, pexpect.popen_spawn.PopenSpawn):
    # See pexpect/popen_spawn.py

    def __init__(self, cmd, *, timeout=None, maxread=2000, searchwindowsize=None,
                 logfile=None, env=None, encoding=None,
                 errors='strict', preexec_fn=None,
                 bufsize=0,
                 stdin=None, stdout=None, stderr=None,
                 read_from='auto',
                 **kwargs):
        pexpect.spawnbase.SpawnBase.__init__(  # Skip pexpect.popen_spawn.PopenSpawn!
                self, timeout=timeout, maxread=maxread,
                searchwindowsize=searchwindowsize, logfile=logfile,
                encoding=encoding, codec_errors=errors)

        # Note that `SpawnBase` initializes `self.crlf` to `\r\n`
        # because the default behaviour for a PTY is to convert
        # incoming LF to `\r\n` (see the `onlcr` flag and
        # https://stackoverflow.com/a/35887657/5397009). Here we set
        # it to `os.linesep` because that is what the spawned
        # application outputs by default and `popen` doesn't translate
        # anything.
        if encoding is None:
            self.crlf = os.linesep.encode ("ascii")
        else:
            self.crlf = self.string_type (os.linesep)

        if sys.platform == 'win32':
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            kwargs['startupinfo'] = startupinfo
            kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP

        if isinstance(cmd, pexpect.utils.string_types) and sys.platform != 'win32':
            cmd = shlex.split(cmd, posix=os.name == 'posix')

        if read_from == 'auto':
            if stdout == subprocess.PIPE:
                read_from = 'stdout'
            elif stderr == subprocess.PIPE:
                read_from = 'stderr'
            else:
                # raise ValueError('read_from not set and neither stdout nor stderr are pipes')
                read_from = None

        self.proc = subprocess.Popen(cmd,
                                     bufsize=bufsize,
                                     stdin=stdin, stdout=stdout, stderr=stderr,
                                     **kwargs)
        self.pid = self.proc.pid
        self.closed = False
        self._buf = self.string_type()

        self._read_from = read_from
        if self._read_from:
            self._read_queue = Queue()
            self._read_thread = threading.Thread(target=self._read_incoming)
            self._read_thread.setDaemon(True)
            self._read_thread.start()
        else:
            self._read_reached_eof = True

    def _read_incoming(self):
        """Run in a thread to move output from a pipe to a queue."""
        fileno = getattr(self.proc, self._read_from).fileno()
        while 1:
            buf = b''
            try:
                buf = os.read(fileno, 1024)
            except OSError as e:
                self._log(e, 'read')

            if not buf:
                # This indicates we have reached EOF
                self._read_queue.put(None)
                return

            self._read_queue.put(buf)

    def close(self, force=True):
        # Missing from pexpect.popen_spawn.PopenSpawn!
        if not force and self.proc.stdin:
            self.flush()
            self.sendeof()
        self.kill(signal.SIGKILL if force else signal.SIGTERM)
        self.closed = True

def dbg_exec_cmd(cmd, *, hidden_args=[],
                 dry_run=None, log_append='', return_CompletedProcess=False,
                 fd=None,
                 stdout=None,
                 **kwargs):
    assert fd is None
    if log.isEnabledFor(logging.DEBUG):
        log.verbose('CMD: %s%s',
                    list2cmdline(cmd),
                    log_append)
    # return subprocess.check_output(cmd + hidden_args, **kwargs)
    if 'input' in kwargs and kwargs['input'] is None:
        # Explicitly passing input=None was previously equivalent to passing an
        # empty string. That is maintained here for backwards compatibility.
        kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b''
    if stdout is None:
        stdout = subprocess.PIPE
    cmd = list2cmdlist(cmd)
    hidden_args = list2cmdlist(hidden_args)
    run_out = subprocess.run(cmd + hidden_args,
                             stdout=stdout,
                             check=True, **kwargs)
    if return_CompletedProcess:
        return run_out
    else:
        return run_out.stdout

def do_exec_cmd(cmd, *,
                dry_run=None, log_append='', return_CompletedProcess=False,
                **kwargs):
    if dry_run is None:
         dry_run = getattr(app.args, 'dry_run', False)
    if dry_run:
        log.verbose('CMD (dry-run): %s%s',
                    list2cmdline(cmd),
                    log_append)
        if return_CompletedProcess:
            return subprocess.CompletedProcess(args=None, returncode=0, stdout='', stderr='')
        else:
            return ''
    else:
        return dbg_exec_cmd(cmd, log_append=log_append, return_CompletedProcess=return_CompletedProcess, **kwargs)

def suggest_exec_cmd(cmd, dry_run=None, **kwargs):
    log.info('SUGGEST: %s',
             list2cmdline(cmd))

def dbg_system_cmd(cmd, *, hidden_args=[], dry_run=None, log_append='',
                   cwd=None,
                   fd=None,
                   encoding=None, errors=None, text=None,
                   **kwargs):
    assert fd is None
    if log.isEnabledFor(logging.DEBUG):
        log.verbose('CMD: %s%s',
                    list2cmdline(cmd),
                    log_append)
    # text_mode = text or encoding or errors
    assert not kwargs, kwargs
    assert cwd is None
    return os.system(list2cmdline(cmd),
                     **kwargs)

def do_system_cmd(cmd, *, dry_run=None, log_append='', **kwargs):
    if dry_run is None:
         dry_run = getattr(app.args, 'dry_run', False)
    if dry_run:
        log.verbose('CMD (dry-run): %s%s',
                    list2cmdline(cmd),
                    log_append)
        return ''
    else:
        return dbg_system_cmd(cmd, dry_run=dry_run, log_append=log_append, **kwargs)

def dbg_popen_cmd(cmd, *, hidden_args=[], dry_run=None, log_append='', **kwargs):
    if log.isEnabledFor(logging.DEBUG):
        log.verbose('CMD: %s%s',
                    list2cmdline(cmd),
                    log_append)
    cmd = list2cmdlist(cmd)
    hidden_args = list2cmdlist(hidden_args)
    return subprocess.Popen(cmd + hidden_args, **kwargs)

def do_popen_cmd(cmd, *, dry_run=None, log_append='', **kwargs):
    if dry_run is None:
         dry_run = getattr(app.args, 'dry_run', False)
    if dry_run:
        log.verbose('CMD (dry-run): %s%s',
                    list2cmdline(cmd),
                    log_append)
        p = types.SimpleNamespace()
        pcm = contextlib.nullcontext(p)
        scm = contextlib.nullcontext(None)
        pcm.stdout = p.stdout = scm
        return pcm
    else:
        return dbg_popen_cmd(cmd, dry_run=dry_run, log_append=log_append, **kwargs)

def dbg_popen_spawn_cmd(cmd, *, hidden_args=[], dry_run=None, log_append='', **kwargs):
    if log.isEnabledFor(logging.DEBUG):
        log.verbose('CMD: %s%s',
                    list2cmdline(cmd),
                    log_append)
    return popen_spawn(cmd + hidden_args, **kwargs)

def do_popen_spawn_cmd(cmd, *, dry_run=None, log_append='', **kwargs):
    if dry_run is None:
         dry_run = getattr(app.args, 'dry_run', False)
    if dry_run:
        log.verbose('CMD (dry-run): %s%s',
                    list2cmdline(cmd),
                    log_append)
        p = types.SimpleNamespace()
        pcm = contextlib.nullcontext(p)
        scm = contextlib.nullcontext(None)
        pcm.stdout = p.stdout = scm
        return pcm
    else:
        return dbg_popen_spawn_cmd(cmd, dry_run=dry_run, log_append=log_append, **kwargs)

def dbg_spawn_cmd(cmd, hidden_args=[],
                  fd=None,
                  dry_run=None, no_status=False, yes=False, logfile=True,
                  cwd=None,
                  encoding=None, errors=None,
                  ):
    if app.log.isEnabledFor(logging.DEBUG):
        app.log.verbose('CMD: %s',
                        list2cmdline(cmd))
    out = ''
    if logfile is True:
        logfile = sys.stdout if encoding else sys.stdout.buffer
    elif logfile is False:
        logfile = None
    spawn_func = functools.partial(fdspawn, fd=fd) if fd is not None else spawn
    p = spawn_func(cmd[0], args=cmd[1:] + hidden_args, timeout=None,
                   cwd=cwd,
                   encoding=encoding, errors=errors,
                   logfile=logfile)
    while True:
        index = p.expect([
            r'Select match, 0 for none(?: \[0-\d+\]\?\r*\n)?',  # 0
            r'File \'.*\' already exists\. Overwrite \? \[y/N\] $',  # 1
            r'.*[\r\n]',  # 2
            pexpect.EOF,  # 3
            ])
        if index == 2:
            #app.log.debug('<<< %s%s', byte_decode(p.before), byte_decode(p.match.group(0)))
            out += byte_decode(p.before) + byte_decode(p.match.group(0))
        elif index == 0:
            #app.log.debug('<<< %s%s', byte_decode(p.before), p.match.group(0))
            #puts [list <<< $expect_out(buffer)]
            out += byte_decode(p.before) + byte_decode(p.match.group(0))
            logfile = p.logfile
            logfile_send = p.logfile_send
            try:
                if yes:
                    s = "0"
                else:
                    print('<interact>', end='', flush=True)
                    s = input()
                    print('</interact>', end='', flush=True)
                    p.logfile = None
                    p.logfile_send = None
                #app.log.debug('>>> sending %r', s)
                p.send(s)
                #puts [list >>> sending eol]
                p.send('\r')
            finally:
                p.logfile_send = logfile_send
                p.logfile = logfile
        elif index == 1:
            #app.log.debug('<<< %s%s', byte_decode(p.before), p.match.group(0))
            #puts [list <<< $expect_out(buffer)]
            out += byte_decode(p.before) + byte_decode(p.match.group(0))
            logfile = p.logfile
            logfile_send = p.logfile_send
            try:
                if yes:
                    s = "y"
                else:
                    print('<interact>', end='', flush=True)
                    s = input()
                    print('</interact>', end='', flush=True)
                    p.logfile = None
                    p.logfile_send = None
                #app.log.debug('>>> sending %r', s)
                p.send(s)
                #puts [list >>> sending eol]
                p.send('\r')
            finally:
                p.logfile_send = logfile_send
                p.logfile = logfile
        elif index == 3:
            #app.log.debug('<<< %s%s', byte_decode(p.before))
            out += byte_decode(p.before)
            break
    try:
        p.wait()
    except pexpect.ExceptionPexpect as err:
        if err.value != 'Cannot wait for dead child process.':
            raise
    p.close()
    if p.signalstatus is not None:
        raise Exception('Command exited due to signal %r' % (p.signalstatus,))
    if not no_status and p.exitstatus:
        raise subprocess.CalledProcessError(
                returncode=p.exitstatus,
                cmd=list2cmdline(cmd),
                output=out)
    return out

def do_spawn_cmd(cmd, dry_run=None, **kwargs):
    if dry_run is None:
         dry_run = getattr(app.args, 'dry_run', False)
    if dry_run:
        app.log.verbose('CMD (dry-run): %s',
                        list2cmdline(cmd))
        return ''
    else:
        return dbg_spawn_cmd(cmd, **kwargs)

def clean_cmd_output(out):
    out = byte_decode(out)
    out = re.sub(r'\x1B\[[0-9;]*m', '', out)
    out = re.sub(r'\r+\n', '\n', out)
    out = re.sub(r'.*\r', '', out, flags=re.MULTILINE)
    out = re.sub(r'\t', ' ', out)
    out = re.sub(r' +$', '', out, flags=re.MULTILINE)
    return out

class IoniceClass(enum.IntEnum):
    # None = 0
    Realtime = 1
    BestEffort = 2
    Idle = 3

class FakeDryRunPopen(subprocess.Popen):

    def __init__(self, args, *,
                 stdin=None, stdout=None, stderr=None,
                 **kwargs):
        self._in_stdout = stdout
        self._in_stderr = stderr
        super().__init__(args=args,
                         stdin=None, stdout=None, stderr=None,
                         **kwargs)

    def _execute_child(self, *args, **kwargs):
        self._child_created = False
        self._closed_child_pipe_fds = True

    def communicate(self, *args, **kwargs):
        self._communication_started = True
        self.returncode = 0
        stdout = ('' if self.text_mode else b'') if self._in_stdout == subprocess.PIPE else None
        stderr = ('' if self.text_mode else b'') if self._in_stderr == subprocess.PIPE else None
        return (stdout, stderr)

class Args(object):
    """Save given arguments and keywords.
    """

    def __new__(cls,
                # 3.8: /,
                *args, **keywords):

        self = super(Args, cls).__new__(cls)

        self.args = args
        self.keywords = keywords
        return self

    @classmethod
    def new_from(cls, other):
        if isinstance(other, Args):
            return Args(*other.args, **other.keywords)
        if isinstance(other, collections.abc.Mapping):
            return Args(**other)
        if isinstance(other, collections.abc.Sequence):
            return Args(*other)
        raise TypeError(other)

    def __add__(self, other):
        args = self.args + other.args
        keywords = dict(self.keywords)
        keywords.update(other.keywords)
        return self.__class__(*args, **keywords)

class Executable(metaclass=abc.ABCMeta):

    Args = Args

    popen_class = subprocess.Popen

    run_func = None
    run_func_options = (
        # options from do_exec_cmd/dbg_exec_cmd/subprocess.run/Popen
        #'dry_run',
        #'input',
        'stdin', 'stdout', 'stderr',
        'encoding', 'errors',
        #'universal_newlines', 'text',
    )
    popen_func = None
    popen_func_options = (
        # options from popen_spawn
        'stdin', 'stdout', 'stderr',
        'encoding', 'errors',
    )

    encoding = None
    encoding_errors = None

    nice_adjustment = None
    ionice_class = None
    ionice_level = None
    ionice_ignore = True

    needs_tty = False

    def _spawn_run_func(self, cmd=None, *, fd=None, hidden_args=[], dry_run=None, no_status=False, logfile=None,
                        stdin=None, stdout=None, stderr=None,
                        encoding=None, errors=None, text=None, universal_newlines=None,
                        **kwargs):

        if universal_newlines:
            # Backward compatibility
            text = True

        text_mode = encoding or errors or text
        if text_mode and encoding is None:
            # Sane default -- See _pyio.py TextIOWrapper
            encoding = 'utf-8'

        if stdin or stdout or stderr:
            stdin = stdin or subprocess.PIPE
            stdout = stdout or subprocess.PIPE
            stderr = stderr or subprocess.STDOUT  # Default from Executable._run
            #assert self.popen_func and self.popen_spawn, f'self={self!r}: popen_func={self.popen_func!r} and popen_spawn={self.popen_spawn!r}'
            assert logfile is None
            assert no_status == False
            assert fd is None
            return self.popen(cmd, hidden_args=hidden_args, dry_run=dry_run,
                              stdin=stdin, stdout=stdout, stderr=stderr,
                              encoding=encoding, errors=errors, text=text,
                              **kwargs)

        if fd is not None:
            if cmd is None:
                cmd = ['<fd>']

        if dry_run is None:
             dry_run = getattr(app.args, 'dry_run', False)
        if dry_run:
            app.log.verbose('CMD (dry-run): %s',
                            list2cmdline(cmd))
            return ''
        if logfile is True:
            logfile = sys.stdout.buffer
        elif logfile is False:
            logfile = None
        if app.log.isEnabledFor(logging.DEBUG):
            app.log.verbose('CMD: %s',
                            list2cmdline(cmd))

        spawn_func = functools.partial(self.fdspawn, fd=fd) if fd is not None else self.spawn
        p = spawn_func(cmd[0], args=cmd[1:] + hidden_args, logfile=logfile,
                       encoding=encoding, errors=errors,  # text=text,
                       **kwargs)
        with p:
            pattern_dict = p.get_pattern_dict()
            out = '' if text_mode else b''
            for v in p.communicate(pattern_dict=pattern_dict):
                out += p.before
                if p.match and p.match is not pexpect.EOF:
                    out += p.match.group(0)
                if callable(v):
                    if p.match is pexpect.EOF:
                        b = v(None)
                    else:
                        b = v(p.match.group(0))
                    if not b:
                        break
                if p.after is pexpect.EOF:
                    break
        if p.signalstatus is not None:
            raise Exception('Command exited due to signal %r' % (p.signalstatus,))
        if not no_status and p.exitstatus:
            raise SpawnedProcessError(
                returncode=p.exitstatus,
                cmd=list2cmdline(cmd),
                output=out,
                spawn=p)
        if text_mode:
            out = byte_decode(out)
        return {
            'out': out,
            'spawn': p,
        }

    def _spawn_popen_func(self, cmd, hidden_args=[], dry_run=None, no_status=False, logfile=None, **kwargs):
        if dry_run is None:
             dry_run = getattr(app.args, 'dry_run', False)
        if dry_run:
            app.log.verbose('CMD (dry-run): %s',
                            list2cmdline(cmd))
            return ''
        if app.log.isEnabledFor(logging.DEBUG):
            app.log.verbose('CMD: %s',
                            list2cmdline(cmd))
        if logfile is True:
            logfile = sys.stdout.buffer
        elif logfile is False:
            logfile = None
        p = self.popen_spawn(cmd + hidden_args, logfile=logfile, **kwargs)
        with p:
            pattern_dict = p.get_pattern_dict()
            out = ''
            for v in p.communicate(pattern_dict=pattern_dict):
                out += byte_decode(p.before)
                if p.match and p.match is not pexpect.EOF:
                    out += byte_decode(p.match.group(0))
                if callable(v):
                    if p.match is pexpect.EOF:
                        b = v(None)
                    else:
                        b = v(p.match.group(0))
                    if not b:
                        break
                if p.after is pexpect.EOF:
                    break
        if p.signalstatus is not None:
            raise Exception('Command exited due to signal %r' % (p.signalstatus,))
        if not no_status and p.exitstatus:
            raise SpawnedProcessError(
                returncode=p.exitstatus,
                cmd=list2cmdline(cmd),
                output=out,
                spawn=p)
        return out

    @property
    @abc.abstractmethod
    def name(self):
        raise NotImplementedError

    def which(self, mode=os.F_OK | os.X_OK, path=None, assert_found=True):
        cmd = shutil.which(os.fspath(self.name), mode=mode, path=path)
        if cmd is None and assert_found:
            raise OSError(errno.ENOENT, f'Command not found: {self.name}')
        return cmd

    @classmethod
    def clean_cmd_output(cls, out):
        return clean_cmd_output(out)

    @classmethod
    def kwargs_to_cmdargs(cls, **kwargs):
        if kwargs:
            raise ValueError('Unsupported keyword arguments: %r' % (kwargs,))
        return []

    @classmethod
    def kwargs_to_cmdargs_gnu_getopt(cls, **kwargs):
        cmdargs = []
        for k, v in kwargs.items():
            if v in (None, False):
                # Dropped for ease of passing unused arguments
                continue
            k = {
                '_class': 'class',
                '_continue': 'continue',
            }.get(k, k)
            if len(k) == 1:
                cmdargs.append('-' + k)
            else:
                cmdargs.append('--' + k)
            if v is not True:
                cmdargs.append(arg2cmdarg(v))
        return cmdargs

    @classmethod
    def kwargs_to_cmdargs_gnu_getopt_dash(cls, **kwargs):
        return cls.kwargs_to_cmdargs_gnu_getopt(
            **{k.replace('_', '-'): v
               for k, v in kwargs.items()})

    @classmethod
    def kwargs_to_cmdargs_win_slash(cls, **kwargs):
        cmdargs = []
        for k, v in kwargs.items():
            if v in (None, False):
                # Dropped for ease of passing unused arguments
                continue
            k = {
                '_class': 'class',
                '_continue': 'continue',
            }.get(k, k)
            cmdargs.append('/' + k)
            if v is not True:
                cmdargs.append(arg2cmdarg(v))
        return cmdargs

    def build_cmd(self, *args, **kwargs):
        nice_adjustment = kwargs.pop('nice_adjustment', self.nice_adjustment)
        ionice_class = kwargs.pop('ionice_class', self.ionice_class)
        ionice_level = kwargs.pop('ionice_level', self.ionice_level)
        ionice_ignore = kwargs.pop('ionice_ignore', self.ionice_ignore)

        cmd = [self.which()] \
            + list2cmdlist(args) \
            + self.kwargs_to_cmdargs(**kwargs)

        if ionice_class is not None or ionice_level is not None:
            if ionice_class is not None:
                ionice_class = int(IoniceClass(ionice_class))
            if ionice_level is not None:
                ionice_level = int(ionice_level)
            if ionice_ignore is not None:
                ionice_ignore = bool(ionice_ignore)
            cmd = ionice.build_cmd(*cmd,
                                   _class=ionice_class,
                                   classdata=ionice_level,
                                   ignore=ionice_ignore,
                                   )

        if nice_adjustment is not None:
            if nice_adjustment is not None:
                nice_adjustment = int(nice_adjustment)
            cmd = nice.build_cmd(*cmd,
                                 adjustment=nice_adjustment,
                                 )

        return cmd

    def popen_new(self, *args,
                  cwd=None,
                  stdin=None, stdout=None, stderr=None,
                  capture_output=False,
                  text=None, encoding=None, errors=None,
                  dry_run=None,
                  **kwargs):
        if dry_run is None:
             dry_run = getattr(app.args, 'dry_run', False)

        if capture_output:
            if stdout is not None or stderr is not None:
                raise ValueError('stdout and stderr arguments may not be used '
                                 'with capture_output.')
            stdout = subprocess.PIPE
            stderr = subprocess.PIPE

        cmd = self.build_cmd(*args, **kwargs)
        cmd = list2cmdlist(cmd)
        text_mode, encoding, errors = self.get_text_mode_info(
            cmd=cmd, text=text, encoding=encoding, errors=errors)

        if dry_run:
            log.verbose('CMD (dry-run): %s',
                        list2cmdline(cmd))
            popen_class = FakeDryRunPopen
        else:
            if log.isEnabledFor(logging.DEBUG):
                log.verbose('CMD: %s',
                            list2cmdline(cmd))
            popen_class = self.popen_class

        return popen_class(cmd,
                           cwd=cwd,
                           stdin=stdin, stdout=stdout, stderr=stderr,
                           encoding=encoding, errors=errors,
                           **kwargs)

    def run_new(self, *args,
                cwd=None,
                stdin=None, stdout=None, stderr=None,
                capture_output=False,
                text=None, encoding=None, errors=None,
                timeout=None, check=False,
                dry_run=None,
                **kwargs):

        with self.popen_new(*args,
                            cwd=cwd,
                            stdin=stdin, stdout=stdout, stderr=stderr,
                            capture_output=capture_output,
                            encoding=encoding, errors=errors,
                            dry_run=dry_run,
                            **kwargs) as process:
            try:
                stdout, stderr = process.communicate(timeout=timeout)
            except TimeoutExpired as exc:
                process.kill()
                if _mswindows:
                    # Windows accumulates the output in a single blocking
                    # read() call run on child threads, with the timeout
                    # being done in a join() on those threads.  communicate()
                    # _after_ kill() is required to collect that and add it
                    # to the exception.
                    exc.stdout, exc.stderr = process.communicate()
                else:
                    # POSIX _communicate already populated the output so
                    # far into the TimeoutExpired exception.
                    process.wait()
                raise
            except:  # Including KeyboardInterrupt, communicate handled that.
                process.kill()
                # We don't call process.wait() as .__exit__ does that for us.
                raise
            retcode = process.poll()
        comp = subprocess.CompletedProcess(process.args, retcode, stdout, stderr)
        if check:
            comp.check_returncode()
        return comp

    def _run(self, *args,
             fd=None,
             cwd=None,
             run_func=None, dry_run=False,
             **kwargs):
        #print(f'Executable._run(args={args!r}, fd={fd!r}, cwd={cwd!r}, run_func={run_func!r}, dry_run={dry_run!r}, kwargs={kwargs!r}')
        d = types.SimpleNamespace()

        run_func_kwargs = {}
        for k in self.run_func_options:
            try:
                run_func_kwargs[k] = kwargs.pop(k)
            except KeyError:
                pass
        run_func_kwargs.setdefault('encoding', self.encoding)
        run_func_kwargs.setdefault('errors', self.encoding_errors)
        cmd = self.build_cmd(*args, **kwargs)
        cmd = list2cmdlist(cmd)

        run_func = run_func or self.run_func or functools.partial(do_exec_cmd, stderr=subprocess.STDOUT)

        t0 = time.time()
        out = run_func(cmd, fd=fd,
                       cwd=cwd,
                       dry_run=dry_run,
                       **run_func_kwargs)
        t1 = time.time()

        if isinstance(out, collections.abc.Mapping):
            for k, v in out.items():
                setattr(d, k, v)
        else:
            d.out = out
        d.elapsed_time = t1 - t0

        return d

    def run(self, *args, **kwargs):
        return self._run(*args, **kwargs)

    __call__ = run

    def popen(self, *args, **kwargs):
        return self._popen(*args, **kwargs)

    def get_text_mode_info(self, cmd=None, text=None, encoding=None, errors=None):
        encoding = encoding or self.encoding
        errors = errors or self.encoding_errors
        text_mode = bool(text or encoding or errors)
        if text_mode:
            if encoding is None:
                encoding = 'utf-8'
            if errors is None:
                errors = 'strict'
        return text_mode, encoding, errors

    def _popen(self, *args, popen_func=None, dry_run=False,
               cwd=None,
               stdin=None, stdout=None, stderr=None, errors=None,
               text=None, encoding=None, bufsize=-1,
               **kwargs):
        text_mode, encoding, errors = self.get_text_mode_info(text=text, encoding=encoding, errors=errors)
        """p1 = myexe1.popen([...], stdout=subprocess.PIPE)
           p2 = myexe2.popen([...], stdin=p1.stdout, stdout=myfile.fp)
        """
        popen_func_kwargs = {}
        for k in self.popen_func_options:
            try:
                popen_func_kwargs[k] = kwargs.pop(k)
            except KeyError:
                pass
        cmd = self.build_cmd(*args, **kwargs)
        cmd = list2cmdlist(cmd)
        popen_func = popen_func or self.popen_func or do_popen_cmd
        return popen_func(
            cmd,
            cwd=cwd,
            dry_run=dry_run,
            stdin=stdin, stdout=stdout, stderr=stderr,
            encoding=encoding, errors=errors,
            universal_newlines=text,  # 3.7: text=text
            bufsize=bufsize,
            **popen_func_kwargs,
            )

class SystemExecutable(Executable):

    def which(self, *, mode=os.F_OK | os.X_OK, path=None, assert_found=True):
        if path is None:
            path = '/sbin'
        return super().which(mode=mode, path=path, assert_found=assert_found)

class PipedExecutable(Executable):
    pass

class PipedScript(PipedExecutable):
    pass

class PipedPortableScript(PipedScript):
    pass

class XdgExecutable(Executable, XdgResource):

    @property
    def xdg_resource(self):
        return self.name

class Xdg_open(Executable):

    name = 'xdg-open'

    kwargs_to_cmdargs = Executable.kwargs_to_cmdargs_gnu_getopt

xdg_open = Xdg_open()

class Nice(Executable):

    name = 'nice'

    kwargs_to_cmdargs = Executable.kwargs_to_cmdargs_gnu_getopt

    def build_cmd(self, *args, **kwargs):
        # kwargs before args
        cmd = [self.which()] \
            + self.kwargs_to_cmdargs(**kwargs) \
            + list2cmdlist(args)
        return cmd

nice = Nice()

class Renice(Executable):

    name = 'renice'

    kwargs_to_cmdargs = Executable.kwargs_to_cmdargs_gnu_getopt

    def build_cmd(self, *args, **kwargs):
        keys1 = set(kwargs.keys())
        keys2 = keys1 & {
            'g', 'pgrp',
            'p', 'pid',
            'u', 'user',
        }
        keys1 -= keys2
        cmd = [self.which()] \
            + self.kwargs_to_cmdargs(**{k: v for k, v in kwargs.items() if k in keys1}) \
            + self.kwargs_to_cmdargs(**{k: v for k, v in kwargs.items() if k in keys2}) \
            + list2cmdlist(args)
        return cmd

renice = Renice()

class Ionice(Executable):

    name = 'ionice'

    kwargs_to_cmdargs = Executable.kwargs_to_cmdargs_gnu_getopt

    def build_cmd(self, *args, **kwargs):
        keys1 = set(kwargs.keys())
        keys2 = keys1 & {
            'p', 'pid',
            'P', 'pgid',
        }
        keys1 -= keys2
        cmd = [self.which()] \
            + self.kwargs_to_cmdargs(**{k: v for k, v in kwargs.items() if k in keys1}) \
            + self.kwargs_to_cmdargs(**{k: v for k, v in kwargs.items() if k in keys2}) \
            + list2cmdlist(args)
        return cmd

ionice = Ionice()

class PipeRecordThread(threading.Thread):

    def __init__(self, file_r=None, text=False, blocksize=1024*8, target=None, **kwargs):
        if file_r is None:
            r, w = os.pipe()
            self.file_r = os.fdopen(r, mode='r' + ('t' if text else 'b'), closefd=True)
            self.file_w = os.fdopen(w, mode='w' + ('t' if text else 'b'), closefd=True)
        self.text = text
        if self.text:
            self.output = ''
        else:
            self.output = b''
            self.blocksize = blocksize
        super().__init__(**kwargs)

    def run(self):
        file_r = self.file_r
        target = self.target
        if self.text:
            for line in file_r:
                line = byte_decode(line)
                self.output += line
                if target:
                    target(line)
        else:
            blocksize = self.blocksize
            while True:
                out = file_r.read(blocksize)
                if not out:
                    break
                self.output += out
                if target:
                    target(out)

class Editor(Executable):

    @property
    def run_func(self):
        return do_system_cmd

    _name = None

    @property
    def name(self):
        editor = self._name
        if not editor:
            EDITOR = os.environ.get('EDITOR', None)
            if EDITOR:
                cmd = shlex.split(EDITOR, posix=os.name == 'posix')
                if cmd:
                    editor = cmd[0]
        if not editor:
            for e in ('vim', 'vi', 'emacs'):
                editor = shutil.which(e)
                if editor:
                    break
        if not editor:
            raise Exception('No editor found; Please set \'EDITOR\' environment variable.')
        return editor

    @name.setter
    def name(self, value):
        self._name = value

    _args = None

    @property
    def args(self):
        args = self._args
        if args is None:
            EDITOR = os.environ.get('EDITOR', None)
            if EDITOR:
                cmd = shlex.split(EDITOR, posix=os.name == 'posix')
                if cmd:
                    args = tuple(cmd[1:])
        return args or ()

    @args.setter
    def args(self, value):
        self._args = value

    def _run(self, *args, **kwargs):
        args = tuple(self.args) + args
        return super()._run(*args, **kwargs)

EDITOR = Editor()

class Difftool(Executable):

    _name = None
    @property
    def run_func(self):
        return do_system_cmd

    @property
    def name(self):
        difftool = self._name
        if not difftool:
            difftool = os.environ.get('DIFFTOOL', None)
        if not difftool:
            for e in (
                    'vimdiff',
                    # 'araxis',
                    # 'gvimdiff',
                    # 'gvimdiff2',
                    # 'gvimdiff3',
                    # 'vimdiff2',
                    # 'vimdiff3',
                    # 'bc',
                    # 'bc3',
                    # 'codecompare',
                    # 'deltawalker',
                    # 'diffmerge',
                    # 'diffuse',
                    # 'ecmerge',
                    # 'emerge',
                    # 'examdiff',
                    # 'guiffy',
                    # 'kdiff3',
                    # 'kompare',
                    # 'meld',
                    # 'opendiff',
                    # 'p4merge',
                    # 'smerge',
                    # 'tkdiff',
                    # 'winmerge',
                    # 'xxdiff',
            ):
                difftool = shutil.which(e)
                if difftool:
                    break
        if not difftool:
            raise Exception('No diff tool found; Please set \'DIFFTOOL\' environment variable.')
        return difftool

    @name.setter
    def name(self, value):
        self._name = value

DIFFTOOL = Difftool()

def edfile(file):
    file = Path(file)
    start_mtime = file.stat().st_mtime
    EDITOR(file)
    try:
        modified = file.stat().st_mtime != start_mtime
    except:
        # File removed?
        modified = True
    return modified

def edvar(value, *, json=None, suffix=None, encoding=None,
          preserve_whitespace_tags=None):
    orig_value = value

    xml = False
    if json is None:
        json = False
        if isinstance(value, str):
            pass
        elif isinstance(value, ET.ElementTree):
            xml = True
            value = prettyxml(value, preserve_whitespace_tags=preserve_whitespace_tags)
        else:
            json = True

    if json:
        from qip.json import JsonFile
        tmp_file_cls = JsonFile
    elif xml:
        from qip.file import XmlFile
        tmp_file_cls = XmlFile
    else:
        from qip.file import TextFile
        tmp_file_cls = TextFile

    with tmp_file_cls.NamedTemporaryFile(suffix=suffix, encoding=encoding) as tmp_file:

        if json:
            tmp_file.write_json(value, indent=2, sort_keys=True, ensure_ascii=False)
        else:
            tmp_file.write(value)

        # write -> read
        tmp_file.flush()
        tmp_file.seek(0)

        if not edfile(tmp_file):
            return (False, orig_value)

        if json:
            new_value = tmp_file.read_json()
        else:
            new_value = tmp_file.read()

    if xml:
        new_value = ET.ElementTree(ET.fromstring(new_value))

    #if type(new_value) is not type(value):
    #    raise ValueError(new_value)
    return (True, new_value)

def eddiffvar(value1, value2, *,
              json1=None, json2=None,
              suffix1=None, suffix2=None,
              encoding1=None, encoding2=None,
              preserve_whitespace_tags=None):
    with contextlib.ExitStack() as exit_stack:

        orig_value1 = value1

        xml1 = False
        if json1 is None:
            json1 = False
            if isinstance(value1, str):
                pass
            elif isinstance(value1, ET.ElementTree):
                xml1 = True
                value = prettyxml(value1, preserve_whitespace_tags=preserve_whitespace_tags)
            else:
                json1 = True

        if json1:
            from qip.json import JsonFile
            tmp_file_cls1 = JsonFile
        elif xml1:
            from qip.file import XmlFile
            tmp_file_cls1 = XmlFile
        else:
            from qip.file import TextFile
            tmp_file_cls1 = TextFile

        orig_value2 = value2

        xml2 = False
        if json2 is None:
            json2 = False
            if isinstance(value2, str):
                pass
            elif isinstance(value2, ET.ElementTree):
                xml2 = True
                value = prettyxml(value2, preserve_whitespace_tags=preserve_whitespace_tags)
            else:
                json2 = True

        if json2:
            from qip.json import JsonFile
            tmp_file_cls2 = JsonFile
        elif xml2:
            from qip.file import XmlFile
            tmp_file_cls2 = XmlFile
        else:
            from qip.file import TextFile
            tmp_file_cls2 = TextFile

        tmp_file1 = tmp_file_cls1.NamedTemporaryFile(suffix=suffix1, encoding=encoding1)
        exit_stack.enter_context(tmp_file1)

        if json1:
            tmp_file1.write_json(value1, indent=2, sort_keys=True, ensure_ascii=False)
        else:
            tmp_file1.write(value1)

        # write -> read
        tmp_file1.flush()
        tmp_file1.seek(0)

        tmp_file2 = tmp_file_cls2.NamedTemporaryFile(suffix=suffix2, encoding=encoding2)
        exit_stack.enter_context(tmp_file2)

        if json2:
            tmp_file2.write_json(value2, indent=2, sort_keys=True, ensure_ascii=False)
        else:
            tmp_file2.write(value2)

        # write -> read
        tmp_file2.flush()
        tmp_file2.seek(0)

        if not eddiff([tmp_file1, tmp_file2]):
            return (False, orig_value1, orig_value2)

        if json1:
            new_value1 = tmp_file1.read_json()
        else:
            new_value1 = tmp_file1.read()

        if xml1:
            new_value1 = ET.ElementTree(ET.fromstring(new_value1))

        if json2:
            new_value2 = tmp_file2.read_json()
        else:
            new_value2 = tmp_file2.read()

        if xml2:
            new_value2 = ET.ElementTree(ET.fromstring(new_value2))

        return (True, new_value1, new_value2)

def eddiff(files):
    files = [Path(file) for file in files]
    start_mtimes = [file.stat().st_mtime for file in files]
    DIFFTOOL(*files)
    try:
        modified = [file.stat().st_mtime for file in files] != start_mtimes
    except:
        # File removed?
        modified = True
    return modified

class Stdout_wrapper(Executable):

    name = Path(__file__).parent / 'bin' / 'stdout-wrapper'

stdout_wrapper = Stdout_wrapper()

def clean_file_name(file_name, keep_ext=True, extra=''):
    if keep_ext:
        name, ext = os.path.splitext(os.fspath(file_name))
    else:
        name, ext = os.fspath(file_name), ''
    name = unidecode.unidecode(name)
    # http://en.wikipedia.org/wiki/Filename {{{
    # UNIX: a leading . indicates that ls and file managers will not show the file by default
    name = re.sub(r'^[.]+', '', name)
    # Remove leading spaces too
    name = re.sub(r'^[ ]+', '', name)
    # NTFS: The Win32 API strips trailing space and period (full-stop) characters from filenames, except when UNC paths are used.
    # XXXJST: Include ! which may be considered as an event command even within double-quotes
    name = re.sub(r'[ .!]+$', '', name)
    # most: forbids the use of 0x00
    name = re.sub(r'\x00', '_', name)
    # NTFS/vfat: forbids the use of characters in range 1-31 (0x01-0x1F) and characters " * : < > ? \ / | unless the name is flagged as being in the Posix namespace.
    name = re.sub(r'[\x01-\x1F\"*:<>?\\/|]', '_', name)
    # XXXJST: Include ! which may be considered as an event command even within double-quotes
    name = re.sub(r'[!]', '_', name)
    # vfat: forbids the use of 0x7F
    name = re.sub(r'\x7F', '_', name)
    # Shouldn't be empty!
    if len(name) + len(extra) == 0:
        name = '_'
    # NTFS allows each path component (directory or filename) to be 255 characters long.
    over = len(name) + len(extra) + len(ext) - 255
    if over > 0:
        name = name[:len(name)-over]
    # }}}
    file_name = name + extra + ext
    return file_name


#!/usr/bin/python
from __future__ import print_function
import yaml
import sys

if __name__:
    with open("file.yml", 'r') as stream:
        try:
            print('Listing hosts which are not virtual guests:\n')
            data=yaml.load(stream)
            for keys in data.keys():
                print ('\nSection: {}'.format(keys))
                for host in data[keys]:
                    try:
                        if 'guest' in host['virtual']['mode']:
                            break
                    except:
                        pass
                    for k, v in host.items():
                        if k == 'name' or k == 'description':
                            print ('{0:12}  {1}'.format(k,v))

        except yaml.YAMLError as exc:
            print(exc)


import re
import urllib.request
import requests
import os

def download_img(img_url,img_name,file_name):
    if(not os.path.exists(file_name)):
        os.makedirs(file_name)

    file_name = file_name + img_name
    r = requests.get(img_url, { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'})
    if r.status_code == 200:
        open(file_name, 'wb').write(r.content)  # 将内容写入图片
        del  r
        return img_name
    del r
    return False

if __name__ == '__main__':
    print("请输入需要转换的.md文档的地址",'类似于：',r'C:/aaa/bbb/su.md')

    fileFullPath = input('地址为:')
    fileFullPath.replace('\\','/')
    baseName,dirName = os.path.split(fileFullPath)
    filename, extension = os.path.splitext(dirName)

    with open(fileFullPath ,encoding="UTF-8") as f:
        mdstr = f.read()
        pattern = re.compile(r'(?:!\[(.*?)\]\((.*?)\))')
        urldetails = pattern.findall(mdstr)

    for urldetail in urldetails:
        img_url = urldetail[1]
        img_name =img_url[-10:]
        file_name = baseName + '/assets/'
        downlod_result = download_img(img_url=img_url,img_name=img_name,file_name=file_name)
        mdstr.replace(img_url,'assets/'+downlod_result)
        print("download  "+img_url+"------"+"suceess")
    with open(os.path.join(baseName,filename+"_new"+extension) ,'w+') as f:
        f.write(mdstr)