<commit_before>from __future__ import unicode_literals, division, absolute_import

import base64
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import os
import json
import sys
import logging
import threading
import traceback
from time import sleep

import cherrypy
from flask import Response, jsonify
from flask_restplus import inputs
from pyparsing import Word, Keyword, Group, Forward, Suppress, OneOrMore, oneOf, White, restOfLine, ParseException, \
    Combine
from pyparsing import nums, alphanums, printables

from flexget._version import __version__
from flexget.api import api, APIResource, ApiError, __version__ as __api_version__

log = logging.getLogger('api.server')

server_api = api.namespace('server', description='Manage Daemon')

@server_api.route('/reload/')
class ServerReloadAPI(APIResource):
    @api.response(ApiError, description='Error loading the config')
    @api.response(200, description='Newly reloaded config')
    def get(self, session=None):
        """ Reload Flexget config """
        log.info('Reloading config from disk.')
        try:
            self.manager.load_config()
        except ValueError as e:
            raise ApiError('Error loading config: %s' % e.args[0])

        log.info('Config successfully reloaded from disk.')
        return {}

pid_schema = api.schema('server.pid', {
    'type': 'object',
    'properties': {
        'pid': {
            'type': 'integer'
        }
    }
})

@server_api.route('/pid/')
class ServerPIDAPI(APIResource):
    @api.response(200, description='Reloaded config', model=pid_schema)
    def get(self, session=None):
        """ Get server PID """
        return {'pid': os.getpid()}

shutdown_parser = api.parser()
shutdown_parser.add_argument('force', type=inputs.boolean, required=False, default=False,
                             help='Ignore tasks in the queue')

@server_api.route('/shutdown/')
class ServerShutdownAPI(APIResource):
    @api.doc(parser=shutdown_parser)
    @api.response(200, 'Shutdown requested')
    def get(self, session=None):
        """ Shutdown Flexget Daemon """
        args = shutdown_parser.parse_args()
        self.manager.shutdown(args['force'])
        return {}

@server_api.route('/config/')
class ServerConfigAPI(APIResource):
    @api.response(200, description='Flexget config')
    def get(self, session=None):
        """ Get Flexget Config """
        return self.manager.config

@server_api.route('/raw_config/')
class ServerConfigAPI(APIResource):
    @api.response(200, description='Flexget raw YAML config file')
    def get(self, session=None):
        """ Get raw YAML config file """
        with open(self.manager.config_path, 'r', encoding='utf-8') as f:
            raw_config = base64.b64encode(f.read())
        return jsonify({'raw_config': raw_config})

version_schema = api.schema('server.version', {
    'type': 'object',
    'properties': {
        'flexget_version': {'type': 'string'},
        'api_version': {'type': 'integer'}
    }
})

@server_api.route('/version/')
class ServerVersionAPI(APIResource):
    @api.response(200, description='Flexget version', model=version_schema)
    def get(self, session=None):
        """ Flexget Version """
        return {'flexget_version': __version__, 'api_version': __api_version__}

dump_threads_schema = api.schema('server.dump_threads', {
    'type': 'object',
    'properties': {
        'threads': {
            'type': 'array',
            'items': {
                'type': 'object',
                'properties': {
                    'name': {'type': 'string'},
                    'id': {'type': 'string'},
                    'dump': {
                        'type': 'array',
                        'items': {'type': 'string'}
                    }
                },
            },
        }
    }
})

@server_api.route('/dump_threads/')
class ServerDumpThreads(APIResource):
    @api.response(200, description='Flexget threads dump', model=dump_threads_schema)
    def get(self, session=None):
        """ Dump Server threads for debugging """
        id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
        threads = []
        for threadId, stack in sys._current_frames().items():
            dump = []
            for filename, lineno, name, line in traceback.extract_stack(stack):
                dump.append('File: "%s", line %d, in %s' % (filename, lineno, name))
                if line:
                    dump.append(line.strip())
            threads.append({
                'name': id2name.get(threadId),
                'id': threadId,
                'dump': dump
            })

        return {'threads': threads}

server_log_parser = api.parser()
server_log_parser.add_argument(
    'lines', type=int, required=False, default=200,
    help='How many lines to find before streaming'
)
server_log_parser.add_argument('search', type=str, required=False, help='Search filter support google like syntax')

def reverse_readline(fh, start_byte=0, buf_size=8192):
    """a generator that returns the lines of a file in reverse order"""
    segment = None
    offset = 0
    if start_byte:
        fh.seek(start_byte)
    else:
        fh.seek(0, os.SEEK_END)
    total_size = remaining_size = fh.tell()
    while remaining_size > 0:
        offset = min(total_size, offset + buf_size)
        fh.seek(-offset, os.SEEK_END)
        buf = fh.read(min(remaining_size, buf_size))
        remaining_size -= buf_size
        lines = buf.decode(sys.getfilesystemencoding()).split('\n')
        # the first line of the buffer is probably not a complete line so
        # we'll save it and append it to the last line of the next buffer
        # we read
        if segment is not None:
            # if the previous chunk starts right from the beginning of line
            # do not concact the segment to the last line of new chunk
            # instead, yield the segment first
            if buf[-1] is not '\n':
                lines[-1] += segment
            else:
                yield segment
        segment = lines[0]
        for index in range(len(lines) - 1, 0, -1):
            if len(lines[index]):
                yield lines[index]
    yield segment

def file_inode(filename):
    try:
        fd = os.open(filename, os.O_RDONLY)
        inode = os.fstat(fd).st_ino
        return inode
    except OSError:
        return 0
    finally:
        if fd:
            os.close(fd)

@server_api.route('/log/')
class ServerLogAPI(APIResource):
    @api.doc(parser=server_log_parser)
    @api.response(200, description='Streams as line delimited JSON')
    def get(self, session=None):
        """ Stream Flexget log Streams as line delimited JSON """
        args = server_log_parser.parse_args()

        def follow(lines, search):
            log_parser = LogParser(search)
            stream_from_byte = 0

            lines_found = []

            if os.path.isabs(self.manager.options.logfile):
                base_log_file = self.manager.options.logfile
            else:
                base_log_file = os.path.join(self.manager.config_base, self.manager.options.logfile)

            yield '{"stream": ['  # Start of the json stream

            # Read back in the logs until we find enough lines
            for i in range(0, 9):
                log_file = ('%s.%s' % (base_log_file, i)).rstrip('.0')  # 1st log file has no number

                if not os.path.isfile(log_file):
                    break

                with open(log_file, 'rb') as fh:
                    fh.seek(0, 2)  # Seek to bottom of file
                    end_byte = fh.tell()
                    if i == 0:
                        stream_from_byte = end_byte  # Stream from this point later on

                    if len(lines_found) >= lines:
                        break

                    # Read in reverse for efficiency
                    for line in reverse_readline(fh, start_byte=end_byte):
                        if len(lines_found) >= lines:
                            break
                        if log_parser.matches(line):
                            lines_found.append(log_parser.json_string(line))

                    for l in reversed(lines_found):
                        yield l + ',\n'

            # We need to track the inode in case the log file is rotated
            current_inode = file_inode(base_log_file)

            while True:
                # If the server is shutting down then end the stream nicely
                if cherrypy.engine.state != cherrypy.engine.states.STARTED:
                    break

                new_inode = file_inode(base_log_file)
                if current_inode != new_inode:
                    # File updated/rotated. Read from beginning
                    stream_from_byte = 0
                    current_inode = new_inode

                try:
                    with open(base_log_file, 'rb') as fh:
                        fh.seek(stream_from_byte)
                        line = fh.readline().decode(sys.getfilesystemencoding())
                        stream_from_byte = fh.tell()
                except IOError:
                    yield '{}'
                    continue

                # If a valid line is found and does not pass the filter then set it to none
                line = log_parser.json_string(line) if log_parser.matches(line) else '{}'

                if line == '{}':
                    # If no match then delay to prevent many read hits on the file
                    sleep(2)

                yield line + ',\n'

            yield '{}]}'  # End of stream

        return Response(follow(args['lines'], args['search']), mimetype='text/event-stream')

