<commit_before>#!/usr/bin/python

# PlistToProfile.py
# Simple utility to assist with creating Custom Settings Configuration Profiles
# from plist files and Directory Services nodes

import sys
import os
import optparse
import subprocess
from uuid import uuid4
from Foundation import NSDate
import FoundationPlist

class PayloadDict:
    """Class to represent the complete plist contents of a Configuration Profile (.mobileconfig) file"""
    def __init__(self, identifier, removal_allowed, organization):
        self.data = {}
        self.data['PayloadVersion'] = 1
        self.data['PayloadOrganization'] = organization
        self.data['PayloadUUID'] = makeNewUUID()
        if removal_allowed == 'Always':
            self.data['PayloadRemovalDisallowed'] = False
        elif removal_allowed == 'Never':
            self.data['PayloadRemovalDisallowed'] = True
        self.data['PayloadType'] = 'Configuration'
        self.data['PayloadScope'] = 'System'
        self.data['PayloadDescription'] = "Included custom settings:\n"
        self.data['PayloadDisplayName'] = "PlistToProfile: "
        self.data['PayloadIdentifier'] = identifier

        # An empty list for 'sub payloads' that we'll fill later
        self.data['PayloadContent'] = []

    def addPayload(self, plist_dict, domain, manage):
        """Add one plist dict contents to the profile's payloads. 'domain' is the preferences domain (ie. com.apple.finder),
and 'manage' is one of 'Once', 'Often' or 'Always'.
        """
        payload_dict = {}
        # Boilerplate
        payload_dict['PayloadVersion'] = 1
        payload_dict['PayloadUUID'] = makeNewUUID()
        payload_dict['PayloadEnabled'] = True
        payload_dict['PayloadDisplayName'] = "Settings for %s" % domain
        payload_dict['PayloadType'] = 'com.apple.ManagedClient.preferences'
        payload_dict['PayloadIdentifier'] = "%s.%s.alacarte.customsettings.%s" % (
                                            'PlistToProfile', self.data['PayloadUUID'], payload_dict['PayloadUUID'])

        # Update the top-level descriptive info
        self.data['PayloadDescription'] += "%s\n" % domain
        self.data['PayloadDisplayName'] += "%s, " % domain

        # Frequency to apply settings, or 'state'
        if manage == 'Always':
            state = 'Forced'
        else:
            state = 'Set-Once'

        # Yet another nested dict for the actual contents
        payload_dict['PayloadContent'] = {}
        payload_dict['PayloadContent'][domain] = {}
        payload_dict['PayloadContent'][domain][state] = []
        payload_dict['PayloadContent'][domain][state].append({})
        payload_dict['PayloadContent'][domain][state][0]['mcx_preference_settings'] = plist_dict
        # Add a datestamp if we're managing 'Once'
        if manage == 'Once':
            now = NSDate.new()
            payload_dict['PayloadContent'][domain][state][0]['mcx_data_timestamp'] = now
        self.data['PayloadContent'].append(payload_dict)

    def addMCXPayload(self, mcxdata):
        """Add MCX data to the profile's payloads.
        """
        domains = mcxdata.keys()
        if len(domains) == 1:
            domain = domains[0]
        else:
            domain = 'multiple preference domains'
        payload_dict = {}
        # Boilerplate
        payload_dict['PayloadVersion'] = 1
        payload_dict['PayloadUUID'] = makeNewUUID()
        payload_dict['PayloadEnabled'] = True
        payload_dict['PayloadDisplayName'] = "Settings for %s" % domain
        payload_dict['PayloadType'] = 'com.apple.ManagedClient.preferences'
        payload_dict['PayloadIdentifier'] = "%s.%s.alacarte.customsettings.%s" % (
                                            'MCXToProfile', self.data['PayloadUUID'], payload_dict['PayloadUUID'])
        # Yet another nested dict for the actual contents
        payload_dict['PayloadContent'] = mcxdata

        # Update the top-level descriptive info
        self.data['PayloadDescription'] += '/n'.join(domains)
        self.data['PayloadDisplayName'] += domain
        # add nested payload to top-level payload
        self.data['PayloadContent'].append(payload_dict)

def makeNewUUID():
    return str(uuid4())

def errorAndExit(errmsg):
    print >> sys.stderr, errmsg
    exit(-1)

def getDomainFromPlist(plist_path_or_name):
    """Assuming the domain is also the name of the plist file, strip the path and the ending '.plist'"""
    return os.path.basename(plist_path_or_name).split('.plist')[0]

def getMCXData(ds_object):
    '''Returns a dictionary representation of dsAttrTypeStandard:MCXSettings
    from the given DirectoryServices object'''
    ds_object_parts = ds_object.split('/')
    ds_node = '/'.join(ds_object_parts[0:3])
    ds_object_path = '/' + '/'.join(ds_object_parts[3:])
    cmd = ['/usr/bin/dscl', '-plist', ds_node, 'read', ds_object_path,
           'dsAttrTypeStandard:MCXSettings']
    proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    (pliststr, err) = proc.communicate()
    if proc.returncode:
        errorAndExit("dscl error: %s" % err)
    # decode plist string returned by dscl
    try:
        mcx_dict = FoundationPlist.readPlistFromString(pliststr)
    except FoundationPlist.FoundationPlistException:
        errorAndExit(
            "Could not decode plist data from dscl:\n" % pliststr)
    # mcx_settings is a plist encoded inside the plist!
    try:
        mcx_data_plist = mcx_dict['dsAttrTypeStandard:MCXSettings'][0]
    except KeyError:
        errorAndExit("No mcx_settings in %s:\n%s" % (ds_object, pliststr))
    except IndexError:
        errorAndExit(
            "Unexpected mcx_settings format in %s:\n%s" % (ds_object, pliststr))
    # decode the embedded plist
    mcx_data = FoundationPlist.readPlistFromString(str(mcx_data_plist))
    return mcx_data['mcx_application_data']

def main():
    parser = optparse.OptionParser()
    parser.set_usage(
        """usage: %prog [--dsobject DSOBJECT | --plist PLIST] --identifier IDENTIFIER [options]
       One of '--dsobject' or '--plist' must be specified.""")

    # Required options
    parser.add_option('--dsobject', '-d', metavar='DSOBJECT',
        help="""Directory Services object from which to convert MCX data.
Examples: /Local/Default/Computers/foo
          /LDAPv3/some_ldap_server/ComputerGroups/bar""")
    parser.add_option('--plist', '-p', action="append", metavar='PLIST_FILE',
        help="""Path to a plist to be added as a profile payload.
Can be specified multiple times.""")
    parser.add_option('--identifier', '-i',
        action="store",
        help="""Top-level payload identifier. This is used to uniquely identify a profile.
A profile can be removed using this identifier using the 'profiles' command and the '-R -p' options.""")

    # Optionals
    parser.add_option('--removal-allowed', '-r',
        action="store",
        default="Never",
        help="""Specifies when the profile can be removed. Currently supported options are 'Never' and 'Always',
and defaults to 'Never'""")
    parser.add_option('--organization', '-g',
        action="store",
        default="",
        help="Cosmetic name for the organization deploying the profile.")
    parser.add_option('--output', '-o',
        action="store",
        metavar='PATH',
        help="Output path for profile. Defaults to 'identifier.mobileconfig' in the current working directory.")

    # Plist-specific
    plist_options = optparse.OptionGroup(parser,
        title="Plist-specific options",
        description="""These options are useful only in conjunction with --plist.
If multiple plists are supplied, they are applied to all, not on a
per-plist basis.""")

    parser.add_option_group(plist_options)

    plist_options.add_option('--manage', '-m',
        action="store",
        help="Management frequency - Once, Often or Always. Defaults to Always.")

    options, args = parser.parse_args()

    if len(args):
        parser.print_usage()
        sys.exit(-1)

    if options.dsobject and options.plist:
        parser.print_usage()
        errorAndExit("Error: The '--dsobject' and '--plist' options are mutually exclusive.")

    if options.dsobject and options.manage:
        print options.manage
        parser.print_usage()
        errorAndExit("Error: The '--manage' option is used only in conjunction with '--plist'. DS Objects already contain this information.")

    if not options.identifier:
        parser.print_usage()
        errorAndExit("Error: An identifier must be specified.")

    if options.plist:
        if not options.manage:
            manage = 'Always'
        else:
            manage = options.manage

    if options.output:
        output_file = options.output
    else:
        output_file = os.path.join(os.getcwd(), options.identifier + '.mobileconfig')

    newPayload = PayloadDict(identifier=options.identifier,
        removal_allowed=options.removal_allowed,
        organization=options.organization)

    if options.plist:
        for plist_path in options.plist:
            source_data = FoundationPlist.readPlist(plist_path)
            source_domain = getDomainFromPlist(plist_path)
            newPayload.addPayload(source_data, source_domain, manage)
    if options.dsobject:
        mcx_data = getMCXData(options.dsobject)
        newPayload.addMCXPayload(mcx_data)

    FoundationPlist.writePlist(newPayload.data, output_file)

if __name__ == "__main__":
    main()
<commit_msg>--identifier already in usage statement, simplifying for now<commit_after>#!/usr/bin/python

# PlistToProfile.py
# Simple utility to assist with creating Custom Settings Configuration Profiles
# from plist files and Directory Services nodes

import sys
import os
import optparse
import subprocess
from uuid import uuid4
from Foundation import NSDate
import FoundationPlist

