#! /bin/env python

'''
Tests MVA performance on multiple cores to speed it up
'''

import rootpy.io as io
import rootpy
from rootpy.tree import Tree
import ROOT
import array
from sklearn.externals import joblib
log = rootpy.log["/test_training"]
log.setLevel(rootpy.log.INFO)
from argparse import ArgumentParser
from pdb import set_trace
import os
import re
import fileserver
from fnmatch import fnmatch
import localsettings as site
import pickle
import features
import multiprocessing

parser = ArgumentParser()
parser.add_argument('training', help='training to be used')
parser.add_argument('inputs', help='input root files to test on')
parser.add_argument('output', help='output directory')
parser.add_argument('--testEvery', type=int, default=1,  help='pick one testing event every')
parser.add_argument('--category', default='*', help='category to be used for training/testing (POSIX regex)')
parser.add_argument('--debug', action='store_true')
args = parser.parse_args()

class TMVAEvaluator(object):
   def __init__(self, infile, variables):
      nvars = len(variables)
      TMVA_tools = ROOT.TMVA.Tools.Instance()
      self.reader = ROOT.TMVA.Reader('TMVAClassification_BDTG')
      self.vars = [array.array('f',[0]) for _ in range(nvars)]
      self.nvars = nvars
      for idx, name in enumerate(variables):
         self.reader.AddVariable(name, self.vars[idx])
      self.reader.BookMVA(
         "BDTG",
         infile,
         )

   def predict_proba(vals2d):
      vals = vals2d[0]
      if len(vals) != len(self.vars):
         raise RuntimeError("Values provided are not matching the input variables (too few/many)")
      for val, var in zip(vals, self.vars):
         var[0] = val
      return [[None, self.reader.EvaluateMVA("BDTG")]]

def get_training(input_file, variables):
   if input_file.endswith('.xml'):
      return TMVAEvaluator(input_file, variables)
   else:
      return joblib.load(input_file)

def test_file(inname, outname, train_file, variables, testEvery):
   log.info('START processing: %s', os.path.basename(inname))
   bdt = get_training(train_file, variables)
   with io.root_open(outname, 'w') as tout:
      out_tree = Tree('tree')
      out_tree.create_branches({
            'flavour' : 'F',
            'vertexCategory' : 'I',
            'jetPt' : 'F',
            'jetEta' : 'F',
            'BDTG' : 'F',
            })
      with io.root_open(inname) as tin:
         in_tree = tin.tree
         in_tree.SetBranchStatus('*', 0)
         in_tree.SetBranchStatus('flavour', 1)
         in_tree.SetBranchStatus('vertexCategory', 1)
         in_tree.SetBranchStatus('jetPt', 1)
         in_tree.SetBranchStatus('jetEta', 1)
         for var in variables:
            in_tree.SetBranchStatus(var, 1)
         for idx, entry in enumerate(in_tree):
            if testEvery != 1 and (idx % testEvery) == 0: continue
            var_vals = [getattr(entry, i) for i in variables]
            btd_out = bdt.predict_proba([var_vals])[0][1]
            out_tree.flavour = entry.flavour
            out_tree.vertexCategory = entry.vertexCategory
            out_tree.jetPt = entry.jetPt
            out_tree.jetEta = entry.jetEta
            out_tree.BDTG = btd_out
            out_tree.fill()
      out_tree.write()
   log.info('DONE processing: %s', os.path.basename(inname))

input_files = [i.strip() for i in open(args.inputs)]
if args.category != '*':
   input_files = [i for i in input_files if fnmatch(os.path.basename(i), args.category)]
   variables = features.general
   #add vtx vars
   if 'RecoVertex' in args.category:
      log.info('adding SV input variables')
      variables.extend(features.vertex)
   elif 'NoVertex' in args.category or 'PseudoVertex' in args.category:
      log.info('skipping SV input variables')
   else:
      log.info('Category selection does not specify SV type, adding SV input variables for safety')
      variables.extend(features.vertex)
   #add lep vars
   if 'SoftElectron' in args.category or 'SoftMuon' in args.category:
      log.info('adding SL input variables')
      variables.extend(features.leptons)
   elif 'NoSoftLepton' in args.category:
      log.info('skipping SL input variables')
   else:
      log.info('Category selection does not specify SL type, adding SL input variables for safety')
      variables.extend(features.leptons)
else:
   log.info('No category selection, using all the input variables')
   variables=features.general+features.vertex+features.leptons

if not os.path.isdir(args.output):
   os.makedirs(args.output)

output_files=[]
for infile in input_files:
   split = os.path.basename(infile).replace('.root','').split('_')
   category = split[-2]
   flavour = split[-1]
   output_files.append(
      os.path.join(
         args.output,
         '_'.join(['tested', category, flavour])+'.root'
         )
      )

if not args.debug:
   ncpus = multiprocessing.cpu_count()
   pool = multiprocessing.Pool(ncpus)
   for i, o in zip(input_files, output_files):
      pool.apply_async(test_file, args=(i,o, args.training, variables, args.testEvery))

   pool.close()
   pool.join()
else:
   for i, o in zip(input_files, output_files):
      test_file(i,o, args.training, variables, args.testEvery)


#this is our main app , we create apps in our website which are of two types one is main app(i.e this) and one is accounts app

from django.urls import path
from . import views
app_name ="main"

urlpatterns = [
    path('',views.home, name="home"), #here blank sapce in first ' ' because it is supposed to be our home page. there is nothing before to be written before the url of our home page
    path('details/<int:id>/' , views.detail, name="detail"),
    path('genre/<int:genreid>/' , views.genre, name="genre"),
    path('search/' , views.searchresults, name="searchresults"),
]