class LogParser(object):
    """
    Filter log file.

    Supports
      * 'and', 'or' and implicit 'and' operators;
      * parentheses;
      * quoted strings;
    """

    def __init__(self, query):
        self._methods = {
            'and': self.evaluate_and,
            'or': self.evaluate_or,
            'not': self.evaluate_not,
            'parenthesis': self.evaluate_parenthesis,
            'quotes': self.evaluate_quotes,
            'word': self.evaluate_word,
        }

        self.line = ''
        self.query = query.lower() if query else ''

        if self.query:
            # TODO: Cleanup
            operator_or = Forward()
            operator_word = Group(Word(alphanums)).setResultsName('word')

            operator_quotes_content = Forward()
            operator_quotes_content << (
                (operator_word + operator_quotes_content) | operator_word
            )

            operator_quotes = Group(
                Suppress('"') + operator_quotes_content + Suppress('"')
            ).setResultsName('quotes') | operator_word

            operator_parenthesis = Group(
                (Suppress('(') + operator_or + Suppress(")"))
            ).setResultsName('parenthesis') | operator_quotes

            operator_not = Forward()
            operator_not << (Group(
                Suppress(Keyword('no', caseless=True)) + operator_not
            ).setResultsName('not') | operator_parenthesis)

            operator_and = Forward()
            operator_and << (Group(
                operator_not + Suppress(Keyword('and', caseless=True)) + operator_and
            ).setResultsName('and') | Group(
                operator_not + OneOrMore(~oneOf('and or') + operator_and)
            ).setResultsName('and') | operator_not)

            operator_or << (Group(
                operator_and + Suppress(Keyword('or', caseless=True)) + operator_or
            ).setResultsName('or') | operator_and)

            self._query_parser = operator_or.parseString(self.query)[0]
        else:
            self._query_parser = False

        time_cmpnt = Word(nums).setParseAction(lambda t: t[0].zfill(2))
        date = Combine((time_cmpnt + '-' + time_cmpnt + '-' + time_cmpnt) + ' ' + time_cmpnt + ':' + time_cmpnt)
        word = Word(printables)

        self._log_parser = (
            date.setResultsName('timestamp') +
            word.setResultsName('log_level') +
            word.setResultsName('plugin') +
            (
                White(min=16).setParseAction(lambda s, l, t: [t[0].strip()]).setResultsName('task') |
                (White(min=1).suppress() & word.setResultsName('task'))
            ) +
            restOfLine.setResultsName('message')
        )

    def evaluate_and(self, argument):
        return self.evaluate(argument[0]) and self.evaluate(argument[1])

    def evaluate_or(self, argument):
        return self.evaluate(argument[0]) or self.evaluate(argument[1])

    def evaluate_not(self, argument):
        return not self.evaluate(argument[0])

    def evaluate_parenthesis(self, argument):
        return self.evaluate(argument[0])

    def evaluate_quotes(self, argument):
        search_terms = [term[0] for term in argument]
        return ' '.join(search_terms) in ' '.join(self.line.split())

    def evaluate_word(self, argument):
        return argument[0] in self.line

    def evaluate(self, argument):
        return self._methods[argument.getName()](argument)

    def matches(self, line):
        if not line:
            return False

        self.line = line.lower()

        if not self._query_parser:
            return True
        else:
            return self.evaluate(self._query_parser)

    def json_string(self, line):
        try:
            return json.dumps(self._log_parser().parseString(line).asDict())
        except ParseException:
            return '{}'
<commit_msg>Improved raw config api doc<commit_after>from __future__ import unicode_literals, division, absolute_import

import base64
from builtins import *  # pylint: disable=unused-import, redefined-builtin

import os
import json
import sys
import logging
import threading
import traceback
from time import sleep

import cherrypy
from flask import Response, jsonify
from flask_restplus import inputs
from pyparsing import Word, Keyword, Group, Forward, Suppress, OneOrMore, oneOf, White, restOfLine, ParseException, \
    Combine
from pyparsing import nums, alphanums, printables

from flexget._version import __version__
from flexget.api import api, APIResource, ApiError, __version__ as __api_version__

log = logging.getLogger('api.server')

server_api = api.namespace('server', description='Manage Daemon')

@server_api.route('/reload/')
class ServerReloadAPI(APIResource):
    @api.response(ApiError, description='Error loading the config')
    @api.response(200, description='Newly reloaded config')
    def get(self, session=None):
        """ Reload Flexget config """
        log.info('Reloading config from disk.')
        try:
            self.manager.load_config()
        except ValueError as e:
            raise ApiError('Error loading config: %s' % e.args[0])

        log.info('Config successfully reloaded from disk.')
        return {}

pid_schema = api.schema('server.pid', {
    'type': 'object',
    'properties': {
        'pid': {
            'type': 'integer'
        }
    }
})

@server_api.route('/pid/')
class ServerPIDAPI(APIResource):
    @api.response(200, description='Reloaded config', model=pid_schema)
    def get(self, session=None):
        """ Get server PID """
        return {'pid': os.getpid()}

shutdown_parser = api.parser()
shutdown_parser.add_argument('force', type=inputs.boolean, required=False, default=False,
                             help='Ignore tasks in the queue')

@server_api.route('/shutdown/')
class ServerShutdownAPI(APIResource):
    @api.doc(parser=shutdown_parser)
    @api.response(200, 'Shutdown requested')
    def get(self, session=None):
        """ Shutdown Flexget Daemon """
        args = shutdown_parser.parse_args()
        self.manager.shutdown(args['force'])
        return {}

@server_api.route('/config/')
class ServerConfigAPI(APIResource):
    @api.response(200, description='Flexget config')
    def get(self, session=None):
        """ Get Flexget Config """
        return self.manager.config

raw_config_object = {
    'type': 'object',
    'properties': {
        'raw_config': {'type': 'string'}
    }
}
raw_config_schema = api.schema('raw_config', raw_config_object)

@server_api.route('/raw_config/')
class ServerConfigAPI(APIResource):
    @api.doc(description='Return config file encoded in Base64')
    @api.response(200, model=raw_config_schema, description='Flexget raw YAML config file')
    def get(self, session=None):
        """ Get raw YAML config file """
        with open(self.manager.config_path, 'r', encoding='utf-8') as f:
            raw_config = base64.b64encode(f.read())
        return jsonify({'raw_config': raw_config})

version_schema = api.schema('server.version', {
    'type': 'object',
    'properties': {
        'flexget_version': {'type': 'string'},
        'api_version': {'type': 'integer'}
    }
})

@server_api.route('/version/')
class ServerVersionAPI(APIResource):
    @api.response(200, description='Flexget version', model=version_schema)
    def get(self, session=None):
        """ Flexget Version """
        return {'flexget_version': __version__, 'api_version': __api_version__}