class PayloadDict:
    """Class to represent the complete plist contents of a Configuration Profile (.mobileconfig) file"""
    def __init__(self, identifier, removal_allowed, organization):
        self.data = {}
        self.data['PayloadVersion'] = 1
        self.data['PayloadOrganization'] = organization
        self.data['PayloadUUID'] = makeNewUUID()
        if removal_allowed == 'Always':
            self.data['PayloadRemovalDisallowed'] = False
        elif removal_allowed == 'Never':
            self.data['PayloadRemovalDisallowed'] = True
        self.data['PayloadType'] = 'Configuration'
        self.data['PayloadScope'] = 'System'
        self.data['PayloadDescription'] = "Included custom settings:\n"
        self.data['PayloadDisplayName'] = "PlistToProfile: "
        self.data['PayloadIdentifier'] = identifier

        # An empty list for 'sub payloads' that we'll fill later
        self.data['PayloadContent'] = []

    def addPayload(self, plist_dict, domain, manage):
        """Add one plist dict contents to the profile's payloads. 'domain' is the preferences domain (ie. com.apple.finder),
and 'manage' is one of 'Once', 'Often' or 'Always'.
        """
        payload_dict = {}
        # Boilerplate
        payload_dict['PayloadVersion'] = 1
        payload_dict['PayloadUUID'] = makeNewUUID()
        payload_dict['PayloadEnabled'] = True
        payload_dict['PayloadDisplayName'] = "Settings for %s" % domain
        payload_dict['PayloadType'] = 'com.apple.ManagedClient.preferences'
        payload_dict['PayloadIdentifier'] = "%s.%s.alacarte.customsettings.%s" % (
                                            'PlistToProfile', self.data['PayloadUUID'], payload_dict['PayloadUUID'])

        # Update the top-level descriptive info
        self.data['PayloadDescription'] += "%s\n" % domain
        self.data['PayloadDisplayName'] += "%s, " % domain

        # Frequency to apply settings, or 'state'
        if manage == 'Always':
            state = 'Forced'
        else:
            state = 'Set-Once'

        # Yet another nested dict for the actual contents
        payload_dict['PayloadContent'] = {}
        payload_dict['PayloadContent'][domain] = {}
        payload_dict['PayloadContent'][domain][state] = []
        payload_dict['PayloadContent'][domain][state].append({})
        payload_dict['PayloadContent'][domain][state][0]['mcx_preference_settings'] = plist_dict
        # Add a datestamp if we're managing 'Once'
        if manage == 'Once':
            now = NSDate.new()
            payload_dict['PayloadContent'][domain][state][0]['mcx_data_timestamp'] = now
        self.data['PayloadContent'].append(payload_dict)

    def addMCXPayload(self, mcxdata):
        """Add MCX data to the profile's payloads.
        """
        domains = mcxdata.keys()
        if len(domains) == 1:
            domain = domains[0]
        else:
            domain = 'multiple preference domains'
        payload_dict = {}
        # Boilerplate
        payload_dict['PayloadVersion'] = 1
        payload_dict['PayloadUUID'] = makeNewUUID()
        payload_dict['PayloadEnabled'] = True
        payload_dict['PayloadDisplayName'] = "Settings for %s" % domain
        payload_dict['PayloadType'] = 'com.apple.ManagedClient.preferences'
        payload_dict['PayloadIdentifier'] = "%s.%s.alacarte.customsettings.%s" % (
                                            'MCXToProfile', self.data['PayloadUUID'], payload_dict['PayloadUUID'])
        # Yet another nested dict for the actual contents
        payload_dict['PayloadContent'] = mcxdata

        # Update the top-level descriptive info
        self.data['PayloadDescription'] += '/n'.join(domains)
        self.data['PayloadDisplayName'] += domain
        # add nested payload to top-level payload
        self.data['PayloadContent'].append(payload_dict)

def makeNewUUID():
    return str(uuid4())

def errorAndExit(errmsg):
    print >> sys.stderr, errmsg
    exit(-1)

def getDomainFromPlist(plist_path_or_name):
    """Assuming the domain is also the name of the plist file, strip the path and the ending '.plist'"""
    return os.path.basename(plist_path_or_name).split('.plist')[0]

def getMCXData(ds_object):
    '''Returns a dictionary representation of dsAttrTypeStandard:MCXSettings
    from the given DirectoryServices object'''
    ds_object_parts = ds_object.split('/')
    ds_node = '/'.join(ds_object_parts[0:3])
    ds_object_path = '/' + '/'.join(ds_object_parts[3:])
    cmd = ['/usr/bin/dscl', '-plist', ds_node, 'read', ds_object_path,
           'dsAttrTypeStandard:MCXSettings']
    proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    (pliststr, err) = proc.communicate()
    if proc.returncode:
        errorAndExit("dscl error: %s" % err)
    # decode plist string returned by dscl
    try:
        mcx_dict = FoundationPlist.readPlistFromString(pliststr)
    except FoundationPlist.FoundationPlistException:
        errorAndExit(
            "Could not decode plist data from dscl:\n" % pliststr)
    # mcx_settings is a plist encoded inside the plist!
    try:
        mcx_data_plist = mcx_dict['dsAttrTypeStandard:MCXSettings'][0]
    except KeyError:
        errorAndExit("No mcx_settings in %s:\n%s" % (ds_object, pliststr))
    except IndexError:
        errorAndExit(
            "Unexpected mcx_settings format in %s:\n%s" % (ds_object, pliststr))
    # decode the embedded plist
    mcx_data = FoundationPlist.readPlistFromString(str(mcx_data_plist))
    return mcx_data['mcx_application_data']

def main():
    parser = optparse.OptionParser()
    parser.set_usage(
        """usage: %prog [--dsobject DSOBJECT | --plist PLIST] --identifier IDENTIFIER [options]
       One of '--dsobject' or '--plist' must be specified.""")

    # Required options
    parser.add_option('--dsobject', '-d', metavar='DSOBJECT',
        help="""Directory Services object from which to convert MCX data.
Examples: /Local/Default/Computers/foo
          /LDAPv3/some_ldap_server/ComputerGroups/bar""")
    parser.add_option('--plist', '-p', action="append", metavar='PLIST_FILE',
        help="""Path to a plist to be added as a profile payload.
Can be specified multiple times.""")
    parser.add_option('--identifier', '-i',
        action="store",
        help="""Top-level payload identifier. This is used to uniquely identify a profile.
A profile can be removed using this identifier using the 'profiles' command and the '-R -p' options.""")

    # Optionals
    parser.add_option('--removal-allowed', '-r',
        action="store",
        default="Never",
        help="""Specifies when the profile can be removed. Currently supported options are 'Never' and 'Always',
and defaults to 'Never'""")
    parser.add_option('--organization', '-g',
        action="store",
        default="",
        help="Cosmetic name for the organization deploying the profile.")
    parser.add_option('--output', '-o',
        action="store",
        metavar='PATH',
        help="Output path for profile. Defaults to 'identifier.mobileconfig' in the current working directory.")

    # Plist-specific
    plist_options = optparse.OptionGroup(parser,
        title="Plist-specific options",
        description="""These options are useful only in conjunction with --plist.
If multiple plists are supplied, they are applied to all, not on a
per-plist basis.""")

    parser.add_option_group(plist_options)

    plist_options.add_option('--manage', '-m',
        action="store",
        help="Management frequency - Once, Often or Always. Defaults to Always.")

    options, args = parser.parse_args()

    if len(args):
        parser.print_usage()
        sys.exit(-1)

    if options.dsobject and options.plist:
        parser.print_usage()
        errorAndExit("Error: The '--dsobject' and '--plist' options are mutually exclusive.")

    if options.dsobject and options.manage:
        print options.manage
        parser.print_usage()
        errorAndExit("Error: The '--manage' option is used only in conjunction with '--plist'. DS Objects already contain this information.")

    if not options.identifier:
        parser.print_usage()
        sys.exit(-1)

    if options.plist:
        if not options.manage:
            manage = 'Always'
        else:
            manage = options.manage

    if options.output:
        output_file = options.output
    else:
        output_file = os.path.join(os.getcwd(), options.identifier + '.mobileconfig')

    newPayload = PayloadDict(identifier=options.identifier,
        removal_allowed=options.removal_allowed,
        organization=options.organization)

    if options.plist:
        for plist_path in options.plist:
            source_data = FoundationPlist.readPlist(plist_path)
            source_domain = getDomainFromPlist(plist_path)
            newPayload.addPayload(source_data, source_domain, manage)
    if options.dsobject:
        mcx_data = getMCXData(options.dsobject)
        newPayload.addMCXPayload(mcx_data)

    FoundationPlist.writePlist(newPayload.data, output_file)

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before>import molecules
import numpy as np

class Logger(object):

    def __init__(self):
        self.__temp_data=[] # Array (length = time) of dictionary(keys = states):

    def add_step(self,x):
        self.__temp_data.append(dict(x))

    def output(self):

        def get_count(x):
            if isinstance(x,list):
                return len(x)
            else:
                try:
                    return x.count
                except:
                    return None

        def set_attributes(element,x,t):
            try:
                element['mass']=x.mass
            except:
                element['mass']=None
            try:
                element['sequence']=x.sequence
            except:
                element['sequence']=None
            try:
                element['timecourse'][t]=get_count(x)
            except:
                element['timecourse'][t]=None

        set_of_keys=self.__temp_data[99].keys()

        temp = {'mass': None,
                'sequence': None,
                'timecourse': np.zeros(100)}

        result = {}
        for i in set_of_keys:
            #print i
            result[i]=temp.copy()

        #print self.__temp_data
        for t in xrange(100):
            for y in set_of_keys :
                set_attributes(result[y],self.__temp_data[99][y],99)
                #result[y]=element

            #     #continue
            #     #prufen, ob Objekt Eigenschaft masse besitzt.
            #     #dann mass=masse von Objekt
            #     #ansonsten continue
        return result

