"""
Overview
========

Used to insert tabs based on the type of file being edited.

Key-Commands
============

Namespace: spacing

Mode: INSERT
Event: <Tab>
Description: Insert a tab/space based on the programming file type.

"""

from os.path import splitext
from vyapp.plugins import ENV
from vyapp.areavi import AreaVi

class Tab(object):
    DEFAULT_SIZE, DEFAULT_CHAR = 4, ' '
    SCHEME, SIZE, CHAR         = {}, 4, ' '

    def __init__(self, area):
        self.area = area
        area.install('spacing',
        (-1, '<<LoadData>>', self.set_tab_scheme),
        (-1, '<<SaveData>>', self.set_tab_scheme),
        (-1, '<<ClearData>>', self.set_tab_scheme),
        ('INSERT', '<Tab>', lambda event:
        self.insert_tab(event.widget)))

    def set_tab_scheme(self, event):
        ph, ext = splitext(self.area.filename.lower())
        opt     = self.SCHEME.get(
        ext, (self.DEFAULT_SIZE, self.DEFAULT_CHAR))

        Tab.SIZE, Tab.CHAR = opt

    def insert_tab(self, area):
        area.edit_separator()
        data = self.CHAR * self.SIZE

        area.insert('insert', data)
        return 'break'

def tabset(size, char=Tab.CHAR):
    """
    Change tab size/char globally based
    on the actual areavi filename extension.
    """

    ph, ext = splitext(
    AreaVi.ACTIVE.filename.lower())
    Tab.SCHEME[ext]    = size, char
    Tab.SIZE, Tab.CHAR = size, char

ENV['tabset'] = tabset
install = Tab


# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import copy
import os
import unittest

from azure.cli.command_modules.batch import _help
from azure.cli.command_modules.batch_extensions import _template_utils as utils