dump_threads_schema = api.schema('server.dump_threads', {
    'type': 'object',
    'properties': {
        'threads': {
            'type': 'array',
            'items': {
                'type': 'object',
                'properties': {
                    'name': {'type': 'string'},
                    'id': {'type': 'string'},
                    'dump': {
                        'type': 'array',
                        'items': {'type': 'string'}
                    }
                },
            },
        }
    }
})

@server_api.route('/dump_threads/')
class ServerDumpThreads(APIResource):
    @api.response(200, description='Flexget threads dump', model=dump_threads_schema)
    def get(self, session=None):
        """ Dump Server threads for debugging """
        id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
        threads = []
        for threadId, stack in sys._current_frames().items():
            dump = []
            for filename, lineno, name, line in traceback.extract_stack(stack):
                dump.append('File: "%s", line %d, in %s' % (filename, lineno, name))
                if line:
                    dump.append(line.strip())
            threads.append({
                'name': id2name.get(threadId),
                'id': threadId,
                'dump': dump
            })

        return {'threads': threads}

server_log_parser = api.parser()
server_log_parser.add_argument(
    'lines', type=int, required=False, default=200,
    help='How many lines to find before streaming'
)
server_log_parser.add_argument('search', type=str, required=False, help='Search filter support google like syntax')

def reverse_readline(fh, start_byte=0, buf_size=8192):
    """a generator that returns the lines of a file in reverse order"""
    segment = None
    offset = 0
    if start_byte:
        fh.seek(start_byte)
    else:
        fh.seek(0, os.SEEK_END)
    total_size = remaining_size = fh.tell()
    while remaining_size > 0:
        offset = min(total_size, offset + buf_size)
        fh.seek(-offset, os.SEEK_END)
        buf = fh.read(min(remaining_size, buf_size))
        remaining_size -= buf_size
        lines = buf.decode(sys.getfilesystemencoding()).split('\n')
        # the first line of the buffer is probably not a complete line so
        # we'll save it and append it to the last line of the next buffer
        # we read
        if segment is not None:
            # if the previous chunk starts right from the beginning of line
            # do not concact the segment to the last line of new chunk
            # instead, yield the segment first
            if buf[-1] is not '\n':
                lines[-1] += segment
            else:
                yield segment
        segment = lines[0]
        for index in range(len(lines) - 1, 0, -1):
            if len(lines[index]):
                yield lines[index]
    yield segment

def file_inode(filename):
    try:
        fd = os.open(filename, os.O_RDONLY)
        inode = os.fstat(fd).st_ino
        return inode
    except OSError:
        return 0
    finally:
        if fd:
            os.close(fd)

@server_api.route('/log/')
class ServerLogAPI(APIResource):
    @api.doc(parser=server_log_parser)
    @api.response(200, description='Streams as line delimited JSON')
    def get(self, session=None):
        """ Stream Flexget log Streams as line delimited JSON """
        args = server_log_parser.parse_args()

        def follow(lines, search):
            log_parser = LogParser(search)
            stream_from_byte = 0

            lines_found = []

            if os.path.isabs(self.manager.options.logfile):
                base_log_file = self.manager.options.logfile
            else:
                base_log_file = os.path.join(self.manager.config_base, self.manager.options.logfile)

            yield '{"stream": ['  # Start of the json stream

            # Read back in the logs until we find enough lines
            for i in range(0, 9):
                log_file = ('%s.%s' % (base_log_file, i)).rstrip('.0')  # 1st log file has no number

                if not os.path.isfile(log_file):
                    break

                with open(log_file, 'rb') as fh:
                    fh.seek(0, 2)  # Seek to bottom of file
                    end_byte = fh.tell()
                    if i == 0:
                        stream_from_byte = end_byte  # Stream from this point later on

                    if len(lines_found) >= lines:
                        break

                    # Read in reverse for efficiency
                    for line in reverse_readline(fh, start_byte=end_byte):
                        if len(lines_found) >= lines:
                            break
                        if log_parser.matches(line):
                            lines_found.append(log_parser.json_string(line))

                    for l in reversed(lines_found):
                        yield l + ',\n'

            # We need to track the inode in case the log file is rotated
            current_inode = file_inode(base_log_file)

            while True:
                # If the server is shutting down then end the stream nicely
                if cherrypy.engine.state != cherrypy.engine.states.STARTED:
                    break

                new_inode = file_inode(base_log_file)
                if current_inode != new_inode:
                    # File updated/rotated. Read from beginning
                    stream_from_byte = 0
                    current_inode = new_inode

                try:
                    with open(base_log_file, 'rb') as fh:
                        fh.seek(stream_from_byte)
                        line = fh.readline().decode(sys.getfilesystemencoding())
                        stream_from_byte = fh.tell()
                except IOError:
                    yield '{}'
                    continue

                # If a valid line is found and does not pass the filter then set it to none
                line = log_parser.json_string(line) if log_parser.matches(line) else '{}'

                if line == '{}':
                    # If no match then delay to prevent many read hits on the file
                    sleep(2)

                yield line + ',\n'

            yield '{}]}'  # End of stream

        return Response(follow(args['lines'], args['search']), mimetype='text/event-stream')

class LogParser(object):
    """
    Filter log file.

    Supports
      * 'and', 'or' and implicit 'and' operators;
      * parentheses;
      * quoted strings;
    """

    def __init__(self, query):
        self._methods = {
            'and': self.evaluate_and,
            'or': self.evaluate_or,
            'not': self.evaluate_not,
            'parenthesis': self.evaluate_parenthesis,
            'quotes': self.evaluate_quotes,
            'word': self.evaluate_word,
        }

        self.line = ''
        self.query = query.lower() if query else ''

        if self.query:
            # TODO: Cleanup
            operator_or = Forward()
            operator_word = Group(Word(alphanums)).setResultsName('word')

            operator_quotes_content = Forward()
            operator_quotes_content << (
                (operator_word + operator_quotes_content) | operator_word
            )

            operator_quotes = Group(
                Suppress('"') + operator_quotes_content + Suppress('"')
            ).setResultsName('quotes') | operator_word

            operator_parenthesis = Group(
                (Suppress('(') + operator_or + Suppress(")"))
            ).setResultsName('parenthesis') | operator_quotes

            operator_not = Forward()
            operator_not << (Group(
                Suppress(Keyword('no', caseless=True)) + operator_not
            ).setResultsName('not') | operator_parenthesis)

            operator_and = Forward()
            operator_and << (Group(
                operator_not + Suppress(Keyword('and', caseless=True)) + operator_and
            ).setResultsName('and') | Group(
                operator_not + OneOrMore(~oneOf('and or') + operator_and)
            ).setResultsName('and') | operator_not)

            operator_or << (Group(
                operator_and + Suppress(Keyword('or', caseless=True)) + operator_or
            ).setResultsName('or') | operator_and)

            self._query_parser = operator_or.parseString(self.query)[0]
        else:
            self._query_parser = False

        time_cmpnt = Word(nums).setParseAction(lambda t: t[0].zfill(2))
        date = Combine((time_cmpnt + '-' + time_cmpnt + '-' + time_cmpnt) + ' ' + time_cmpnt + ':' + time_cmpnt)
        word = Word(printables)

        self._log_parser = (
            date.setResultsName('timestamp') +
            word.setResultsName('log_level') +
            word.setResultsName('plugin') +
            (
                White(min=16).setParseAction(lambda s, l, t: [t[0].strip()]).setResultsName('task') |
                (White(min=1).suppress() & word.setResultsName('task'))
            ) +
            restOfLine.setResultsName('message')
        )

    def evaluate_and(self, argument):
        return self.evaluate(argument[0]) and self.evaluate(argument[1])

    def evaluate_or(self, argument):
        return self.evaluate(argument[0]) or self.evaluate(argument[1])

    def evaluate_not(self, argument):
        return not self.evaluate(argument[0])

    def evaluate_parenthesis(self, argument):
        return self.evaluate(argument[0])

    def evaluate_quotes(self, argument):
        search_terms = [term[0] for term in argument]
        return ' '.join(search_terms) in ' '.join(self.line.split())

    def evaluate_word(self, argument):
        return argument[0] in self.line

    def evaluate(self, argument):
        return self._methods[argument.getName()](argument)

    def matches(self, line):
        if not line:
            return False

        self.line = line.lower()

        if not self._query_parser:
            return True
        else:
            return self.evaluate(self._query_parser)

    def json_string(self, line):
        try:
            return json.dumps(self._log_parser().parseString(line).asDict())
        except ParseException:
            return '{}'