<commit_msg>rewrte logger.py<commit_after>import molecules
import numpy as np

class Logger(object):

    def __init__(self):
        self.__temp_data=[] # Array (length = time) of dictionary(keys = states):

    def add_step(self,x):
        self.__temp_data.append(dict(x))

    def output(self):

        result = {}
        set_of_keys=set()

        def get_keys():
            for i in self.__temp_data:
                #sprint i.keys()
                for key in i.keys():
                    set_of_keys.add(key)

        def init_output():
            temp = {'mass': None,
                    'sequence': None,
                    'timecourse': np.zeros(100)}

            for i in set_of_keys:
                result[i]=temp.copy()

        def get_count(x):
            if isinstance(x,list):
                return len(x)
            else:
                try:
                    return x.count
                except:
                    return None

        def set_attributes(element,x,t):
            try:
                element['mass']=x.mass
            except:
                element['mass']=None
            try:
                element['sequence']=x.sequence
            except:
                element['sequence']=None
            try:
                element['timecourse'][t]=get_count(x)
            except:
                element['timecourse'][t]=None

        init_output() # Ausgabe vorbereiten
        get_keys()
        #print set_of_keys

        #print self.__temp_data
        # for t in xrange(100):
        #     for y in set_of_keys :
        #         set_attributes(result[y],self.__temp_data[99][y],99)

        return result

<|endoftext|>


<commit_before>from ofxstatement.plugin import Plugin
from ofxstatement.parser import CsvStatementParser
from ofxstatement.statement import StatementLine

class FrankfurterSparkasse1822Plugin(Plugin):
    def get_parser(self, filename):
        encoding = self.settings.get('charset', 'iso-8859-1')
        f = open(filename, 'r', encoding=encoding)
        parser = FrankfurterSparkasse1822Parser(f)
        parser.statement.account_id = self.settings['account']
        parser.statement.bank_id = self.settings.get('bank', '50050201')
        parser.statement.currency = self.settings.get('currency', 'EUR')
        return parser

class FrankfurterSparkasse1822Parser(CsvStatementParser):
    """
    This plugin tries to parse the provided CSV data into the same
    format, as the discontinued OFX export
    """
    date_format = "%d.%m.%Y"

    def parse_float(self, f):
	# convert a number in german localization (e.g. 1.234,56) into a float
        return float(f.replace('.','').replace(',','.'))

    def parse_record(self, line):
        # FIXME: add header validation
        #print(self.cur_record, line)
        if self.cur_record < 2:
            return None
        if len(line) < 3:
            """e.g.: ['# 1 vorgemerkte Umsätze nicht angezeigt']"""
            return None
        if not line[2]:
            return None
        sl = StatementLine()
        sl.id = line[1]
        sl.date = self.parse_datetime(line[2])
        sl.amount = self.parse_float(line[4])
        sl.trntype = 'DEBIT' if sl.amount < 0 else 'CREDIT'
        sl.payee = line[7]
        sl.memo = "(%s/%s): %s"  % (line[8],line[9], " ".join(line[15:]).strip())

        return sl

<commit_msg>refactor importer<commit_after>import csv

from ofxstatement.plugin import Plugin
from ofxstatement.parser import CsvStatementParser
from ofxstatement.statement import StatementLine

class FrankfurterSparkasse1822Plugin(Plugin):
    def get_parser(self, filename):
        encoding = self.settings.get('charset', 'iso-8859-1')
        f = open(filename, 'r', encoding=encoding)
        parser = FrankfurterSparkasse1822Parser(f)
        parser.statement.account_id = self.settings['account']
        parser.statement.bank_id = self.settings.get('bank', '50050201')
        parser.statement.currency = self.settings.get('currency', 'EUR')
        return parser

class FrankfurterSparkasse1822Parser(CsvStatementParser):
    """
    This plugin tries to parse the provided CSV data into the same
    format, as the discontinued OFX export
    """
    date_format = "%d.%m.%Y"

    def split_records(self):
        return csv.reader(self.fin)

    def parse_float(self, f):
	# convert a number in german localization (e.g. 1.234,56) into a float
        return float(f.replace('.','').replace(',','.'))

    def parse_record(self, line):
        # FIXME: add header validation
        #print(self.cur_record, line)
        if self.cur_record < 2:
            return None
        if len(line) < 3:
            """e.g.: ['# 1 vorgemerkte Umsätze nicht angezeigt']"""
            return None
        if not line[2]:
            return None
        sl = StatementLine()
        sl.id = line[1]
        sl.date = self.parse_datetime(line[2])
        sl.amount = self.parse_float(line[4])
        sl.trntype = 'DEBIT' if sl.amount < 0 else 'CREDIT'
        sl.payee = line[7]
        sl.memo = "(%s/%s): %s"  % (line[8],line[9], " ".join(line[15:]).strip())

        return sl

<|endoftext|>


<commit_before>#!/usr/bin/env python3

#
## Overview
#
# This short Python example illustrates how to build a simple extension to the Zabbix agent to monitor
# Pure Storage FlashArrays. The Pure Storage Python REST Client is used to query the FlashArray basic performance
# counters. The typical sampling mechanism of Zabbix tends to acquire a single counter at time and this
# somewhat discords with the queries that can be executed through the Python REST Client which
# usualy gather multiple counters from a single request. Therefore, in order to avoid multiple call to the
# same method to get different counters the script optimizes the number of calls by using a dedicated SQLite
# database to store the results of a single query and limits the sample rate to the minimum interval of 60 seconds.
#
## Installation
#
# The script should be copied to a convenient folder location on the machine hosting the Zabbix agent meant to monitor
# also the FlashArray, for example the /usr/local/bin folder.
# Change the execution rights of the program to allow the execution to 'all' (usually chmod 0755).
# Create a file named userparameter_pure.conf in the /etc/zabbix/zabbix_agentd.d/ folder. The file should
# contain just the following line
#
# `UserParameter=pureFA.fainfo[*],/usr/local/bin/pure-FA.py $1 $2 $3 $4`
#
# Restart the Zabbix agent
# Add a template to the Zabbix server configuration to model FlashArrays and populate the template with one application
# containing the seven item representing the monitored counters: 'input_per_sec', 'output_per_sec', 'queue_depth', 'reads_per_sec',
# 'writes_per_sec', 'usec_per_read_op' and 'usec_per_write_op'.
# Each single item should have a Key specified like the following
#
# pureFA.fainfo[{$ENDPOINT},{$APITOKEN},{$CACHE}, *counter_name*]
#
# where *counter_name* is one of above mentioned counters.
# Add to the template the graphs you may want to draw combininig the specified Items. The items can be used
# to define Triggers as well.
# Add each single FlashArray to the monitored hosts of the Zabbix server
# Define the macros to be associated to the key variables {$ENDPOINT},{$APITOKEN} and{$CACHE}. ENDPOINT is
# the hostname or the IP address of the Pure FlashArray, APITOKEN is the authentication token for that FlashArray
# and CACHE is the local path of the SQLite database to store the temporary sampled counters.
#
#
## Dependencies
#
#  purestorage       Pure Storage Python REST Client (https://github.com/purestorage/rest-client)
#  posix_ipc
#

import argparse
import sys
import json
import purestorage
import urllib3
import sqlite3
import posix_ipc
from dateutil.parser import parse
from datetime import datetime, timedelta
from time import sleep

# Global variables
SEM_NAME = '/pure_sem_01'
MIN_INTERVAL = 60
TIMEOUT = 600

def getFAinfo(flash_array, apitoken):
    # Retrieves the basic statistics of the given flash_array
    urllib3.disable_warnings()
    fa = purestorage.FlashArray(flash_array, api_token=apitoken)
    fainfo = fa.get(action='monitor')
    fa.invalidate_cookie()
    return(fainfo)

parser = argparse.ArgumentParser(description="Retrieves basic FA info")
parser.add_argument("endpoint", help="FA hostname or ip address")
parser.add_argument("apitoken", help="FA api_token")
parser.add_argument("cache", help="SQLite cache database")
parser.add_argument("kpi", choices=['input_per_sec',
                                    'output_per_sec',
                                    'queue_depth',
                                    'reads_per_sec',
                                    'writes_per_sec',
                                    'usec_per_read_op',
                                    'usec_per_write_op'])
args = parser.parse_args()

conn = sqlite3.connect(args.cache, isolation_level=None)

#  Get the most recent sampled data from db
c = conn.cursor()
c.execute("SELECT * FROM fainfo WHERE endpoint=?", (args.endpoint,))
row =  c.fetchone()
fa_info = [{}];

if row is None:
    # table fainfo not initialized with this flasharray
    dt1 = datetime.min
else:
    dt1 = parse(row[8])
    fa_info[0]['input_per_sec'] = row[1]
    fa_info[0]['output_per_sec'] = row[2]
    fa_info[0]['queue_depth'] = row[3]
    fa_info[0]['reads_per_sec'] = row[4]
    fa_info[0]['writes_per_sec'] = row[5]
    fa_info[0]['usec_per_read_op'] = row[6]
    fa_info[0]['usec_per_write_op'] = row[7]
    fa_info[0]['time'] = row[8]

# Check if last sample is too old.
dt2 = datetime.now(dt1.tzinfo)
d = dt2 - dt1