"""empty message

Revision ID: 441c86e2e9e2
Revises: 123d9aa03103
Create Date: 2021-08-04 20:30:25.331300

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '441c86e2e9e2'
down_revision = '123d9aa03103'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('person',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=150), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('pokemon',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(), nullable=True),
    sa.Column('sprite', sa.Text(), nullable=True),
    sa.Column('my_trait', sa.String(length=50), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('comment',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('body', sa.Text(), nullable=True),
    sa.Column('pokemon_id', sa.Integer(), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['pokemon_id'], ['pokemon.id'], ),
    sa.ForeignKeyConstraint(['user_id'], ['person.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.add_column('user', sa.Column('token', sa.String(), nullable=True))
    op.create_index(op.f('ix_user_token'), 'user', ['token'], unique=True)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_user_token'), table_name='user')
    op.drop_column('user', 'token')
    op.drop_table('comment')
    op.drop_table('pokemon')
    op.drop_table('person')
    # ### end Alembic commands ###


import json
from tokens import remove_punctuation
import string

if __name__ == '__main__':
    quotes = []
    names = []

    filename = "data/allquotes.json"
    source = open(filename)
    data = json.load(source)

    quotes.append("MARKOVSTART")
    for quote in data:
        if quote.get('Character') == 'Jake':
            quotes.append(quote.get('Line'))
    quotes.append("MARKOVEND")

    all_quotes = " ".join(quotes)
    corpus_file = open("data/corpus.txt", "w")
    corpus_file.write(all_quotes)

    all_names = "\n".join(names)
    names_file = open("data/names.txt", "w")
    names_file.write(all_names)


import re
import sys
import time
import traceback
import operator
from itertools import chain, zip_longest

import pytest

from . import clissh
from . import clinns
from . import entry_template
from . import linux_host_bash
from . import loggers
from .custom_exceptions import ArgumentError

UI_MAP = {
    "linux_bash": linux_host_bash.LinuxHostBash,
}

class NICHelper(object):
    @staticmethod
    def NICS_IF_NO_LO(nic):
        return 'lo' != nic['name']

    @staticmethod
    def NICS_IF_NO_MGMT(nic):
        """TODO
        """
        pass

    @staticmethod
    def NIC_OBJ(nic):
        return nic

    NIC_NAME = operator.itemgetter('name')
    NIC_IP_ADDR = operator.itemgetter('ip_addr')

def autologin(function):
    """
    @brief  Decorator: performs login for self.ssh object.
    """
    def wrapper(*args, **kwargs):
        logout = False
        if not args[0].ssh.login_status:
            logout = True
            args[0].ssh.login()
        try:
            result = function(*args, **kwargs)
        finally:
            if logout:
                args[0].ssh.close()
        return result

    return wrapper

def autoshell(function):
    """
    @brief  Decorator: performs login and opens shell for self.ssh object.
    """
    def wrapper(*args, **kwargs):
        logout = False
        if not args[0].ssh.login_status:
            logout = True
            args[0].ssh.login()
        if not args[0].ssh.check_shell():
            args[0].ssh.open_shell()
        try:
            result = function(*args, **kwargs)
        finally:
            if logout:
                args[0].ssh.close()
        return result

    return wrapper

class GenericLinuxHost(entry_template.GenericEntry):
    """
    @description  Generic Linux host pattern class.
    """

    class_logger = loggers.ClassLogger()

    ipaddr = None
    ssh_user = None
    ssh_pass = None
    ssh_pkey = None
    ssh_pkey_file = None
    ssh_port = 22

    def __init__(self, config, opts):
        """
        @brief  Initialize GenericLinuxHost class
        @param  config:  Configuration information.
        @type  config:  dict
        @param  opts:  py.test config.option object which contains all py.test cli options.
        @type  opts:  OptionParser
        """
        super(GenericLinuxHost, self).__init__(config, opts)
        self.name = config['name'] if "name" in config else "noname"
        self.id = config['id']
        self.type = config['instance_type']
        self.nics = None
        self.ports, self.speed_ports, self.ports_map = self._get_speed_ports()
        self.port_list = self.speed_ports[:]

        # This should be set during start()
        self.mgmt_iface = None

        # ssh configs
        for cfg_item in ("ipaddr", "ssh_user", "ssh_pass", "ssh_port", "ssh_pkey", "ssh_pkey_file"):
            setattr(self, cfg_item, config.get(cfg_item, getattr(self.__class__, cfg_item)))
        if self.ipaddr and self.ssh_user and (self.ssh_pass or self.ssh_pkey or self.ssh_pkey_file):
            self.ssh = clissh.CLISSH(self.ipaddr, self.ssh_port, self.ssh_user, self.ssh_pass,
                                     pkey=self.ssh_pkey, key_filename=self.ssh_pkey_file)

        self.ssh_su_pass = config.get('ssh_su_pass')

        self.config_file = config.get('config_file')

        self.class_logger.info("Init Generic Linux Host: %s", self.ipaddr)

        self.config = config
        self.opts = opts

        self.status = False

        # Status dicts (are used to cleanup configuration).
        # Created bridge ifaces. (list of bridge names)
        self.bridges = []
        # Created vlan ifaces. (dict, key=iface, value=list of vlans)
        self.vlans = {}
        # Check if system supports VLAN creation.
        self.vlan_enabled = False
        # Created routes. (list of routes)
        self.route_list = []
        # Set address. (list of set address)
        self.ifconf_addrs = []

        # Initialize UI based on UI_MAP and cli --ui option
        self.ui = UI_MAP[self.opts.lhost_ui](self)
        self.class_logger.debug("ui = %s", self.ui)

    def _set_mgmt_interface(self, mgmt_ip):

        raw_data = self.exec_cmd(command="ip address show to {0}".format(mgmt_ip)).stdout
        if not raw_data:
            raise AttributeError("No management iface matches IP {0}.".format(mgmt_ip))
        row = re.search(r'(?P<index>\d*):\s(?P<name>[\w-]*)[@:]', raw_data)
        self.mgmt_iface = row.group('name')

    def connect_port(self, port_id):
        """
        @brief  Emulate port connection via setting adminMode into Up state
        @param  port_id:  Port number
        @type  port_id:  int | str
        """
        # Set initial ports speed
        self.speed_preconfig()

        self.class_logger.debug("Emulating connecting for port ID = %s", port_id)
        _port = self.ui.get_table_ports([port_id])[0]
        if _port['operationalStatus'] != "NotPresent":
            # Check if port is LAG member
            if _port["type"] == "LAGMember":
                # Use lag id as port id
                lag_table = self.ui.get_table_ports2lag()
                port_id = [x["lagId"] for x in lag_table if x["portId"] == port_id][0]
            self.ui.modify_ports([port_id], adminMode="Up")

    def exec_cmd(self, command, check_root=True):
        """
        @brief  Exec shell command with root privileges and print warning message in case StdErr isn't empty.

        @param command:  Command to be executed
        @param check_root:  Flag indicates root privileges
        @return  Returns CmdStatus namedtuple of stdout, stderr, return code
        @rtype: tuple(str, str, int) | CmdStatus
        @par Example:
        @code
        env.lhost[1].ssh.exec_cmd('sudo brctl addbr br0')
        @endcode
        """
        if check_root and self.ssh_user != "root":
            # requires password less sudo config
            command = "sudo {}".format(command)
        cmd_status = self.ssh.exec_command(command)
        return cmd_status

    # @autologin
    def ifconfig(self, mode=None, ports=None, ipaddr=None, ip6addr=None, mac=None):
        """
        @brief  Assign an address to a network interface and/or configure network interface parameters.
        @param  mode:  Flag 'up/down' activates/deactivates the specified network interface, flag 'stats' displays tx/rx statistic of the given interface
        @type  mode:  str
        @param  ports:  Specific interface name parameter
        @type  ports:  list
        @param  ipaddr:  IPv4 address to be assigned to the specific interface
        @type  ipaddr:  list
        @param  ip6addr:  IPv6 address to be assigned to the specific interface
        @type  ip6addr:  list
        @param  mac:  Set the hardware address on the interface
        @type  mac:  list
        @raise  ArgumentError:  ports value is None, mode is not in {"up", "down"}, length of ports, ipaddr, ip6addr or mac not equal if set
        @rtype:  dict
        @return:  if mode='stats', return interface statistic
        @par Example:
        @code
        env.tg[1].ifconfig("up", ports=[ports[("tg1", "lh1")][1]], ipaddr=["193.160.0.1/24"], ip6addr=["1000:160::2/64"], mac=["00:12:14:00:10:13"])
        @endcode
        """
        # Validate that params list corresponds with ports list.
        def validate_params(var, name):
            if not len(var) == len(ports):
                raise ArgumentError("The lengths of the {0} and ports lists are not equal.".format(name))

        if mode not in ["up", "down", "stats"]:
            raise ArgumentError("Unknown mode parameter value - {0}".format(mode))

        self.ui.generate_port_name_mapping()
        if mode in ["up", "down"]:
            if ports is None:
                ports = ["lo", ] + self.ports

            if ipaddr:
                validate_params(ipaddr, "ipaddr")
                for ipaddress, port in zip(ipaddr, ports):
                    if ipaddress is not None:
                        if ipaddress == "0.0.0.0":
                            self.ui.modify_ports([port], ipAddr=None)
                        else:
                            self.ui.modify_ports([port], ipAddr=ipaddress)
                            self.ifconf_addrs.append('ip addr del {1} dev {0}'.format(port, ipaddress))

            if ip6addr:
                validate_params(ip6addr, "ip6addr")
                for ip6address, port in zip(ip6addr, ports):
                    if ip6address is not None:
                        self.ui.modify_ports([port], ipAddr=ip6address)
                        self.ifconf_addrs.append('ip addr del {1} dev {0}'.format(port, ip6address))
            if mac:
                validate_params(mac, "mac")
            else:
                mac = []
            for macaddress, port in zip_longest(mac, ports):
                if macaddress is None:
                    self.ui.modify_ports([port], adminMode=mode.capitalize())
                else:
                    self.ui.modify_ports([port], macAddress=macaddress, adminMode=mode.capitalize())

        elif mode == "stats":
            stats = {}
            for port in ports:
                command = "ifconfig -s -a {0}".format(port)
                so = self.exec_cmd(command).stdout
                if so:
                    raw_stat = [x.split("\t") for x in re.sub("[\t]+", "\t", so).split("\n")]
                    raw_stat_params = raw_stat[0][0].split(" ")
                    raw_stat_values = raw_stat[1][0].split(" ")
                    while raw_stat_values.count('') > 0:
                        raw_stat_values.remove('')
                    while raw_stat_params.count('') > 0:
                        raw_stat_params.remove('')
                    stats[port] = {}
                    for i, v in enumerate(raw_stat_params):
                        stats[port][raw_stat_params[i]] = raw_stat_values[i]
            return stats

    @autologin
    def routes(self, mode=None, netwrk=None, netwrk6=None, ports=None, next_hop=None,
               next_hop6=None, option=None, metric=None, prefixtoroute=None, lo=None):
        """
        @brief  Assign routes to specific hosts or networks via an interface after it has been configured with the ifconfig utility
        @param  mode:  Flag 'up/down' change state of the interface to up or down.
        @type  mode:  str
        @param  netwrk:  List of v4 routes to be assigned on the device.
        @type  netwrk:  list
        @param  netwrk6:  List of v6 routes to be assigned on the device.
        @type  netwrk6:  list
        @param  ports:  List of Port ID
        @type  ports:  list
        @param  next_hop:  List of v4 nexthop router parameters
        @type  next_hop:  list
        @param  next_hop6:  List of v6 nexthop router parameters
        @type  next_hop6:  list
        @param  option:  Flag indicates to validate params
        @type  option:  bool
        @param  metric:  Allow to configure metric
        @type  metric:  bool
        @param  prefixtoroute:  Prefixtoroute value
        @type  prefixtoroute:  str
        @param  lo:  IPv4 local address
        @type  lo:  str
        @raise  Exception:  mode is not in {"up", "down"}
        @return:  None
        @par Example:
        @code
        env.tg[1].routes(netwrk6=["default"], next_hop6=["1000:160::1"])
        @endcode
        """
        # Validate that params list corresponds with ports list.
        def validate_params(var, var_2, name, name_2):
            if not len(var) == len(var_2):
                raise Exception("The lengths of the lists {0} and {1} is not equal.".format(name, name_2))

        commands = []

        if mode in ["up", "down"]:
            if ports:
                for port in ports:
                    command_list = ["ip", "link", "set", "dev", port, mode]
                    commands.append(' '.join(command_list))
            else:
                ports = ["lo", ] + self.ports
                for port in ports:
                    command_list = ["ip", "link", "set", "dev", port, mode]
                    commands.append(' '.join(command_list))

            device = ""
            if next_hop is not None and next_hop[0] == '0.0.0.0' and len(next_hop) == 1 and len(netwrk) == 1 and len(ports) == 1:
                device = "dev {0}".format(ports[0])

            if next_hop:
                for i, v in enumerate(ports):
                    if netwrk[i] and next_hop[i]:
                        version = "-4"
                        if netwrk[i] == "default":
                            validate_params(next_hop, ports, "nexthop", "ports")
                            command_list = ["ip", version, "default", "via", next_hop[i], "dev", ports[i],
                                            device]
                            if device == "":
                                command_list.pop()
                            commands.append(' '.join(command_list))
                        else:
                            validate_params(next_hop, netwrk, "nexthop", "netwrk")
                            command_list = ["ip", version, "route", "add", netwrk[i], "via", next_hop[i], "dev", ports[i]]
                            commands.append(' '.join(command_list))

            if next_hop6:
                for i, v in enumerate(next_hop6):
                    if netwrk6[i] and next_hop6[i]:
                        version = "-6"
                        if netwrk6[i] == "default":
                            if not option:
                                command_list = ["ip", version, "route", "add", "default", "via", next_hop6[i], "dev", ports[i]]
                                commands.append(' '.join(command_list))
                            else:
                                validate_params(next_hop6, ports, "nexthop6", "ports6")
                                command_list = ["ip", version, "route", "add", "default", "via", next_hop6[i], "dev", ports[i]]
                                commands.append(' '.join(command_list))
                        else:
                            validate_params(next_hop6, netwrk6, "nexthop6", "netwrk6")
                            command_list = ["ip", version, "route", "add", netwrk6[i], "via", next_hop6[i], "dev", ports[i]]
                            commands.append(' '.join(command_list))

            if metric:
                command_list = ["ip", "-6", "route", "add", prefixtoroute, "via", lo, "dev", "sit1", "metric", "1"]
                commands.append(' '.join(command_list))

            del_commands = [command.replace("add", "del").replace("up", "down") for command in commands]
            self.route_list.extend(del_commands)

            for command in commands:
                self.exec_cmd(command)
        else:
            raise Exception("Unknown mode parameter value - {0}".format(mode))

    @autologin
    def ipforward(self, version=None):
        """
        @brief  Enabling ipv4 and ipv6 forwarding
        @param version:  List of v4/v6 versions
        @type  version:  list
        @raise  Exception:  incorrect IP version
        @return:  None
        @par Example:
        @code
        env.tg[1].ipforward(version=["-4", "-6"])
        @endcode
        """
        allowed_versions = ["-4", "-6"]
        if version is None:
            version = ["-4"]
        # Verificaton:
        for _v in version:
            if _v not in allowed_versions:
                raise Exception("Incorrect version value: {0}. Allowed values is: {1}".format(version, allowed_versions))
        for i, v in enumerate(version):
            if version[i] == "-4":
                command_list = ["sysctl", "-w", "net.ipv4.ip_forward=1"]
                command_forward = ' '.join(command_list)
                self.exec_cmd(command_forward)
            if version[i] == "-6":
                command_list = ["sysctl", "-w", "net.ipv6.conf.all.forwarding=1"]
                command_forward = ' '.join(command_list)
                self.exec_cmd(command_forward)

    @autologin
    def brctl(self, mode="add", ports=None, brname=None, stp=None, stp_cfg=None):
        """
        @brief  Create/delete/configure bridge interface.
        @param mode:  Allowed values: add, cfg, del, stpstat, macs
                add - allow to create new instance of the eth bridge
                cfg - allow to change previously set specific configurations
                del - allow to delete the instance of the ethernet bridges
                delif - allow to delete interface from bridge
                stpstat - allow to show current interfaces stp status
                macs - allow to show a list of a learned MAC address for the bridge
        @type  mode:  str
        @param ports:  List of interfaces
        @type  ports:  list
        @param brname:  Name of the instance of the ethernet bridges
        @type  brname:  str
        @param stp: Flag  'up/down' enable/disable stp on the bridges
        @type  stp:  str
        @param stp_cfg:  Dictionary of settings,
                keys:   'bprio' - bridge priority parameter
                        'pathcost' - list of tupples with ports and pathcosts(to be assigned on the port) values
                        'hello' - set bridge's the hello time
                        'maxage' - set bridge's maximum message age
                        'fwdelay' - set bridge's forward delay
                        'pprio' - lists of tuples with ports and port priorities(to be assigned on the port) value
        @type  stp_cfg:  str
        @raise  Exception:  brname is None, unknown mode.
        @rtype:  str
        @return:  bridge name if mode='add', or stp bridge status if mode='stpstat'
        @par Example:
        @code
        env.tg[1].brctl("add", ports=[p1, p2], stp=True, stp_cfg={"bprio": 1000, "pathcost": [(p1, 10), (p2, 100)], "hello":300, "maxage":10,
        "fwdelay":30, "pprio":[(p1, 10)]})
        env.tg[1].brctl("stpstat", brname=br0)
        env.tg[1].brctl("delif", ports=[p2], brname=br0)
        @endcode
        """
        def stp_cfg_processing():
            for key in stp_cfg:
                if key == "bprio":
                    commands.append("brctl setbridgeprio {0} {1}".format(brname, stp_cfg[key]))
                elif key == "pathcost":
                    for port, cost in stp_cfg[key]:
                        commands.append("brctl setpathcost {0} {1} {2}".format(brname, port, cost))
                elif key == "hello":
                    commands.append("brctl sethello {0} {1}".format(brname, stp_cfg[key]))
                elif key == "maxage":
                    commands.append("brctl setmaxage {0} {1}".format(brname, stp_cfg[key]))
                elif key == "fwdelay":
                    commands.append("brctl setfd {0} {1}".format(brname, stp_cfg[key]))
                elif key == "pprio":
                    for port, prio in stp_cfg[key]:
                        commands.append("brctl setportprio {0} {1} {2}".format(brname, port, prio))

        def add_ports():
            for port in ports:
                commands.append("brctl addif {0} {1}".format(brname, port))

        if mode == "add":
            bridges = self.ssh.exec_command("ifconfig -s -a | grep "
                                            "^lhbr | awk '{print "
                                            "$1}'").stdout
            bridges = bridges.split("\n") if bridges else []
            max_id = max([int(x[4:]) if x[4:].isdigit() else None for x in bridges]) if bridges else 0
            brname = "lhbr" + str(max_id + 1)

            commands = ["brctl addbr " + brname]
            if ports:
                add_ports()
            stp = stp if stp is not None else False
            commands.append("brctl stp {0} {1}".format(brname, "on" if stp else "off"))
            if stp_cfg is not None:
                stp_cfg_processing()
            commands.append("ifconfig {0} up".format(brname))

            for command in commands:
                self.exec_cmd(command)

            self.bridges.append(brname)

            return brname

        elif mode == "del":
            if brname is None:
                raise Exception("Bridge name is not set.")
            commands = ["ifconfig {0} down".format(brname),
                        "brctl delbr {0}".format(brname)]

            for command in commands:
                self.exec_cmd(command)

        elif mode == "delif":
            if brname is None or ports is None:
                raise Exception("Bridge name or port is not set.")
            commands = []
            for port in ports:
                commands.append("brctl delif {0} {1}".format(brname, port))
            for command in commands:
                self.exec_cmd(command)

        elif mode == "cfg":
            if brname is None:
                raise Exception("Bridge name is not set.")
            commands = []
            if stp is not None:
                stp_cmd = "on" if stp else "off"
                commands.append("brctl stp {0} {1}".format(brname, stp_cmd))
            if ports:
                add_ports()
            if stp_cfg is not None:
                stp_cfg_processing()

            for command in commands:
                self.exec_cmd(command)

        elif mode == "stpstat":
            if brname is None:
                raise Exception("Bridge name is not set.")
            command = "brctl showstp {0}".format(brname)
            so = self.exec_cmd(command).stdout
            stats = {}
            if so:
                # Remove repeated \t and split stdout by \t and \n.
                raw_stat = [x.split("\t") for x in re.sub("[\t]+", "\t", so).split("\n")]
                key = None
                for item in raw_stat:
                    if len(item) == 1:
                        # Port or empty line found
                        key = item[0].strip()
                        # In case it's port, it should contain it's own number. E.g. 'eth0 (1)'.
                        name_num = key.split(" ")
                        port_num = None
                        if len(name_num) == 2:
                            key = name_num[0]
                            port_num = name_num[1]
                        stats[key] = {}
                        if port_num is not None:
                            stats[key]['port number'] = port_num.strip("(").strip(")")
                        continue
                    if len(item) >= 2:
                        # 2 elements: key    value
                        stats[key][item[0].strip()] = item[1].strip()
                    if len(item) >= 4:
                        # 4 elements: key    value    key    value
                        # Skip reading of the first pair because it has to be read in previous if-block.
                        stats[key][item[2].strip()] = item[3].strip()
            return stats

        elif mode == "macs":
            if brname is None:
                raise Exception("Bridge name is not set.")
            command = "brctl showmacs {0}".format(brname)
            so = self.exec_cmd(command).stdout
            macs = {}
            if so:
                # Remove repeated \t and split stdout by \t and \n.
                raw_macs = [x.split("\t") for x in re.sub("[\t]+", "\t", so).split("\n")]
                keys = raw_macs[0]
                for line in raw_macs[1:]:
                    pnum = line[0].strip()
                    if pnum not in macs:
                        macs[pnum] = []
                    macs[pnum].append({k.strip(): v.strip() for k, v in zip(keys[1:], line[1:])})
                # Drop empty key.
                macs.pop("")
            return macs

        else:
            message = "Unknown mode for brctl method."
            self.class_logger.error(message)
            raise Exception(message)

    @autologin
    def getmac(self, port):
        """
        @brief  Return port's MAC address.
        @param port:  Traffic generator's port
        @type  port:  str/tuple for Ixia
        @rtype:  str
        @return:  Mac address of the device
        @par Example:
        @code
        stp_env.tg[4].getmac(ports[("tg4", "tg3")][1])
        @endcode
        """
        command = "ip link show {0}".format(port)
        so = self.exec_cmd(command).stdout
        mac = None
        if so:
            lines = so.split("\n")[1].split(" ")
            lines = list(filter(len, lines))
            mac = lines[1]
        return mac.strip()

    @autologin
    def enable_8021q(self):
        """
        @brief  Check and enable VLANs if system supports 802.1q.
        @raise  Exception:  unsupported 802.1q feature
        @note  Method searchs 8021q kernel module and tries to load them.
        """
        # Check if system supports 8021q
        so = self.ssh.exec_command("modprobe -l | grep 8021q").stdout
        if not so or "8021q" not in so:
            raise Exception("Current OS doesn't support 802.1q.")
        # Check if 8021q is already loaded and try to load it if not.
        so = self.ssh.exec_command("lsmod | grep ^8021q").stdout
        if not so or "8021q" not in so:
            command = "modprobe 8021q 2>&1"
            if self.ssh_user != "root":
                command = "sudo " + command
            so_load = self.ssh.exec_command(command).stdout
            so = self.ssh.exec_command("lsmod | grep ^8021q").stdout
            if not so or "8021q" not in so:
                raise Exception("Fail to load 8021q:\n{0}".format(so_load))
        self.vlan_enabled = True

    @autologin
    def vconfig(self, mode, port, vlan):
        """
        @brief  Perform VLAN configuration.
        @param mode:  Flag add/rem allow to create/remove vlan-devices
        @type  mode:  str
        @param port:  Name of the ethernet card that hosts the VLAN
        @type  port:  str
        @param vlan:  Vlan-device which represents the virtual lan on the physical lan
        @type  vlan:  int
        @raise  Exception:  mode not in {"add", "rem"}, port is already in vlan
        @rtype:  str
        @return:  Vlan-device value in format 'port.vlan'
        @par Example:
        @code
        env.tg[1].vconfig("add", port=ports[("tg1", "tg2")][1], vlan=3)
        env.tg[1].vconfig("rem", port=ports[("tg1", "tg2")][1], vlan=3)
        @endcode
        """
        if not self.vlan_enabled:
            self.enable_8021q()

        if mode in "add":
            if port in self.vlans and vlan in self.vlans[port]:
                raise Exception("Port {0} already in {1} vlan".format(port, vlan))
            command = "vconfig add {0} {1}".format(port, vlan)
            self.exec_cmd(command)
            if port not in self.vlans:
                self.vlans[port] = []
            self.vlans[port].append(vlan)
            return "{0}.{1}".format(port, vlan)

        elif mode == "rem":
            command = "vconfig rem {0}.{1}".format(port, vlan)
            self.exec_cmd(command)
            self.vlans[port].remove(vlan)
            if not self.vlans[port]:
                self.vlans.pop(port)
            return "{0}.{1}".format(port, vlan)

        else:
            raise Exception("Incorrect mode={0}".format(mode))

    @autologin
    def ethtool(self, port, mode, **kwargs):
        """
        @brief  Perform ethtool configuration.
        @param  port:  Name of the interface
        @type  port:  str
        @param  mode:  Flag allows to configure interface ('generic')
        @type  mode:  str
        @param  kwargs:  Interface configuration key/value pairs
        @type  kwargs:  dict
        @raise  Exception:  mode is not "generic"
        """
        if mode in "generic":
            args = " ".join(["{0} {1}".format(*i) for i in list(kwargs.items())])
            command = "ethtool -s {0} {1}".format(port, args)
            self.exec_cmd(command)

        else:
            raise Exception("Incorrect mode={0}".format(mode))

    def _get_nics(self, force_check=False):
        """Returns list of detected network adapterrs in the system
        Note: Order of the adapters is very important. It should be according to how the
        networks are defined when VM is created. Proper order is in self.os_networks

        @param force_check: force re-reading nics
        @type force_check: bool
        @return: list of nics
        @rtype: list
        """
        if self.nics is None or force_check:
            detected_nics = self.ui.get_table_ports(ip_addr=True)
            # filter out interfaces with no IP
            self.nics = [nic for nic in detected_nics if nic['ip_addr']]
        return self.nics

    def get_nics_if(self, f, force_check=False):
        if f:
            return list(filter(f, self._get_nics(force_check)))
        return self._get_nics()

    def map_nics_if(self, f, mapper=NICHelper.NIC_OBJ, force_check=False):
        nics = self.get_nics_if(f, force_check)
        if mapper:
            return list(map(mapper, nics))
        return nics

    def get_nics(self, no_lo=True, mapper=None, force_check=False):
        f = NICHelper.NICS_IF_NO_LO if no_lo else None
        return self.map_nics_if(f=f, mapper=mapper, force_check=force_check)

    def get_nics_names(self, no_lo=True, force_check=False):
        f = NICHelper.NICS_IF_NO_LO if no_lo else None
        mapper = NICHelper.NIC_NAME
        return self.map_nics_if(f=f, mapper=mapper, force_check=force_check)

    def get_nics_ips(self, no_lo=True, force_check=False):
        f = NICHelper.NICS_IF_NO_LO if no_lo else None
        mapper = NICHelper.NIC_IP_ADDR
        return self.map_nics_if(f=f, mapper=mapper, force_check=force_check)

    def get(self, init_start=False, retry_count=7):
        """
        @brief  Get or start linux host instance.
        @param init_start:  Perform switch start operation or not
        @type  init_start:  bool
        @param retry_count:  Number of retries to start(restart) linux host
        @type  retry_count:  int
        @return None or raise an exception.
        @note  Also self.opts.fail_ctrl attribute affects logic of this method.
               fail_ctrl is set in py.test command line options (read py.test --help for more information).
        """
        # If fail_ctrl != "restart", restart retries won't be performed
        if self.opts.fail_ctrl != "restart":
            retry_count = 1

        for retry in range(retry_count):
            try:
                if retry == 0:
                    if init_start:
                        self.start()
                    else:
                        self.waiton()
                # else:
                #     Restart not implemented for lhost yet
                #     self.restart()
                break
            except KeyboardInterrupt as ex:
                message = "KeyboardInterrupt while checking device {0}({1})...".format(
                        self.name, self.ipaddr)
                self.class_logger.info(message)
                self.sanitize()
                pytest.exit(message)
            except Exception:
                self.class_logger.warning(
                    "Error while checking device %s(%s)...", self.name, self.ipaddr)
                retry += 1
                exc_type, exc_value, exc_traceback = sys.exc_info()
                traceback_message = traceback.format_exception(exc_type, exc_value, exc_traceback)
                message = "Error while checking device {0}({1}):\n{2}".format(
                    self.name, self.ipaddr, "".join(traceback_message))
                sys.stderr.write(message)
                sys.stderr.flush()
                self.class_logger.error(message)
                if retry >= retry_count + 1:
                    message = "Could not complete start device method after {0} retries. " \
                              "Something went wrong...\n".format(retry_count)
                    sys.stderr.write(message)
                    sys.stderr.flush()
                    self.class_logger.error(message)
                    if self.opts.fail_ctrl != "ignore":
                        pytest.exit(message)
                    else:
                        pytest.fail(message)

    def waiton(self, timeout=90):
        """
        @brief  Wait until device is fully operational.
        @param  timeout:  Wait timeout
        @type  timeout:  int
        @raise  SwitchException:  device doesn't response
        @rtype:  dict
        @return  Status dictionary from probe method or raise an exception.
        """
        status = None
        message = "Waiting until device {0}({1}) is up.".format(self.name, self.ipaddr)
        self.class_logger.info(message)
        stop_flag = False
        end_time = time.time() + timeout
        while not stop_flag:
            if loggers.LOG_STREAM:
                sys.stdout.write(".")
                sys.stdout.flush()
            if time.time() < end_time:
                # While time isn't elapsed continue probing switch.
                try:
                    status = self.probe()
                except KeyboardInterrupt:
                    message = "KeyboardInterrupt while checking switch {0}({1})...".format(
                            self.name, self.ipaddr)
                    self.class_logger.info(message)
                    self.sanitize()
                    pytest.exit(message)
                if status["isup"]:
                    stop_flag = True
            else:
                # Time is elapsed.

                port = self._get_port_for_probe()
                message = "Timeout exceeded. IP address {0} port {1} doesn't respond.".format(
                    self.ipaddr, port)
                self.class_logger.warning(message)
                raise Exception(message)
            if not stop_flag:
                time.sleep(0.75)

        return status

    def probe(self):
        """
        @brief  Probe linux host with UI call.
        @rtype:  dict
        @return:  Dictionary (_object) with switchpp status parameters or raise an exception.
        """
        _object = {
            'isup': False,
            'type': "unknown",
            'prop': {}
        }

        if clissh.probe_port(self.ipaddr, self._get_port_for_probe(), self.class_logger):
            try:
                # Try to wait until device is ready to process
                self.ui.check_device_state()
                _object['isup'] = True
            except Exception as err:
                self.class_logger.info(
                    "Caught an exception while probing the device: "
                    "Error type: %s. Error msg: %s", type(err), err)
        return _object

    def start(self, wait_on=True):
        """
        @brief  Mandatory method for environment specific classes.
        @param  wait_on:  Wait for device is loaded
        @type  wait_on:  bool
        """
        # Optionally put power board information here for restart
        if wait_on:
            self.waiton()
        self.speed_preconfig()
        self._set_mgmt_interface(self.config['ipaddr'])

    def stop(self, with_cleanup=True):
        """
        @brief  Mandatory method for environment specific classes.
        @param  with_cleanup:  Flag to perform cleanup
        @type  with_cleanup:  bool
        """
        if not self.status:
            self.class_logger.info(
                "GenericLinuxHost %s:%s is already stopped.", self.name, self.id)
        else:
            if with_cleanup:
                self.cleanup()

    def cleanup(self):
        """
        @brief  Remove created configuration.
        """
        if self.bridges:
            for brname in self.bridges[:]:
                self.brctl("del", brname=brname)
        if self.vlans:
            for port in list(self.vlans):
                for vlan in self.vlans[port][:]:
                    self.vconfig("rem", port, vlan)
        if self.route_list:
            for command in self.route_list[:]:
                self.exec_cmd(command)
                self.route_list.remove(command)
        if self.ifconf_addrs:
            for command in self.ifconf_addrs[:]:
                self.exec_cmd(command)
                self.ifconf_addrs.remove(command)
        self.ui.clear_config()

    def restart(self, wait_on=True):
        """
        @brief  Mandatory method for environment specific classes.
        @param  wait_on:  Wait for device is loaded
        @type  wait_on:  bool
        """
        pass

    def create(self):
        """
        @brief  Start linux host or get running one.

        @note  This is mandatory method for all environment classes.
               Also self.opts.get_only attribute affects logic of this method.
               get_only is set in py.test command line options (read py.test --help for more information).
        """
        init_start = not self.opts.get_only
        return self.get(init_start=init_start)

    def destroy(self):
        """
        @brief  Stop or release linux host.

        @note  This is mandatory method for all environment classes.
               Also self.opts.leave_on and get_only  attributes affect logic of this method.
               leave_on and get_only are set in py.test command line options (read py.test --help for more information).
        """
        if not self.status:
            self.class_logger.info(
                "Skip Linux Host id:%s(%s) destroying because it already has Off status.", self.id, self.name)
            return
        if not self.opts.leave_on and not self.opts.get_only:
            self.stop()

        self.sanitize()

    def sanitize(self):
        """
        @brief  Perform any necessary operations to leave environment in normal state.
        """
        pass

    def check(self):
        """
        @brief  Mandatory method for environment specific classes.
        """
        pass

    def _get_port_for_probe(self):
        """
        @brief  Get port ID.
        @rtype:  int
        @return:  ssh tunnel ports ID
        """
        return int(self.ssh_port)

    def _get_speed_ports(self):
        """
        @brief  Get slave and master ports from config.
        @rtype:  list
        @return:  List of ports (slave and master) used in real config
        @note  This function check if master port should be split into slave ports.
        """
        speed_ports = self.config.get("port_list", [])
        ports_map = self.config.get("ports_map", [])

        # speed_ports expected format: [[port1_num, port1_speed], ...]
        if speed_ports:
            ports = [x[0] for x in speed_ports]
        else:
            ports = self.config.get("ports", [])

        return ports, speed_ports, ports_map

    def speed_preconfig(self, wait_for_ports=False):
        """
        @brief  Function for ports speed preconfiguration
        @param wait_for_ports:  wait for Ports table changes size
        @type  wait_for_ports:  int
        """

        def _normalize_port_list(ports_list):
            """
            @brief  Get list of Master ports.
            """
            master_ports = set()
            ports = set()
            for _port in ports_list:
                m_port = _get_master_port(_port)
                master_ports.add(m_port)
                if m_port != _port:
                    ports.add(_port)

            return list(chain(master_ports, ports))

        def _get_master_port(port):
            """
            @brief  Get Master port.
            """
            try:
                return next(r for r, s in self.ports_map if port in s)
            except StopIteration:
                return port

        # Separate ports per preconfigured speed
        if self.speed_ports:
            speed_dict = {}
            for port, speed in self.speed_ports:
                speed_dict.setdefault(speed, []).append(port)

            normalized_speed_dict = {}
            for key, ports in speed_dict.items():
                normalized_speed_dict[key] = _normalize_port_list(ports)

            for speed, ports in normalized_speed_dict.items():
                self.setup_ports_speed_configuration(ports, speed)

    def setup_ports_speed_configuration(self, ports=None, speed=10000):
        """
        @brief  Configure ports speed.
        @param  ports:  list of ports to set speed value
        @type  ports:  list[int]
        @param  speed:  speed value
        @type  speed:  int
        """
        if ports is not None:
            self.class_logger.debug("Performing ports speed configuration on real switch.")
            err_message = "Cannot perform ports speed configuration.\nDescription: %s\nERROR: %s"

            try:
                self.ui.modify_ports(ports=ports, speed=int(speed))
                ports_table = self.ui.get_table_ports(ports)
                for port_table in ports_table:
                    assert port_table["speed"] == speed
            except AssertionError as err:
                message = err_message % ("Switch doesn't accept commands.", err, )
                self.class_logger.error(message)
                pytest.fail(message)
            except Exception as err:
                message = err_message % ("Unknown.", err, )
                self.class_logger.error(message)
                pytest.fail(message)
            else:
                self.class_logger.debug("Ports speed configuration - OK")

class IpNetworkNamespace(GenericLinuxHost):
    """
    @brief  Namespace simulated class
    """

    class_logger = loggers.ClassLogger()

    def __init__(self, config, opts):
        """
        @brief  Initialize IpNetworkNamespace class
        @param  config:  Configuration information.
        @type  config:  dict
        @param  opts:  py.test config.option object which contains all py.test cli options.
        @type  opts:  OptionParser
        """
        self.class_logger.info("Init namespace started.")
        super(IpNetworkNamespace, self).__init__(config, opts)
        self.name = config['name']
        # SSH emulator
        # Sudo prompt is required parameter for CLISSHNetNS and it is set to default Ubuntu sudo prompt.
        # But in most cases TAF has to be started with sudo and password shouldn't be asked.
        self.ssh = clinns.CLISSHNetNS(self.name, self.ipaddr, self.ssh_port or 22,
                                      self.ssh_user, self.ssh_pass,
                                      sudo_prompt="[sudo] password for {0}:".format(self.ssh_user))
        # Mgmt br ip is always the last host ip in network
        self.mgmt_ip = self.ipaddr[0:self.ipaddr.rfind(".")] + ".254"
        # Set up management ifaces
        self.mgmt_br = "mbr{0}".format(self.mgmt_ip.replace(".", ""))
        # Management iface
        self.mgmt_if = "veth{0}".format(self.id)

    def start(self, wait_on=True):
        """
        @brief  Method for network namespace create
        @param  wait_on:  Wait for device is loaded
        @type  wait_on:  bool
        @raise  Exception:  error on namespace creating
        """
        command = "ip netns list"
        so, _, rc = self.ssh.native_cmd(command)
        if self.name in so.split():
            message = "Namespace is already created"
            raise Exception(message)

        command = "ip netns add " + self.name

        so, se, rc = self.ssh.native_cmd(command)
        if rc != "0":
            message = "Cannot create network namespace. Return code = {0}".format(rc)
            self.class_logger.error(message)
            raise Exception(message)

        self.add_mgmt_bridge()
        self.add_mgmt_iface()

        self.status = True

    def stop(self, with_cleanup=True, del_mgmt_br=False):
        """
        @brief  Method for namespace restore
        @param  with_cleanup:  Flag to perform cleanup
        @type  with_cleanup:  bool
        @param  del_mgmt_br:  Flag to delete management bridge
        @type  del_mgmt_br:  bool
        """
        if self.opts.get_only or self.opts.leave_on:
            # Skipping stop in case get_only or leave_on
            return

        if not self.status:
            self.class_logger.info(
                "IpNetworkNamespace %s:%s is already stopped.", self.name, self.id)
            return

        if with_cleanup:
            self.cleanup()
        if del_mgmt_br:
            self.del_mgmt_bridge()

        command = "ip netns delete " + self.name
        so, se, rc = self.ssh.native_cmd(command)

        self.status = False

    def check_mgmt_bridge(self):
        """
        @brief  Check if mgmt bridge is created.
        """
        command = "ifconfig " + self.mgmt_br
        so, _, _ = self.ssh.native_cmd(command)
        if so:
            return True
        else:
            return False

    def add_mgmt_bridge(self):
        """
        @brief  Create mgmt bridge on host.
        @raise  Exception:  error on bridge creating
        """
        so, se, rc = None, None, "0"
        if not self.check_mgmt_bridge():
            command = "brctl addbr " + self.mgmt_br
            so, se, rc = self.ssh.native_cmd(command)
        if rc != "0" or not self.check_mgmt_bridge():
            message = ("Failed to create management bridge for Network namespaces.\n" +
                       "Stdout: {0}, Stderr: {1}".format(so, se))
            self.class_logger.error(message)
            raise Exception(message)
        else:
            command = "ifconfig {0} {1} up".format(self.mgmt_br, self.mgmt_ip)
            self.ssh.native_cmd(command)

    def del_mgmt_bridge(self):
        """
        @brief  Delete mgmt bridge on host.
        @raise  Exception:  error on bridge deleting
        """
        if self.check_mgmt_bridge():
            command = "ifconfig {0} down".format(self.mgmt_br)
            self.ssh.native_cmd(command)
            command = "brctl delbr " + self.mgmt_br
            so, se, rc = self.ssh.native_cmd(command)
        if rc != "0" or not self.check_mgmt_bridge():
            message = ("Failed to delete management bridge for Network namespaces.\n" +
                       "Stdout: {0}, Stderr: {1}".format(so, se))
            self.class_logger.error(message)
            raise Exception(message)

    def add_mgmt_iface(self):
        """
        @brief  Create management iface and add it to host level bridge.
        @raise  Exception:  error on creating management interface
        """
        command = "ip link add {0} type veth peer name {0} netns {1}".format(self.mgmt_if, self.name)
        so, se, rc = self.ssh.native_cmd(command)
        if rc != "0":
            message = ("Failed to create management iface for {0}.\n".format(self.name))
            self.class_logger.error(message)
            raise Exception(message)
        else:
            self.ssh.native_cmd("brctl addif {0} {1}".format(self.mgmt_br, self.mgmt_if))
            self.ssh.native_cmd("ifconfig {0} up".format(self.mgmt_if))
            self.ssh.exec_command("ifconfig {0} {1} up".format(self.mgmt_if, self.ipaddr))

    def del_mgmt_iface(self):
        """
        @brief  Delete management iface and add it to host level bridge.
        @raise  Exception:  error on deleting management interface
        """
        command = "ip link delete {0}".format(self.mgmt_if)
        so, se, rc = self.ssh.native_cmd(command)
        if rc != "0":
            message = ("Failed to delete management iface for {0}.\n".format(self.name))
            self.class_logger.error(message)
            raise Exception(message)

    def create(self):
        """
        @brief  Start Linux host or get running one.

        @note  This is mandatory method for all environment classes.
               Also self.opts.get_only attribute affects logic of this method.
               get_only is set in py.test command line options (read py.test --help for more information).
        """
        if not self.opts.get_only:
            return self.start()

    def destroy(self):
        """
        @brief  Stop or release Linux host.

        @note  This is mandatory method for all environment classes.
               Also self.opts.leave_on and get_only  attributes affect logic of this method.
               leave_on and get_only are set in py.test command line options (read py.test --help for more information).
        """
        if not self.status:
            self.class_logger.info(
                "Skip Linux Host:%s(%s) destroying because it's has already Off status.", self.id, self.name)
            return
        if not self.opts.leave_on and not self.opts.get_only:
            self.stop()

        self.sanitize()

    def sanitize(self):
        """
        @brief  Perform any necessary operations to leave environment in normal state.
        """
        pass

ENTRY_TYPE = "linux_host"
INSTANCES = {"generic": GenericLinuxHost, "netns": IpNetworkNamespace}
NAME = "lhost"
LINK_NAME = "lh"


# diagram.py
from diagrams import Diagram, Cluster, Edge
from diagrams.custom import Custom
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
from diagrams.gcp.api import Endpoints

main_edge = lambda label=None: Edge(color='purple', label=label)
internal_edge = lambda: Edge(color='darkgreen', label='internal')
http_edge = lambda: Edge(color='darkgrey')

with Diagram("System Diagram: PS > MB", show=True, direction="LR"):
    with Cluster('mbpy'):
        mbpy = Custom("api interface", 'logos/code.png')
        algorithm = Custom('algorithm', 'logos/code.png')
        mbpy2 = Custom("api interface", 'logos/code.png')

    with Cluster("PowerSchool"):
        ps_plugin = Custom('PS plugin', 'logos/code.png')
        ps_app = Custom("PS app", 'logos/ps.png')
        ps_plugin >> internal_edge() << ps_app
        mbpy >> http_edge() << ps_plugin

    with Cluster('ManageBac (read)'):
        mb_api = Endpoints('Public REST API')
        mb_app = Custom("MB app", 'logos/mb.png')
        mb_api >> internal_edge() << mb_app
        mbpy >> http_edge() << mb_api

    with Cluster('Managebac (write)'):
        mb_api2 = Endpoints('Public REST API')
        mb_app2 = Custom("MB app", 'logos/mb.png')

        mbpy >> main_edge() >> algorithm >> main_edge(label="Update this only") >> mbpy2 >> main_edge() >> mb_api2
        mb_api2 >> internal_edge() << mb_app2


# -*- coding: UTF-8 -*-
"""
@Project -> File   ：cnn_models_comparation.pytorch -> test_ResNet
@IDE    ：PyCharm
@Author ：QiangZiBro
@Date   ：2020/5/23 12:58 下午
@Desc   ：
"""
from unittest import TestCase
from model.models.ResNet import *
import torch

class TestResNet(TestCase):
    def test_for_resnet_any_input(self):
        model = resnet18(num_classes=10)
        img = torch.rand((32, 3, 32, 32))
        out = model(img)
        self.assertEqual((32,10), out.shape)

        img = torch.rand((32, 3, 320, 320))
        out = model(img)
        self.assertEqual((32,10), out.shape)


from Praw_Counter import new_final_nouns
import sqlite3
from collections import Counter
from datetime import datetime

Counter_Nouns = Counter()

conn = sqlite3.connect(r"nouns.db")
c = conn.cursor()

def Action():
    date = datetime.today().strftime("%b %Y")
    for item, number in new_final_nouns:
        c.execute("INSERT INTO Noun_Counter VALUES (?, ? , ?)", (date,item, number))
    c.execute("SELECT * FROM Noun_Counter")
    data = [i for i in c.fetchall()]
    map([Counter_Nouns.update({card: val}) for date, card, val in data], data)
    c.execute("DROP TABLE Noun_Counter")
    c.execute('''CREATE TABLE Noun_Counter (Date, Nouns, Occurences)''')
    [c.execute("INSERT INTO Noun_Counter Values(?, ?, ?)", (date, item, number)) for item, number in Counter_Nouns.items()]
    c.execute("SELECT * FROM Noun_Counter")
    conn.commit()
    conn.close()

try:
    c.execute('''CREATE TABLE Noun_Counter (Date, Nouns, Occurences)''')
    Action()
except sqlite3.OperationalError:
    Action()
print("done")


import hashlib
import hmac
import urlparse
import httplib
import mimetypes
from datetime import datetime, timedelta

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

try:
    import simplejson as json
except ImportError:
    import json

BASE_API = 'http://api2.transloadit.com/assemblies'
FILE_BOUNDARY = '----------Python_Transloadit_Client_Boundary_$'
CRLF = '\r\n'

class Client(object):
    def __init__(self, key, secret, api=None):
        self.key = key
        self.secret = secret
        if api:
            self.api = api
        else:
            self.api = BASE_API

    def _sign_request(self, params):
        return hmac.new(self.secret, json.dumps(params),
            hashlib.sha1).hexdigest()

    def _send_request(self, files, **fields):
        parts = urlparse.urlparse(self.api)
        content_type, body = self._encode_request(fields, files)
        req = httplib.HTTP(parts[1])
        req.putrequest('POST', parts[2])
        req.putheader('Content-Type', content_type)
        req.putheader('Content-Length', str(len(body)))
        req.endheaders()
        req.send(body)
        errcode, errmsg, headers = req.getreply()
        return json.loads(req.file.read())

    def _encode_request(self, fields, files):
        body = StringIO()

        for key, value in fields.iteritems():
            body.write('--%s%s' % (FILE_BOUNDARY, CRLF))
            body.write('Content-Disposition: form-data; name="%s"%s' % (key, CRLF))
            body.write(CRLF)
            body.write(value)
            body.write(CRLF)

        if files:
            for key, filename, value in files:
                content_type = self._get_content_type(filename)
                body.write('--%s%s' % (FILE_BOUNDARY, CRLF))
                body.write('Content-Disposition: form-data;' + \
                    ' name="%s"; filename="%s"%s' % (key, filename, CRLF))
                body.write('Content-Type: %s%s' % (content_type, CRLF))
                body.write(CRLF)
                body.write(value)
                body.write(CRLF)

        body.write('--%s--%s' % (FILE_BOUNDARY, CRLF))
        body.write(CRLF)
        content_type = 'multipart/form-data; boundary=%s' % FILE_BOUNDARY
        return content_type, body.getvalue()

    def _get_content_type(self, filename):
        return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

    def request(self, files=None, **params):
        if 'auth' not in params:
            params['auth'] = {
                'key': self.key,
                'expires': (datetime.now() +
                    timedelta(days=1)).strftime('%Y/%m/%d %H:%M:%S')
            }

        fields = {
            'params': json.dumps(params),
            'signature': self._sign_request(params)
        }

        return self._send_request(files, **fields)


from typing import List

class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        total = sum(nums)
        l , w, mw = 0 , 0, -1
        for r in range(len(nums)) :
            w += nums[r]
            while w > total - x and l <= r :
                w -= nums[l]
                l += 1
            if w == total-x :
                mw = max(mw,r-l+1)
        return len(nums)-mw if mw != -1 else -1

s = Solution()
ip = [1,1,4,2,3]
ans = s.minOperations(ip,5)
print(ans)


import numpy as np
import cv2
import pytesseract
import math
from PIL import Image

image = cv2.imread('../samples/sample02.png', 0)
cv2.imshow("Original Image", image)
cv2.waitKey(0)

def GaussianFilter(sigma):
    filter_size = 2 * int(4 * sigma + 0.5) + 1
    gaussian_filter = np.zeros((filter_size, filter_size), np.float32)
    m = filter_size//2
    n = filter_size//2

    for x in range(-m, m+1):
        for y in range(-n, n+1):
            x1 = 2*np.pi*(sigma**2)
            x2 = np.exp(-(x**2 + y**2)/(2* sigma**2))
            gaussian_filter[x+m, y+n] = (1/x1)*x2

    return gaussian_filter, filter_size

def adaptive_thresh(image):

    # sigma = 5 for sample02
    sigma = 9 # for sample01

    gauss_filter, window_size = GaussianFilter(sigma)

    output = np.zeros_like(image)

    for col in range(image.shape[1]-window_size):
        for row in range(image.shape[0]-window_size):
            y0 = int(max(row-window_size, row))
            y1 = int(min(row+window_size, image.shape[0]))
            x0 = int(max(col-window_size, col))
            x1 = int(min(col+window_size, image.shape[1]))

            temp = image[y0:y1, x0:x1]

            t = np.multiply(temp, gauss_filter)
            t = np.sum(t)

            if image[row, col] < t:
                output[row,col] = 0
            else:
                output[row,col] = 255

    output[:,image.shape[1]-window_size:] = 255
    output[image.shape[0]-window_size:, :] = 255

    return output

image = adaptive_thresh(image)
cv2.imshow("Adaptive Thresholding", image)
text = pytesseract.image_to_string(image)
print(text)
cv2.waitKey(0)


# -*- coding: utf-8 -*-
"""
Created on Sun May 14 14:33:15 2017