<|endoftext|>


<commit_before>""" ImageKit image specifications

All imagekit specifications must inherit from the ImageSpec class. Models
inheriting from IKModel will be modified with a descriptor/accessor for each
spec found.

"""
import os
from imagekit.lib import *
from imagekit.utils import img_to_fobj
from django.core.files.base import ContentFile

class ImageSpec(object):
    pre_cache = False
    quality = 70
    increment_count = False
    processors = []

    @classmethod
    def name(cls):
        return getattr(cls, 'access_as', cls.__name__.lower())

    @classmethod
    def process(cls, image, obj):
        processed_image = image.copy()
        for proc in cls.processors:
            processed_image = proc.process(processed_image, obj)
        return processed_image

class Accessor(object):
    def __init__(self, obj, spec):
        self._img = None
        self._obj = obj
        self.spec = spec

    def _get_imgfile(self):
        format = self._img.format or 'JPEG'
        if format != 'JPEG':
            imgfile = img_to_fobj(self._img, format)
        else:
            imgfile = img_to_fobj(self._img, format,
                                  quality=int(self.spec.quality),
                                  optimize=True)
        return imgfile

    def _create(self):
        if self._exists():
            return
        self._img = self.spec.process(Image.open(self._obj._imgfield.file),
                                      self._obj)
        content = ContentFile(self._get_imgfile().read())
        self._obj._imgfield.storage.save(self._path(), content)

    def _delete(self):
        self._obj._imgfield.storage.delete(self._path())

    def _exists(self):
        return self._obj._imgfield.storage.exists(self._path())

    def _name(self):
        filename, ext =  os.path.splitext(os.path.basename(self._obj._imgfield.path))
        return self._obj._ik.cache_filename_format % \
            {'filename': filename,
             'specname': self.spec.name(),
             'extension': ext.lstrip('.')}

    def _path(self):
        return os.path.join(self._obj._ik.cache_dir, self._name())

    @property
    def url(self):
        self._create()
        if self.spec.increment_count:
            fieldname = self._obj._ik.save_count_as
            if fieldname is not None:
                current_count = getattr(self._obj, fieldname)
                setattr(self._obj, fieldname, current_count + 1)
                self._obj.save(clear_cache=False)
        return self._obj._imgfield.storage.url(self._path())

    @property
    def file(self):
        self._create()
        return self._obj._imgfield.storage.open(self._path())

    @property
    def image(self):
        if self._img is None:
            self._create()
            self._img = Image.open(self.file)
        return self._img

    @property
    def width(self):
        return self.image.size[0]

    @property
    def height(self):
        return self.image.size[1]

class Descriptor(object):
    def __init__(self, spec):
        self._spec = spec

    def __get__(self, obj, type=None):
        return Accessor(obj, self._spec)
<commit_msg>Accessor._img is assigned only if need in _create<commit_after>""" ImageKit image specifications

All imagekit specifications must inherit from the ImageSpec class. Models
inheriting from IKModel will be modified with a descriptor/accessor for each
spec found.

"""
import os
from imagekit.lib import *
from imagekit.utils import img_to_fobj
from django.core.files.base import ContentFile

class ImageSpec(object):
    pre_cache = False
    quality = 70
    increment_count = False
    processors = []

    @classmethod
    def name(cls):
        return getattr(cls, 'access_as', cls.__name__.lower())

    @classmethod
    def process(cls, image, obj):
        processed_image = image.copy()
        for proc in cls.processors:
            processed_image = proc.process(processed_image, obj)
        return processed_image

class Accessor(object):
    def __init__(self, obj, spec):
        self._img = None
        self._obj = obj
        self.spec = spec

    def _get_imgfile(self):
        format = self._img.format or 'JPEG'
        if format != 'JPEG':
            imgfile = img_to_fobj(self._img, format)
        else:
            imgfile = img_to_fobj(self._img, format,
                                  quality=int(self.spec.quality),
                                  optimize=True)
        return imgfile

    def _create(self):
        if self._exists():
            if self._img is None:
                self._img = Image.open(self.file)
            return
        self._img = self.spec.process(Image.open(self._obj._imgfield.file),
                                      self._obj)
        content = ContentFile(self._get_imgfile().read())
        self._obj._imgfield.storage.save(self._path(), content)

    def _delete(self):
        self._obj._imgfield.storage.delete(self._path())

    def _exists(self):
        return self._obj._imgfield.storage.exists(self._path())

    def _name(self):
        filename, ext =  os.path.splitext(os.path.basename(self._obj._imgfield.path))
        return self._obj._ik.cache_filename_format % \
            {'filename': filename,
             'specname': self.spec.name(),
             'extension': ext.lstrip('.')}

    def _path(self):
        return os.path.join(self._obj._ik.cache_dir, self._name())

    @property
    def url(self):
        self._create()
        if self.spec.increment_count:
            fieldname = self._obj._ik.save_count_as
            if fieldname is not None:
                current_count = getattr(self._obj, fieldname)
                setattr(self._obj, fieldname, current_count + 1)
                self._obj.save(clear_cache=False)
        return self._obj._imgfield.storage.url(self._path())

    @property
    def file(self):
        self._create()
        return self._obj._imgfield.storage.open(self._path())

    @property
    def image(self):
        if self._img is None:
            self._create()
        return self._img

    @property
    def width(self):
        return self.image.size[0]

    @property
    def height(self):
        return self.image.size[1]

class Descriptor(object):
    def __init__(self, spec):
        self._spec = spec

    def __get__(self, obj, type=None):
        return Accessor(obj, self._spec)
<|endoftext|>


<commit_before>from plenum.client.client import Client
from plenum.client.wallet import Wallet
from plenum.common.txn import STEWARD, TXN_TYPE, NYM, ROLE, TARGET_NYM, ALIAS, \
    NODE_PORT, CLIENT_IP, NODE_IP, DATA, NEW_NODE, CLIENT_PORT, CHANGE_HA, \
    CHANGE_KEYS, VERKEY

from plenum.client.signer import SimpleSigner
from plenum.common.raet import initLocalKeep
from plenum.common.util import randomString, hexToCryptonym
from plenum.common.port_dispenser import genHa
from plenum.test.eventually import eventually
from plenum.test.helper import checkSufficientRepliesRecvd, genHa, TestNode, \
    TestClient, genTestClient
from plenum.test.helper import TestRequestIdStore