if (d.total_seconds() > MIN_INTERVAL):
    # Last
    sem = posix_ipc.Semaphore(SEM_NAME, posix_ipc.O_CREAT, initial_value = 1)
    if (d.total_seconds() > TIMEOUT):
        sem.release()
        sem.unlink()
        sem = posix_ipc.Semaphore(SEM_NAME, posix_ipc.O_CREAT, initial_value = 1)

    try:
        # Attempt to enter critical section. This is necessary in order to have a single writer
		# accessing the sqlite database at time
        sem.acquire(0)
		# Get basic statistics from FlashArray
        fa_info = getFAinfo(args.endpoint, args.apitoken)

        if row is None:
		   # No entry for this FlashArrayA. Prepare the statement to add the record for this FlashArray
           sql = ''' INSERT INTO fainfo(
                          in_per_sec,
                          out_per_sec,
                          q_depth,
                          rd_per_sec,
                          wr_per_sec,
                          rd_latency,
                          wr_latency,
                          time,
                          endpoint)
                     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)'''
        else:
		    # Prepare the statement to update  the record for this FlashArray.
            sql = ''' UPDATE fainfo
                      SET in_per_sec = ? ,
                          out_per_sec = ? ,
                          q_depth = ? ,
                          rd_per_sec = ? ,
                          wr_per_sec = ? ,
                          rd_latency = ? ,
                          wr_latency = ? ,
                          time = ?
                      WHERE endpoint = ?'''

		# Execute the SQL query
        c.execute(sql, (fa_info[0]['input_per_sec'],
                        fa_info[0]['output_per_sec'],
                        fa_info[0]['queue_depth'],
                        fa_info[0]['reads_per_sec'],
                        fa_info[0]['writes_per_sec'],
                        fa_info[0]['usec_per_read_op'],
                        fa_info[0]['usec_per_write_op'],
                        fa_info[0]['time'],
                        args.endpoint))
        sem.release()
    except posix_ipc.BusyError:
        pass

# Print to standard outout, This returns the value to the Zabbix agent
print(fa_info[0][args.kpi])
conn.close()
sys.exit(0)
<commit_msg>Delete Pure-FA_zabbix.py<commit_after><|endoftext|>


<commit_before><commit_msg>sql_em_estoque eliminando tipo 'sp' e corrigindo get 'ref'<commit_after><|endoftext|>


<commit_before>"""Database connector.
For a plugin to access the database an API is provided.
Plugins receive a DBAPI instance with an interface for common actions
Parameters of connection to the database are set in DBAPIConfiguration
"""

import sqlite3 as mdb
from enum import Enum
import logging
import gc
from multiprocessing import Process, Queue, Pool
from functools import partial

class DBAPIconfiguration(object):
    """ Configuration class for DBAPI.

    Configuration is set through respective setters and read through getters.

    Attributes:
        dbname (str): Sqlite3 database file to use
    """

    def __init__(self):
        """Default constructor.
        """

        self.dbname = ""
        self.limit = 0

    def getDbname(self):
        """ Database name getter.
        """

        return self.dbname

    def setDbname(self, dbname):
        """Database name setter.

        Args:
            dbname: database name where data are stored
        """

        self.dbname = dbname

    def getLimit(self):
        return self.limit

    def setLimit(self, limit):
        self.limit = limit

class VerificationStatus(Enum):

    requested = "REQUESTED"
    done_ok = "DONE - OK"
    done_ko = "DONE - KO"
    done_ignored = "DONE - IGNORED"

class Query(Enum):

    transactions = 1
    link = 2
    defect = 5
    defect_types = 3
    aliases = 4
    cookies = 6
    transactions_load = 7
    transactions_status = 8
    link_status = 0

class TableError(LookupError):

    pass

class DBAPI(object):
    """ API for access to underlying database.
        Connection to the database is initiated in constructor and closed in
        destructor.
    """
    def __init__(self, conf):
        self.conf = conf
        self.limit = conf.getLimit()
        self.findingId = -1
        self.query_types = [Query.defect_types, Query.transactions, Query.transactions_load, Query.transactions_status, Query.aliases,  Query.link, Query.link_status, Query.defect, Query.cookies]
        self.queries = dict()
        self.queries[Query.link] = 'INSERT INTO link (findingId, toUri, requestId, responseId) VALUES (?,?,?,?)'
        self.queries[Query.defect_types] = 'INSERT INTO defectType (id, type, description) VALUES (?, ?, ?)'
        self.queries[Query.defect] = 'INSERT INTO defect (findingId, type, evidence, severity, responseId) VALUES (?, ?, ?, ?, ?)'
        self.queries[Query.cookies] = 'INSERT INTO cookies (findingId, name, value, responseId) VALUES (?, ?, ?, ?)'
        self.queries[Query.aliases] = 'INSERT INTO aliases (transactionId, uri) VALUES (?, ?)'
        self.queries[Query.transactions] = 'INSERT INTO transactions (id, method, uri, verificationStatus, depth) VALUES (?, ?, ?, ?, ?)'
        self.queries[Query.transactions_load] = 'UPDATE transactions SET verificationStatus = ?, uri = ?, contentType = ?, responseStatus = ? WHERE id = ?'
        self.queries[Query.transactions_status] = 'UPDATE transactions SET verificationStatus = ? WHERE id = ?'
        self.queries[Query.link_status] = 'UPDATE link SET processed = ? WHERE toUri = ?'
        self.logs = dict()
        for qtype in self.query_types:
            self.logs[qtype] = []
        self.defect_types = []
        self.defectId = -1
        self.defectTypesWithId = dict()
        self.bufferedQueries = 0

    def log(self, query, query_params):
        if query in self.logs:
            self.logs[query].append(query_params)
            self.bufferedQueries = self.bufferedQueries + 1
            if self.bufferedQueries > self.limit:
                self.sync()
                gc.collect()
        else:
            raise TableError()

    def log_link(self, parent_id, uri, new_id):
       self.findingId = self.findingId + 1
       self.log(Query.link, (str(self.findingId), uri, str(new_id), str(parent_id)))

    def log_defect(self, transactionId, name, additional, evidence, severity = 0.5):
        self.findingId = self.findingId + 1
        if name not in self.defect_types:
            self.defectId = self.defectId + 1
            self.log(Query.defect_types, (str(self.defectId), str(name), str(additional)))
            self.defect_types.append(name)
            self.defectTypesWithId[name] = self.defectId
        defId = self.defectTypesWithId[name]
        self.log(Query.defect, (str(self.findingId), str(defId), str(evidence), str(severity), str(transactionId)))

    def log_cookie(self, transactionId, name, value):
        self.findingId = self.findingId + 1
        self.log(Query.cookies, (str(self.findingId), str(name), str(value), str(transactionId)))

    def sync(self):
        logging.getLogger().info("Writing into database")
        with mdb.connect(self.conf.getDbname()) as con:
            try:
                cursor = con.cursor()

                for qtype in self.query_types:
                    cursor.executemany(self.queries[qtype], self.logs[qtype])

            except mdb.Error as e:
                self.error(e, con)

            else:
                for qtype in self.query_types:
                    self.logs[qtype] = []
                self.bufferedQueries = 0

    def error(self, e, con):
        con.rollback()
        log = logging.getLogger()
        log.error("SQL Error: "+str(e))

    def load_defect_types(self, con):
        query = 'SELECT type, id FROM defectType'
        cursor = con.cursor()
        cursor.execute(query)
        types = cursor.fetchall()
        for dt in types:
            if dt is not None:
                if dt[0] is not None:
                    self.defect_types.append(dt[0])
                    if dt[1] is not None:
                        self.defectTypesWithId[dt[0]] = dt[1]
        query = 'SELECT MAX(id) from defectType'
        cursor.execute(query)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                self.defectId = row[0]

    def load_finding_id(self, con):
        maxs = []
        for t in ['link', 'defect', 'cookies']:
            maxs.append(self.__load_max_finding_id(t, con))
        self.findingId =  max(maxs)

    def __load_max_finding_id(self, table, con):
        query = 'SELECT MAX(findingId) FROM %s' % (table)
        cursor = con.cursor()
        cursor.execute(query)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                return int(row[0])
        return 0

    def get_requested_transactions(self, con):
        q = 'CREATE TEMPORARY VIEW linkedUris AS SELECT link.toUri, transactions.id FROM link INNER JOIN transactions ON link.responseId = transactions.id'
        query = ('SELECT linkedUris.toUri AS uri, transactions.depth AS depth, linkedUris.id AS srcId, transactions.id AS idno'
                 ' FROM transactions LEFT JOIN linkedUris ON transactions.uri = linkedUris.toUri WHERE transactions.verificationStatus = ?')

        cursor = con.cursor()
        cursor.execute(q)
        cursor.execute(query, [str(VerificationStatus.requested)])
        data = cursor.fetchall()
        cursor.execute('DROP VIEW linkedUris')
        return data

    def get_seen_uris(self, con):
        query = 'SELECT uri FROM aliases'
        c = con.cursor()
        c.execute(query)
        return c.fetchall()

    def get_max_transaction_id(self, con):
        q = 'SELECT MAX(id) FROM transactions'
        cursor = con.cursor()
        cursor.execute(q)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                return row[0]
        return 0

    def get_urls(self):
        with mdb.connect(self.conf.getDbname()) as con:
            q = 'SELECT uri FROM transactions'
            c = con.cursor()
            c.execute(q)
            return [x[0] for x in c.fetchall()]

    def get_known_defect_types(self, con):
        q = 'SELECT type, description FROM defectType'
        c = con.cursor()
        c.execute(q)
        return c.fetchall()

    def create_report_payload(self):
        log = logging.getLogger(__name__)
        log.info("Creating report")
        qt = Queue()
        tproc = Process(target=DBAPI.__create_transactions, args=(self.conf.getDbname(), qt, 4))

        ql = Queue()
        lproc = Process(target=DBAPI.__create_links, args=(self.conf.getDbname(), ql))

        qd = Queue()
        dproc = Process(target=DBAPI.__create_defects, args=(self.conf.getDbname(), qd))

        log.debug("Starting report worker processes")
        tproc.start()
        lproc.start()
        dproc.start()

        log.debug("Getting data from workers")
        payload = dict()
        payload['defect'] = qd.get()
        log.info("Got defects")
        payload['link'] = ql.get()
        log.info("Got links")
        payload['transactions'] = qt.get()
        log.info("Got transactions")

        log.info("Joining")
        lproc.join()
        dproc.join()
        tproc.join()

        return payload

    @staticmethod
    def __create_transactions(dbname, queue, allowance):
        log = logging.getLogger(__name__)
        with mdb.connect(dbname) as con:
            transactions = []
            q = ('SELECT id, method, responseStatus, contentType, '
                 'verificationStatus, depth, uri FROM transactions')

            c = con.cursor()
            c.execute(q)
            for row in c.fetchall(): #type(row): tuple
                transaction = dict()
                transaction['id'] = row[0]
                transaction['method'] = row[1]
                transaction['responseStatus'] = row[2]
                transaction['contentType'] = row[3]
                transaction['verificationStatus'] = row[4]
                transaction['depth'] = row[5]
                transaction['uri'] = row[6]
                if row[5] == 0:
                    transaction['parentId'] = transaction['id']
                transactions.append(transaction)

            log.info("%s transactions, processing in pool of %s processes" % (str(len(transactions)), str(allowance)))

            with Pool(allowance) as pool:
                partial_process = partial(process_transaction, dbname=dbname)
                queue.put(pool.map(partial_process, transactions))

    @staticmethod
    def __create_links(dbname, queue):
        with mdb.connect(dbname) as con:
            c = con.cursor()
            links = []
            proc0 = 0
            total0 = 0
            good0 = 0
            q = ('SELECT link.findingId, transactions.uri, '
                 'transactions.verificationStatus, link.toUri, link.processed, '
                 'link.requestId, link.responseId '
                 'FROM link '
                 'INNER JOIN transactions ON link.requestId = transactions.id ')
            c.execute(q)
            for row in c.fetchall():
                link = dict()
                link['findingId'] = row[0]
                link['fromUri'] = row[1]
                link['good'] = (row[2] != 'VerificationStatus.done_ko')
                link['toUri'] = row[3]
                link['processed'] = row[4]
                link['requestId'] = row[5]
                link['responseId'] = row[6]
                links.append(link)
                if row[4]:
                    proc0 = proc0 + 1
                total0 = total0 + 1
                if link['good']:
                    good0 = good0 + 1

            if total0 == 0.0:
                perc0 = 0.0
            else:
                perc0 = proc0 / total0 * 100.0
            queue.put(links)

    @staticmethod
    def __create_defects(dbname, queue):
        with mdb.connect(dbname) as con:
            defects = []
            q = ('SELECT defect.findingId, defectType.type, '
                 'defectType.description, defect.evidence, defect.severity, '
                 'defect.responseId, transactions.uri FROM defect '
                 'INNER JOIN defectType ON defect.type = defectType.id '
                 'INNER JOIN transactions ON defect.responseId = transactions.id')
            c = con.cursor()
            c.execute(q)
            for row in c.fetchall():
                defect = dict()
                defect['findingId'] = row[0]
                defect['type'] = row[1]
                defect['description'] = row[2]
                defect['evidence'] = row[3]
                defect['severity'] = row[4]
                defect['responseId'] = row[5]
                defect['uri'] = row[6]
                defects.append(defect)
            queue.put(defects)