@author: ek028m
"""

import sqlite3
import csv

conn = sqlite3.connect('map.db')
c = conn.cursor()

# Once created, no need to run again.
def create_tables():
     c.execute('CREATE TABLE IF NOT EXISTS nodes(id INTEGER PRIMARY KEY NOT NULL, lat REAL, lon REAL, user TEXT, uid INTEGER, version INTEGER, changeset INTEGER, timestamp TEXT)')
     c.execute('CREATE TABLE IF NOT EXISTS nodes_tags(id INTEGER, key TEXT, value TEXT, type TEXT, FOREIGN KEY (id) REFERENCES nodes(id))')
     c.execute('CREATE TABLE IF NOT EXISTS ways(id INTEGER PRIMARY KEY NOT NULL, user TEXT, uid INTEGER, version TEXT, changeset INTEGER, timestamp TEXT)')
     c.execute('CREATE TABLE IF NOT EXISTS ways_tags(id INTEGER NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL, type TEXT, FOREIGN KEY (id) REFERENCES ways(id))')
     c.execute('CREATE TABLE IF NOT EXISTS ways_nodes(id INTEGER NOT NULL,node_id INTEGER NOT NULL, position INTEGER NOT NULL, FOREIGN KEY (id) REFERENCES ways(id), FOREIGN KEY (node_id) REFERENCES nodes(id))')

create_tables()
conn.commit()

def insert_nodes():
    with open('new_nodes.csv','r') as fin:
        # csv.DictReader uses first line in file for column headings by default
        dr = csv.DictReader(fin) # comma is default delimiter
        to_db = [(i['id'].decode('utf-8'), i['lat'].decode('utf-8'),i['lon'].decode('utf-8'), i['user'].decode('utf-8'), i['uid'].decode('utf-8'), i['version'].decode('utf-8'), i['changeset'].decode('utf-8'), i['timestamp'].decode('utf-8')) for i in dr]

    # insert the data
    c.executemany('INSERT INTO nodes(id, lat, lon, user, uid, version, changeset, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?);', to_db)
    # commit the changes
    conn.commit()

def insert_nodes_tags():
    with open('new_nodes_tags.csv','r') as fin:
        dr = csv.DictReader(fin)
        to_db = [(i['id'].decode('utf-8'), i['key'].decode('utf-8'),i['value'].decode('utf-8'), i['type'].decode('utf-8')) for i in dr]
        #for i in dr:
            #if i['id']:
                #to_db = [(i['id'].decode('utf-8'), i['key'].decode('utf-8'),i['value'].decode('utf-8'), i['type'].decode('utf-8'))]

    c.executemany('INSERT INTO nodes_tags(id, key, value, type) VALUES (?, ?, ?, ?);', to_db)
    conn.commit()

def insert_ways():
    with open('new_ways.csv','r') as fin:
        dr = csv.DictReader(fin)
        to_db = [(i['id'].decode('utf-8'), i['user'].decode('utf-8'),i['uid'].decode('utf-8'), i['version'].decode('utf-8'), i['changeset'].decode('utf-8'), i['timestamp'].decode('utf-8')) for i in dr]

    c.executemany('INSERT INTO ways(id, user, uid, version, changeset, timestamp) VALUES (?, ?, ?, ?, ?, ?);', to_db)
    conn.commit()

def insert_ways_tags():
    with open('new_ways_tags.csv','r') as fin:
        dr = csv.DictReader(fin)
        to_db = [(i['id'].decode('utf-8'), i['key'].decode('utf-8'),i['value'].decode('utf-8'), i['type'].decode('utf-8')) for i in dr]

    c.executemany('INSERT INTO ways_tags(id, key, value, type) VALUES (?, ?, ?, ?);', to_db)
    conn.commit()

def insert_ways_nodes():
    with open('new_ways_nodes.csv','r') as fin:
        dr = csv.DictReader(fin)
        to_db = [(i['id'].decode('utf-8'), i['node_id'].decode('utf-8'),i['position'].decode('utf-8')) for i in dr]

    c.executemany('INSERT INTO ways_nodes(id, node_id, position) VALUES (?, ?, ?);', to_db)
    conn.commit()

insert_nodes()
insert_nodes_tags()
insert_ways()
insert_ways_tags()
insert_ways_nodes()

conn.close()


import Chemins
from Utils import UTILS_Adaptations
from Utils.UTILS_Traduction import _
import wx
from Ctrl import CTRL_Bouton_image
import GestionDB
import datetime
from Ctrl import CTRL_Editeur_email
from Utils import UTILS_Dates
import six

class Dialog(wx.Dialog):
    def __init__(self, parent, donnees=[], texte_xml=None):
        wx.Dialog.__init__(self, parent, -1, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
        self.parent = parent
        self.donnees = donnees
        self.texte_xml = texte_xml

        listeAdresses = []
        for dictTemp in self.donnees :
            listeAdresses.append(dictTemp["adresse"])

        # Navigation
        self.bouton_premier = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Premier.png"), wx.BITMAP_TYPE_ANY))
        self.bouton_reculer = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Reculer.png"), wx.BITMAP_TYPE_ANY))
        self.ctrl_adresse = wx.ComboBox(self, -1, choices=listeAdresses, style=wx.CB_DROPDOWN )
        self.ctrl_adresse.SetEditable(False)
        if len(listeAdresses) > 0 :
            self.ctrl_adresse.Select(0)
        self.bouton_avancer = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Avancer.png"), wx.BITMAP_TYPE_ANY))
        self.bouton_dernier = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Dernier.png"), wx.BITMAP_TYPE_ANY))

        # Aperçu
        self.ctrl_editeur = CTRL_Editeur_email.Editeur(self)
        self.ctrl_editeur.SetEditable(False)

        # Boutons
        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage="Images/32x32/Aide.png")
        self.bouton_fermer = CTRL_Bouton_image.CTRL(self, texte=_(u"Fermer"), cheminImage="Images/32x32/Fermer.png")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnBoutonPremier, self.bouton_premier)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonReculer, self.bouton_reculer)
        self.Bind(wx.EVT_CHOICE, self.OnChoixAdresse, self.ctrl_adresse)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAvancer, self.bouton_avancer)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonDernier, self.bouton_dernier)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonFermer, self.bouton_fermer)

        # Init contrôles
        self.bouton_fermer.SetFocus()
        self.MAJ_apercu()

    def __set_properties(self):
        self.SetTitle(_(u"Aperçu de la fusion"))
        self.bouton_premier.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour atteindre le premier")))
        self.bouton_reculer.SetMinSize((50, -1))
        self.bouton_reculer.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour atteindre le précédent")))
        self.bouton_avancer.SetMinSize((50, -1))
        self.bouton_avancer.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour atteindre le suivant")))
        self.bouton_dernier.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour atteindre le dernier")))
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_fermer.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour fermer")))
        self.SetMinSize((600, 500))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=0, hgap=0)

        # Navigation
        grid_sizer_navigation = wx.FlexGridSizer(rows=1, cols=7, vgap=0, hgap=0)
        grid_sizer_navigation.Add(self.bouton_premier, 0, 0, 0)
        grid_sizer_navigation.Add(self.bouton_reculer, 0, 0, 0)
        grid_sizer_navigation.Add( (10, 5), 0, 0, 0)
        grid_sizer_navigation.Add(self.ctrl_adresse, 1, wx.EXPAND, 0)
        grid_sizer_navigation.Add( (10, 5), 0, 0, 0)
        grid_sizer_navigation.Add(self.bouton_avancer, 0, 0, 0)
        grid_sizer_navigation.Add(self.bouton_dernier, 0, 0, 0)
        grid_sizer_navigation.AddGrowableCol(3)
        grid_sizer_base.Add(grid_sizer_navigation, 1, wx.ALL|wx.EXPAND, 10)

        # Ctrl Aperçu
        grid_sizer_base.Add(self.ctrl_editeur, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)

        # Boutons
        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=3, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_fermer, 0, 0, 0)
        grid_sizer_boutons.AddGrowableCol(1)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.ALL|wx.EXPAND, 10)

        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        grid_sizer_base.AddGrowableRow(1)
        grid_sizer_base.AddGrowableCol(0)
        self.Layout()
        self.CenterOnScreen()

    def OnBoutonPremier(self, event):
        self.ctrl_adresse.Select(0)
        self.MAJ_apercu()

    def OnBoutonReculer(self, event):
        index = self.ctrl_adresse.GetSelection()
        if index > 0 :
            self.Navigation(-1)

    def OnChoixAdresse(self, event):
        self.MAJ_apercu()

    def OnBoutonAvancer(self, event):
        index = self.ctrl_adresse.GetSelection()
        if index < len(self.donnees) :
            self.Navigation(+1)

    def OnBoutonDernier(self, event):
        self.ctrl_adresse.Select(len(self.donnees)-1)
        self.MAJ_apercu()

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("EditeurdEmails")

    def OnBoutonFermer(self, event):
        self.EndModal(wx.ID_CANCEL)

    def Navigation(self, sens=1):
        index = self.ctrl_adresse.GetSelection()
        if index != -1 :
            self.ctrl_adresse.Select(index+sens)
            self.MAJ_apercu()

    def MAJ_apercu(self):
        index = self.ctrl_adresse.GetSelection()
        if index == -1 :
            return
        xml = self.texte_xml
        if xml == None :
            return
        if six.PY3:
            xml = xml.decode("utf-8")
        # Remplacement des champs standards
        for motcle, valeur in CTRL_Editeur_email.GetChampsStandards().items():
            xml = xml.replace(motcle, valeur)
        # Remplacement des champs spécifiques
        dictDonnee = self.donnees[index]
        for motcle, valeur in dictDonnee["champs"].items() :
            if valeur == None or valeur == "//None" :
                valeur = ""
            if type(valeur) == int :
                valeur = str(valeur)
            if type(valeur) == datetime.date:
                valeur = UTILS_Dates.DateDDEnFr(valeur)
            xml = xml.replace(motcle, valeur)
        # MAJ éditeur
        self.ctrl_editeur.SetXML(xml)

if __name__ == u"__main__":
    app = wx.App(0)
    #wx.InitAllImageHandlers()

    DB = GestionDB.DB()
    req = """SELECT categorie, nom, description, objet, texte_xml, IDadresse, defaut
    FROM modeles_emails
    WHERE IDmodele=1;"""
    DB.ExecuterReq(req)
    listeDonnees = DB.ResultatReq()
    DB.Close()
    categorie, nom, description, objet, texte_xml, IDadresse, defaut = listeDonnees[0]

    donnees = [
        {"adresse" : "monadresse1@gmail.com", "pieces" : [], "champs" : {} },
        {"adresse" : "monadresse2@gmail.com", "pieces" : [], "champs" : {} },
        {"adresse" : "monadresse3@gmail.com", "pieces" : [], "champs" : {} },
        ]

    dialog_1 = Dialog(None, donnees=donnees, texte_xml=texte_xml)
    app.SetTopWindow(dialog_1)
    dialog_1.ShowModal()
    app.MainLoop()


from sgp4.api import Satrec
from sgp4.api import SatrecArray

import matplotlib.pyplot as plt

import cartopy.crs as ccrs
from cartopy.feature.nightshade import Nightshade

from earth import *

class Tracker:
    def __init__(self, database):
        self.estimator = None
        self.database = database
        self.tracked_objects = []
        self.tracked_indexes = []
        self.n_tracked_objects = 0
        # Earth object for earth coordinates transformations
        self.earth = Earth()

    def ground_station(self, position):
        """ Defines the on-ground tracking station"""
        longitude, latitude, elevation = geo_coordinates(position)
        print("Ground Station at : ", np.degrees(longitude), "° long ", np.degrees(latitude), "° lat ")
        self.earth.define_observer(longitude, latitude, elevation)

    def update_objects(self, numbers):
        self.tracked_objects = []
        self.tracked_indexes = []
        self.n_tracked_objects = 0
        for number in numbers:
            index = self.database.search_index(number)
            self.tracked_objects.append(number)
            self.tracked_indexes.append(index)
            self.n_tracked_objects += 1
        self.load_estimator()

    def load_estimator(self):
        satellites = []
        for i in self.tracked_indexes:
            line1 = self.database.data[i][1]
            line2 = self.database.data[i][2]
            satellites.append(Satrec.twoline2rv(line1, line2))
        self.estimator = SatrecArray(satellites)

    def estimate(self, times):
        jd, fr = julian_fractions(times)
        e, r, v = self.estimator.sgp4(jd, fr)
        return r, v

    def sub_points(self, times):
        r, v = self.estimate(times)
        X, Y, Z = r[:, :, 0] * 1000, r[:, :, 1] * 1000, r[:, :, 2] * 1000
        longitudes = np.zeros_like(X)
        latitudes = np.zeros_like(X)
        heights = np.zeros_like(X)
        for i in range(self.n_tracked_objects):
            x, y, z = self.earth.ECI_ECEF(X[i, :], Y[i, :], Z[i, :], times)
            long, lat, h = self.earth.ECEF_geodetic(x, y, z)
            longitudes[i, :] = long
            latitudes[i, :] = lat
            heights[i, :] = h
        return longitudes, latitudes, heights

    def topocentric(self, times):
        if self.earth.observer_position is not None:
            r, v = self.estimate(times)
            X, Y, Z = r[:, :, 0] * 1000, r[:, :, 1] * 1000, r[:, :, 2] * 1000
            azimuths = np.zeros_like(X)
            elevations = np.zeros_like(X)
            ranges = np.zeros_like(X)
            for i in range(self.n_tracked_objects):
                x, y, z = self.earth.ECI_ECEF(X[i, :], Y[i, :], Z[i, :], times)
                long, lat, h = self.earth.ECEF_geodetic(x, y, z)
                azimuths[i, :] = long
                elevations[i, :] = lat
                ranges[i, :] = h
            return azimuths, elevations, ranges

    def draw2D(self, times):
        Long, Lat, H = self.sub_points(times)
        Long = np.degrees(Long)
        Lat = np.degrees(Lat)
        ax = plt.axes(projection=ccrs.PlateCarree())
        for i in range(self.n_tracked_objects):
            line = ax.plot(Long[i, :], Lat[i, :], transform=ccrs.Geodetic(), c="red")
        ax.set_extent([-180, 180, -90, 90])
        ax.stock_img()
        ax.coastlines()
        current_time = datetime.datetime.utcnow()
        ax.add_feature(Nightshade(current_time, alpha=0.3))
        ax.gridlines(draw_labels=False, linewidth=1, color='blue', alpha=0.3, linestyle='--')
        plt.show()

    def draw3D(self, T=12 * 3600):
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.set_title(' '.join(self.tracked_objects))
        ax.set_xlim3d(-50000, 50000)
        ax.set_ylim3d(-50000, 50000)
        ax.set_zlim3d(-50000, 50000)
        ax.set_xlabel('\nX [ km ]', linespacing=3.2)
        ax.set_ylabel('\nY [ km ]', linespacing=3.1)
        ax.set_zlabel('\nZ [ km ]', linespacing=3.4)
        t0 = time.time()
        times = np.linspace(t0, t0 + T, 3000)
        R, V = self.estimate(times)
        X, Y, Z = R[:, :, 0], R[:, :, 1], R[:, :, 2]
        for i in range(self.n_tracked_objects):
            x, y, z = X[i, :], Y[i, :], Z[i, :]
            ax.plot(x, y, z, c='b')
            ax.plot(x[0], y[0], z[0], c="r")
        plt.show()

    def above_passing(self, name, times):
        """ Returns the overhead passing of the target object in a time range beginning t the instance of lauch.
            Available time ranges : 1h ; 6h ; 12h ; 24h ; day ; 48h ; week
        """
        if name in self.tracked_objects:
            i = self.tracked_objects.index(name)
            print("Calculating above-head passing of " + name)
            Azimuths, Elevations, Ranges = self.topocentric(times)
            print(Azimuths.shape)
            print(Azimuths)
            fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
            ax.plot(Azimuths[i, :], Elevations[i, :])
            horizon = np.linspace(-np.pi, np.pi, num=200)
            ax.plot(horizon, np.zeros_like(horizon), color='black')
            ax.invert_yaxis()
            ax.set_ylim(np.pi / 2, 0)
            ax.set_theta_zero_location("S")
            # ax.set_xticklabels(['S', '', 'E', '', 'N', '', 'W', ''])
            plt.show()

######## NEEDED FUNCTIONS ########
def geo_coordinates(coordinates):
    """coords must be in this example format :
       43°33'45"N   1°28'09"E   166m """
    [long, lat, elevation] = coordinates.split()
    # Elevation handling
    elevation = float(elevation[:-1])
    # Longitude handling
    long = long.replace('°', ' ')
    long = long.replace("'", ' ')
    long = long.replace('''"''', ' ')
    if long[-1] == 'S':
        sign = -1
    else:
        sign = 1
    long = str_to_float_list(long[:-2])
    long = sign * np.radians(angle(long[0], long[1], long[2]))
    lat = lat.replace('°', ' ')
    lat = lat.replace("'", ' ')
    lat = lat.replace('''"''', ' ')
    if lat[-1] == 'W':
        sign = -1
    else:
        sign = 1
    lat = str_to_float_list(lat[:-2])
    lat = sign * np.radians(angle(lat[0], lat[1], lat[2]))
    return long, lat, elevation

def angle(degrees, minutes, seconds):
    return degrees + minutes / 60 + seconds / 3600

def str_to_float_list(string):
    L = string.split(' ')
    n = len(L)
    for i in range(n):
        L[i] = float(L[i])
    return L