def addNewClient(role, looper, creatorClient: Client, creatorWallet: Wallet,
                 name: str):
    wallet = Wallet(name, requestIdStore=TestRequestIdStore())
    wallet.addSigner()
        verstr = wallet.defaultSigner.verstr

    op = {
        TXN_TYPE: NYM,
        ROLE: role,
        TARGET_NYM: verstr,
        ALIAS: name
    }

    req = creatorWallet.signOp(op)
    creatorClient.submitReqs(req)

    nodeCount = len(creatorClient.nodeReg)
    looper.run(eventually(checkSufficientRepliesRecvd, creatorClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=3*nodeCount))
    return wallet

def addNewNode(looper, stewardClient, stewardWallet, newNodeName, tdir, tconf,
               allPluginsPath=None, autoStart=True):
    sigseed = randomString(32).encode()
    nodeSigner = SimpleSigner(seed=sigseed)

    (nodeIp, nodePort), (clientIp, clientPort) = genHa(2)

    op = {
        TXN_TYPE: NEW_NODE,
        TARGET_NYM: nodeSigner.verstr,
        DATA: {
            NODE_IP: nodeIp,
            NODE_PORT: nodePort,
            CLIENT_IP: clientIp,
            CLIENT_PORT: clientPort,
            ALIAS: newNodeName
        }
    }

    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)

    nodeCount = len(stewardClient.nodeReg)
    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=3*nodeCount))
    initLocalKeep(newNodeName, tdir, sigseed, override=True)
    node = TestNode(newNodeName, basedirpath=tdir, config=tconf,
                    ha=(nodeIp, nodePort), cliha=(clientIp, clientPort),
                    pluginPaths=allPluginsPath)
    if autoStart:
        looper.add(node)
    return node

def addNewStewardAndNode(looper, creatorClient, creatorWallet, stewardName,
                         newNodeName, tdir, tconf,
                         allPluginsPath=None, autoStart=True):
    newStewardWallet = addNewClient(STEWARD, looper, creatorClient,
                                    creatorWallet, stewardName)
    newSteward = TestClient(name=stewardName,
                            nodeReg=None, ha=genHa(),
                            # DEPR
                            # signer=newStewardSigner,
                            basedirpath=tdir)

    looper.add(newSteward)
    looper.run(newSteward.ensureConnectedToNodes())
    newNode = addNewNode(looper, newSteward, newStewardWallet, newNodeName,
                         tdir, tconf, allPluginsPath, autoStart=autoStart)
    return newSteward, newStewardWallet, newNode

def changeNodeHa(looper, stewardClient, stewardWallet, node, nodeHa, clientHa):
    nodeNym = hexToCryptonym(node.nodestack.local.signer.verhex)
    (nodeIp, nodePort), (clientIp, clientPort) = nodeHa, clientHa
    op = {
        TXN_TYPE: CHANGE_HA,
        TARGET_NYM: nodeNym,
        DATA: {
            NODE_IP: nodeIp,
            NODE_PORT: nodePort,
            CLIENT_IP: clientIp,
            CLIENT_PORT: clientPort,
            ALIAS: node.name
        }
    }

    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)
    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=5))
    node.nodestack.clearLocalKeep()
    node.nodestack.clearRemoteKeeps()
    node.clientstack.clearLocalKeep()
    node.clientstack.clearRemoteKeeps()

def changeNodeKeys(looper, stewardClient, stewardWallet, node, verkey):
    nodeNym = hexToCryptonym(node.nodestack.local.signer.verhex)

    op = {
        TXN_TYPE: CHANGE_KEYS,
        TARGET_NYM: nodeNym,
        DATA: {
            VERKEY: verkey,
            ALIAS: node.name
        }
    }
    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)

    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=5))
    node.nodestack.clearLocalRoleKeep()
    node.nodestack.clearRemoteRoleKeeps()
    node.nodestack.clearAllDir()
    node.clientstack.clearLocalRoleKeep()
    node.clientstack.clearRemoteRoleKeeps()
    node.clientstack.clearAllDir()

def buildPoolClientAndWallet(clientData, tempDir, clientClass=None,
                             walletClass=None):
    walletClass = walletClass or Wallet
    clientClass = clientClass or TestClient
    name, sigseed = clientData
    w = walletClass(name)
    w.addSigner(seed=sigseed)
    client, _ = genTestClient(name=name, identifier=w.defaultId,
                              tmpdir=tempDir, usePoolLedger=True,
                              testClientClass=clientClass)
    return client, w
<commit_msg>fix indets in pool_transactions/helper.py<commit_after>from plenum.client.client import Client
from plenum.client.wallet import Wallet
from plenum.common.txn import STEWARD, TXN_TYPE, NYM, ROLE, TARGET_NYM, ALIAS, \
    NODE_PORT, CLIENT_IP, NODE_IP, DATA, NEW_NODE, CLIENT_PORT, CHANGE_HA, \
    CHANGE_KEYS, VERKEY

from plenum.client.signer import SimpleSigner
from plenum.common.raet import initLocalKeep
from plenum.common.util import randomString, hexToCryptonym
from plenum.common.port_dispenser import genHa
from plenum.test.eventually import eventually
from plenum.test.helper import checkSufficientRepliesRecvd, genHa, TestNode, \
    TestClient, genTestClient
from plenum.test.helper import TestRequestIdStore

def addNewClient(role, looper, creatorClient: Client, creatorWallet: Wallet,
                 name: str):
    wallet = Wallet(name, requestIdStore=TestRequestIdStore())
    wallet.addSigner()
    verstr = wallet.defaultSigner.verstr

    op = {
        TXN_TYPE: NYM,
        ROLE: role,
        TARGET_NYM: verstr,
        ALIAS: name
    }

    req = creatorWallet.signOp(op)
    creatorClient.submitReqs(req)

    nodeCount = len(creatorClient.nodeReg)
    looper.run(eventually(checkSufficientRepliesRecvd, creatorClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=3*nodeCount))
    return wallet

def addNewNode(looper, stewardClient, stewardWallet, newNodeName, tdir, tconf,
               allPluginsPath=None, autoStart=True):
    sigseed = randomString(32).encode()
    nodeSigner = SimpleSigner(seed=sigseed)

    (nodeIp, nodePort), (clientIp, clientPort) = genHa(2)

    op = {
        TXN_TYPE: NEW_NODE,
        TARGET_NYM: nodeSigner.verstr,
        DATA: {
            NODE_IP: nodeIp,
            NODE_PORT: nodePort,
            CLIENT_IP: clientIp,
            CLIENT_PORT: clientPort,
            ALIAS: newNodeName
        }
    }

    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)

    nodeCount = len(stewardClient.nodeReg)
    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=3*nodeCount))
    initLocalKeep(newNodeName, tdir, sigseed, override=True)
    node = TestNode(newNodeName, basedirpath=tdir, config=tconf,
                    ha=(nodeIp, nodePort), cliha=(clientIp, clientPort),
                    pluginPaths=allPluginsPath)
    if autoStart:
        looper.add(node)
    return node

def addNewStewardAndNode(looper, creatorClient, creatorWallet, stewardName,
                         newNodeName, tdir, tconf,
                         allPluginsPath=None, autoStart=True):
    newStewardWallet = addNewClient(STEWARD, looper, creatorClient,
                                    creatorWallet, stewardName)
    newSteward = TestClient(name=stewardName,
                            nodeReg=None, ha=genHa(),
                            # DEPR
                            # signer=newStewardSigner,
                            basedirpath=tdir)

    looper.add(newSteward)
    looper.run(newSteward.ensureConnectedToNodes())
    newNode = addNewNode(looper, newSteward, newStewardWallet, newNodeName,
                         tdir, tconf, allPluginsPath, autoStart=autoStart)
    return newSteward, newStewardWallet, newNode