def process_transaction(t, dbname):
    with mdb.connect(dbname) as con:
        c = con.cursor()
        if t['depth'] > 0:
            q = ('SELECT link.responseId FROM link '
                 'WHERE link.requestId = ? '
                 'AND link.processed = "true" LIMIT 1')
            c.execute(q, [t['id']])
            try:
                t['parentId'] = c.fetchone()[0]
            except TypeError:
                t['parentId'] = -1
                logging.getLogger().error("No parent for link with requestId: %s (depth: %s)" % (str(t['id']), str(t['depth'])))

        q = ('SELECT uri FROM aliases WHERE transactionId = ?')
        c.execute(q, [t['id']])
        t['aliases'] = [row[0] for row in c.fetchall()]
        return t
<commit_msg>Configurable core count<commit_after>"""Database connector.
For a plugin to access the database an API is provided.
Plugins receive a DBAPI instance with an interface for common actions
Parameters of connection to the database are set in DBAPIConfiguration
"""

import sqlite3 as mdb
from enum import Enum
import logging
import gc
from multiprocessing import Process, Queue, Pool
from functools import partial

class DBAPIconfiguration(object):
    """ Configuration class for DBAPI.

    Configuration is set through respective setters and read through getters.

    Attributes:
        dbname (str): Sqlite3 database file to use
    """

    def __init__(self):
        """Default constructor.
        """

        self.dbname = ""
        self.limit = 0

    def getDbname(self):
        """ Database name getter.
        """

        return self.dbname

    def setDbname(self, dbname):
        """Database name setter.

        Args:
            dbname: database name where data are stored
        """

        self.dbname = dbname

    def getLimit(self):
        return self.limit

    def setLimit(self, limit):
        self.limit = limit

class VerificationStatus(Enum):

    requested = "REQUESTED"
    done_ok = "DONE - OK"
    done_ko = "DONE - KO"
    done_ignored = "DONE - IGNORED"

class Query(Enum):

    transactions = 1
    link = 2
    defect = 5
    defect_types = 3
    aliases = 4
    cookies = 6
    transactions_load = 7
    transactions_status = 8
    link_status = 0

class TableError(LookupError):

    pass