class TestBatchNCJAppTemplates(unittest.TestCase):
    # pylint:disable=too-few-public-methods

    def setUp(self):
        self.data_dir = os.path.join(os.path.dirname(__file__), 'data')

        # File path to an application template with no parameters - a static
        # template that always does exactly the same thing
        self.static_apptemplate_path = os.path.join(self.data_dir,
            'batch-applicationTemplate-static.json')

        # File path to an application path with parameters
        self.apptemplate_with_params_path = os.path.join(self.data_dir,
            'batch-applicationTemplate-parameters.json')
        return super(TestBatchNCJAppTemplates, self).setUp()

    def test_batch_ncj_validate_job_requesting_app_template(self):
        # Should do nothing for a job not using an application template'
        job = {'id': 'jobid'}
        utils._validate_job_requesting_app_template(job, '.')  # pylint: disable=protected-access

        # Should throw an error if job does not specify template location
        job = {'id': 'jobid', 'applicationTemplateInfo': {}}
        with self.assertRaises(ValueError):
            utils._validate_job_requesting_app_template(job, '.')  # pylint: disable=protected-access

        # Should throw an error if the template referenced by the job does not
        # exist
        job = {
            'id': 'jobid',
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path + '.notfound'
            }
        }
        with self.assertRaises(ValueError):
            utils._validate_job_requesting_app_template(job, '.')  # pylint: disable=protected-access

        # Should throw an error if job uses property reserved for application
        # template use
        job = {
            'id': 'jobid',
            'applicationTemplateInfo': {'filePath': self.static_apptemplate_path},
            'usesTaskDependencies': True
        }
        with self.assertRaises(ValueError):
            utils._validate_job_requesting_app_template(job, '.')  # pylint: disable=protected-access

    def test_batch_ncj_validate_application_template(self):
        # should throw an error if the template uses a property reserved for
        # use by the job
        template = {
            'usesTaskDependencies': True,
            'displayName': 'display this name'
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_application_template(template)  # pylint: disable=protected-access
        self.assertIn('displayName', ve.exception.args[0],
                      'Expect property \'displayName\' to be mentioned')

        # should throw an error if the template uses a property not recognized
        template = {
            'usesTaskDependencies': True,
            'vendor': 'origin'
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_application_template(template)  # pylint: disable=protected-access
        self.assertIn('vendor', ve.exception.args[0],
                      'Expect property \'vendor\' to be mentioned')

        # should throw an error if a parameter does not declare a specific type
        template = {
            'usesTaskDependencies': True,
            'parameters': {
                'name': {
                    'defaultValue': 'Mouse'
                }
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_application_template(template)  # pylint: disable=protected-access
        self.assertIn('name', ve.exception.args[0],
                      'Expect parameter \'name\' to be mentioned')

        # should throw an error if a parameter does not declare a supported
        # type
        template = {
            'usesTaskDependencies': True,
            'parameters': {
                'name': {
                    'defaultValue': 'Mouse',
                    'type': 'dateTime'
                }
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_application_template(template)  # pylint: disable=protected-access
        self.assertIn('name', ve.exception.args[0],
                      'Expect parameter \'name\' to be mentioned')

    def test_batch_ncj_validate_parameter_usage(self):
        # should throw an error if no value is provided for a parameter without
        # a default
        parameters = {}
        definitions = {
            'name': {
                'type': 'string'
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        self.assertIn('name', ve.exception.args[0],
                      'Expect parameter \'name\' to be mentioned')

        # should throw an error if the value provided for an int parameter is
        # not type compatible
        parameters = {
            'age': 'eleven'
        }
        definitions = {
            'age': {
                'type': 'int'
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        self.assertIn('age', ve.exception.args[0],
                      'Expect parameter \'age\' to be mentioned')

        # should not throw an error if the default value provided for an int
        # parameter is used
        parameters = {}
        definitions = {
            'age': {
                'type': 'int',
                'defaultValue': 11
            }
        }
        utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access

        # should not throw an error if the default value provided for an int
        # parameter is not an integer
        parameters = {}
        definitions = {
            'age': {
                'type': 'int',
                'defaultValue': 'eleven'
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        self.assertIn('age', ve.exception.args[0], 'Expect parameter \'age\' to be mentioned')

        # should throw an error if the value provided for an bool parameter is
        # not type compatible
        parameters = {
            'isMember': 'frog'
        }
        definitions = {
            'isMember': {
                'type': 'bool'
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        self.assertIn('isMember', ve.exception.args[0],
                      'Expect parameter \'isMember\' to be mentioned')

        # should throw an error if a value is provided for a non-existing
        # parameter
        parameters = {
            'membership': 'Gold'
        }
        definitions = {
            'customerType': {
                'type': 'string',
                'defaultValue': 'peasant'
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        self.assertIn('membership', ve.exception.args[0],
                      'Expect parameter \'membership\' to be mentioned')

        # should accept having no job parameters if there are no template
        # parameters
        parameters = None
        definitions = None
        utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        # Pass implied by no Error

        # should accept having no job parameters if all template parameters
        # have defaults
        parameters = None
        definitions = {
            'customerType': {
                'type': 'string',
                'defaultValue': 'peasant'
            }
        }
        utils._validate_parameter_usage(parameters, definitions)  # pylint: disable=protected-access
        # Pass implied by no Error

    def test_batch_ncj_merge_metadata(self):
        # should return empty metadata when no metadata supplied
        alpha = None
        beta = None
        result = utils._merge_metadata(alpha, beta)  # pylint: disable=protected-access
        self.assertEqual(result, [])

        # should return base metadata when only base metadata supplied
        alpha = [
            {
                'name': 'name',
                'value': 'Adam'
            },
            {
                'name': 'age',
                'value': 'old'
            }]
        beta = None
        result = utils._merge_metadata(alpha, beta)  # pylint: disable=protected-access
        self.assertEqual(result, alpha)

        # should return more metadata when only more metadata supplied
        alpha = None
        beta = [{
            'name': 'gender',
            'value': 'unspecified'
        }]
        result = utils._merge_metadata(alpha, beta)  # pylint: disable=protected-access
        self.assertEqual(result, beta)

        # should throw an error if the two collections overlap
        alpha = [
            {
                'name': 'name',
                'value': 'Adam'
            },
            {
                'name': 'age',
                'value': 'old'
            }]
        beta = [
            {
                'name': 'name',
                'value': 'Brian'
            },
            {
                'name': 'gender',
                'value': 'unspecified'
            }]
        with self.assertRaises(ValueError) as ve:
            utils._merge_metadata(alpha, beta)  # pylint: disable=protected-access
        self.assertIn('name', ve.exception.args[0],
                      'Expect metadata \'name\' to be mentioned')

        # should return merged metadata when there is no overlap
        alpha = [
            {
                'name': 'name',
                'value': 'Adam'
            },
            {
                'name': 'age',
                'value': 'old'
            }]
        beta = [
            {
                'name': 'gender',
                'value': 'unspecified'
            }]
        expected = [
            {
                'name': 'name',
                'value': 'Adam'
            },
            {
                'name': 'age',
                'value': 'old'
            },
            {
                'name': 'gender',
                'value': 'unspecified'
            }]
        result = utils._merge_metadata(alpha, beta)  # pylint: disable=protected-access
        self.assertEqual(result, expected)

    def test_batch_ncj_generate_job(self):
        # should throw an error if the generated job uses a property reserved for template use
        job = {
            'id': 'jobid',
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            },
            'usesTaskDependencies': True
        }
        with self.assertRaises(ValueError) as ve:
            utils._validate_generated_job(job)  # pylint: disable=protected-access
        self.assertIn('applicationTemplateInfo', ve.exception.args[0],
                      'Expect property \'applicationTemplateInfo\' to be mentioned')

    def test_batch_ncj_template_merging(self):
        # pylint: disable=too-many-statements
        # should do nothing when no application template is required
        job = {
            'id': "jobid"
        }
        result = utils.expand_application_template(job, '.')
        self.assertEqual(result, job)

        # should throw error if no filePath supplied for application template
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
            }
        }
        with self.assertRaises(ValueError):
            utils.expand_application_template(job, '.')

        # should merge a template with no parameters
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertIsNotNone(result['jobManagerTask'],
            "expect the template to have provided jobManagerTask.")

        # should preserve properties on the job when expanding the template
        job_id = "importantjob"
        priority = 500
        job = {
            'id': job_id,
            'priority': priority,
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertEqual(result['id'], job_id)
        self.assertEqual(result['priority'], priority)

        # should use parameters from the job to expand the template
        job = {
            'id': "parameterJob",
            'applicationTemplateInfo': {
                'filePath': self.apptemplate_with_params_path,
                'parameters': {
                    'blobName': "music.mp3",
                    'keyValue': "yale"
                }
            }
        }
        job1 = copy.deepcopy(job)
        result = utils.expand_application_template(job, '.')
        self.assertEqual(
            result['jobManagerTask']['resourceFiles'][1]['filePath'],
            job1['applicationTemplateInfo']['parameters']['blobName'])
        self.assertEqual(result['metadata'][0]['value'],
            job1['applicationTemplateInfo']['parameters']['keyValue'])

        # should throw an error if any parameter has an undefined type
        untyped_parameter_path = os.path.join(self.data_dir,
            'batch-applicationTemplate-untypedParameter.json')
        job = {
            'id': "parameterJob",
            'applicationTemplateInfo': {
                'filePath': untyped_parameter_path,
                'parameters': {
                    'blobName': "music.mp3",
                    'keyValue': "yale"
                }
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('blobName', ve.exception.args[0],
                      'Expect parameter \'blobName\' to be mentioned')

        # should not have an applicationTemplateInfo property on the expanded job
        job_id = "importantjob"
        priority = 500
        job = {
            'id': job_id,
            'priority': priority,
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertNotIn('applicationTemplateInfo', result,
                         'Expect applicationTemplateInfo from job to not be present.')

        # should not copy templateMetadata to the expanded job
        job = {
            'id': 'importantjob',
            'priority': 500,
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertNotIn('templateMetadata', result,
                         'Expect templateMetadata from template to not be present.')

        # should not have a parameters property on the expanded job
        job_id = 'importantjob'
        priority = 500
        job = {
            'id': job_id,
            'priority': priority,
            'applicationTemplateInfo': {
                'filePath': self.apptemplate_with_params_path,
                'parameters': {
                    'blobName': "Blob",
                    'keyValue': "Key"
                }
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertNotIn('parameters', result,
                         'Expect parameters from template to not be present.')

        # should throw error if application template specifies \'id\' property
        templateFilePath = os.path.join(self.data_dir,
            'batch-applicationTemplate-prohibitedId.json')
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': templateFilePath
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('id', ve.exception.args[0], 'Expect property \'id\' to be mentioned')

        # should throw error if application template specifies \'poolInfo\' property
        templateFilePath = os.path.join(self.data_dir,
            'batch-applicationTemplate-prohibitedPoolInfo.json')
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': templateFilePath
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('poolInfo', ve.exception.args[0],
                      'Expect property \'poolInfo\' to be mentioned')

        # should throw error if application template specifies \'applicationTemplateInfo\' property
        templateFilePath = os.path.join(self.data_dir,
            'batch-applicationTemplate-prohibitedApplicationTemplateInfo.json')
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': templateFilePath
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('applicationTemplateInfo', ve.exception.args[0],
                      'Expect property \'applicationTemplateInfo\' to be mentioned')

        # should throw error if application template specifies \'priority\' property', function(_){
        templateFilePath = os.path.join(self.data_dir,
            'batch-applicationTemplate-prohibitedPriority.json')
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': templateFilePath
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('priority', ve.exception.args[0],
                      'Expect property \'priority\' to be mentioned')

        # should throw error if application template specifies unrecognized property
        templateFilePath = os.path.join(self.data_dir,
            'batch-applicationTemplate-unsupportedProperty.json')
        job = {
            'id': "jobid",
            'applicationTemplateInfo': {
                'filePath': templateFilePath
            }
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('fluxCapacitorModel', ve.exception.args[0],
                      'Expect property \'fluxCapacitorModel\' to be mentioned')

        # should include metadata from original job on generated job
        job = {
            'id': 'importantjob',
            'priority': 500,
            'applicationTemplateInfo': {
                'filePath': self.apptemplate_with_params_path,
                'parameters': {
                    'blobName': 'henry',
                    'keyValue': 'yale'
                }
            },
            'metadata': [
                {
                    'name': 'author',
                    'value': 'batman'
                }]
        }
        result = utils.expand_application_template(job, '.')
        self.assertIn('metadata', result, 'Expect to have metadata.')
        self.assertIn({'name': 'author', 'value': 'batman'},
                      result['metadata'])

        # should include metadata from template on generated job
        job = {
            'id': 'importantjob',
            'priority': 500,
            'applicationTemplateInfo': {
                'filePath': self.apptemplate_with_params_path,
                'parameters': {
                    'blobName': 'henry',
                    'keyValue': 'yale'
                }
            },
            'metadata': [
                {
                    'name': 'author',
                    'value': 'batman'
                }
            ]
        }
        result = utils.expand_application_template(job, '.')
        self.assertIn('metadata', result, 'Expect to have metadata.')
        self.assertIn({'name': 'myproperty', 'value': 'yale'},
                      result['metadata'])

        # should add a metadata property with the template location
        job = {
            'id': 'importantjob',
            'priority': 500,
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            }
        }
        result = utils.expand_application_template(job, '.')
        self.assertIn('metadata', result, 'Expect to have metadata.')
        self.assertIn({'name': 'az_batch:template_filepath',
                       'value': self.static_apptemplate_path},
                      result['metadata'])

        # should not allow the job to use a metadata property with our reserved prefix
        job = {
            'id': 'importantjob',
            'priority': 500,
            'applicationTemplateInfo': {
                'filePath': self.static_apptemplate_path
            },
            'metadata': [
                {
                    'name': 'az_batch:property',
                    'value': 'something'
                }
            ]
        }
        with self.assertRaises(ValueError) as ve:
            utils.expand_application_template(job, '.')
        self.assertIn('az_batch:property', ve.exception.args[0],
                      'Expect metadata \'az_batch:property\' to be mentioned')


##################################################################################
# params.py -- Set of parameters for UP-state-mediated_plast_fig4E.py
#
#
# Author: Victor Pedrosa
# Imperial College London, London, UK - Dec 2017
##################################################################################

import numpy as np

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Define the parameters -----------------------------------------------------------------------------

sinwave=0

# Neuron model parameters  (integrate and fire) -----------------------------------------------------
tau_m = 10. 		      		# [ms] Time constant for the leaky integrator
R = 1. 						# [Ohm] Resistance of the leaky I-F model for excitatory neurons
El = 0.						# [mV] Resting potential (leaky)
Vth = 10. 					# [mV] Threshold potential
Vres = 0. 					# [mV] Reset potential
Vspike = 10.		      		# [mV] Extra potential to indicate a spike - Just to make it prettier
Tref = 3. 					# [ms] Refractory time

# Network parameters --------------------------------------------------------------------------------
NE = 100	                   	# Number of excitatory neurons in the input layer
LE = 100                    # Number of excitatory neurons in the output layer
# Simulation parameters -----------------------------------------------------------------------------
t_max = 10000	      	    # [ms] Total time of simulation
dt = 1. 		                  # [ms] Simulation time step
nSteps = np.int(t_max/dt)       # Number of steps in simulation

# Excitatory plasticity -----------------------------------------------------------------------------
tp_plast = 20.                	# [ms] Decay time for pre->post activity
tm_plast = 20. 	           	# [ms] Decay time for post->pre activity

a_pre = {}		      		# Pre-synaptic activity term (non-Hebbian)
a_post = {}	     			# Post-synaptic activity term
a_plus = {}					# Coefficient related to pre->post activity
a_minus = {}		       	# Coefficient related to post->pre activity

# Down states -> standard STDP.
# Up states -> Pre alone leads to depression + standard STDP

a_pre["up"] = -0.0002
a_post["up"] = -0.0
a_plus["up"] = 0.005
a_minus["up"] = -0.005

a_pre["down"] = 0.0
a_post["down"] = -0.0
a_plus["down"] = 0.005
a_minus["down"] = -0.005

# Connections (synapses) -----------------------------------------------------------------------------
EsynE = 30.					# [mV] Reversal potential for exc. syn.
w_min = 0. 					# lower bound on all weights
w_max = 5. 					# upper bound on exc weights

# Synaptic conductance
tauSynEx = 10.				# [ms] Time constant for excitatory postsynaptic potential
tauSynIn = 10.				# [ms] Time constant for inhibitory postsynaptic potential
gBarEx = .4 				# Peak synaptic conductance for excitatory synapses

# Synaptic weights (constants) ------------------------------------------------------------------------

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Parameters for speeding up the simulation +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

step_tauSynEx = dt/tauSynEx
step_tau_m = dt/tau_m
step_tp_plast = dt/tp_plast
step_tm_plast = dt/tm_plast


from bson import ObjectId

__author__ = 'qhuydtvt'

from mongoengine import Document, StringField, EmbeddedDocumentField, ListField, IntField
from answer_choices import AnswerChoice

class Question(Document):
    _id = ObjectId()
    type = StringField()
    sub_type = StringField()
    stimulus = StringField()
    stem = StringField()
    answer_choices = ListField(EmbeddedDocumentField('AnswerChoice'))
    right_answer = IntField()

    @classmethod
    def to_formatted_json(cls, question_list):
        json_list = [question.to_json(sort_keys=True, indent= 4 * "&nbsp",
                                          separators=(',', ': ')) for question in question_list]
        return str.format("[
{0}
]",
                      (",
".join(json_list)).replace("\n", "
"))

class QuestionCollection(Document):
    version = StringField()
    questions = ListField(EmbeddedDocumentField('Question'))

    # def get_json(self, json_encoder):
    #     return json_encoder.encode(self.to_mongo())

# def from_questions_to_json_string(question_list):
#     # json_encoder = JSONEncoder()
#     json_list = [question.to_json(sort_keys=True, indent= 4 * "&nbsp", separators=(',', ': ')) for question in question_list]
#     # return str.format('{0}: [
' +  + '
]')
#     return str.format("{0} : [
{1}
]", QUESTION_KEY,
#                       (",
".join(json_list)).replace("\n", "
"))
        # .replace(" ", "&nbsp")

# def from_json_to_string(json_object):
#     print(json.dumps(json_object, sort_keys=True, indent=4, separators=(',', ': ')))
#     return json.dumps(json_object, sort_keys=True, indent=4, separators=(',', ': '))


# Copyright 2018, National Technology & Engineering Solutions of Sandia, LLC
# (NTESS).  Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
# Government retains certain rights in this software.

"""Functionality for working with the :ref:`database`."""

from __future__ import absolute_import, division, print_function, unicode_literals

import contextlib
import logging
import os
import shutil
import socket
import subprocess
import tempfile
import time

import gridfs
import pymongo

log = logging.getLogger(__name__)

class Server(object):
    """Create an instance of mongod for unit tests and tutorials.

    For real work you may want to setup and administer a dedicated instance of
    MongoDB; this class makes it easy to start a temporary instance of MongoDB
    for use with tutorials and our unit tests::

        >>> server = samlab.database.Server()
        >>> database = samlab.database.connect(server.uri)

        ... Use the database here ...

        >>> server.stop()

    Alternatively, you can use the server object as a context manager for automatic cleanup::

        >>> with samlab.database.Server() as server:
        ...     database = samlab.database.connect(server.uri)
        ...     ... Use the database here ...

        >>> # Server is automatically cleaned-up outside the `with` block.

    Parameters
    ----------
    dbpath: string, optional
        Filesystem path to a directory for MongoDB storage.  The directory will
        be created automatically if it doesn't already exist.  If left
        unspecified, a temporary directory will be created.
    host: string, optional
        Host interface that mongodb will listen on.  Defaults to localhost to
        prevent outside connections.
    port: int, optional
        Port for binding.  Defaults to a randomly-chosen open port.
    reset: bool, optional
        If `True`, deletes `dbpath` before starting the server.  This is useful
        when running tutorials or unit tests with a specific path.  The default
        is `False` in case you choose to use the server for real experiments.
    quiet: bool, optional
        if `True` (the default), suppresses output from the mongod process.
    """
    def __init__(self, dbpath=None, host=None, port=None, replicaset=None, reset=False, quiet=True):
        # Choose a directory for storage.
        if dbpath is None:
            dbpath=tempfile.mkdtemp()

        # Optionally reset data storage.
        if reset and os.path.exists(dbpath):
            shutil.rmtree(dbpath)

        # Ensure the data storage exists.
        if not os.path.exists(dbpath):
            os.makedirs(dbpath)

        # Choose an interface for binding.
        if host is None:
            host = "127.0.0.1"

        # Find an available port.
        if port is None:
            # Try the default.
            try:
                port = 27017
                with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
                    sock.bind((host, port))
            except:
                # Let the OS assign a port.
                with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
                    sock.bind((host, 0))
                    port = sock.getsockname()[1]

        # Make sure we have replicaset name.
        if replicaset is None:
            replicaset = "samlab"

        # Optionally suppress output from the server.
        if quiet:
            output = open(os.devnull, "wb")
        else:
            output = None

        # Start the server
        command = ["mongod", "--dbpath", dbpath, "--directoryperdb", "--replSet", replicaset, "--bind_ip", host, "--port", str(port)]
        log.info("Starting database server: %s", " ".join(command))
        self._mongod = subprocess.Popen(command, stdout=output, stderr=output)

        self._dbpath = dbpath
        self._host = host
        self._port = port
        self._replicaset = replicaset
        self._reset = reset

        # Connect the client.
        client = pymongo.MongoClient(self.uri)

        # Look for an existing replica set.
        config = client.local["system.replset"].find_one({"_id": replicaset})

        if config is None:
            # Create a new config from scratch.
            client.admin.command({"replSetInitiate": {"_id": replicaset, "members": [{"_id": 0, "host": "%s:%s" % (host, port)}]}})
        else:
            # Modify the config to match our host and port.
            for member in config["members"]:
                member["host"] = f"{host}:{port}"
            client.admin.command({"replSetReconfig": config, "force": True})

    def __repr__(self):
        return "samlab.database.Server(dbpath=%r, host=%r, port=%r, reset=%r)" % (self._dbpath, self._host, self._port, self._reset)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop()
        return False

    @property
    def uri(self):
        """MongoDB connection URI that can be used to connect to the running a database.

        Typically, you would pass this as an argument to :func:`samlab.database.connect`.
        """
        return "mongodb://%s:%s" % (self._host, self._port)

    @property
    def replicaset(self):
        return self._replicaset

    def stop(self):
        """Stop the running mongod instance.

        Raises
        ------
        RuntimeError, if called more than once, or called on an instance used a as a context manager.
        """
        if not self._mongod:
            raise RuntimeError("Database server already stopped.")

        log.info("Stopping database server.")
        self._mongod.terminate()
        self._mongod.wait()
        self._mongod = None
        log.info("Database server stopped.")

def connect(name="samlab", uri="mongodb://localhost:27017", replicaset="samlab"):
    """Open a database connection.

    Parameters
    ----------
    name: string, required
        Database name.
    uri: string, optional
        Database uri.
    replicaset: string, optional
        Database replica set.

    Returns
    -------
    database: :class:`pymongo.mongo_client.MongoClient`
        Database connection object.
    fs: :class:`gridfs.GridFS`
        Database file storage object.
    """
    assert(isinstance(name, str))
    assert(isinstance(uri, str))
    assert(isinstance(replicaset, str))

    client = pymongo.MongoClient(uri, replicaset=replicaset)
    database = client[name]
    fs = gridfs.GridFS(database)

    # Force the database into existence, so we can follow change streams.
    with contextlib.suppress(pymongo.errors.CollectionInvalid):
        database.create_collection("artifacts")
    with contextlib.suppress(pymongo.errors.CollectionInvalid):
        database.create_collection("experiments")
    with contextlib.suppress(pymongo.errors.CollectionInvalid):
        database.create_collection("observations")
    with contextlib.suppress(pymongo.errors.CollectionInvalid):
        database.create_collection("layouts")
    with contextlib.suppress(pymongo.errors.CollectionInvalid):
        database.create_collection("timeseries")

    # Create database indexes
    database.layouts.create_index("lid")
    database.artifacts.create_index([("$**", pymongo.TEXT)])
    database.artifacts.create_index("tags")
    database.experiments.create_index([("$**", pymongo.TEXT)])
    database.experiments.create_index("tags")
    database.observations.create_index([("$**", pymongo.TEXT)])
    database.observations.create_index("tags")
    database.timeseries.create_index([("$**", pymongo.TEXT)])
    database.timeseries.create_index("key")

    return database, fs


from django.shortcuts import render, redirect
from .models import Pizza, Toppings
from .forms import PizzaForm, CommentForm

def index(request):
    """home page for pizzas."""
    return render(request, "pizzas/index.html")

def pizzas(request):
    pizzas = Pizza.objects.order_by("date_added")

    context = {"pizzas": pizzas}

    return render(request, "pizzas/topics.html", context)

def pizza(request, pizza_id):
    pizza = Pizza.objects.get(id=pizza_id)

    entries = pizza.toppings_set.order_by("-date_added")
    comments = pizza.comment_set.order_by("-date_added")
    context = {"pizza": pizza, "entries": entries, "comments": comments}
    image = Pizza.objects.get(id=pizza_id)

    return render(request, "pizzas/topic.html", context)

def new_pizza(request):
    if request.method != "POST":
        form = PizzaForm()
    else:
        form = PizzaForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect("pizzas:pizzas")
    context = {"form": form}
    return render(request, "pizzas/new_topic.html", context)

def comment(request, pizza_id):
    if request.method != "POST":
        form = CommentForm()
    else:
        pizza = Pizza.objects.get(id=pizza_id)
        form = CommentForm(data=request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.pizza = pizza
            comment.save()
            return redirect("pizzas:pizzas")
    context = {"form": form, "pizza_id": pizza_id}
    return render(request, "pizzas/comment.html", context)


from torchvision import transforms, datasets
import os
from draw_hand_trasform_CNN import DrawHands

data_dir = '../images/'

data_transforms = {
    'train': transforms.Compose([
            DrawHands(),
            transforms.Resize((32, 32)),
            transforms.RandomRotation(45),
            transforms.RandomVerticalFlip(p=0.4),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
    ]),
    'validation': transforms.Compose([
            DrawHands(),
            transforms.Resize((32, 32)),
            transforms.ToTensor(),
    ]),
}

image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
                                          data_transforms[x]) for x in ['train', 'validation']}

dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'validation']}
class_names = image_datasets['train'].classes


import pigpio
from src.Controller import step_controller, Controller
from src.HardwareInterface import send_servo_commands, initialize_pwm
from src.PupperConfig import (
    MovementReference,
    GaitParams,
    StanceParams,
    SwingParams,
    ServoParams,
    PWMParams,
)
import time
import numpy as np
import UDPComms

def main():
    """Main program
    """
    pi_board = pigpio.pi()
    pwm_params = PWMParams()
    servo_params = ServoParams()

    controller = Controller()
    controller.movement_reference = MovementReference()
    controller.movement_reference.v_xy_ref = np.array([0.0, 0.0])
    controller.movement_reference.wz_ref = 0

    controller.movement_reference.pitch = 15.0 * np.pi / 180.0
    controller.movement_reference.roll = 0

    controller.swing_params = SwingParams()
    controller.swing_params.z_clearance = 0.06
    controller.stance_params = StanceParams()
    controller.stance_params.delta_y = 0.08
    controller.gait_params = GaitParams()
    controller.gait_params.dt = 0.01

    initialize_pwm(pi_board, pwm_params)

    values = UDPComms.Subscriber(8830, timeout=0.3)
    last_loop = time.time()
    now = last_loop
    start = time.time()
    for i in range(60000):
        last_loop = time.time()
        step_controller(controller)
        send_servo_commands(pi_board, pwm_params, servo_params, controller.joint_angles)

        try:
            msg = values.get()
            print(msg)
        except UDPComms.timeout:
            print("timout")
            msg = {"x": 0, "y": 0, "twist": 0, "pitch": 0}
        x_vel = msg["y"] / 7.0
        y_vel = -msg["x"] / 7.0
        yaw_rate = -msg["twist"] * 0.8

        pitch = msg["pitch"] * 30.0 * np.pi / 180.0
        print(pitch)

        controller.movement_reference.v_xy_ref = np.array([x_vel, y_vel])
        controller.movement_reference.wz_ref = yaw_rate
        controller.movement_reference.pitch = pitch
        while now - last_loop < controller.gait_params.dt:
            now = time.time()
        # print("Time since last loop: ", now - last_loop)
    end = time.time()
    print("seconds per loop: ", (end - start) / 1000.0)

main()


"""
Setuptools script for ForML package.
"""
import os.path
import sys
import setuptools

sys.path.insert(0, 'src')
import forml

EXTRAS_STDLIB = {
    'pandas',
    'scikit-learn'
}

EXTRAS_GRAPHVIZ = {
    'graphviz'
}

EXTRAS_DASK = {
    'dask',
    'cloudpickle'
}

EXTRAS_DOC = {
    'sphinx'
}

EXTRAS_ALL = EXTRAS_STDLIB | EXTRAS_GRAPHVIZ | EXTRAS_DASK | EXTRAS_DOC

setuptools.setup(name='forml',
                 version=forml.__version__,
                 description='Lifecycle management framework for Data science projects',
                 long_description=open('README.md', 'r').read(),
                 long_description_content_type='text/markdown',
                 maintainer='Antony Mayi',
                 maintainer_email='antonymayi@yahoo.com',
                 license='Apache License 2.0',
                 packages=setuptools.find_packages(where='src'),
                 package_dir={'': 'src'},
                 package_data={'forml.conf': ['*.ini']},
                 setup_requires=['pytest-runner', 'pytest-pylint'],
                 tests_require=['pytest-cov', 'pylint', 'pytest'],
                 install_requires=['joblib', 'pip'],
                 extras_require={
                     'all': EXTRAS_ALL,
                     'doc': EXTRAS_DOC,
                     'stdlib': EXTRAS_STDLIB,
                     'graphviz': EXTRAS_GRAPHVIZ,
                     'dask': EXTRAS_DASK
                 },
                 python_requires='>=3.6',
                 classifiers=[
                     'Development Status :: 1 - Planning',
                     'Environment :: Console',
                     'Intended Audience :: Developers',
                     'Intended Audience :: Science/Research',
                     'License :: Other/Proprietary License',
                     'Programming Language :: Python :: 3',
                     'Topic :: Scientific/Engineering :: Artificial Intelligence',
                     'Topic :: System :: Distributed Computing'
                 ],
                 zip_safe=False)


# -*- coding: utf-8 -*-
"""
Created on Thu Apr 16 14:32:32 2020

@author: Kyle

From CodeWars kata "Recover a secret string from random triplets"
https://www.codewars.com/kata/53f40dff5f9d31b813000774/
"""

from Triplets_Secret_String import recoverSecret

def test_whatisup():
    secret = "whatisup"
    triplets = [['t','u','p'],
                ['w','h','i'],
                ['t','s','u'],
                ['a','t','s'],
                ['h','a','p'],
                ['t','i','s'],
                ['w','h','s']]
    assert recoverSecret(triplets) == secret


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#----------------------------------------------------------------------
# xoutil.aop.classical
#----------------------------------------------------------------------
# Copyright (c) 2012, 2013, 2014 Merchise Autrement and Contributors
# All rights reserved.
#
# Author: Manuel Vázquez Acosta
# Contributors: see CONTRIBUTORS and HISTORY file
#
# This is free software; you can redistribute it and/or modify it under the
# terms of the LICENCE attached (see LICENCE file) in the distribution
# package.
#
# Created on Apr 26, 2012

'''This module provides a very simple and classical way to weave 'aspect
classes' into your own classes/modules.

This "classical" approach is different from the basic approach in
:mod:`~xoutil.aop.basic` in that this one is meant to apply changes to the
behavior of objects that endure beyond any given context of execution. Once a
class/module has been weaved, it will remain weaved forever.

Also, this implementation does not (can't) weave built-in types.

'''

from __future__ import (division as _py3_division,
                        print_function as _py3_print,
                        unicode_literals as _py3_unicode,
                        absolute_import as _py3_abs_import)

import types
from functools import wraps as _wraps, partial

from xoutil import Unset
from six import PY3 as _py3, callable
from xoutil.deprecation import deprecated as _deprecated
from xoutil.names import strlist as strs

if _py3:
    from inspect import getfullargspec as _getfullargspec
else:
    from inspect import getargspec as _getfullargspec
del _py3

__all__ = strs('weave', 'StopExceptionChain')
del strs

def wraps(target):
    '''Hacks functools.wraps to bypass wrapper descriptors (for __repr__,
    etc.)

    '''
    from xoutil.types import is_slotwrapper
    if not is_slotwrapper(target):
        return _wraps(target)
    else:
        return target

class StopExceptionChain(Exception):
    pass

def _filter_args_byspec(method, *args, **kwargs):
    from xoutil.objects import get_first_of
    spec = _getfullargspec(method)
    if not spec.varargs:
        args = ()
    # XXX: [manu] In Python 3.2, the FullArgsSpec named tuple does not have a
    # keywords attribute, but a varkw and both kwonlyargs and
    # kwonlydefaults.
    #
    # Since spec is a named tuple, it must be enclosed in an outer tuple.
    keywords = get_first_of((spec, ), 'keywords', 'varkw')
    if not keywords:
        kwargs = {}
    return (args, kwargs)

# TODO: [manu] This is repeated in "xoutil.proxy"
def _mro_getattr(obj, attr, default=Unset):
    '''Gets the attr from obj's MRO'''
    from xoutil.types import mro_dict
    unset = object()
    res = mro_dict(obj).get(attr, unset)
    if res is unset:
        if default is Unset:
            raise AttributeError(attr)
        else:
            return default
    else:
        return res
_mro_getattrdef = partial(_mro_getattr, default=None)

def get_staticattr(obj, attr, default=None):
    '''Gets the attribute `attr` by using `getattr`.'''
    value = getattr(obj, attr, default)
    # XXX: In Python 2.7, this may return a bound/unbound method, with a
    #      im_func.
    value = getattr(value, 'im_func', value)
    return value

def bind_method(method, *args, **kwargs):
    '''Returns the method to be called already bound to self if needed'''
    from xoutil.types import is_instancemethod, is_classmethod, is_staticmethod
    if args and is_instancemethod(method):
        self = args[0]
        args = args[1:]
        bound_method = _wraps(method)(lambda *args, **kwargs: method(self,
                                                                    *args,
                                                                    **kwargs))
    elif args and is_classmethod(method):
        self = args[0]
        args = args[1:]
        bound_method = _wraps(method.__func__)(lambda *a, **kw:
                                               method.__func__(self,
                                                               *a,
                                                               **kw))
    elif is_staticmethod(method):
        self = None
        bound_method = method.__func__
    else:
        self = None
        bound_method = method
    return self, bound_method, args, kwargs

def build_method(method, inner):
    from xoutil.types import is_staticmethod, is_classmethod
    if is_staticmethod(method):
        return staticmethod(inner)
    elif is_classmethod(method):
        return classmethod(inner)
    else:
        return inner

def _weave_after_method(target, aspect, method_name,
                        after_method_name='_after_{method_name}'):
    '''Weaves an after method given by `method_name` defined (by name
    convention) in `aspect` into the class `target`.

    The following two classes define a single method `echo`. The second class
    may raise `ZeroDivisionError`s::

        >>> class GoodClass(object):
        ...    def echo(self, what):
        ...        return what
        ...
        ...    @classmethod
        ...    def superecho(cls, what):
        ...        return what

        >>> class BadClass(object):
        ...    def echo(self, what):
        ...        return (what+1)//what

        >>> good_instance = GoodClass()
        >>> good_instance.echo(0)
        0

        >>> bad_instance = BadClass()
        >>> bad_instance.echo(0)               # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        ZeroDivisionError: ...

    Now, let's define a simple class that defines an _after_echo and weave the
    previous classes::

        >>> class Logging(object):
        ...    def _after_echo(self, method, result, exc_value):
        ...        if not exc_value:
        ...            print('Method {m} returned {result!r}'.
        ...                  format(m=method, result=result))
        ...        else:
        ...            print('When calling method {m}, {exc!r} was raised!'.
        ...                  format(m=method, exc=exc_value))
        ...        return result
        ...
        ...    def _after_superecho(self, method, result, exc_value):
        ...        print(type(self))
        ...        return result

        >>> _weave_after_method(GoodClass, Logging, 'echo')
        >>> _weave_after_method(GoodClass, Logging, 'superecho')
        >>> _weave_after_method(BadClass, Logging, 'echo')

    After weaving every instance (even those that already exists) will behave
    with the new functionality included::

        >>> good_instance.echo(0)       # doctest: +ELLIPSIS
        Method <...> returned 0
        0

        # You won't see the print result cause the Exception in doctests.
        >>> bad_instance.echo(0)        # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        ZeroDivisionError: ...

        # Class methods remains classmethods
        >>> good_instance.superecho(0)  # doctest: +ELLIPSIS
        <...'type'>
        0

    You may define another 'aspect' elsewhere an weave it on top::

        >>> class Security(object):
        ...    current_user = 'manu'
        ...    __perms__ = {'manu': {'respond': ['echo'], }, 'anon': {}}
        ...
        ...    @staticmethod
        ...    def _after_echo(self, method, result, exc_value):
        ...        if Security.current_user_mayrespond('echo'):
        ...            return result
        ...
        ...    @classmethod
        ...    def current_user_mayrespond(cls, method):
        ...        current_user = cls.get_current_user()
        ...        if current_user in cls.__perms__:
        ...            perms = cls.__perms__.setdefault(current_user, {})
        ...            respond_perms = perms.setdefault('respond', [])
        ...            return method in respond_perms
        ...        else:
        ...            return False
        ...
        ...    @classmethod
        ...    def get_current_user(cls):
        ...        return cls.current_user

        >>> _weave_after_method(GoodClass, Security, 'echo')

        >>> good_instance.echo(0)        # doctest: +ELLIPSIS
        Method <...> returned 0
        0

        # Changing the current user to other than 'manu', has the effect that
        # the Security aspect does not allow to return a response.
        >>> Security.current_user = 'other'
        >>> good_instance.echo(0)                        # doctest: +ELLIPSIS
        Method <...> returned 0

    '''
    from xoutil.types import is_module
    if is_module(target):
        method = getattr(target, method_name, None)
    else:
        method = _mro_getattr(target, method_name, None)
    after_method_name = after_method_name.format(method_name=method_name)
    after_method = get_staticattr(aspect, after_method_name, None)

    if method and after_method:
        @wraps(getattr(method, '__func__', method))
        def inner(*args, **kwargs):
            self, bound_method, args, kwargs = bind_method(method,
                                                           *args, **kwargs)
            try:
                # We don't need to pass self to a bound method
                result = bound_method(*args, **kwargs)
            except Exception as error:
                result = None
                exc_value = error
            else:
                exc_value = None
            try:
                after_args, after_kw = _filter_args_byspec(after_method,
                                                           *args, **kwargs)
                result = after_method(self, method, result, exc_value,
                                      *after_args, **after_kw)
                if exc_value:
                    raise exc_value
                else:
                    return result
            except StopExceptionChain:
                pass

        wrapper = build_method(method, inner)
        if isinstance(target, types.ModuleType):
            import sys
            from xoutil.names import nameof
            target = sys.modules[nameof(target, inner=True)]
        setattr(target, method_name, wrapper)

def _weave_before_method(target, aspect, method_name,
                         before_method_name='_before_{method_name}'):
    '''Tries to weave a before method given by `method_name` defined (by name
    convention) in `aspect` into the class `target`.

    The following two classes define a single method `echo`. The second class
    may raise `ZeroDivisionError`s::

        >>> class GoodClass(object):
        ...    def echo(self, what):
        ...        return what

        >>> class BadClass(object):
        ...    def echo(self, what):
        ...        return (what+1)//what

        >>> good_instance = GoodClass()
        >>> good_instance.echo(0)
        0

        >>> bad_instance = BadClass()
        >>> bad_instance.echo(0)    # doctest: +ELLIPSIS
        Traceback (most recent call last):
            ...
        ZeroDivisionError: ...

    The following class defines a Security aspect that allows the execution of
    methods by user::

        >>> class Security(object):
        ...    current_user = 'manu'
        ...    __perms__ = {'manu': {'execute': ['echo'], }, 'anon': {}}
        ...
        ...    @staticmethod
        ...    def check_execution_permissions(self, method):
        ...        from xoutil.names import nameof
        ...        methodname = nameof(method, inner=True)
        ...        if Security.current_user_may_execute(methodname):
        ...            return result
        ...
        ...    @classmethod
        ...    def current_user_may_execute(cls, method):
        ...        current_user = cls.get_current_user()
        ...        if current_user in cls.__perms__:
        ...            perms = cls.__perms__.setdefault(current_user, {})
        ...            respond_perms = perms.setdefault('execute', [])
        ...            if method not in respond_perms:
        ...                raise Exception('Forbidden')
        ...        else:
        ...            raise Exception('Forbidden')
        ...
        ...    @classmethod
        ...    def get_current_user(cls):
        ...        return cls.current_user

    Now let's apply our security aspect::

        >>> _weave_before_method(GoodClass, Security,
        ...                      'echo', 'check_execution_permissions')
        >>> _weave_before_method(BadClass, Security,
        ...                      'echo', 'check_execution_permissions')

    Now 'manu' may still execute the 'echo' method for both GoodClass and
    BadClass instances::

        >>> good_instance.echo(1)
        1

        >>> bad_instance.echo(1)
        2

    Other users are not allowed::

        >>> Security.current_user = 'other'
        >>> bad_instance.echo(0) # If allowed it'd raise a ZeroDivisionError
        Traceback (most recent call last):
            ...
        Exception: Forbidden

    '''
    method = _mro_getattr(target, method_name, None)
    before_method_name = before_method_name.format(method_name=method_name)
    before_method = get_staticattr(aspect, before_method_name, None)

    @wraps(method)
    def inner(*args, **kwargs):
        self, bound_method, args, kwargs = bind_method(method, *args, **kwargs)
        before_args, before_kwargs = _filter_args_byspec(before_method,
                                                         *args,
                                                         **kwargs)
        result = before_method(self, method, *before_args, **before_kwargs)
        # We don't need to pass self to a bound method
        return bound_method(*args, **kwargs) or result

    if method and before_method:
        wrapped = build_method(method, inner)
        setattr(target, method_name, wrapped)

def _weave_around_method(cls, aspect, method_name,
                          around_method_name='_around_{method_name}'):
    '''Simply put, replaces a method by another::

        >>> class OriginalClass(object):
        ...    def echo(self, what):
        ...        return what
        ...
        ...    def superecho(self, what):
        ...        return what * what

        >>> class Logger(object):
        ...    def _around_any(self, method, *args, **kwargs):
        ...        print('Calling {m} with {args}, {kwargs}'.
        ...              format(m=method, args=args, kwargs=kwargs))
        ...        result = method(*args, **kwargs)
        ...        print('... and {result!r} was returned'.
        ...              format(result=result))
        ...        return self.superecho(result)

        >>> obj = OriginalClass()
        >>> obj.echo(10)
        10

        >>> _weave_around_method(OriginalClass, Logger, 'echo', '_around_any')

        >>> obj.echo(10)            # doctest: +ELLIPSIS
        Calling ... with (10,), {}
        ... and 10 was returned
        100

    '''
    method = _mro_getattr(cls, method_name, None)
    around_method_name = around_method_name.format(method_name=method_name)
    around_method = get_staticattr(aspect, around_method_name, None)

    @wraps(method)
    def inner(*args, **kwargs):
        self, bound_method, args, kwargs = bind_method(method, *args, **kwargs)
        result = around_method(self, bound_method, *args, **kwargs)
        return result

    if method and around_method:
        wrapped = build_method(method, inner)
        setattr(cls, method_name, wrapped)

_method_name = lambda attr: attr[attr[1:].find('_') + 2:]
_not = lambda func: (lambda *a, **kw: not func(*a, **kw))
_and = lambda *preds: (lambda *a, **kw: all(p(*a, **kw) for p in preds))
_or = lambda *preds: (lambda *a, **kw: any(p(*a, **kw) for p in preds))

_private = lambda attr: attr.startswith('_')
_aspect_method = lambda attr: any(attr.startswith(prefix) and attr != prefix
                                    for prefix in ('_after_',
                                                   '_before_',
                                                   '_around_'))
#_public = _not(_private)
_public = lambda attr: not attr.startswith('_')

@_deprecated('None', msg="This entire module is deprecated and will be "
             "removed.", removed_in_version='1.6.0')
def weave(aspect, target, *ignored):
    '''Weaves an aspect into `target`. The weaving involves:

    - First every public attribute from `aspect` that is not an after method,
      before method, or around method is injected into `target`.

    - Then, we weave any after, before and around methods into `target` if
      there's a matching method.

    - Lastly, if there's a `_after_` method in `aspect` it is weaved into all
      *public* methods of `target` (even those which were injected and weaved
      previously).

      The same is done for `_before_` and `_around_`.

    Since the introduction :mod:`xoutil.aop.extended` this method might look
    for a `_before_weave` or a `_around_weave` method in `aspect`; which allow
    aspects to hook this method.

    :param aspect: The aspect class.
    :param target: The class to be weaved

    :param ignored: Any attribute name passed in `ignored` is not weaved.

                    .. versionadded:: 1.1.6

    '''
    from xoutil.objects import fdir
    from xoutil.iterators import flatten
    ignored = tuple(flatten(ignored))
    # Inject all public, non-aspect method
    for attr in fdir(aspect, _and(_public, _not(_aspect_method)),
                     getter=_mro_getattrdef):
        setattr(target, attr, get_staticattr(aspect, attr))
    # Weave aspect methods but keep an order scheme:
    #     afters < before < around
    key = lambda n: (not callable(_mro_getattr(aspect, n, None)),
                     not n.startswith('_after_'),
                     not n.startswith('_before_'),
                     not n.startswith('_around_'),)
    for attr in sorted(fdir(aspect, _aspect_method, callable,
                            getter=_mro_getattrdef),
                       key=key):
        ok = lambda what: (attr.startswith('_' + what + '_') and
                           attr not in ignored)
        if ok('after'):
            _weave_after_method(target, aspect, _method_name(attr))
        elif ok('before'):
            _weave_before_method(target, aspect, _method_name(attr))
        elif ok('around'):
            _weave_around_method(target, aspect, _method_name(attr))
    aspect_dict = dir(aspect)
    method = lambda maybe: isinstance(maybe, (types.MethodType,
                                              types.FunctionType))
    if '_after_' in aspect_dict:
        for attr in fdir(target, attr_filter=_public, value_filter=method,
                         getter=_mro_getattrdef):
            _weave_after_method(target, aspect, attr, '_after_')
    if '_before_' in aspect_dict:
        for attr in fdir(target, attr_filter=_public, value_filter=method,
                         getter=_mro_getattrdef):
            _weave_before_method(target, aspect, attr, '_before_')
    if '_around_' in aspect_dict:
        for attr in fdir(target, attr_filter=_public, value_filter=method,
                         getter=_mro_getattrdef):
            _weave_around_method(target, aspect, attr, '_around_')

del _deprecated


from datetime import time
from operator import itemgetter

h = [
    {'start_time': '12:00', 'end_time': '14:00', 'priority': 1, 'less': False},
    {'start_time': '14:00', 'end_time': '10:00', 'priority': 2, 'less': True},
    {'start_time': '14:00', 'end_time': '18:00', 'priority': 0, 'less': True},
    {'start_time': '13:00', 'end_time': '14:00', 'priority': 3, 'less': False}
]

a = sorted(h, key=lambda x: (-x['less'], x['start_time'], -x['priority']))
print(a)

# ==>
# [{'start_time': '14:00', 'end_time': '18:00', 'priority': 0, 'less': True},
# {'start_time': '14:00', 'end_time': '10:00', 'priority': 2, 'less': True},
# {'start_time': '12:00', 'end_time': '14:00', 'priority': 1, 'less': False},
# {'start_time': '13:00', 'end_time': '14:00', 'priority': 3, 'less': False}
# ]

b = sorted(h, key=itemgetter('less', 'start_time', 'priority'), reverse=True)
print(b)
# ==>
# [
# {'start_time': '14:00', 'end_time': '10:00', 'priority': 2, 'less': True},
# {'start_time': '14:00', 'end_time': '18:00', 'priority': 0, 'less': True},
# {'start_time': '13:00', 'end_time': '14:00', 'priority': 3, 'less': False},
# {'start_time': '12:00', 'end_time': '14:00', 'priority': 1, 'less': False}
# ]
# print(h)

print(sorted([True, False]))

# ==>
# [False, True]

class Bucket:
    def __init__(self, start_time, end_time, priority, less, is_work):
        self.start_time = start_time
        self.end_time = end_time
        self.priority = priority
        self.less = less
        self.is_work = is_work

buckets = [Bucket(start_time=time(hour=10), end_time=time(hour=11), priority=1, less=False, is_work=False),
           Bucket(start_time=time(hour=14), end_time=time(hour=10), priority=2, less=True, is_work=False),
           Bucket(start_time=time(hour=14), end_time=time(hour=12), priority=0, less=True, is_work=True),
           Bucket(start_time=time(hour=13), end_time=time(hour=17), priority=3, less=False, is_work=True)]

sb = sorted(buckets, key=lambda x: (-x.less, x.start_time, -x.priority))
for b in sb:
    print(b.__dict__)

    # ==>
    # {'start_time': '14:00', 'end_time': '10:00', 'priority': 2, 'less': True, 'is_work': False}
    # {'start_time': '14:00', 'end_time': '12:00', 'priority': 0, 'less': True, 'is_work': True}
    # {'start_time': '10:00', 'end_time': '11:00', 'priority': 1, 'less': False, 'is_work': False}
    # {'start_time': '13:00', 'end_time': '19:00', 'priority': 3, 'less': False, 'is_work': True}

class BucketNode:
    def __init__(self, time_value, is_work):
        self.time_value = time_value
        self.is_work = is_work
        self.next = None
        self.prev = None

# def insert_note(nodelist, bucket: Bucket):
#     if nodelist is None:
#         if bucket.less:
#             node1 = BucketNode(time_value=time(hour=0), is_work=bucket.is_work)
#             node2 = BucketNode(time_value=bucket.end_time, is_work=bucket.is_work)
#             node3 = BucketNode(time_value=time(hour=23, minute=59, second=59, microsecond=999), is_work=bucket.is_work)
#             node1.next = node2
#             node2.prev = node1
#             node2.next = node3
#             node3.prev = node2
#
#             bucketlinkliststart = node1
#     else:
#         if bucket.less:
#             node1 = BucketNode(time_value=time(hour=0), is_work=bucket.is_work)
#             fn = find_node(nodelist, node1.time_value)
#             if fn:
#                 node1.next = fn.next
#                 if fn.prev:
#                     fn.prev.next = node1
#                     fn.prev.next.prev = node1
#                     node1.prev = fn.prev
#                 else:
#                     bucketlinkliststart = node1
#             else:
#                 pass

#
# def merge_nodes(nodelist1, nodelist2):
#     p1, p2 = nodelist1, nodelist2
#     if p1 and p2:
#         if p1.time_value < p2.time_value:
#             head = p1
#             p1 = p1.next
#         else:
#             head = p2
#             p2 = p2.next
#         current = head
#
#     elif p1:
#         return p1
#     else:
#         return p2
#
#     while p1 and p2:
#         if p1.time_value < p2.time_value:
#             current.next = p1
#             current.is_work = p2.is_work
#             p1 = p1.next
#         else:
#             current.next = p2
#             current.is_work = p2.is_work
#             p2 = p2.next
#         current = current.next
#     if p1:
#         current.next = p1
#     else:
#         current.next = p2
#
#     return head

def insert_node(nodelist: BucketNode, start_node: BucketNode, end_node: BucketNode):
    p1 = nodelist

    if p1.time_value <= start_node:
        head = p1
        p1 = p1.next
        current = start_node
        head.next = current
    else:
        current = start_node
        head = current

    # 找到比endnode大的值：
    while p1:
        if p1.time_value < end_node.time_value:
            p1 = p1.next
        else:
            end_node.next = p1
            break
    current.next = end_node
    return head

def find_next_node(nodelist, time_value) -> BucketNode:
    if nodelist is None:
        return None
    else:
        if nodelist.time_value > time_value:
            return nodelist
        else:
            if nodelist.next:
                find_next_node(nodelist.next, time_value)
            else:
                return None


from django.contrib import admin
from django.urls import path
from Home_Rental_System import views

urlpatterns = [
    path("",views.index,name='home'),
    path("about",views.about,name='about'),
    path("contact",views.contact,name='contact'),
    path("apartment",views.apartment,name='apartment'),
    path("registrationpage",views.registrationpage,name='registrationpage'),
    path("login",views.login,name='login'),
    path("logout",views.logout,name='logout')
]


import json
def import_items():
    dataPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\item.json'
    existingData = None
    itemCount = 0

    with open(dataPath) as f:
        existingData = json.load(f)
    itemCount = len(existingData)

    with open('./tools/item_add.txt') as f:
        for line in f:
            props = line.rstrip().split('|')
            existingData[props[0].lower()] = {
                "id": itemCount,
                "name": props[0].lower(),
                "price": props[1],
                "type": props[2]
            }
            itemCount += 1

    with open(dataPath, 'w') as f:
        json.dump(existingData, f)

def import_fish():
    fishPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\fish.json'
    itemPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\item.json'
    fishData = None
    itemData = None

    with open(itemPath) as f:
        itemData = json.load(f)
    with open(fishPath) as f:
        fishData = json.load(f)

    with open('./tools/fish_add.txt') as f:
        for line in f:
            props = line.rstrip().split('|')
            fishData[props[0].lower()] = {
                "id": itemData[props[0].lower()]["id"],
                "name": props[0].lower(),
                "env": props[1],
                "when": props[3],
                "size": props[2],
                "jan": props[4],
                "feb": props[5],
                "mar": props[6],
                "apr": props[7],
                "may": props[8],
                "jun": props[9],
                "jul": props[10],
                "aug": props[11],
                "sep": props[12],
                "oct": props[13],
                "nov": props[14],
                "dec": props[15]
            }

    with open(fishPath, 'w') as f:
        json.dump(fishData, f)

def import_bugs():
    bugsPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\bug.json'
    itemPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\item.json'
    bugsData = None
    itemData = None
    itemCount = 0

    with open(bugsPath) as f:
        bugsData = json.load(f)
    with open(itemPath) as f:
        itemData = json.load(f)
    itemCount = len(itemData)

    with open('./tools/bugs_add.txt') as f:
        for line in f:
            props = line.rstrip().split('|')
            itemData[props[0].lower()] = {
                "id": itemCount,
                "name": props[0].lower(),
                "price": props[2],
                "type": "bug"
            }
            bugsData[props[0].lower()] = {
                "id": itemData[props[0].lower()]["id"],
                "name": props[0].lower(),
                "env": props[3],
                "when": props[4],
                "jan": props[5],
                "feb": props[6],
                "mar": props[7],
                "apr": props[8],
                "may": props[9],
                "jun": props[10],
                "jul": props[11],
                "aug": props[12],
                "sep": props[13],
                "oct": props[14],
                "nov": props[15],
                "dec": props[16]
            }
            itemCount += 1

    with open(itemPath, 'w') as f:
        json.dump(itemData, f)
    with open(bugsPath, 'w') as f:
        json.dump(bugsData, f)

def import_crafting():
    crafPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\crafting.json'
    itemPath = 'C:\\Users\\shrot\\Documents\\CodeProjects\\AC_Bot\\data\\item.json'
    crafData = None
    itemData = None
    itemCount = 0

    with open(crafPath) as f:
        crafData = json.load(f)
    with open(itemPath) as f:
        itemData = json.load(f)
    itemCount = len(itemData)

    with open('./tools/crafting_add.txt') as f:
        for line in f:
            props = line.rstrip().split('|')
            itemData[props[0].lower()] = {
                "id": itemCount,
                "name": props[0].lower(),
                "price": props[3],
                "type": "crafting"
            }
            crafData[props[0].lower()] = {
                "id": itemData[props[0].lower()]["id"],
                "name": props[0].lower(),
                "acquire":props[2]
            }
            itemCount += 1

    with open(itemPath, 'w') as f:
        json.dump(itemData, f)
    with open(crafPath, 'w') as f:
        json.dump(crafData, f)

import_crafting()
#import_items()
#import_fish()
#mport_bugs()


from config.MongoDBClient import MongoDBClient
import json
import urllib.parse
import pandas as pd
from pandas.io.json import json_normalize
from bson import json_util

class MongoDBConnector(object):
    def __init__(self):
        self.db = MongoDBClient().db
        self.collection = "web_event"

        self.query = {"date": "2018-08-31", "e": "pageview"}
        self.projection = {"_id": 0, "kv.id": 1}

    def CursorFind(self):
        cnx = self.db[self.collection]
        cursor = cnx.find(self.query, self.projection)
        return cursor

class DataWasher(object):
    def __init__(self, cursor):
        self.cursor = cursor

    def mongoFlatten(self):
        sanitized = json.loads(json_util.dumps(self.cursor))
        normalized = json_normalize(sanitized)
        df = pd.DataFrame(normalized)
        return df

def main():
    f = MongoDBConnector()
    cursor = f.CursorFind()
    df = DataWasher(cursor).mongoFlatten()
    print(df)

if __name__ == "__main__":
    main()


import os
from utils import yaml_stream
from sqlalchemy import Table

def importyaml(connection, metadata, source_path):
    eveGraphics = Table('eveGraphics',metadata)

    print("Importing Graphics")
    trans = connection.begin()

    with open(
        os.path.join(source_path, 'fsd', 'graphicIDs.yaml'), 'r'
    ) as yamlstream:
        for graphic in yaml_stream.read_by_any(yamlstream):
            for graphic_id, graphic_details in graphic.items():
                connection.execute(
                    eveGraphics.insert(),
                    graphicID=graphic_id,
                    sofFactionName=graphic_details.get('sofFactionName', ''),
                    graphicFile=graphic_details.get('graphicFile', ''),
                    sofHullName=graphic_details.get('sofHullName', ''),
                    sofRaceName=graphic_details.get('sofRaceName', ''),
                    description=graphic_details.get('description', '')
                )
    trans.commit()