def changeNodeHa(looper, stewardClient, stewardWallet, node, nodeHa, clientHa):
    nodeNym = hexToCryptonym(node.nodestack.local.signer.verhex)
    (nodeIp, nodePort), (clientIp, clientPort) = nodeHa, clientHa
    op = {
        TXN_TYPE: CHANGE_HA,
        TARGET_NYM: nodeNym,
        DATA: {
            NODE_IP: nodeIp,
            NODE_PORT: nodePort,
            CLIENT_IP: clientIp,
            CLIENT_PORT: clientPort,
            ALIAS: node.name
        }
    }

    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)
    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=5))
    node.nodestack.clearLocalKeep()
    node.nodestack.clearRemoteKeeps()
    node.clientstack.clearLocalKeep()
    node.clientstack.clearRemoteKeeps()

def changeNodeKeys(looper, stewardClient, stewardWallet, node, verkey):
    nodeNym = hexToCryptonym(node.nodestack.local.signer.verhex)

    op = {
        TXN_TYPE: CHANGE_KEYS,
        TARGET_NYM: nodeNym,
        DATA: {
            VERKEY: verkey,
            ALIAS: node.name
        }
    }
    req = stewardWallet.signOp(op)
    stewardClient.submitReqs(req)

    looper.run(eventually(checkSufficientRepliesRecvd, stewardClient.inBox,
                          req.reqId, 1,
                          retryWait=1, timeout=5))
    node.nodestack.clearLocalRoleKeep()
    node.nodestack.clearRemoteRoleKeeps()
    node.nodestack.clearAllDir()
    node.clientstack.clearLocalRoleKeep()
    node.clientstack.clearRemoteRoleKeeps()
    node.clientstack.clearAllDir()

def buildPoolClientAndWallet(clientData, tempDir, clientClass=None,
                             walletClass=None):
    walletClass = walletClass or Wallet
    clientClass = clientClass or TestClient
    name, sigseed = clientData
    w = walletClass(name)
    w.addSigner(seed=sigseed)
    client, _ = genTestClient(name=name, identifier=w.defaultId,
                              tmpdir=tempDir, usePoolLedger=True,
                              testClientClass=clientClass)
    return client, w
<|endoftext|>


<commit_before>from pykka.actor import Actor
from pykka.future import Future, get_all, wait_all
from pykka.proxy import ActorProxy, CallableProxy
from pykka.registry import ActorRegistry

__all__ = ['Actor', 'ActorProxy', 'ActorRegistry', 'CallableProxy', 'Future',
    'get_all', 'wait_all']

VERSION = (0, 4)

def get_version():
    version = '%s.%s' % (VERSION[0], VERSION[1])
    if len(VERSION) > 2:
        version = '%s.%s' % (version, VERSION[2])
    return version
<commit_msg>Release v0.5<commit_after>from pykka.actor import Actor
from pykka.future import Future, get_all, wait_all
from pykka.proxy import ActorProxy, CallableProxy
from pykka.registry import ActorRegistry

__all__ = ['Actor', 'ActorProxy', 'ActorRegistry', 'CallableProxy', 'Future',
    'get_all', 'wait_all']

VERSION = (0, 5)

def get_version():
    version = '%s.%s' % (VERSION[0], VERSION[1])
    if len(VERSION) > 2:
        version = '%s.%s' % (version, VERSION[2])
    return version
<|endoftext|>


<commit_before>from math import sqrt, pi, sin, cos, atan2, acos

def cartesian_2_sphericalPolar(positionVectorCartesian):
    '''Convert cartesian coordinates to radial-azimuthal-polar spherical coordinates, in radians.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Extract the Cartesian vector comopnents.
    x = positionVectorCartesian[0]
    y = positionVectorCartesian[1]
    z = positionVectorCartesian[2]
    #Calculate the radius.
    radius = sqrt(x**2 + y**2 + z**2)
    #Calculate azimuthal (theta) and zenith (phi) angles
    theta = acos(z/radius)
    phi = atan2(y,x)
    return [radius, theta, phi]

def cartesian_2_lonlatradius(positionVectorCartesian):
    '''Convert cartesian coordinates on a sphere to longitude-latitude-radius. Longitude and latitude are returned in degrees.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Calculate azimuthal (phi), polar (theta) angles and distance from origin.
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Claculate longitude and latitude
    lon = phi*180.0/pi
    lat = (pi/2 - theta)*180.0/pi

    positionVectorLonlat = [lon, lat, radius]
    return positionVectorLonlat

def lonlatradius_2_cartesian(positionVectorLonLatRad):
    '''Convert longitude-latitude-radial coordinates on the surface of the Earth (in degrees) to cartesian coordinates. Longitude and latitude must be in degrees.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #Calculate spherical-polar coordinates form longitude-latitude-radius.
    [radius, theta, phi] = lonlatradius_2_sphericalPolar(positionVectorLonLatRad)
    #Calculate Cartesian coordinates from spherical-polar coordinates.
    x = radius*np.sin(theta)*np.cos(phi)
    y = radius*np.sin(theta)*np.sin(phi)
    y = radius*np.cos(theta)
    return [x, y, z]

def lonlatradius_2_sphericalPolar(positionVectorLonLatRad):
    '''Convert longitude-latitude-radial coordinates on the surface of the Earth (in degrees) to cartesian coordinates. Longitude and latitude must be in degrees, the azimuthal and polar angles are returned in radians.'''
    [longitude, latitude, radius] = positionVectorLonLatRad
    #Calculate azimuthal (phi), polar (theta) angles.
    phi = longitude*pi/180.0
    theta = pi/2 - latitude*pi/180.0
    return [radius, theta, phi]

def transform_tensor_sphericalPolar_2_cartesian(positionVectorSpherical, tensor):
    '''Function changing the basis of a tensor from zonal-meridional-radial basis to a cartesian basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    from numpy import linalg
    #extract distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = positionVectorSpherical
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.cos(theta)*np.cos(phi),  -np.sin(phi)],\
                 [np.sin(theta)*np.sin(phi),   np.cos(theta)*np.sin(phi),   np.cos(phi)],\
                 [np.cos(theta),              -np.sin(theta),              0]])
    transposedTransformationMatrix = transformationMatrix.transpose()
    #Calculate the components of the tesnor in the reference system.
    transformed_Tensor = np.dot(transformationMatrix, np.array(tensor))
    transformed_Tensor = np.dot(transformed_Tensor,transposedTransformationMatrix)
    return transformed_Tensor

def transform_tensor_cartesian_2_sphericalPolar(positionVectorCartesian, tensor):
    '''Function transforming the components of a tensor from a cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    from numpy import linalg
    #Calculate azimuthal (theta) and zenith (phi) angles and distance from origin
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.sin(theta)*np.sin(phi),   np.cos(theta)],\
                 [np.cos(theta)*np.cos(phi),   np.cos(theta)*np.sin(phi),  -np.sin(theta)],\
                 [-np.sin(phi),                np.cos(phi),                 0]])
    transposedTransformationMatrix = transformationMatrix.transpose()
    #Calculate the components of the tesnor in the reference system.
    transformed_Tensor = np.dot(transformationMatrix, np.array(tensor))
    transformed_Tensor = np.dot(transformed_Tensor,transposedTransformationMatrix)
    return transformed_Tensor

def transform_tensor_sphericalPolar_2_lon_lat_rad(tensor):
    '''Function transforming the components of a tensor from a spherical-polar basis to a zonal-meridional-radial basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Tensor = np.dot(np.dot(transformationMatrix, np.array(tensor)), transformationMatrix)
    return transformed_Tensor