class DBAPI(object):
    """ API for access to underlying database.
        Connection to the database is initiated in constructor and closed in
        destructor.
    """
    def __init__(self, conf):
        self.conf = conf
        self.limit = conf.getLimit()
        self.findingId = -1
        self.query_types = [Query.defect_types, Query.transactions, Query.transactions_load, Query.transactions_status, Query.aliases,  Query.link, Query.link_status, Query.defect, Query.cookies]
        self.queries = dict()
        self.queries[Query.link] = 'INSERT INTO link (findingId, toUri, requestId, responseId) VALUES (?,?,?,?)'
        self.queries[Query.defect_types] = 'INSERT INTO defectType (id, type, description) VALUES (?, ?, ?)'
        self.queries[Query.defect] = 'INSERT INTO defect (findingId, type, evidence, severity, responseId) VALUES (?, ?, ?, ?, ?)'
        self.queries[Query.cookies] = 'INSERT INTO cookies (findingId, name, value, responseId) VALUES (?, ?, ?, ?)'
        self.queries[Query.aliases] = 'INSERT INTO aliases (transactionId, uri) VALUES (?, ?)'
        self.queries[Query.transactions] = 'INSERT INTO transactions (id, method, uri, verificationStatus, depth) VALUES (?, ?, ?, ?, ?)'
        self.queries[Query.transactions_load] = 'UPDATE transactions SET verificationStatus = ?, uri = ?, contentType = ?, responseStatus = ? WHERE id = ?'
        self.queries[Query.transactions_status] = 'UPDATE transactions SET verificationStatus = ? WHERE id = ?'
        self.queries[Query.link_status] = 'UPDATE link SET processed = ? WHERE toUri = ?'
        self.logs = dict()
        for qtype in self.query_types:
            self.logs[qtype] = []
        self.defect_types = []
        self.defectId = -1
        self.defectTypesWithId = dict()
        self.bufferedQueries = 0

    def log(self, query, query_params):
        if query in self.logs:
            self.logs[query].append(query_params)
            self.bufferedQueries = self.bufferedQueries + 1
            if self.bufferedQueries > self.limit:
                self.sync()
                gc.collect()
        else:
            raise TableError()

    def log_link(self, parent_id, uri, new_id):
       self.findingId = self.findingId + 1
       self.log(Query.link, (str(self.findingId), uri, str(new_id), str(parent_id)))

    def log_defect(self, transactionId, name, additional, evidence, severity = 0.5):
        self.findingId = self.findingId + 1
        if name not in self.defect_types:
            self.defectId = self.defectId + 1
            self.log(Query.defect_types, (str(self.defectId), str(name), str(additional)))
            self.defect_types.append(name)
            self.defectTypesWithId[name] = self.defectId
        defId = self.defectTypesWithId[name]
        self.log(Query.defect, (str(self.findingId), str(defId), str(evidence), str(severity), str(transactionId)))

    def log_cookie(self, transactionId, name, value):
        self.findingId = self.findingId + 1
        self.log(Query.cookies, (str(self.findingId), str(name), str(value), str(transactionId)))

    def sync(self):
        logging.getLogger().info("Writing into database")
        with mdb.connect(self.conf.getDbname()) as con:
            try:
                cursor = con.cursor()

                for qtype in self.query_types:
                    cursor.executemany(self.queries[qtype], self.logs[qtype])

            except mdb.Error as e:
                self.error(e, con)

            else:
                for qtype in self.query_types:
                    self.logs[qtype] = []
                self.bufferedQueries = 0

    def error(self, e, con):
        con.rollback()
        log = logging.getLogger()
        log.error("SQL Error: "+str(e))

    def load_defect_types(self, con):
        query = 'SELECT type, id FROM defectType'
        cursor = con.cursor()
        cursor.execute(query)
        types = cursor.fetchall()
        for dt in types:
            if dt is not None:
                if dt[0] is not None:
                    self.defect_types.append(dt[0])
                    if dt[1] is not None:
                        self.defectTypesWithId[dt[0]] = dt[1]
        query = 'SELECT MAX(id) from defectType'
        cursor.execute(query)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                self.defectId = row[0]

    def load_finding_id(self, con):
        maxs = []
        for t in ['link', 'defect', 'cookies']:
            maxs.append(self.__load_max_finding_id(t, con))
        self.findingId =  max(maxs)

    def __load_max_finding_id(self, table, con):
        query = 'SELECT MAX(findingId) FROM %s' % (table)
        cursor = con.cursor()
        cursor.execute(query)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                return int(row[0])
        return 0

    def get_requested_transactions(self, con):
        q = 'CREATE TEMPORARY VIEW linkedUris AS SELECT link.toUri, transactions.id FROM link INNER JOIN transactions ON link.responseId = transactions.id'
        query = ('SELECT linkedUris.toUri AS uri, transactions.depth AS depth, linkedUris.id AS srcId, transactions.id AS idno'
                 ' FROM transactions LEFT JOIN linkedUris ON transactions.uri = linkedUris.toUri WHERE transactions.verificationStatus = ?')

        cursor = con.cursor()
        cursor.execute(q)
        cursor.execute(query, [str(VerificationStatus.requested)])
        data = cursor.fetchall()
        cursor.execute('DROP VIEW linkedUris')
        return data

    def get_seen_uris(self, con):
        query = 'SELECT uri FROM aliases'
        c = con.cursor()
        c.execute(query)
        return c.fetchall()

    def get_max_transaction_id(self, con):
        q = 'SELECT MAX(id) FROM transactions'
        cursor = con.cursor()
        cursor.execute(q)
        row = cursor.fetchone()
        if row is not None:
            if row[0] is not None:
                return row[0]
        return 0

    def get_urls(self):
        with mdb.connect(self.conf.getDbname()) as con:
            q = 'SELECT uri FROM transactions'
            c = con.cursor()
            c.execute(q)
            return [x[0] for x in c.fetchall()]

    def get_known_defect_types(self, con):
        q = 'SELECT type, description FROM defectType'
        c = con.cursor()
        c.execute(q)
        return c.fetchall()

    def create_report_payload(self):
        log = logging.getLogger(__name__)
        log.info("Creating report")
        qt = Queue()
        tproc = Process(target=DBAPI.__create_transactions,
                        args=(self.conf.getDbname(), qt,
                              self.conf.getProperty("cores", 4))

        ql = Queue()
        lproc = Process(target=DBAPI.__create_links,
                        args=(self.conf.getDbname(), ql))

        qd = Queue()
        dproc = Process(target=DBAPI.__create_defects,
                        args=(self.conf.getDbname(), qd))

        log.debug("Starting report worker processes")
        tproc.start()
        lproc.start()
        dproc.start()

        log.debug("Getting data from workers")
        payload = dict()
        payload['defect'] = qd.get()
        log.info("Got defects")
        payload['link'] = ql.get()
        log.info("Got links")
        payload['transactions'] = qt.get()
        log.info("Got transactions")

        log.info("Joining")
        lproc.join()
        dproc.join()
        tproc.join()

        return payload

    @staticmethod
    def __create_transactions(dbname, queue, allowance):
        log = logging.getLogger(__name__)
        with mdb.connect(dbname) as con:
            transactions = []
            q = ('SELECT id, method, responseStatus, contentType, '
                 'verificationStatus, depth, uri FROM transactions')

            c = con.cursor()
            c.execute(q)
            for row in c.fetchall(): #type(row): tuple
                transaction = dict()
                transaction['id'] = row[0]
                transaction['method'] = row[1]
                transaction['responseStatus'] = row[2]
                transaction['contentType'] = row[3]
                transaction['verificationStatus'] = row[4]
                transaction['depth'] = row[5]
                transaction['uri'] = row[6]
                if row[5] == 0:
                    transaction['parentId'] = transaction['id']
                transactions.append(transaction)

            log.info("%s transactions, processing in pool of %s processes" % (str(len(transactions)), str(allowance)))

            with Pool(allowance) as pool:
                partial_process = partial(process_transaction, dbname=dbname)
                queue.put(pool.map(partial_process, transactions))

    @staticmethod
    def __create_links(dbname, queue):
        with mdb.connect(dbname) as con:
            c = con.cursor()
            links = []
            proc0 = 0
            total0 = 0
            good0 = 0
            q = ('SELECT link.findingId, transactions.uri, '
                 'transactions.verificationStatus, link.toUri, link.processed, '
                 'link.requestId, link.responseId '
                 'FROM link '
                 'INNER JOIN transactions ON link.requestId = transactions.id ')
            c.execute(q)
            for row in c.fetchall():
                link = dict()
                link['findingId'] = row[0]
                link['fromUri'] = row[1]
                link['good'] = (row[2] != 'VerificationStatus.done_ko')
                link['toUri'] = row[3]
                link['processed'] = row[4]
                link['requestId'] = row[5]
                link['responseId'] = row[6]
                links.append(link)
                if row[4]:
                    proc0 = proc0 + 1
                total0 = total0 + 1
                if link['good']:
                    good0 = good0 + 1

            if total0 == 0.0:
                perc0 = 0.0
            else:
                perc0 = proc0 / total0 * 100.0
            queue.put(links)

    @staticmethod
    def __create_defects(dbname, queue):
        with mdb.connect(dbname) as con:
            defects = []
            q = ('SELECT defect.findingId, defectType.type, '
                 'defectType.description, defect.evidence, defect.severity, '
                 'defect.responseId, transactions.uri FROM defect '
                 'INNER JOIN defectType ON defect.type = defectType.id '
                 'INNER JOIN transactions ON defect.responseId = transactions.id')
            c = con.cursor()
            c.execute(q)
            for row in c.fetchall():
                defect = dict()
                defect['findingId'] = row[0]
                defect['type'] = row[1]
                defect['description'] = row[2]
                defect['evidence'] = row[3]
                defect['severity'] = row[4]
                defect['responseId'] = row[5]
                defect['uri'] = row[6]
                defects.append(defect)
            queue.put(defects)

def process_transaction(t, dbname):
    with mdb.connect(dbname) as con:
        c = con.cursor()
        if t['depth'] > 0:
            q = ('SELECT link.responseId FROM link '
                 'WHERE link.requestId = ? '
                 'AND link.processed = "true" LIMIT 1')
            c.execute(q, [t['id']])
            try:
                t['parentId'] = c.fetchone()[0]
            except TypeError:
                t['parentId'] = -1
                logging.getLogger().error("No parent for link with requestId: %s (depth: %s)" % (str(t['id']), str(t['depth'])))

        q = ('SELECT uri FROM aliases WHERE transactionId = ?')
        c.execute(q, [t['id']])
        t['aliases'] = [row[0] for row in c.fetchall()]
        return t
<|endoftext|>


<commit_before>import json

import click

import click_utils

def process(**kwargs):
    ctx = click.get_current_context()

    # debug_ = ctx.params.get('debug') or ctx.parent.params.get('debug') if ctx.parent else False
    # if debug_:
    #     click_utils.echo_context(ctx)

    click_utils.inherit_parent_params(ctx, ('debug',))

    debug_ = ctx.params['debug']

    if debug_:
        click.echo('Debug mode: %s' % ('enabled' if debug_ else 'disabled'))
        click_utils.echo_context(ctx)
        click_utils.echo_kwargs(kwargs)

    subcommand = ctx.invoked_subcommand
    if subcommand == 'info':
        pass

@click.group(context_settings=click_utils.CONTEXT_SETTINGS, invoke_without_command=True)
@click.version_option(version='1.0.0')
@click.option('--debug/--silent', '-d/-s', 'debug', default=False)
# @click.option('--debug', '-d', 'debug', flag_value=True, default=True)
# @click.option('--silent', '-s', 'debug', flag_value=False)
def cli(debug):
    ctx = click.get_current_context()
    if debug:
        click_utils.echo_context(ctx)

    subcommand = ctx.invoked_subcommand
    # click.echo('Subcommand: {}'.format(subcommand))
    if subcommand is None:
        click.echo('I was invoked without a subcommand...')
    else:
        if debug:
            click.echo('I am about to invoke subcommand: %s.' % subcommand)

@cli.command()
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def echo(input, **kwargs):
    """
    Echo the (unparsed) input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        s = f.read()
        click.echo(s)

@cli.command(name='repr')
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def reprcommand(input, **kwargs):
    """
    Provides the python repr() representation of the parsed input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        data = json.load(f)
        s = repr(data)
        click.echo(s)

@cli.command()
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def info(input, **kwargs):
    """
    Provides info about the input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        data = json.load(f)
        d = {
            'type': type(data),
            'length': len(data),
            # 'repr': repr(data),
            'keys': data.keys()
        }
        # click.echo('type={}'.format(t))
        # click.echo('len={}'.format(len(data)))
        # click.echo('keys={}'.format(', '.join(data.keys())))
        click.echo(d)
        # click.echo('iter={}'.format(', '.join(iter(data))))
        # click.echo('dir={}'.format(dir(data)))
        # click.echo('repr={}'.format(repr(data)))

@cli.command(name='format')
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input."
                   " Or '-' to use stdin (e.g. piped input).")
@click.option('--compact', '-c', 'style', flag_value='compact',
              help='output format style that minimizes the output.'
                   ' overrides the indent and separator options.')
@click.option('--pretty', '-p', 'style', flag_value='pretty',
              help='output format style that generates human readable output.'
                   ' overrides the indent and separator options.')
@click.option('--flat', '-f', 'style', flag_value='flat',
              help='output format style that generates multi-line, non-indented output.'
                   ' overrides the indent and separator options.')
@click.option('--indent', type=click.IntRange(min=0),
              help='Default is None. Must be a non-negative integer.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--skip-keys', '--skip', '--ignore-key-errors', '-ike', 'skip_keys', type=click.BOOL)
@click.option('--sort-keys', '--sorted/--unsorted', '--sort', '-s', 'sort_keys', default=False,
              help='causes the keys of each element to be output in sorted order.')
@click.option('--ensure-ascii/--ensure-ascii-off', '-ea+/-ea-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--check-circular/--check-circular-ff', '-cc+/-cc-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--allow-nan/--allow-nan-off', '-nan+/-nan-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--item-separator', '-is', default=', ', help='the item separator')
@click.option('--dict-separator', '-ds', default=': ', help='the dictionary/element separator')
def formatcommand(input, style, indent, skip_keys, sort_keys, ensure_ascii, check_circular, allow_nan,
                  item_separator, dict_separator, **kwargs):
    """
    Formats the JSON input. See the docs of the json.dumps() function (in python's builtin json module) for details.
    """
    if style == 'compact':
        separators = (',', ':')
        indent = None
    elif style == 'pretty':
        # separators = (',', ':')
        separators = None
        indent = 2
    elif style == 'flat':
        separators = (',', ': ')
        indent = 0
    elif item_separator or dict_separator:
        if not item_separator:
            item_separator = ', '
        if not dict_separator:
            dict_separator = ': '
        separators = (item_separator, dict_separator)
    else:
        separators = None

    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        # s = f.read()
        # json.loads(s)
        data = json.load(f)
        s = json.dumps(data, skipkeys=skip_keys, sort_keys=sort_keys,
                       ensure_ascii=ensure_ascii, check_circular=check_circular,
                       allow_nan=allow_nan, indent=indent, separators=separators)
        click.echo(s)

def main():
    cli()

if __name__ == '__main__':
    # main(default_map={
    #     'info': {
    #         'input': 'rfxml_parse.input.01.xml'
    #     }
    # })
    main()
<commit_msg>jsontool: added a new command: flatten.<commit_after>import json

import click

import click_utils
from dict_utils import flatten

def process(**kwargs):
    ctx = click.get_current_context()

    # debug_ = ctx.params.get('debug') or ctx.parent.params.get('debug') if ctx.parent else False
    # if debug_:
    #     click_utils.echo_context(ctx)

    click_utils.inherit_parent_params(ctx, ('debug',))

    debug_ = ctx.params['debug']

    if debug_:
        click.echo('Debug mode: %s' % ('enabled' if debug_ else 'disabled'))
        click_utils.echo_context(ctx)
        click_utils.echo_kwargs(kwargs)

    subcommand = ctx.invoked_subcommand
    if subcommand == 'info':
        pass

@click.group(context_settings=click_utils.CONTEXT_SETTINGS, invoke_without_command=True)
@click.version_option(version='1.0.0')
@click.option('--debug/--silent', '-d/-s', 'debug', default=False)
# @click.option('--debug', '-d', 'debug', flag_value=True, default=True)
# @click.option('--silent', '-s', 'debug', flag_value=False)
def cli(debug):
    ctx = click.get_current_context()
    if debug:
        click_utils.echo_context(ctx)

    subcommand = ctx.invoked_subcommand
    # click.echo('Subcommand: {}'.format(subcommand))
    if subcommand is None:
        click.echo('I was invoked without a subcommand...')
    else:
        if debug:
            click.echo('I am about to invoke subcommand: %s.' % subcommand)

@cli.command()
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def echo(input, **kwargs):
    """
    Echo the (unparsed) input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        s = f.read()
        click.echo(s)

@cli.command(name='repr')
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def reprcommand(input, **kwargs):
    """
    Provides the python repr() representation of the parsed input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        data = json.load(f)
        s = repr(data)
        click.echo(s)

@cli.command()
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input. Or '-' to use stdin (e.g. piped input).")
def info(input, **kwargs):
    """
    Provides info about the input.
    """
    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        data = json.load(f)
        d = {
            'type': type(data),
            'length': len(data),
            # 'repr': repr(data),
            'keys': data.keys()
        }
        # click.echo('type={}'.format(t))
        # click.echo('len={}'.format(len(data)))
        # click.echo('keys={}'.format(', '.join(data.keys())))
        click.echo(d)
        # click.echo('iter={}'.format(', '.join(iter(data))))
        # click.echo('dir={}'.format(dir(data)))
        # click.echo('repr={}'.format(repr(data)))

@cli.command(name='format')
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input."
                   " Or '-' to use stdin (e.g. piped input).")
@click.option('--compact', '-c', 'style', flag_value='compact',
              help='output format style that minimizes the output.'
                   ' overrides the indent and separator options.')
@click.option('--pretty', '-p', 'style', flag_value='pretty',
              help='output format style that generates human readable output.'
                   ' overrides the indent and separator options.')
@click.option('--flat', '-f', 'style', flag_value='flat',
              help='output format style that generates multi-line, non-indented output.'
                   ' overrides the indent and separator options.')
@click.option('--indent', type=click.IntRange(min=0),
              help='Default is None. Must be a non-negative integer.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--skip-keys', '--skip', '--ignore-key-errors', '-ike', 'skip_keys', type=click.BOOL)
@click.option('--sort-keys', '--sorted/--unsorted', '--sort', '-s', 'sort_keys', default=False,
              help='causes the keys of each element to be output in sorted order.')
@click.option('--ensure-ascii/--ensure-ascii-off', '-ea+/-ea-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--check-circular/--check-circular-ff', '-cc+/-cc-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--allow-nan/--allow-nan-off', '-nan+/-nan-', default=True,
              help='Default is True.'
                   ' Maps to the corresponding argument of the json.dumps() function.')
@click.option('--item-separator', '-is', default=', ', help='the item separator')
@click.option('--dict-separator', '-ds', default=': ', help='the dictionary/element separator')
def formatcommand(input, style, indent, skip_keys, sort_keys, ensure_ascii, check_circular, allow_nan,
                  item_separator, dict_separator, **kwargs):
    """
    Formats the JSON input. See the docs of the json.dumps() function (in python's builtin json module) for details.
    """
    if style == 'compact':
        separators = (',', ':')
        indent = None
    elif style == 'pretty':
        # separators = (',', ':')
        separators = None
        indent = 2
    elif style == 'flat':
        separators = (',', ': ')
        indent = 0
    elif item_separator or dict_separator:
        if not item_separator:
            item_separator = ', '
        if not dict_separator:
            dict_separator = ': '
        separators = (item_separator, dict_separator)
    else:
        separators = None

    if not input:
        input = '-'
    with click.open_file(input, mode='rb') as f:
        # s = f.read()
        # json.loads(s)
        data = json.load(f)
        s = json.dumps(data, skipkeys=skip_keys, sort_keys=sort_keys,
                       ensure_ascii=ensure_ascii, check_circular=check_circular,
                       allow_nan=allow_nan, indent=indent, separators=separators)
        click.echo(s)

@cli.command(name='flatten')
@click.option('--input', '-i', type=click.Path(exists=True, dir_okay=False, allow_dash=True),
              help="the path to the file containing the input."
                   " Or '-' to use stdin (e.g. piped input).")
@click.option('--separator', '-s', type=click.STRING, help='the key/element separator. Default is "__".')
@click.option('--sort-keys', '--sorted/--unsorted', '--sort', 'sort_keys', default=False,
              help='causes the keys of each element to be output in sorted order.')
@click.option('--compact', '-c', 'style', flag_value='compact',
              help='output format style that minimizes the output.'
                   ' for more options, use the jsontool.format command.')
@click.option('--pretty', '-p', 'style', flag_value='pretty',
              help='output format style that generates human readable output.'
                   ' for more options, use the jsontool.format command.')
@click.option('--flat', '-f', 'style', flag_value='flat',
              help='output format style that generates multi-line, non-indented output.'
                   ' for more options, use the jsontool.format command.')
def flattencommand(input, separator, sort_keys, style, **kwargs):
    """
    Flattens JSON input with nested or hierarchical structure into a flat hierarchy.
    """
    if style == 'compact':
        dumps_separators = (',', ':')
        dumps_indent = None
    elif style == 'pretty':
        dumps_separators = None
        dumps_indent = 2
    elif style == 'flat':
        dumps_separators = (',', ': ')
        dumps_indent = 0
    else:
        dumps_separators = None
        dumps_indent = None

    if not input:
        input = '-'
    if separator is None:
        separator = '__'
    with click.open_file(input, mode='rb') as f:
        data = json.load(f)
        data = flatten(data, separator)
        s = json.dumps(data, indent=dumps_indent, separators=dumps_separators, sort_keys=sort_keys)
        click.echo(s)

def main():
    cli()

if __name__ == '__main__':
    # main(default_map={
    #     'info': {
    #         'input': 'rfxml_parse.input.01.xml'
    #     }
    # })
    main()
<|endoftext|>


<commit_before>"""Simultaneous eccentricity and inclination changes.
References
----------
* Pollard, J. E. "Simplified Analysis of Low-Thrust Orbital Maneuvers", 2000.
"""
import numpy as np

from astropy import units as u

from poliastro.twobody.decorators import state_from_vector
from poliastro.util import norm, circular_velocity
from poliastro.twobody import rv
from poliastro.jit import jit

@jit
def beta(ecc_0, ecc_f, inc_0, inc_f, argp):
    # Note: "The argument of perigee will vary during the orbit transfer
    # due to the natural drift and because e may approach zero.
    # However, [the equation] still gives a good estimate of the desired
    # thrust angle."
    return np.arctan(abs(3 * np.pi * (inc_f - inc_0) / (4 * np.cos(argp) * (ecc_0 - ecc_f + np.log(
        (1 + ecc_f) * (-1 + ecc_0) / ((1 + ecc_0) * (-1 + ecc_f)))))))

@jit
def delta_V(V_0, ecc_0, ecc_f, beta_):
    """Compute required increment of velocity.
    """
    return 2 * V_0 * np.abs(np.arcsin(ecc_0) - np.arcsin(ecc_f)) / (3 * np.cos(beta_))

def extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f):
    """Extra quantities given by the model.
    """
    beta_ = beta(ecc_0, ecc_f, inc_0, inc_f, argp)
    V_0 = circular_velocity(k, a)
    delta_V_ = delta_V(V_0, ecc_0, ecc_f, beta_)
    t_f_ = delta_V_ / f

    return delta_V_, beta_, t_f_

def change_inc_ecc(ss_0, ecc_f, inc_f, f):
    """Guidance law from the model.
    Thrust is aligned with an inertially fixed direction perpendicular to the
    semimajor axis of the orbit.
    Parameters
    ----------
    ss_0 : Orbit
        Initial orbit, containing all the information.
    ecc_f : float
        Final eccentricity.
    inc_f : float
        Final inclination.
    f : float
        Magnitude of constant acceleration.
    """
    k = ss_0.attractor.k.to(u.km**3 / u.s**2).value
    a = ss_0.a.to(u.km).value
    # We fix the inertial direction at the beginning
    ecc_0 = ss_0.ecc.value
    if ecc_0 > 0.001:  # Arbitrary tolerance
        ref_vec = ss_0.e_vec / ecc_0
    else:
        ref_vec = ss_0.r / norm(ss_0.r)

    h_unit = ss_0.h_vec / norm(ss_0.h_vec)
    thrust_unit = np.cross(h_unit, ref_vec) * np.sign(ecc_f - ecc_0)

    inc_0 = ss_0.inc.to(u.rad).value
    argp = ss_0.argp.to(u.rad).value

    beta_0_ = beta(ecc_0, ecc_f, inc_0, inc_f, argp)

    def a_d(t0, u_, k):
        r = u_[:3]
        v = u_[3:]
        nu = rv.rv2coe(k, r, v)[-1]
        beta_ = beta_0_ * np.sign(np.cos(nu))  # The sign of ß reverses at minor axis crossings

        w_ = np.cross(r, v) / norm(np.cross(r, v))
        accel_v = f * (
            np.cos(beta_) * thrust_unit +
            np.sin(beta_) * w_
        )
        return accel_v

    delta_V, beta_, t_f = extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f)
    return a_d, delta_V, beta_, t_f
<commit_msg>fixed codeclimate<commit_after>"""Simultaneous eccentricity and inclination changes.
References
----------
* Pollard, J. E. "Simplified Analysis of Low-Thrust Orbital Maneuvers", 2000.
"""
import numpy as np

from astropy import units as u

from poliastro.twobody.decorators import state_from_vector
from poliastro.util import norm, circular_velocity
from poliastro.twobody import rv
from poliastro.jit import jit

@jit
def beta(ecc_0, ecc_f, inc_0, inc_f, argp):
    # Note: "The argument of perigee will vary during the orbit transfer
    # due to the natural drift and because e may approach zero.
    # However, [the equation] still gives a good estimate of the desired
    # thrust angle."
    return np.arctan(abs(3 * np.pi * (inc_f - inc_0) / (4 * np.cos(argp) * (ecc_0 - ecc_f + np.log(
        (1 + ecc_f) * (-1 + ecc_0) / ((1 + ecc_0) * (-1 + ecc_f)))))))

@jit
def delta_V(V_0, ecc_0, ecc_f, beta_):
    """Compute required increment of velocity.
    """
    return 2 * V_0 * np.abs(np.arcsin(ecc_0) - np.arcsin(ecc_f)) / (3 * np.cos(beta_))

def extra_quantities(k, a, ecc_0, ecc_f, inc_0, inc_f, argp, f):
    """Extra quantities given by the model.
    """
    beta_ = beta(ecc_0, ecc_f, inc_0, inc_f, argp)
    V_0 = circular_velocity(k, a)
    delta_V_ = delta_V(V_0, ecc_0, ecc_f, beta_)
    t_f_ = delta_V_ / f

    return delta_V_, beta_, t_f_

def change_inc_ecc(ss_0, ecc_f, inc_f, f):
    """Guidance law from the model.
    Thrust is aligned with an inertially fixed direction perpendicular to the
    semimajor axis of the orbit.
    Parameters
    ----------
    ss_0 : Orbit
        Initial orbit, containing all the information.
    ecc_f : float
        Final eccentricity.
    inc_f : float
        Final inclination.
    f : float
        Magnitude of constant acceleration.
    """
    # We fix the inertial direction at the beginning
    ecc_0 = ss_0.ecc.value
    if ecc_0 > 0.001:  # Arbitrary tolerance
        ref_vec = ss_0.e_vec / ecc_0
    else:
        ref_vec = ss_0.r / norm(ss_0.r)

    h_unit = ss_0.h_vec / norm(ss_0.h_vec)
    thrust_unit = np.cross(h_unit, ref_vec) * np.sign(ecc_f - ecc_0)

    inc_0 = ss_0.inc.to(u.rad).value
    argp = ss_0.argp.to(u.rad).value

    beta_0_ = beta(ecc_0, ecc_f, inc_0, inc_f, argp)

    def a_d(t0, u_, k):
        r = u_[:3]
        v = u_[3:]
        nu = rv.rv2coe(k, r, v)[-1]
        beta_ = beta_0_ * np.sign(np.cos(nu))  # The sign of ß reverses at minor axis crossings

        w_ = np.cross(r, v) / norm(np.cross(r, v))
        accel_v = f * (
            np.cos(beta_) * thrust_unit +
            np.sin(beta_) * w_
        )
        return accel_v

    delta_V, beta_, t_f = extra_quantities(ss_0.attractor.k.to(u.km**3 / u.s**2).value, ss_0.a.to(u.km).value,
                                           ecc_0, ecc_f, inc_0, inc_f, argp, f)
    return a_d, delta_V, beta_, t_f
<|endoftext|>


<commit_before>#!/usr/bin/env python

import os
import robot
from robot.result.jsparser import create_datamodel_from

BASEDIR = os.path.dirname(__file__)
TESTDATA = os.path.join(BASEDIR, 'dir.suite')
OUTPUT = os.path.join(BASEDIR, 'output.xml')
TARGET = os.path.join(BASEDIR, 'data.js')

if __name__ == '__main__':
    robot.run(TESTDATA, log='NONE', report='NONE',
              tagstatlink=['force:http://google.com:<kuukkeli>',
                           'i*:http://%1/:Title of i%1'],
              tagdoc=['test:this_is_*my_bold*_test',
                      'IX:*Combined* & escaped << tag doc'],
              tagstatcombine=['fooANDi*:zap', 'i?:IX'],
              critical=['i?'], noncritical=['*kek*kone*'], outputdir=BASEDIR)
    model = create_datamodel_from(OUTPUT)
    model.set_settings({'logURL': 'log.html',
                        'reportURL': 'report.html',
                        'background': {'fail': 'DeepPink'}})
    with open(TARGET, 'w') as output:
        model.write_to(output)

<commit_msg>refactor create_jsdata -- preparation for jasmine spec data generator<commit_after>#!/usr/bin/env python

import os
import robot
from robot.result.jsparser import create_datamodel_from

BASEDIR = os.path.dirname(__file__)
TESTDATA = os.path.join(BASEDIR, 'dir.suite')
OUTPUT = os.path.join(BASEDIR, 'output.xml')
TARGET = os.path.join(BASEDIR, 'data.js')

def run_robot(outputdirectory, testdata):
    robot.run(testdata, log='NONE', report='NONE',
              tagstatlink=['force:http://google.com:<kuukkeli>',
                           'i*:http://%1/:Title of i%1'],
              tagdoc=['test:this_is_*my_bold*_test',
                      'IX:*Combined* & escaped << tag doc'],
              tagstatcombine=['fooANDi*:zap', 'i?:IX'],
              critical=['i?'], noncritical=['*kek*kone*'], outputdir=outputdirectory)

def create_jsdata(output_xml_file, target):
    model = create_datamodel_from(output_xml_file)
    model.set_settings({'logURL': 'log.html',
                        'reportURL': 'report.html',
                        'background': {'fail': 'DeepPink'}})
    with open(target, 'w') as output:
        model.write_to(output)

if __name__ == '__main__':
    run_robot(BASEDIR, TESTDATA)
    create_jsdata(OUTPUT, TARGET)

<|endoftext|>