def transform_tensor_lon_lat_rad_2_sphericalPolar(tensor):
    '''Function transforming the components of a tensor from a zonal-meridional-radial basis to a spherical-polar basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Tensor = np.dot(np.dot(transformationMatrix, np.array(tensor)), transformationMatrix)
    return transformed_Tensor

def transform_tensor_cartesian_2_lon_lat_rad(positionVectorCartesian, tensor):
    '''Function transforming the components of a tensor from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z-axis goes through the North Pole equivalent.'''
    import numpy as np
    #Transform from Cartesian into spherical-polar
    transformed_Tensor = transform_tensor_cartesian_2_sphericalPolar(positionVectorCartesian, tensor)
    #Transform from spherical-polar into longitude-latitude-radius.
    transformed_Tensor = transform_tensor_sphericalPolar_2_lon_lat_rad(transformed_Tensor)
    return transformed_Tensor

def transform_tensor_lon_lat_rad_2_cartesian(positionVectorLonLatRad, tensor):
    '''Function transforming the components of a tensor from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z-axis goes through the North Pole equivalent.'''
    import numpy as np
    #Transform coordinates from lon-lat-rad into spherical-polar.
    positionVectorSpericalPolar = lonlatradius_2_sphericalPolar(positionVectorLonLatRad)
    #Transform tensor from lon-lat-rad into spherical-polar.
    transformed_Tensor = transform_tensor_lon_lat_rad_2_sphericalPolar(tensor)
    #Transform spherical-polar into Cartesian.
    transformed_Tensor = transform_tensor_sphericalPolar_2_cartesian(positionVectorSpericalPolar, transformed_Tensor)
    return transformed_Tensor

def transform_vector_sphericalPolar_2_cartesian(positionVectorSpherical, vector):
    '''Function transforming the components of a vector from a spherical-polar basis to a cartesian basis. The input position vector must be given as [radius, polar angle, azimuthal angle], all anlges specified in radians.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #extract distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = positionVectorSpherical
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.cos(theta)*np.cos(phi),  -np.sin(phi)],\
                 [np.sin(theta)*np.sin(phi),   np.cos(theta)*np.sin(phi),   np.cos(phi)],\
                 [np.cos(theta),              -np.sin(theta),              0]])
    #Calculate the components of the tesnor in the reference system.
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_cartesian_2_sphericalPolar(positionVectorCartesian, vector):
    '''Function transforming the components of a vector from a cartesian basis to a spherical-polar basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #Calculate distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.sin(theta)*np.sin(phi),   np.cos(theta)],\
                 [np.cos(theta)*np.cos(phi),   np.cos(theta)*np.sin(phi),  -np.sin(theta)],\
                 [-np.sin(phi),                np.cos(phi),                 0]])
    #Calculate the components of the tesnor in the reference system.
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_sphericalPolar_2_lon_lat_rad(vector):
    '''Function transforming the components of a vector from a spherical-polar basis to a zonal-meridional-radial basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_lon_lat_rad_2_sphericalPolar(vector):
    '''Function transforming the components of a vector from a zonal-meridional-radial basis to a spherical-polar basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_cartesian_2_lon_lat_rad(positionVectorCartesian, vector):
    '''Function transforming the components of a vector from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Calculate spherical-polar components of the vector.
    transformed_Vector = transform_vector_cartesian_2_sphericalPolar(positionVectorCartesian, vector)
    #Calculate zonal, meridional and radial components of the vector.
    transformed_Vector = transform_vector_sphericalPolar_2_lon_lat_rad(transformed_Vector)
    return transformed_Vector

def transform_vector_lon_lat_rad_2_cartesian(positionVectorRadLonLat, vector):
    '''Function transforming the components of a vector from a zonal-meridional-radial basis into a Cartesian basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Transform coordinates from longitude-latitude-radius into spherical-polar
    positionVectorSpherical = lonlatradius_2_sphericalPolar(positionVectorRadLonLat)
    #Transform vector from longitude-latitude-radius into spherical-polar
    transformed_Vector = transform_vector_lon_lat_rad_2_sphericalPolar(vector)
    #Transform from spherical-polar into Cartesian
    transformed_Vector = transform_vector_sphericalPolar_2_cartesian(positionVectorSpherical, vector)
<commit_msg>Added licence notice to file.<commit_after>#    Copyright (C) 2012 Imperial College London and others.
#
#    Please see the AUTHORS file in the main source directory for a full list
#    of copyright holders.
#
#    Prof. C Pain
#    Applied Modelling and Computation Group
#    Department of Earth Science and Engineering
#    Imperial College London
#
#    amcgsoftware@imperial.ac.uk
#
#    This library is free software; you can redistribute it and/or
#    modify it under the terms of the GNU Lesser General Public
#    License as published by the Free Software Foundation,
#    version 2.1 of the License.
#
#    This library is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with this library; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
#    USA
from math import sqrt, pi, sin, cos, atan2, acos

def cartesian_2_sphericalPolar(positionVectorCartesian):
    '''Convert cartesian coordinates to radial-azimuthal-polar spherical coordinates, in radians.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Extract the Cartesian vector comopnents.
    x = positionVectorCartesian[0]
    y = positionVectorCartesian[1]
    z = positionVectorCartesian[2]
    #Calculate the radius.
    radius = sqrt(x**2 + y**2 + z**2)
    #Calculate azimuthal (theta) and zenith (phi) angles
    theta = acos(z/radius)
    phi = atan2(y,x)
    return [radius, theta, phi]

def cartesian_2_lonlatradius(positionVectorCartesian):
    '''Convert cartesian coordinates on a sphere to longitude-latitude-radius. Longitude and latitude are returned in degrees.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Calculate azimuthal (phi), polar (theta) angles and distance from origin.
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Claculate longitude and latitude
    lon = phi*180.0/pi
    lat = (pi/2 - theta)*180.0/pi

    positionVectorLonlat = [lon, lat, radius]
    return positionVectorLonlat

def lonlatradius_2_cartesian(positionVectorLonLatRad):
    '''Convert longitude-latitude-radial coordinates on the surface of the Earth (in degrees) to cartesian coordinates. Longitude and latitude must be in degrees.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #Calculate spherical-polar coordinates form longitude-latitude-radius.
    [radius, theta, phi] = lonlatradius_2_sphericalPolar(positionVectorLonLatRad)
    #Calculate Cartesian coordinates from spherical-polar coordinates.
    x = radius*np.sin(theta)*np.cos(phi)
    y = radius*np.sin(theta)*np.sin(phi)
    y = radius*np.cos(theta)
    return [x, y, z]

def lonlatradius_2_sphericalPolar(positionVectorLonLatRad):
    '''Convert longitude-latitude-radial coordinates on the surface of the Earth (in degrees) to cartesian coordinates. Longitude and latitude must be in degrees, the azimuthal and polar angles are returned in radians.'''
    [longitude, latitude, radius] = positionVectorLonLatRad
    #Calculate azimuthal (phi), polar (theta) angles.
    phi = longitude*pi/180.0
    theta = pi/2 - latitude*pi/180.0
    return [radius, theta, phi]

def transform_tensor_sphericalPolar_2_cartesian(positionVectorSpherical, tensor):
    '''Function changing the basis of a tensor from zonal-meridional-radial basis to a cartesian basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    from numpy import linalg
    #extract distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = positionVectorSpherical
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.cos(theta)*np.cos(phi),  -np.sin(phi)],\
                 [np.sin(theta)*np.sin(phi),   np.cos(theta)*np.sin(phi),   np.cos(phi)],\
                 [np.cos(theta),              -np.sin(theta),              0]])
    transposedTransformationMatrix = transformationMatrix.transpose()
    #Calculate the components of the tesnor in the reference system.
    transformed_Tensor = np.dot(transformationMatrix, np.array(tensor))
    transformed_Tensor = np.dot(transformed_Tensor,transposedTransformationMatrix)
    return transformed_Tensor

def transform_tensor_cartesian_2_sphericalPolar(positionVectorCartesian, tensor):
    '''Function transforming the components of a tensor from a cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    from numpy import linalg
    #Calculate azimuthal (theta) and zenith (phi) angles and distance from origin
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.sin(theta)*np.sin(phi),   np.cos(theta)],\
                 [np.cos(theta)*np.cos(phi),   np.cos(theta)*np.sin(phi),  -np.sin(theta)],\
                 [-np.sin(phi),                np.cos(phi),                 0]])
    transposedTransformationMatrix = transformationMatrix.transpose()
    #Calculate the components of the tesnor in the reference system.
    transformed_Tensor = np.dot(transformationMatrix, np.array(tensor))
    transformed_Tensor = np.dot(transformed_Tensor,transposedTransformationMatrix)
    return transformed_Tensor

def transform_tensor_sphericalPolar_2_lon_lat_rad(tensor):
    '''Function transforming the components of a tensor from a spherical-polar basis to a zonal-meridional-radial basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Tensor = np.dot(np.dot(transformationMatrix, np.array(tensor)), transformationMatrix)
    return transformed_Tensor

def transform_tensor_lon_lat_rad_2_sphericalPolar(tensor):
    '''Function transforming the components of a tensor from a zonal-meridional-radial basis to a spherical-polar basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Tensor = np.dot(np.dot(transformationMatrix, np.array(tensor)), transformationMatrix)
    return transformed_Tensor

def transform_tensor_cartesian_2_lon_lat_rad(positionVectorCartesian, tensor):
    '''Function transforming the components of a tensor from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z-axis goes through the North Pole equivalent.'''
    import numpy as np
    #Transform from Cartesian into spherical-polar
    transformed_Tensor = transform_tensor_cartesian_2_sphericalPolar(positionVectorCartesian, tensor)
    #Transform from spherical-polar into longitude-latitude-radius.
    transformed_Tensor = transform_tensor_sphericalPolar_2_lon_lat_rad(transformed_Tensor)
    return transformed_Tensor

def transform_tensor_lon_lat_rad_2_cartesian(positionVectorLonLatRad, tensor):
    '''Function transforming the components of a tensor from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z-axis goes through the North Pole equivalent.'''
    import numpy as np
    #Transform coordinates from lon-lat-rad into spherical-polar.
    positionVectorSpericalPolar = lonlatradius_2_sphericalPolar(positionVectorLonLatRad)
    #Transform tensor from lon-lat-rad into spherical-polar.
    transformed_Tensor = transform_tensor_lon_lat_rad_2_sphericalPolar(tensor)
    #Transform spherical-polar into Cartesian.
    transformed_Tensor = transform_tensor_sphericalPolar_2_cartesian(positionVectorSpericalPolar, transformed_Tensor)
    return transformed_Tensor

def transform_vector_sphericalPolar_2_cartesian(positionVectorSpherical, vector):
    '''Function transforming the components of a vector from a spherical-polar basis to a cartesian basis. The input position vector must be given as [radius, polar angle, azimuthal angle], all anlges specified in radians.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #extract distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = positionVectorSpherical
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.cos(theta)*np.cos(phi),  -np.sin(phi)],\
                 [np.sin(theta)*np.sin(phi),   np.cos(theta)*np.sin(phi),   np.cos(phi)],\
                 [np.cos(theta),              -np.sin(theta),              0]])
    #Calculate the components of the tesnor in the reference system.
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_cartesian_2_sphericalPolar(positionVectorCartesian, vector):
    '''Function transforming the components of a vector from a cartesian basis to a spherical-polar basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    import numpy as np
    #Calculate distance from origin, polar (theta) angles and azimuthal (phi) angles.
    [radius, theta, phi] = cartesian_2_sphericalPolar(positionVectorCartesian)
    #Evaluate components of rotation matrices.
    transformationMatrix =\
       np.array([\
                 [np.sin(theta)*np.cos(phi),   np.sin(theta)*np.sin(phi),   np.cos(theta)],\
                 [np.cos(theta)*np.cos(phi),   np.cos(theta)*np.sin(phi),  -np.sin(theta)],\
                 [-np.sin(phi),                np.cos(phi),                 0]])
    #Calculate the components of the tesnor in the reference system.
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_sphericalPolar_2_lon_lat_rad(vector):
    '''Function transforming the components of a vector from a spherical-polar basis to a zonal-meridional-radial basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_lon_lat_rad_2_sphericalPolar(vector):
    '''Function transforming the components of a vector from a zonal-meridional-radial basis to a spherical-polar basis.'''
    import numpy as np
    #The requested transformation is just a reflection followed by a change in the order
    # of the components in order to get a right-handed system.
    transformationMatrix = np.array([[ 0.0, 0.0, 1.0 ],\
                                     [ 0.0,-1.0, 0.0 ],\
                                     [ 1.0, 0.0, 0.0 ]])
    transformed_Vector = np.dot(transformationMatrix, np.array(vector))
    return transformed_Vector

def transform_vector_cartesian_2_lon_lat_rad(positionVectorCartesian, vector):
    '''Function transforming the components of a vector from a Cartesian basis to a zonal-meridional-radial basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Calculate spherical-polar components of the vector.
    transformed_Vector = transform_vector_cartesian_2_sphericalPolar(positionVectorCartesian, vector)
    #Calculate zonal, meridional and radial components of the vector.
    transformed_Vector = transform_vector_sphericalPolar_2_lon_lat_rad(transformed_Vector)
    return transformed_Vector

def transform_vector_lon_lat_rad_2_cartesian(positionVectorRadLonLat, vector):
    '''Function transforming the components of a vector from a zonal-meridional-radial basis into a Cartesian basis.

The origin of the Cartesian frame of reference is located at the centre of the sphere, the positive half of x-axis goes through 0 deg E, 0 deg N, the positive half of y-axis goes through 90 deg E, 0 deg N and the positive half of the z axis goes through the North Pole equivalent.'''
    #Transform coordinates from longitude-latitude-radius into spherical-polar
    positionVectorSpherical = lonlatradius_2_sphericalPolar(positionVectorRadLonLat)
    #Transform vector from longitude-latitude-radius into spherical-polar
    transformed_Vector = transform_vector_lon_lat_rad_2_sphericalPolar(vector)
    #Transform from spherical-polar into Cartesian
    transformed_Vector = transform_vector_sphericalPolar_2_cartesian(positionVectorSpherical, vector)
<|endoftext|>