<commit_before>from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

def home(request):
    """
    this will render the home page
    :param request:
    :return: home page of the project
    """
    return render(request, 'home.html')

@csrf_exempt
def do_deploy(request):
    """
    deploys on the server after github sends a POST-Receive hook.
    This is initiated by a push on the master branch on github.
    :param request: JSON encoded payload sent by github.
    """
    import simplejson
    import subprocess

    from django.http import HttpResponse, Http404
    from django.conf import settings

    if request.method != 'POST':
        raise Http404

    if not 'payload' in request.POST.keys():
        raise Http404

    payload = simplejson.loads(request.POST['payload'])

    out_json = {'status':'failed'}

    if payload['ref'] == 'refs/heads/master':
        DEPLOY_SCRIPT = getattr(settings,"DEPLOY_SCRIPT", "echo 0")
        subprocess.call(settings.DEPLOY_SCRIPT)
        out_json = {'status' : 'success'}

    return HttpResponse(simplejson.dumps(out_json), content_type='application/json')

@csrf_exempt
def random_schedules(request):
    """
    Random schedule generator
    :param request: JSON encoded payload sent by github.
    """

    from django.http import HttpResponse, Http404

    if request.method != 'GET':
        raise Http404
    import facades
    a = facades.getSubjectsByName("Algoritmos","PRE")[0]
    b = facades.getSubjectsByName("Seguridad en redes","PRE")[0]
    c = facades.getSubjectsByName("Lenguajes de programacion","PRE")[0]

    s = [a.code,b.code,c.code]

    s = facades.getSchedulesBySubjectCodes(s)

    from serializers import ScheduleSerializer
    serializer = ScheduleSerializer()
    return HttpResponse(serializer.serialize(s[0]), content_type='application/json')

@csrf_exempt
def autocomplete_subject(request):
    """
    :param request: JSON with a name parameter
    """
    import simplejson

    from django.http import HttpResponse, Http404

    if request.method != 'POST':
        raise Http404

    request_data = simplejson.loads(request.body)
    if "name" in request_data:
        data = request_data["name"]
        import facades
        subjects = facades.autocomplete(data)

    from serializers import SimpleSubjectsSerializer
    serializer = SimpleSubjectsSerializer()

    return HttpResponse(serializer.serialize(subjects), content_type='application/json')

class RandomScheduleView(APIView):
    def get(self, request, *args, **kw):
        import facades
        a = facades.getSubjectsByName("Algoritmos","PRE")[0]
        b = facades.getSubjectsByName("Seguridad en redes","PRE")[0]
        c = facades.getSubjectsByName("Lenguajes de programacion","PRE")[0]

        s = [a.code,b.code,c.code]

        s = facades.getSchedulesBySubjectCodes(s)

        from serializers import ScheduleSerializer
        serializer = ScheduleSerializer()
        return Response(serializer.serialize(s), status = status.HTTP_200_OK)

class SubjectAutocompleteView(APIView):
    def get(self, request, *args , **kw):
        name = kw['name']
        import facades
        subjects = facades.autocomplete(name)
        from serializers import SimpleSubjectsSerializer
        serializer = SimpleSubjectsSerializer()
        return Response(serializer.serialize(subjects), status = status.HTTP_200_OK)

class GroupsView(APIView):
    def get(self, request, *args , **kw):
        code = kw['subjectCode']
        import facades
        groups = facades.getGroupsBySubjectCode(code)
        from serializers import GroupSerializer
        serializer = GroupSerializer()
        return Response(serializer.serialize(groups), status = status.HTTP_200_OK)

def getScheduleFromQuery(subjects,busy):

    def parseSubjects(string):
        string = string.split(",")
        query = []
        for i in string:
            parts = i.split("|")
            subject = {"code" : str(int(parts[0])), "groups" : None}
            if(len(parts)>1):
                subject["groups"] = []
            for j in range(1,len(parts)):
                subject["groups"].append(int(parts[j]))
            query.append(subject)
        return query

    def parseBusy(string):
        ret = []
        hours = string.split(",")
        if(len(hours)!=7):
            return None
        else:
            for i in hours:
                ret.append(int(i))
            return ret

    import facades
    return facades.getSchedulesByQuery(parseSubjects(subjects),parseBusy(busy));

class SchedulesView(APIView):
    def get(self, request, *args , **kw):
        subjects = kw['subjects']
        busy = kw['busy']
        if(len(subjects)<1):
            return Response([], status = status.HTTP_200_OK)
        try:
            s = getScheduleFromQuery(subjects,busy)
        except Exception:
            return Response([], status = status.HTTP_200_OK)
        from serializers import ScheduleSerializer
        serializer = ScheduleSerializer()
        return Response(serializer.serialize(s), status = status.HTTP_200_OK)

def getICS(request,*args,**kw):
    from django.http import HttpResponse
    subjects = kw['subjects']
    busy = kw['busy']
    schedule = int(kw['schedule'])
    if(len(subjects)<1):
        return Response([], status = status.HTTP_200_OK)
    try:
        s = getScheduleFromQuery(subjects,busy)
    except Exception:
        return Response([], status = status.HTTP_200_OK)
    if(len(s) < schedule):
        return HttpResponse("Wrong schedule number. There are " + str(len(s)) + " < " + str(schedule) + " schedules", status = status.HTTP_200_OK)
    import Helpers
    response = HttpResponse(Helpers.getIcsFromSchedule(s[schedule]),mimetype='application/ics')
    response['Content-Disposition'] = 'attachment; filename=horario.ics'
    return response
<commit_msg>gziping content<commit_after>from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.gzip import gzip_page
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

@gzip_page
def home(request):
    """
    this will render the home page
    :param request:
    :return: home page of the project
    """
    return render(request, 'home.html')

@csrf_exempt
def do_deploy(request):
    """
    deploys on the server after github sends a POST-Receive hook.
    This is initiated by a push on the master branch on github.
    :param request: JSON encoded payload sent by github.
    """
    import simplejson
    import subprocess

    from django.http import HttpResponse, Http404
    from django.conf import settings

    if request.method != 'POST':
        raise Http404

    if not 'payload' in request.POST.keys():
        raise Http404

    payload = simplejson.loads(request.POST['payload'])

    out_json = {'status':'failed'}

    if payload['ref'] == 'refs/heads/master':
        DEPLOY_SCRIPT = getattr(settings,"DEPLOY_SCRIPT", "echo 0")
        subprocess.call(settings.DEPLOY_SCRIPT)
        out_json = {'status' : 'success'}

    return HttpResponse(simplejson.dumps(out_json), content_type='application/json')

@gzip_page
@csrf_exempt
def random_schedules(request):
    """
    Random schedule generator
    :param request: JSON encoded payload sent by github.
    """

    from django.http import HttpResponse, Http404

    if request.method != 'GET':
        raise Http404
    import facades
    a = facades.getSubjectsByName("Algoritmos","PRE")[0]
    b = facades.getSubjectsByName("Seguridad en redes","PRE")[0]
    c = facades.getSubjectsByName("Lenguajes de programacion","PRE")[0]

    s = [a.code,b.code,c.code]

    s = facades.getSchedulesBySubjectCodes(s)

    from serializers import ScheduleSerializer
    serializer = ScheduleSerializer()
    return HttpResponse(serializer.serialize(s[0]), content_type='application/json')

@gzip_page
@csrf_exempt
def autocomplete_subject(request):
    """
    :param request: JSON with a name parameter
    """
    import simplejson

    from django.http import HttpResponse, Http404

    if request.method != 'POST':
        raise Http404

    request_data = simplejson.loads(request.body)
    if "name" in request_data:
        data = request_data["name"]
        import facades
        subjects = facades.autocomplete(data)

    from serializers import SimpleSubjectsSerializer
    serializer = SimpleSubjectsSerializer()

    return HttpResponse(serializer.serialize(subjects), content_type='application/json')

@gzip_page
class RandomScheduleView(APIView):
    def get(self, request, *args, **kw):
        import facades
        a = facades.getSubjectsByName("Algoritmos","PRE")[0]
        b = facades.getSubjectsByName("Seguridad en redes","PRE")[0]
        c = facades.getSubjectsByName("Lenguajes de programacion","PRE")[0]

        s = [a.code,b.code,c.code]

        s = facades.getSchedulesBySubjectCodes(s)

        from serializers import ScheduleSerializer
        serializer = ScheduleSerializer()
        return Response(serializer.serialize(s), status = status.HTTP_200_OK)

@gzip_page
class SubjectAutocompleteView(APIView):
    def get(self, request, *args , **kw):
        name = kw['name']
        import facades
        subjects = facades.autocomplete(name)
        from serializers import SimpleSubjectsSerializer
        serializer = SimpleSubjectsSerializer()
        return Response(serializer.serialize(subjects), status = status.HTTP_200_OK)

@gzip_page
class GroupsView(APIView):
    def get(self, request, *args , **kw):
        code = kw['subjectCode']
        import facades
        groups = facades.getGroupsBySubjectCode(code)
        from serializers import GroupSerializer
        serializer = GroupSerializer()
        return Response(serializer.serialize(groups), status = status.HTTP_200_OK)

@gzip_page
def getScheduleFromQuery(subjects,busy):

    def parseSubjects(string):
        string = string.split(",")
        query = []
        for i in string:
            parts = i.split("|")
            subject = {"code" : str(int(parts[0])), "groups" : None}
            if(len(parts)>1):
                subject["groups"] = []
            for j in range(1,len(parts)):
                subject["groups"].append(int(parts[j]))
            query.append(subject)
        return query

    def parseBusy(string):
        ret = []
        hours = string.split(",")
        if(len(hours)!=7):
            return None
        else:
            for i in hours:
                ret.append(int(i))
            return ret

    import facades
    return facades.getSchedulesByQuery(parseSubjects(subjects),parseBusy(busy));

@gzip_page
class SchedulesView(APIView):
    def get(self, request, *args , **kw):
        subjects = kw['subjects']
        busy = kw['busy']
        if(len(subjects)<1):
            return Response([], status = status.HTTP_200_OK)
        try:
            s = getScheduleFromQuery(subjects,busy)
        except Exception:
            return Response([], status = status.HTTP_200_OK)
        from serializers import ScheduleSerializer
        serializer = ScheduleSerializer()
        return Response(serializer.serialize(s), status = status.HTTP_200_OK)

def getICS(request,*args,**kw):
    from django.http import HttpResponse
    subjects = kw['subjects']
    busy = kw['busy']
    schedule = int(kw['schedule'])
    if(len(subjects)<1):
        return Response([], status = status.HTTP_200_OK)
    try:
        s = getScheduleFromQuery(subjects,busy)
    except Exception:
        return Response([], status = status.HTTP_200_OK)
    if(len(s) < schedule):
        return HttpResponse("Wrong schedule number. There are " + str(len(s)) + " < " + str(schedule) + " schedules", status = status.HTTP_200_OK)
    import Helpers
    response = HttpResponse(Helpers.getIcsFromSchedule(s[schedule]),mimetype='application/ics')
    response['Content-Disposition'] = 'attachment; filename=horario.ics'
    return response
<|endoftext|>


<commit_before># Copyright 2014 ARM Limited
#
# Licensed under the Apache License, Version 2.0
# See LICENSE file for details.

# standard library modules, , ,
from __future__ import print_function
import logging
import os
import json

# colorama, BSD 3-Clause license, cross-platform terminal colours, pip install colorama
import colorama

# validate, , validate things, internal
from .lib import validate
# access, , get components (and check versions), internal
from .lib import access
# fsutils, , misc filesystem utils, internal
from .lib import fsutils

def addOptions(parser):
    parser.add_argument('--all', '-a', dest='show_all', default=False, action='store_true',
        help='Show all dependencies (including repeats, and test-only dependencies)'
    )
    parser.add_argument('--json', '-j', dest='json', default=False, action='store_true',
        help='Output json representation of dependencies.'
    )

def execCommand(args, following_args):
    c = validate.currentDirectoryModule()
    if not c:
        return 1

    if not args.target:
        logging.error('No target has been set, use "yotta target" to set one.')
        return 1

    target, errors = c.satisfyTarget(args.target)
    if errors:
        for error in errors:
            logging.error(error)
        return 1

    dependencies = c.getDependenciesRecursive(
                      target = target,
        available_components = [(c.getName(), c)],
                        test = True
    )
    if args.json:
        putln(formatJsonDeps(target, dependencies, args.show_all))
    else:
        putln(
            ComponentDepsFormatter(
                               target = target,
                 available_components = dependencies,
                                plain = args.plain,
                             list_all = args.show_all
            ).format(
                c, [c.getName()]
            )
        )

def formatJsonDeps(target, available_components, list_all):
    d = {}
    for c in available_components:
        co = available_components[c]
        d[c] = {}
        d[c]['name'] = co.getName()
        d[c]['version'] = str(co.getVersion())
        d[c]['dependencies'] = {}
        for dep in co.getDependencySpecs(target=target):
            depcomp = available_components[dep.name]
            spec = access.remoteComponentFor(dep.name, dep.version_req, 'modules').versionSpec()
            dd = {
                'verspec':dep.version_req,
                   'test':dep.is_test_dependency,
                'missing':not available_components[dep.name],
               'mismatch':not spec.match(depcomp.getVersion()),
                   'link':co.installedLinked()
            }
            d[c]['dependencies'][dep.name]=dd
    return json.dumps(d)

def islast(generator):
    next_x = None
    first = True
    for x in generator:
        if not first:
            yield (next_x, False)
        next_x = x
        first = False
    if not first:
        yield (next_x, True)

def putln(x):
    if u'unicode' in str(type(x)):
        # python 2.7
        print(x.encode('utf-8'))
    else:
        print(x)

def relpathIfSubdir(path):
    relpath = os.path.relpath(path)
    if relpath.startswith('..'):
        return path
    else:
        return relpath

class ComponentDepsFormatter(object):
    def __init__(self, target=None, available_components=None, list_all=False, plain=False):
        # don't even try to do Unicode on windows. Even if we can encode it
        # correctly, the default terminal fonts don't support Unicode
        # characters :(
        self.use_unicode = not ((os.name == 'nt') or plain)
        self.use_colours = not plain
        self.target    = target
        self.list_all  = list_all
        self.available = available_components
        if plain:
            self.L_Char = u' '
            self.T_Char = u' '
            self.Dash_Char = u' '
            self.Pipe_Char = u' '
        elif self.use_unicode:
            self.L_Char = u'\u2517'
            self.T_Char = u'\u2523'
            self.Dash_Char = u'\u2500'
            self.Pipe_Char = u'\u2503'
        else:
            self.L_Char = u'\\'
            self.T_Char = u'|'
            self.Dash_Char = u'_'
            self.Pipe_Char = u'|'
        super(ComponentDepsFormatter, self).__init__()

    def format(
        self,
        component,
        processed,
        indent=u'',
        tee=u'',
        installed_at=u'',
        test_dep=False,
        spec=None
    ):
        r = u''

        if self.use_colours:
            DIM    = colorama.Style.DIM       #pylint: disable=no-member
            BRIGHT = colorama.Style.BRIGHT    #pylint: disable=no-member
            GREEN  = colorama.Fore.GREEN      #pylint: disable=no-member
            RED    = colorama.Fore.RED        #pylint: disable=no-member
            RESET  = colorama.Style.RESET_ALL #pylint: disable=no-member
        else:
            DIM = BRIGHT = GREEN = RED = RESET = u''

        mods_path = component.modulesPath()
        deps = component.getDependencies(
                available_components = self.available,
                              target = self.target,
                                test = True,
                            warnings = False
        )
        specs = dict([(x.name, x) for x in component.getDependencySpecs(target=self.target)])

        def isTestOnly(name):
            return specs[name].is_test_dependency

        def shouldDisplay(x):
            if self.list_all:
                # list everything everywhere (apart from test dependencies of test
                # dependencies, which should be considered irrelevant)
                if component.isTestDependency() and isTestOnly(x[0]):
                    return False
                else:
                    return True
            if (not isTestOnly(x[0]) or not len(indent)):
                # this is non-test dependency, or a top-level test dependency
                if not x[1]:
                    # if it's missing, display it
                    return True
                if x[1].path == os.path.join(mods_path, x[0]):
                    # if it's installed in this module, display it
                    return True
                if x[0] in deps_here:
                    # if it's first depended on by this module, then display it
                    return True
            # everything else shouldn't be displayed here
            return False

        line = indent[:-2] + tee + component.getName() + u' ' + DIM + str(component.getVersion()) + RESET

        if spec and not spec.match(component.getVersion()):
            line += u' ' + RESET + BRIGHT + RED + str(spec) + RESET
        if test_dep:
            line += u' ' + DIM + u'(test dependency)' + RESET
        if len(installed_at):
            line += u' ' + DIM + installed_at + RESET
        if component.installedLinked():
            line += GREEN + BRIGHT + u' -> ' + RESET + GREEN + fsutils.realpath(component.path) + RESET

        r += line + '\n'

        deps_here  = [x for x in list(deps.keys()) if (x not in processed)]
        print_deps = [x for x in list(deps.items()) if shouldDisplay(x)]

        processed += [x[0] for x in print_deps]

        for (name, dep), last in islast(print_deps):
            if last:
                next_indent = indent + u'  '
                tee = self.L_Char + self.Dash_Char + u' '
                next_tee = self.L_Char + self.Dash_Char + u' '
            else:
                next_indent = indent + self.Pipe_Char + u' '
                tee = self.T_Char + self.Dash_Char + u' '
                next_tee = self.T_Char + self.Dash_Char + u' '
            test_dep_status = u''
            if isTestOnly(name):
                test_dep_status = u' (test dependency)'

            if not dep:
                r += indent + tee + name + u' ' + specs[name].version_req + test_dep_status + BRIGHT + RED + ' missing' + RESET + '\n'
            else:
                spec = access.remoteComponentFor(name, specs[name].version_req, 'modules').versionSpec()
                if not spec:
                    spec_descr = u''
                elif spec.match(dep.getVersion()):
                    spec_descr = u' ' + str(spec)
                else:
                    spec_descr = u' ' + RESET + BRIGHT + RED + str(spec)
                spec_descr += test_dep_status

                if name in deps_here:
                    # dependencies that are first used here may actually be
                    # installed higher up our dependency tree, if they are,
                    # illustrate that:
                    if dep.path == os.path.join(mods_path, name):
                        r += self.format(
                                       dep,
                                 processed,
                               next_indent,
                                  next_tee,
                                  test_dep = isTestOnly(name),
                                      spec = spec
                        )
                    else:
                        r += self.format(
                                       dep,
                                 processed,
                               next_indent,
                                  next_tee,
                              installed_at = relpathIfSubdir(dep.path),
                                  test_dep = isTestOnly(name),
                                      spec = spec
                        )
                else:
                    r += indent + tee + DIM + name + spec_descr + RESET + '\n'
        return r
<commit_msg>revised proposed json format<commit_after># Copyright 2014 ARM Limited
#
# Licensed under the Apache License, Version 2.0
# See LICENSE file for details.

# standard library modules, , ,
from __future__ import print_function
import logging
import os

# colorama, BSD 3-Clause license, cross-platform terminal colours, pip install colorama
import colorama

# validate, , validate things, internal
from .lib import validate
# access, , get components (and check versions), internal
from .lib import access
# fsutils, , misc filesystem utils, internal
from .lib import fsutils

def addOptions(parser):
    parser.add_argument('--all', '-a', dest='show_all', default=False, action='store_true',
        help='Show all dependencies (including repeats, and test-only dependencies)'
    )
    parser.add_argument('--json', '-j', dest='json', default=False, action='store_true',
        help='Output json representation of dependencies.'
    )

def execCommand(args, following_args):
    c = validate.currentDirectoryModule()
    if not c:
        return 1

    if not args.target:
        logging.error('No target has been set, use "yotta target" to set one.')
        return 1

    target, errors = c.satisfyTarget(args.target)
    if errors:
        for error in errors:
            logging.error(error)
        return 1

    installed_modules = c.getDependenciesRecursive(
                      target = target,
        available_components = [(c.getName(), c)],
                        test = True
    )
    if args.json:
        dependency_graph = resolveDependencyGraph(target, c, installed_modules)
        print(formatDependencyGraphAsJSON(dependency_graph))
    else:
        putln(
            ComponentDepsFormatter(
                               target = target,
                 available_components = installed_modules,
                                plain = args.plain,
                             list_all = args.show_all
            ).format(
                c, [c.getName()]
            )
        )

def formatDependencyGraphAsJSON(dep_graph):
    from .lib import ordered_json
    return ordered_json.dumps(dep_graph)

def resolveDependencyGraph(target, top_component, available_modules, processed=None):
    from collections import OrderedDict
    r = OrderedDict()

    if processed is None:
        processed = set()

    r['name']     = top_component.getName(),
    r['version']  = str(top_component.getVersion())
    r['path']     = top_component.path
    if top_component.installedLinked():
        r['linkedTo'] = fsutils.realpath(top_component.path)

    specs = dict([(x.name, x) for x in top_component.getDependencySpecs(target=target)])
    deps = top_component.getDependencies(
        available_components = available_modules,
                      target = target,
                        test = True,
                    warnings = False
    )
    if not top_component:
        r['errors'] = [top_component.getError()]
    if not top_component.getName() in processed:
        processed.add(top_component.getName())
        dependencies = OrderedDict()
        for name, dep in deps.items():
            dependencies[name] = resolveDependencyGraph(target, dep, available_modules, processed=processed)
            dependencies[name]['specification'] = str(specs[name].version_req)
            if specs[name].is_test_dependency:
                dependencies[name]['testOnly'] = True
        if len(dependencies):
            r['dependencies'] = dependencies
    return r

def islast(generator):
    next_x = None
    first = True
    for x in generator:
        if not first:
            yield (next_x, False)
        next_x = x
        first = False
    if not first:
        yield (next_x, True)

def putln(x):
    if u'unicode' in str(type(x)):
        # python 2.7
        print(x.encode('utf-8'))
    else:
        print(x)

def relpathIfSubdir(path):
    relpath = os.path.relpath(path)
    if relpath.startswith('..'):
        return path
    else:
        return relpath

class ComponentDepsFormatter(object):
    def __init__(self, target=None, available_components=None, list_all=False, plain=False):
        # don't even try to do Unicode on windows. Even if we can encode it
        # correctly, the default terminal fonts don't support Unicode
        # characters :(
        self.use_unicode = not ((os.name == 'nt') or plain)
        self.use_colours = not plain
        self.target    = target
        self.list_all  = list_all
        self.available = available_components
        if plain:
            self.L_Char = u' '
            self.T_Char = u' '
            self.Dash_Char = u' '
            self.Pipe_Char = u' '
        elif self.use_unicode:
            self.L_Char = u'\u2517'
            self.T_Char = u'\u2523'
            self.Dash_Char = u'\u2500'
            self.Pipe_Char = u'\u2503'
        else:
            self.L_Char = u'\\'
            self.T_Char = u'|'
            self.Dash_Char = u'_'
            self.Pipe_Char = u'|'
        super(ComponentDepsFormatter, self).__init__()

    def format(
        self,
        component,
        processed,
        indent=u'',
        tee=u'',
        installed_at=u'',
        test_dep=False,
        spec=None
    ):
        r = u''

        if self.use_colours:
            DIM    = colorama.Style.DIM       #pylint: disable=no-member
            BRIGHT = colorama.Style.BRIGHT    #pylint: disable=no-member
            GREEN  = colorama.Fore.GREEN      #pylint: disable=no-member
            RED    = colorama.Fore.RED        #pylint: disable=no-member
            RESET  = colorama.Style.RESET_ALL #pylint: disable=no-member
        else:
            DIM = BRIGHT = GREEN = RED = RESET = u''

        mods_path = component.modulesPath()
        deps = component.getDependencies(
                available_components = self.available,
                              target = self.target,
                                test = True,
                            warnings = False
        )
        specs = dict([(x.name, x) for x in component.getDependencySpecs(target=self.target)])

        def isTestOnly(name):
            return specs[name].is_test_dependency

        def shouldDisplay(x):
            if self.list_all:
                # list everything everywhere (apart from test dependencies of test
                # dependencies, which should be considered irrelevant)
                if component.isTestDependency() and isTestOnly(x[0]):
                    return False
                else:
                    return True
            if (not isTestOnly(x[0]) or not len(indent)):
                # this is non-test dependency, or a top-level test dependency
                if not x[1]:
                    # if it's missing, display it
                    return True
                if x[1].path == os.path.join(mods_path, x[0]):
                    # if it's installed in this module, display it
                    return True
                if x[0] in deps_here:
                    # if it's first depended on by this module, then display it
                    return True
            # everything else shouldn't be displayed here
            return False

        line = indent[:-2] + tee + component.getName() + u' ' + DIM + str(component.getVersion()) + RESET

        if spec and not spec.match(component.getVersion()):
            line += u' ' + RESET + BRIGHT + RED + str(spec) + RESET
        if test_dep:
            line += u' ' + DIM + u'(test dependency)' + RESET
        if len(installed_at):
            line += u' ' + DIM + installed_at + RESET
        if component.installedLinked():
            line += GREEN + BRIGHT + u' -> ' + RESET + GREEN + fsutils.realpath(component.path) + RESET

        r += line + '\n'

        deps_here  = [x for x in list(deps.keys()) if (x not in processed)]
        print_deps = [x for x in list(deps.items()) if shouldDisplay(x)]

        processed += [x[0] for x in print_deps]

        for (name, dep), last in islast(print_deps):
            if last:
                next_indent = indent + u'  '
                tee = self.L_Char + self.Dash_Char + u' '
                next_tee = self.L_Char + self.Dash_Char + u' '
            else:
                next_indent = indent + self.Pipe_Char + u' '
                tee = self.T_Char + self.Dash_Char + u' '
                next_tee = self.T_Char + self.Dash_Char + u' '
            test_dep_status = u''
            if isTestOnly(name):
                test_dep_status = u' (test dependency)'

            if not dep:
                r += indent + tee + name + u' ' + specs[name].version_req + test_dep_status + BRIGHT + RED + ' missing' + RESET + '\n'
            else:
                spec = access.remoteComponentFor(name, specs[name].version_req, 'modules').versionSpec()
                if not spec:
                    spec_descr = u''
                elif spec.match(dep.getVersion()):
                    spec_descr = u' ' + str(spec)
                else:
                    spec_descr = u' ' + RESET + BRIGHT + RED + str(spec)
                spec_descr += test_dep_status

                if name in deps_here:
                    # dependencies that are first used here may actually be
                    # installed higher up our dependency tree, if they are,
                    # illustrate that:
                    if dep.path == os.path.join(mods_path, name):
                        r += self.format(
                                       dep,
                                 processed,
                               next_indent,
                                  next_tee,
                                  test_dep = isTestOnly(name),
                                      spec = spec
                        )
                    else:
                        r += self.format(
                                       dep,
                                 processed,
                               next_indent,
                                  next_tee,
                              installed_at = relpathIfSubdir(dep.path),
                                  test_dep = isTestOnly(name),
                                      spec = spec
                        )
                else:
                    r += indent + tee + DIM + name + spec_descr + RESET + '\n'
        return r
<|endoftext|>


<commit_before>from flask import Flask, redirect, render_template, request
from druvw import xyz, uvw
import pandas as pd
from bokeh.plotting import figure, gridplot
from bokeh.embed import components
from bokeh.models import ColumnDataSource

app = Flask(__name__)

# Global Variables
app.vars = dict()
app.vars['ra'] = '165.46627797'
app.vars['dec'] = '-34.70473119'
app.vars['pmra'] = '-66.19'
app.vars['pmdec'] = '-13.90'
app.vars['rv'] = '13.40'
app.vars['dist'] = '53.7'

# Redirect to the main page
@app.route('/')
@app.route('/index')
@app.route('/index.html')
@app.route('/query.html')
def app_home():
    return redirect('/query')

# Main page for queries
@app.route('/query', methods=['GET', 'POST'])
def app_query():
    return render_template('query.html', ra=app.vars['ra'], dec=app.vars['dec'],pmra=app.vars['pmra'],
                           pmdec=app.vars['pmdec'],rv=app.vars['rv'],dist=app.vars['dist'])

# Calculate for known values
@app.route('/results', methods=['GET', 'POST'])
def app_results():
    # Grab the data
    for key in request.form.keys():
        app.vars[key] = request.form[key]

    # Convert to numbers
    df = dict()
    for key in app.vars:
        df[key] = number_convert(app.vars[key])

    # Calculate xyz, uvw
    x, y, z = xyz(df['ra'], df['dec'], df['dist'])
    u, v, w = uvw(df['ra'], df['dec'], df['dist'], df['pmra'], df['pmdec'], df['rv'])

    data = pd.DataFrame({'X': [x], 'Y': [y], 'Z': [z], 'U': [u], 'V': [v], 'W': [w]})

    source = ColumnDataSource(data=data)
    # Figures
    tools = "resize, pan, wheel_zoom, box_zoom, reset, lasso_select, box_select"
    plot_size = 350

    # p1 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools, x_range=None)
    # p1.scatter('X', 'Y', source=source)
    # p1.xaxis.axis_label = 'X (pc)'
    # p1.yaxis.axis_label = 'Y (pc)'

    p1 = basic_plot('X', 'Y', source, xlab='X (pc)', ylab='Y (pc)', tools=tools, plot_size=plot_size)
    p2 = basic_plot('Y', 'Z', source, xlab='Y (pc)', ylab='Z (pc)', tools=tools, plot_size=plot_size)
    p3 = basic_plot('X', 'Z', source, xlab='X (pc)', ylab='Z (pc)', tools=tools, plot_size=plot_size)

    p4 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools)
    p4.scatter('U', 'V', source=source)
    p4.xaxis.axis_label = 'U (km/s)'
    p4.yaxis.axis_label = 'V (km/s)'

    p5 = figure(width=plot_size, plot_height=plot_size, title=None, x_range=p4.y_range, tools=tools)
    p5.scatter('V', 'W', source=source)
    p5.xaxis.axis_label = 'V (km/s)'
    p5.yaxis.axis_label = 'W (km/s)'

    p6 = figure(width=plot_size, plot_height=plot_size, title=None, x_range=p4.x_range, y_range=p5.y_range, tools=tools)
    p6.scatter('U', 'W', source=source)
    p6.xaxis.axis_label = 'U (km/s)'
    p6.yaxis.axis_label = 'W (km/s)'

    # Groups
    p1.oval(x=[1, 2, 3], y=[1, 2, 3], width=0.2, height=40, color="#CAB2D6",
           angle=0, height_units="screen")

    p = gridplot([[p1, p2, p3],[p4, p5, p6]], toolbar_location="left")
    script, div = components(p)

    return render_template('results.html', table=data.to_html(classes='display', index=False), script=script, plot=div)

# Called when you click clear button
@app.route('/clear')
def app_clear():
    clear_values()
    return redirect('/query')

# Function to clear values
def clear_values():
    app.vars['ra'] = ''
    app.vars['dec'] = ''
    app.vars['pmra'] = ''
    app.vars['pmdec'] = ''
    app.vars['rv'] = ''
    app.vars['dist'] = ''

# Function to convert to numbers and have proper error handling
def number_convert(x):
    try:
        val = float(x)
    except ValueError:
        return render_template('error.html', headermessage='Error',
                               errmess='
Error converting number: ' + x + '
')
    return val

# Function for plotting XYZUVW data
def basic_plot(x, y, source, xlab=None, ylab=None,
               tools="resize, pan, wheel_zoom, box_zoom, reset, lasso_select, box_select",
               x_range=None, y_range=None, plot_size=350):
    p = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools, x_range=x_range, y_range=y_range)
    p.scatter(x=x, y=y, source=source)
    p.xaxis.axis_label = xlab
    p.yaxis.axis_label = ylab
    return p<commit_msg>reverted to normal version of plots for now<commit_after>from flask import Flask, redirect, render_template, request
from druvw import xyz, uvw
import pandas as pd
from bokeh.plotting import figure, gridplot
from bokeh.embed import components
from bokeh.models import ColumnDataSource

app = Flask(__name__)

# Global Variables
app.vars = dict()
app.vars['ra'] = '165.46627797'
app.vars['dec'] = '-34.70473119'
app.vars['pmra'] = '-66.19'
app.vars['pmdec'] = '-13.90'
app.vars['rv'] = '13.40'
app.vars['dist'] = '53.7'

# Redirect to the main page
@app.route('/')
@app.route('/index')
@app.route('/index.html')
@app.route('/query.html')
def app_home():
    return redirect('/query')

# Main page for queries
@app.route('/query', methods=['GET', 'POST'])
def app_query():
    return render_template('query.html', ra=app.vars['ra'], dec=app.vars['dec'],pmra=app.vars['pmra'],
                           pmdec=app.vars['pmdec'],rv=app.vars['rv'],dist=app.vars['dist'])

# Calculate for known values
@app.route('/results', methods=['GET', 'POST'])
def app_results():
    # Grab the data
    for key in request.form.keys():
        app.vars[key] = request.form[key]

    # Convert to numbers
    df = dict()
    for key in app.vars:
        df[key] = number_convert(app.vars[key])

    # Calculate xyz, uvw
    x, y, z = xyz(df['ra'], df['dec'], df['dist'])
    u, v, w = uvw(df['ra'], df['dec'], df['dist'], df['pmra'], df['pmdec'], df['rv'])

    data = pd.DataFrame({'X': [x], 'Y': [y], 'Z': [z], 'U': [u], 'V': [v], 'W': [w]})

    source = ColumnDataSource(data=data)
    # Figures
    tools = "resize, pan, wheel_zoom, box_zoom, reset, lasso_select, box_select"
    plot_size = 350

    p1 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools)
    p1.scatter('X', 'Y', source=source)
    p1.xaxis.axis_label = 'X (pc)'
    p1.yaxis.axis_label = 'Y (pc)'

    p2 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools, x_range=p1.y_range)
    p2.scatter('Y', 'Z', source=source)
    p2.xaxis.axis_label = 'Y (pc)'
    p2.yaxis.axis_label = 'Z (pc)'

    p3 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools, x_range=p1.x_range, y_range=p2.x_range)
    p3.scatter('X', 'Z', source=source)
    p3.xaxis.axis_label = 'X (pc)'
    p3.yaxis.axis_label = 'Z (pc)'

    p4 = figure(width=plot_size, plot_height=plot_size, title=None, tools=tools)
    p4.scatter('U', 'V', source=source)
    p4.xaxis.axis_label = 'U (km/s)'
    p4.yaxis.axis_label = 'V (km/s)'

    p5 = figure(width=plot_size, plot_height=plot_size, title=None, x_range=p4.y_range, tools=tools)
    p5.scatter('V', 'W', source=source)
    p5.xaxis.axis_label = 'V (km/s)'
    p5.yaxis.axis_label = 'W (km/s)'

    p6 = figure(width=plot_size, plot_height=plot_size, title=None, x_range=p4.x_range, y_range=p5.y_range, tools=tools)
    p6.scatter('U', 'W', source=source)
    p6.xaxis.axis_label = 'U (km/s)'
    p6.yaxis.axis_label = 'W (km/s)'

    # Groups
    p1.oval(x=[1, 2, 3], y=[1, 2, 3], width=0.2, height=40, color="#CAB2D6",
           angle=0, height_units="screen")

    p = gridplot([[p1, p2, p3],[p4, p5, p6]], toolbar_location="left")
    script, div = components(p)

    return render_template('results.html', table=data.to_html(classes='display', index=False), script=script, plot=div)

# Called when you click clear button
@app.route('/clear')
def app_clear():
    clear_values()
    return redirect('/query')

# Function to clear values
def clear_values():
    app.vars['ra'] = ''
    app.vars['dec'] = ''
    app.vars['pmra'] = ''
    app.vars['pmdec'] = ''
    app.vars['rv'] = ''
    app.vars['dist'] = ''

# Function to convert to numbers and have proper error handling
def number_convert(x):
    try:
        val = float(x)
    except ValueError:
        return render_template('error.html', headermessage='Error',
                               errmess='
Error converting number: ' + x + '
')
    return val<|endoftext|>


<commit_before>## Copyright 2017 Knossos authors, see NOTICE file
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
##     http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.

from __future__ import absolute_import, print_function

import time
import logging

from threading import Thread, Condition
from knossos import center, tasks, qt

class AutoFetcher(Thread):
    _interval = 60 * 60  # = 1 hour
    _inactive_block = None

    def __init__(self):
        super(AutoFetcher, self).__init__()

        self._inactive_block = Condition()
        self.daemon = True

    def trigger(self):
        with self._inactive_block:
            self._inactive_block.notify()

    def run(self):
        while True:
            self.launch_task()
            time.sleep(self._interval)

            if not center.main_win.win.isActiveWindow():
                logging.debug('AutoFetcher paused.')
                with self._inactive_block:
                    self._inactive_block.wait()

                logging.debug('AutoFetcher resumed.')

    @qt.run_in_qt
    def launch_task(self):
        tasks.run_task(tasks.FetchTask())

        if center.settings['update_notify'] and '-dev' not in center.VERSION:
            run_task(CheckUpdateTask())
<commit_msg>Fixed an error that only happens in release builds.<commit_after>## Copyright 2017 Knossos authors, see NOTICE file
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
##     http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.

from __future__ import absolute_import, print_function

import time
import logging

from threading import Thread, Condition
from knossos import center, tasks, qt

class AutoFetcher(Thread):
    _interval = 60 * 60  # = 1 hour
    _inactive_block = None

    def __init__(self):
        super(AutoFetcher, self).__init__()

        self._inactive_block = Condition()
        self.daemon = True

    def trigger(self):
        with self._inactive_block:
            self._inactive_block.notify()

    def run(self):
        while True:
            self.launch_task()
            time.sleep(self._interval)

            if not center.main_win.win.isActiveWindow():
                logging.debug('AutoFetcher paused.')
                with self._inactive_block:
                    self._inactive_block.wait()

                logging.debug('AutoFetcher resumed.')

    @qt.run_in_qt
    def launch_task(self):
        tasks.run_task(tasks.FetchTask())

        if center.settings['update_notify'] and '-dev' not in center.VERSION:
            tasks.run_task(tasks.CheckUpdateTask())
<|endoftext|>


<commit_before>import os
import abc
import six
import json
import logging

from st2client import commands
from st2client.formatters import table

LOG = logging.getLogger(__name__)

def add_auth_token_to_kwargs_from_cli(func):
    def decorate(*args, **kwargs):
        ns = args[1]
        if getattr(ns, 'token', None):
            kwargs['token'] = ns.token
        return func(*args, **kwargs)
    return decorate

class ResourceCommandError(Exception):
    pass

class ResourceNotFoundError(Exception):
    pass

class ResourceBranch(commands.Branch):

    def __init__(self, resource, description, app, subparsers,
                 parent_parser=None, read_only=False, commands={}):

        self.resource = resource
        super(ResourceBranch, self).__init__(
            self.resource.get_alias().lower(), description,
            app, subparsers, parent_parser=parent_parser)

        # Registers subcommands for managing the resource type.
        self.subparsers = self.parser.add_subparsers(
            help=('List of commands for managing %s.' %
                  self.resource.get_plural_display_name().lower()))

        # Resolves if commands need to be overridden.
        if 'list' not in commands:
            commands['list'] = ResourceListCommand
        if 'get' not in commands:
            commands['get'] = ResourceGetCommand
        if 'create' not in commands:
            commands['create'] = ResourceCreateCommand
        if 'update' not in commands:
            commands['update'] = ResourceUpdateCommand
        if 'delete' not in commands:
            commands['delete'] = ResourceDeleteCommand

        # Instantiate commands.
        args = [self.resource, self.app, self.subparsers]
        self.commands['list'] = commands['list'](*args)
        self.commands['get'] = commands['get'](*args)
        if not read_only:
            self.commands['create'] = commands['create'](*args)
            self.commands['update'] = commands['update'](*args)
            self.commands['delete'] = commands['delete'](*args)

@six.add_metaclass(abc.ABCMeta)
class ResourceCommand(commands.Command):

    def __init__(self, resource, *args, **kwargs):

        has_token_opt = kwargs.pop('has_token_opt', True)

        super(ResourceCommand, self).__init__(*args, **kwargs)

        self.resource = resource

        if has_token_opt:
            self.parser.add_argument('-t', '--token', dest='token',
                                     help='Access token for user authentication. '
                                          'Get ST2_AUTH_TOKEN from the environment '
                                          'variables by default.')

        self.parser.add_argument('-j', '--json',
                                 action='store_true', dest='json',
                                 help='Prints output in JSON format.')

    @property
    def manager(self):
        return self.app.client.managers[self.resource.__name__]

    @property
    def arg_name_for_resource_id(self):
        resource_name = self.resource.get_display_name().lower()
        return '%s-id' % resource_name.replace(' ', '-')

    def print_not_found(self, name):
        print ('%s "%s" is not found.\n' %
               (self.resource.get_display_name(), name))

    def get_resource(self, name_or_id, **kwargs):
        return self.get_resource_by_name_or_id(name_or_id=name_or_id, **kwargs)

    def get_resource_by_name_or_id(self, name_or_id, **kwargs):
        instance = self.manager.get_by_name(name_or_id, **kwargs)
        if not instance:
            try:
                instance = self.manager.get_by_id(name_or_id, **kwargs)
            except:
                pass
        if not instance:
            message = ('Resource with id or name "%s" doesn\'t exist.' %
                       (name_or_id))
            raise ResourceNotFoundError(message)
        return instance

    def get_resource_by_ref_or_id(self, ref_or_id, **kwargs):
        query_params = {'ref': ref_or_id}

        try:
            instance = self.manager.query(**query_params)[0]
        except IndexError:
            instance = None

        if not instance:
            try:
                instance = self.manager.get_by_id(ref_or_id, **kwargs)
            except:
                pass
        if not instance:
            message = ('Resource with id or name "%s" doesn\'t exist.' %
                       (ref_or_id))
            raise ResourceNotFoundError(message)
        return instance

    @abc.abstractmethod
    def run(self, args, **kwargs):
        raise NotImplementedError

    @abc.abstractmethod
    def run_and_print(self, args, **kwargs):
        raise NotImplementedError

class ResourceListCommand(ResourceCommand):
    display_attributes = ['id', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceListCommand, self).__init__(resource, 'list',
            'Get the list of %s.' % resource.get_plural_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" will return all '
                                       'attributes.'))
        self.parser.add_argument('-w', '--width', nargs='+', type=int,
                                 default=None,
                                 help=('Set the width of columns in output.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.manager.get_all(**kwargs)

    def run_and_print(self, args, **kwargs):
        instances = self.run(args, **kwargs)
        self.print_output(instances, table.MultiColumnTable,
                          attributes=args.attr, widths=args.width,
                          json=args.json)

class ResourceGetCommand(ResourceCommand):
    display_attributes = ['all']
    attribute_display_order = ['id', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceGetCommand, self).__init__(resource, 'get',
            'Get individual %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" or unspecified will '
                                       'return all attributes.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.get_resource(args.name_or_id, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            instance = self.run(args, **kwargs)
            self.print_output(instance, table.PropertyValueTable,
                              attributes=args.attr, json=args.json,
                              attribute_display_order=self.attribute_display_order)
        except ResourceNotFoundError:
            self.print_not_found(args.name_or_id)

class ContentPackResourceGetCommand(ResourceGetCommand):
    """
    Command for retrieving a single resource which belongs to a content pack.

    Note: All the resources which belong to the content pack can either be
    retrieved by a reference or by an id.
    """

    attribute_display_order = ['id', 'pack', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceGetCommand, self).__init__(resource, 'get',
            'Get individual %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('ref_or_id',
                                 metavar='ref-or-id',
                                 help=('Reference or ID of the %s.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" or unspecified will '
                                       'return all attributes.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.get_resource(ref_or_id=args.ref_or_id, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            instance = self.run(args, **kwargs)
            self.print_output(instance, table.PropertyValueTable,
                              attributes=args.attr, json=args.json,
                              attribute_display_order=self.attribute_display_order)
        except ResourceNotFoundError:
            self.print_not_found(args.ref_or_id)

    def get_resource(self, ref_or_id, **kwargs):
        return self.get_resource_by_ref_or_id(ref_or_id=ref_or_id, **kwargs)

class ResourceCreateCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceCreateCommand, self).__init__(resource, 'create',
            'Create a new %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('file',
                                 help=('JSON file containing the %s to create.'
                                       % resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        if not os.path.isfile(args.file):
            raise Exception('File "%s" does not exist.' % args.file)
        with open(args.file, 'r') as f:
            data = json.loads(f.read())
            instance = self.resource.deserialize(data)
            return self.manager.create(instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        instance = self.run(args, **kwargs)
        self.print_output(instance, table.PropertyValueTable,
                          attributes=['all'], json=args.json)

class ResourceUpdateCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceUpdateCommand, self).__init__(resource, 'update',
            'Updating an existing %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s to be updated.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('file',
                                 help=('JSON file containing the %s to update.'
                                       % resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        if not os.path.isfile(args.file):
            raise Exception('File "%s" does not exist.' % args.file)
        instance = self.get_resource(args.name_or_id, **kwargs)
        with open(args.file, 'r') as f:
            data = json.loads(f.read())
            modified_instance = self.resource.deserialize(data)
            if not getattr(modified_instance, 'id', None):
                modified_instance.id = instance.id
            else:
                if modified_instance.id != instance.id:
                    raise Exception('The value for the %s id in the JSON file '
                                    'does not match the ID provided in the '
                                    'command line arguments.' %
                                    self.resource.get_display_name().lower())
            return self.manager.update(modified_instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        instance = self.run(args, **kwargs)
        self.print_output(instance, table.PropertyValueTable,
                          attributes=['all'], json=args.json)

class ResourceDeleteCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceDeleteCommand, self).__init__(resource, 'delete',
            'Delete an existing %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s.' %
                                       resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        instance = self.get_resource(args.name_or_id, **kwargs)
        self.manager.delete(instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            self.run(args, **kwargs)
        except ResourceNotFoundError:
            self.print_not_found(args.name)
<commit_msg>Fix error message.<commit_after>import os
import abc
import six
import json
import logging

from st2client import commands
from st2client.formatters import table

LOG = logging.getLogger(__name__)

def add_auth_token_to_kwargs_from_cli(func):
    def decorate(*args, **kwargs):
        ns = args[1]
        if getattr(ns, 'token', None):
            kwargs['token'] = ns.token
        return func(*args, **kwargs)
    return decorate

class ResourceCommandError(Exception):
    pass

class ResourceNotFoundError(Exception):
    pass

class ResourceBranch(commands.Branch):

    def __init__(self, resource, description, app, subparsers,
                 parent_parser=None, read_only=False, commands={}):

        self.resource = resource
        super(ResourceBranch, self).__init__(
            self.resource.get_alias().lower(), description,
            app, subparsers, parent_parser=parent_parser)

        # Registers subcommands for managing the resource type.
        self.subparsers = self.parser.add_subparsers(
            help=('List of commands for managing %s.' %
                  self.resource.get_plural_display_name().lower()))

        # Resolves if commands need to be overridden.
        if 'list' not in commands:
            commands['list'] = ResourceListCommand
        if 'get' not in commands:
            commands['get'] = ResourceGetCommand
        if 'create' not in commands:
            commands['create'] = ResourceCreateCommand
        if 'update' not in commands:
            commands['update'] = ResourceUpdateCommand
        if 'delete' not in commands:
            commands['delete'] = ResourceDeleteCommand

        # Instantiate commands.
        args = [self.resource, self.app, self.subparsers]
        self.commands['list'] = commands['list'](*args)
        self.commands['get'] = commands['get'](*args)
        if not read_only:
            self.commands['create'] = commands['create'](*args)
            self.commands['update'] = commands['update'](*args)
            self.commands['delete'] = commands['delete'](*args)

@six.add_metaclass(abc.ABCMeta)
class ResourceCommand(commands.Command):

    def __init__(self, resource, *args, **kwargs):

        has_token_opt = kwargs.pop('has_token_opt', True)

        super(ResourceCommand, self).__init__(*args, **kwargs)

        self.resource = resource

        if has_token_opt:
            self.parser.add_argument('-t', '--token', dest='token',
                                     help='Access token for user authentication. '
                                          'Get ST2_AUTH_TOKEN from the environment '
                                          'variables by default.')

        self.parser.add_argument('-j', '--json',
                                 action='store_true', dest='json',
                                 help='Prints output in JSON format.')

    @property
    def manager(self):
        return self.app.client.managers[self.resource.__name__]

    @property
    def arg_name_for_resource_id(self):
        resource_name = self.resource.get_display_name().lower()
        return '%s-id' % resource_name.replace(' ', '-')

    def print_not_found(self, name):
        print ('%s "%s" is not found.\n' %
               (self.resource.get_display_name(), name))

    def get_resource(self, name_or_id, **kwargs):
        return self.get_resource_by_name_or_id(name_or_id=name_or_id, **kwargs)

    def get_resource_by_name_or_id(self, name_or_id, **kwargs):
        instance = self.manager.get_by_name(name_or_id, **kwargs)
        if not instance:
            try:
                instance = self.manager.get_by_id(name_or_id, **kwargs)
            except:
                pass
        if not instance:
            message = ('Resource with id or name "%s" doesn\'t exist.' %
                       (name_or_id))
            raise ResourceNotFoundError(message)
        return instance

    def get_resource_by_ref_or_id(self, ref_or_id, **kwargs):
        query_params = {'ref': ref_or_id}

        try:
            instance = self.manager.query(**query_params)[0]
        except IndexError:
            instance = None

        if not instance:
            try:
                instance = self.manager.get_by_id(ref_or_id, **kwargs)
            except:
                pass
        if not instance:
            message = ('Resource with id or reference "%s" doesn\'t exist.' %
                       (ref_or_id))
            raise ResourceNotFoundError(message)
        return instance

    @abc.abstractmethod
    def run(self, args, **kwargs):
        raise NotImplementedError

    @abc.abstractmethod
    def run_and_print(self, args, **kwargs):
        raise NotImplementedError

class ResourceListCommand(ResourceCommand):
    display_attributes = ['id', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceListCommand, self).__init__(resource, 'list',
            'Get the list of %s.' % resource.get_plural_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" will return all '
                                       'attributes.'))
        self.parser.add_argument('-w', '--width', nargs='+', type=int,
                                 default=None,
                                 help=('Set the width of columns in output.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.manager.get_all(**kwargs)

    def run_and_print(self, args, **kwargs):
        instances = self.run(args, **kwargs)
        self.print_output(instances, table.MultiColumnTable,
                          attributes=args.attr, widths=args.width,
                          json=args.json)

class ResourceGetCommand(ResourceCommand):
    display_attributes = ['all']
    attribute_display_order = ['id', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceGetCommand, self).__init__(resource, 'get',
            'Get individual %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" or unspecified will '
                                       'return all attributes.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.get_resource(args.name_or_id, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            instance = self.run(args, **kwargs)
            self.print_output(instance, table.PropertyValueTable,
                              attributes=args.attr, json=args.json,
                              attribute_display_order=self.attribute_display_order)
        except ResourceNotFoundError:
            self.print_not_found(args.name_or_id)

class ContentPackResourceGetCommand(ResourceGetCommand):
    """
    Command for retrieving a single resource which belongs to a content pack.

    Note: All the resources which belong to the content pack can either be
    retrieved by a reference or by an id.
    """

    attribute_display_order = ['id', 'pack', 'name', 'description']

    def __init__(self, resource, *args, **kwargs):
        super(ResourceGetCommand, self).__init__(resource, 'get',
            'Get individual %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('ref_or_id',
                                 metavar='ref-or-id',
                                 help=('Reference or ID of the %s.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('-a', '--attr', nargs='+',
                                 default=self.display_attributes,
                                 help=('List of attributes to include in the '
                                       'output. "all" or unspecified will '
                                       'return all attributes.'))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        return self.get_resource(ref_or_id=args.ref_or_id, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            instance = self.run(args, **kwargs)
            self.print_output(instance, table.PropertyValueTable,
                              attributes=args.attr, json=args.json,
                              attribute_display_order=self.attribute_display_order)
        except ResourceNotFoundError:
            self.print_not_found(args.ref_or_id)

    def get_resource(self, ref_or_id, **kwargs):
        return self.get_resource_by_ref_or_id(ref_or_id=ref_or_id, **kwargs)

class ResourceCreateCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceCreateCommand, self).__init__(resource, 'create',
            'Create a new %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('file',
                                 help=('JSON file containing the %s to create.'
                                       % resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        if not os.path.isfile(args.file):
            raise Exception('File "%s" does not exist.' % args.file)
        with open(args.file, 'r') as f:
            data = json.loads(f.read())
            instance = self.resource.deserialize(data)
            return self.manager.create(instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        instance = self.run(args, **kwargs)
        self.print_output(instance, table.PropertyValueTable,
                          attributes=['all'], json=args.json)

class ResourceUpdateCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceUpdateCommand, self).__init__(resource, 'update',
            'Updating an existing %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s to be updated.' %
                                       resource.get_display_name().lower()))
        self.parser.add_argument('file',
                                 help=('JSON file containing the %s to update.'
                                       % resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        if not os.path.isfile(args.file):
            raise Exception('File "%s" does not exist.' % args.file)
        instance = self.get_resource(args.name_or_id, **kwargs)
        with open(args.file, 'r') as f:
            data = json.loads(f.read())
            modified_instance = self.resource.deserialize(data)
            if not getattr(modified_instance, 'id', None):
                modified_instance.id = instance.id
            else:
                if modified_instance.id != instance.id:
                    raise Exception('The value for the %s id in the JSON file '
                                    'does not match the ID provided in the '
                                    'command line arguments.' %
                                    self.resource.get_display_name().lower())
            return self.manager.update(modified_instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        instance = self.run(args, **kwargs)
        self.print_output(instance, table.PropertyValueTable,
                          attributes=['all'], json=args.json)

class ResourceDeleteCommand(ResourceCommand):

    def __init__(self, resource, *args, **kwargs):
        super(ResourceDeleteCommand, self).__init__(resource, 'delete',
            'Delete an existing %s.' % resource.get_display_name().lower(),
            *args, **kwargs)

        self.parser.add_argument('name_or_id',
                                 metavar='name-or-id',
                                 help=('Name or ID of the %s.' %
                                       resource.get_display_name().lower()))

    @add_auth_token_to_kwargs_from_cli
    def run(self, args, **kwargs):
        instance = self.get_resource(args.name_or_id, **kwargs)
        self.manager.delete(instance, **kwargs)

    def run_and_print(self, args, **kwargs):
        try:
            self.run(args, **kwargs)
        except ResourceNotFoundError:
            self.print_not_found(args.name)
<|endoftext|>


<commit_before>import thread
import time
import copy
import json

class System(object):
    """
    Description of System.

    TODO: where are external state parameters?
    """

    def __init__(self, identifier, variables, schemas):
        """
        Constructs a new System.

        :param  identifier: a unique string identifier (i.e., a name) for this\
                            system
        :param  variables:  a dictionary of system variables, indexed by name
        :param  schemas:    a dictionary of action schemas, indexed by name
        """
        self.__identifier = identifier
        self.__variables = variables
        self.__schemas = schemas

    def installed(self):
        """
        Returns true if this system is installed on this machine.
        """
        raise NotImplementedError

    def identifier(self):
        """
        Returns the unique identifier (i.e., the name) for this system.
        """
        return self.__identifier

    def setUp(self, mission):
        """
        Responsible for appropriately configuring and launching the system,
        for a given mission.
        """
        raise NotImplementedError

    def tearDown(self, mission):
        """
        Responsible for safely closing the system, following the execution of
        a given mission.
        """
        raise NotImplementedError

    def execute(self, mission):
        """
        Executes a given mission.

        :param  mission:    the mission that should be executed.

        :return A summary of the outcome of the mission, in the form of a
                MissionOutcome
        """
        assert(self.installed())
        self.setUp(mission)
        try:

            outcomes = []
            for action in mission.getActions():
                schema = self.__schemas[action.getSchemaName()]
                stateBefore = self.getInternalState()

                # check for precondition violations
                (satisfied, violations) = \
                    schema.satisfiedPreconditions(self.__variables, action)
                if not satisfied:
                    stateAfter = self.getInternalState()
                    outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                    outcomes.append(outcome)
                    return MissionOutcome(False, outcomes)

                # dispatch
                schema.dispatch(action.getValues())
                print('Doing: {}'.format(action.getSchemaName()))

                # loop until postconditions are satisfied, or an invariant is violated
                while True:

                    # check for invariant violations
                    (satisfied, violations) = \
                        schema.satisfiedInvariants(self.__variables, action)
                    if not satisfied:
                        stateAfter = self.getInternalState()
                        outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                        outcomes.append(outcome)
                        return MissionOutcome(False, outcomes)

                    # check if postconditions are satisfied
                    (satisfied, violations) = \
                        schema.satisfiedPostConditions(self.__variables, action)
                    if satisfied:
                        stateAfter = self.getInternalState()
                        outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                        outcomes.append(outcome)
                        return MissionOutcome(True, outcomes)

                    time.sleep(0.5) # TODO: parameterise

                    # TODO: enforce a time-out!

        finally:
            self.tearDown(mission)

    def getInternalState(self):
        """
        Returns a description of the current internal state of the system.

        TODO: ensure that the system is actually running!
        """
        assert(self.installed())
        vals = {n: v.read() for (n, v) in self.__variables.items()}
        return InternalState(vals)

    def getActionSchemas(self):
        """
        Returns a copy of action schemas
        """
        return copy.deepcopy(self.__schemas)

class State(object):
    """
    Describes the internal or external state of the system in terms of its
    internal or external variables.
    """

    def __init__(self, values):
        """
        Constructs a description of the system state.

        :param  values: a dictionary describing the values of the state
                        variables, indexed by their names.
        """
        self.__values = copy.copy(values)

    def read(variable):
        """
        Returns the value for a given state variable
        """
        return self.__values[variable]

    def dump(self):
        """
        Prints this state to the standard output.
        """
        for variable in self.__values:
            print('Variable: {} - State: {}'.format(variable, self.read(variable)))

    def toJSON(self):
        """
        Returns a JSON description of this state.
        """
        return {
            'variables': copy.copy(self.__values)
        }

    def __str__(self):
        return str(self.toJSON())

    def __repr__(self):
        return str(self)

class InternalState(State):
    """
    Describes the state of the system in terms of its internal state
    variables.
    """

    @staticmethod
    def fromJSON(jsn):
        """
        Constructs an internal state description from a JSON object
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return InternalState(jsn['variables'])

class ExternalState(State):
    """
    Describes the state of the system in terms of its external state
    variables.
    """

    @staticmethod
    def fromJSON(jsn):
        """
        Constructs an external state description from a JSON object
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return ExternalState(jsn['variables'])

class StateVariable(object):

    def __init__(self, name, getter):
        """
        Constructs a new state variable

        :param  name:   the name of this variable
        :param  type:   the type of this variable
        :param  getter: a lambda function, used to obtain the value of this variable
        """
        self.__name = name
        self.__getter = getter

    """
    Returns the name of this system variable
    """
    def name(self):
        return self.__name

    """
    Inspects the current state of this system variable
    """
    def read(self):
        return self.__getter()

class InternalStateVariable(StateVariable):
    """
    Internal variables describe the internal state of a given system.
    (i.e., they represent a system's knowledge of itself and its surroundings.)
    A user-provided lambda function is used to inspect the value of the state
    variable at any given time.
    """

    def __init__(self, name, getter):
        super(InternalStateVariable, self).__init__(name, getter)

class Environment(object):
    @staticmethod
    def fromJSON(jsn):
        """
        Constructs a description of an environment from its JSON description
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return Environment(jsn['variables'])

    """
    Holds a description of an environment in which a mission should be conducted.
    """

    def __init__(self, values):
        """
        Constructs a description of a mission environment.

        :param  values: a dictionary of environment variable values, indexed
                        by the name of those variables.
        """
        self.__values = copy.copy(values)

    def read(self, variable):
        """
        Returns the value of a given environment variable.
        """
        return self.__values[variable]

    def toJSON(self):
        """
        Returns this environment description as a JSON object (i.e., a dict)
        """
        return {
            'variables': copy.copy(self.__values)
        }

class ActionSchema(object):
    """
    Action schemas are responsible for describing the kinds of actions that
    can be performed within a given system. Action schemas describe actions
    both syntactically, in terms of parameters, and semantically, in terms of
    preconditions, postconditions, and invariants.
    """

    def __init__(self, name, parameters, preconditions, invariants, postconditions):
        """
        Constructs an ActionSchema object.

        :param  name            name of the action schema
        :param  parameters      a list of the parameters for this action schema
        :param  preconditions   predicates that must be met before the action
                                can be executed.
        :param  invariants      predicates that should be met at all times during
                                the execution of an action.
        :param  postconditions  predicates that must be met after the action is
                                completed.
        """
        assert(isinstance(name, str) and not name is None)
        assert(len(name) > 0)
        assert(isinstance(parameters, list) and not parameters is None)
        assert(isinstance(preconditions, list) and not preconditions is None)
        assert(isinstance(postconditions, list) and not postconditions is None)
        assert(isinstance(invariants, list) and not invariants is None)

        self.__name           = name
        self.__parameters     = parameters
        self.__preconditions  = preconditions
        self.__invariants     = invariants
        self.__postconditions = postconditions

    def getName(self):
        """
        Returns the name of this schema.
        """
        return self.__name

    def dispatch(self, action):
        """
        Responsible for invoking an action belonging to this schema.

        :param  action  an Action belonging to this schema
        """
        raise UnimplementedError

    def getParameters(self):
        """
        Returns the parameters being hold for the current action schema. This is
        used to generate actions
        """
        return copy.deepcopy(self.__parameters)

    def satisfiedPostConditions(self, systemVariables, parameters):
        """
        Checks that the postconditions are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the postconditions that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is being executed.
        """
        #print 'Doing postconditions. Action: {}'.format(parameters.getKind())
        postconditionsFailed = []
        success               = True
        for postcondition in self.__postconditions:
            if not postcondition.check(systemVariables, parameters.getValues()):
                postconditionsFailed.append(postcondition.getName())
                success = False

        return (success, postconditionsFailed)

    def satisfiedPreconditions(self, systemVariables, parameters):
        """
        Checks that the preconditions are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the preconditions that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is about to be
                                    dispatched.
        """
        #print 'Doing precondition. Action: {}'.format(parameters.getKind())
        preconditionsFailed = []
        success              = True
        for precondition in self.__preconditions:
            if not precondition.check(systemVariables, parameters.getValues()):
                preconditionsFailed.append(precondition.getName())
                success = False
        return (success, preconditionsFailed)

    def satisfiedInvariants(self, systemVariables, parameters):
        """
        Checks that the invariants are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the invariants that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is about to be
                                    dispatched or that is currently being executed.
        """
        #print 'Doing invariants. Action: {}'.format(parameters.getKind())
        invariantsFailed    = []
        success             = True
        for invariant in self.__invariants:
            if not invariant.check(systemVariables, parameters.getValues()):
                invariantsFailed.append(invariant.getName())
                success = False
        return (success, invariantsFailed)
<commit_msg>implemented getPreconditions<commit_after>import thread
import time
import copy
import json

class System(object):
    """
    Description of System.

    TODO: where are external state parameters?
    """

    def __init__(self, identifier, variables, schemas):
        """
        Constructs a new System.

        :param  identifier: a unique string identifier (i.e., a name) for this\
                            system
        :param  variables:  a dictionary of system variables, indexed by name
        :param  schemas:    a dictionary of action schemas, indexed by name
        """
        self.__identifier = identifier
        self.__variables = variables
        self.__schemas = schemas

    def installed(self):
        """
        Returns true if this system is installed on this machine.
        """
        raise NotImplementedError

    def identifier(self):
        """
        Returns the unique identifier (i.e., the name) for this system.
        """
        return self.__identifier

    def setUp(self, mission):
        """
        Responsible for appropriately configuring and launching the system,
        for a given mission.
        """
        raise NotImplementedError

    def tearDown(self, mission):
        """
        Responsible for safely closing the system, following the execution of
        a given mission.
        """
        raise NotImplementedError

    def execute(self, mission):
        """
        Executes a given mission.

        :param  mission:    the mission that should be executed.

        :return A summary of the outcome of the mission, in the form of a
                MissionOutcome
        """
        assert(self.installed())
        self.setUp(mission)
        try:

            outcomes = []
            for action in mission.getActions():
                schema = self.__schemas[action.getSchemaName()]
                stateBefore = self.getInternalState()

                # check for precondition violations
                (satisfied, violations) = \
                    schema.satisfiedPreconditions(self.__variables, action)
                if not satisfied:
                    stateAfter = self.getInternalState()
                    outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                    outcomes.append(outcome)
                    return MissionOutcome(False, outcomes)

                # dispatch
                schema.dispatch(action.getValues())
                print('Doing: {}'.format(action.getSchemaName()))

                # loop until postconditions are satisfied, or an invariant is violated
                while True:

                    # check for invariant violations
                    (satisfied, violations) = \
                        schema.satisfiedInvariants(self.__variables, action)
                    if not satisfied:
                        stateAfter = self.getInternalState()
                        outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                        outcomes.append(outcome)
                        return MissionOutcome(False, outcomes)

                    # check if postconditions are satisfied
                    (satisfied, violations) = \
                        schema.satisfiedPostConditions(self.__variables, action)
                    if satisfied:
                        stateAfter = self.getInternalState()
                        outcome = ActionOutcome(action, False, stateBefore, stateAfter)
                        outcomes.append(outcome)
                        return MissionOutcome(True, outcomes)

                    time.sleep(0.5) # TODO: parameterise

                    # TODO: enforce a time-out!

        finally:
            self.tearDown(mission)

    def getInternalState(self):
        """
        Returns a description of the current internal state of the system.

        TODO: ensure that the system is actually running!
        """
        assert(self.installed())
        vals = {n: v.read() for (n, v) in self.__variables.items()}
        return InternalState(vals)

    def getActionSchemas(self):
        """
        Returns a copy of action schemas
        """
        return copy.deepcopy(self.__schemas)

class State(object):
    """
    Describes the internal or external state of the system in terms of its
    internal or external variables.
    """

    def __init__(self, values):
        """
        Constructs a description of the system state.

        :param  values: a dictionary describing the values of the state
                        variables, indexed by their names.
        """
        self.__values = copy.copy(values)

    def read(variable):
        """
        Returns the value for a given state variable
        """
        return self.__values[variable]

    def dump(self):
        """
        Prints this state to the standard output.
        """
        for variable in self.__values:
            print('Variable: {} - State: {}'.format(variable, self.read(variable)))

    def toJSON(self):
        """
        Returns a JSON description of this state.
        """
        return {
            'variables': copy.copy(self.__values)
        }

    def __str__(self):
        return str(self.toJSON())

    def __repr__(self):
        return str(self)

class InternalState(State):
    """
    Describes the state of the system in terms of its internal state
    variables.
    """

    @staticmethod
    def fromJSON(jsn):
        """
        Constructs an internal state description from a JSON object
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return InternalState(jsn['variables'])

class ExternalState(State):
    """
    Describes the state of the system in terms of its external state
    variables.
    """

    @staticmethod
    def fromJSON(jsn):
        """
        Constructs an external state description from a JSON object
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return ExternalState(jsn['variables'])

class StateVariable(object):

    def __init__(self, name, getter):
        """
        Constructs a new state variable

        :param  name:   the name of this variable
        :param  type:   the type of this variable
        :param  getter: a lambda function, used to obtain the value of this variable
        """
        self.__name = name
        self.__getter = getter

    """
    Returns the name of this system variable
    """
    def name(self):
        return self.__name

    """
    Inspects the current state of this system variable
    """
    def read(self):
        return self.__getter()

class InternalStateVariable(StateVariable):
    """
    Internal variables describe the internal state of a given system.
    (i.e., they represent a system's knowledge of itself and its surroundings.)
    A user-provided lambda function is used to inspect the value of the state
    variable at any given time.
    """

    def __init__(self, name, getter):
        super(InternalStateVariable, self).__init__(name, getter)

class Environment(object):
    @staticmethod
    def fromJSON(jsn):
        """
        Constructs a description of an environment from its JSON description
        """
        assert('variables' in jsn)
        assert(isinstance(jsn['variables'], dict))
        return Environment(jsn['variables'])

    """
    Holds a description of an environment in which a mission should be conducted.
    """

    def __init__(self, values):
        """
        Constructs a description of a mission environment.

        :param  values: a dictionary of environment variable values, indexed
                        by the name of those variables.
        """
        self.__values = copy.copy(values)

    def read(self, variable):
        """
        Returns the value of a given environment variable.
        """
        return self.__values[variable]

    def toJSON(self):
        """
        Returns this environment description as a JSON object (i.e., a dict)
        """
        return {
            'variables': copy.copy(self.__values)
        }

class ActionSchema(object):
    """
    Action schemas are responsible for describing the kinds of actions that
    can be performed within a given system. Action schemas describe actions
    both syntactically, in terms of parameters, and semantically, in terms of
    preconditions, postconditions, and invariants.
    """

    def __init__(self, name, parameters, preconditions, invariants, postconditions):
        """
        Constructs an ActionSchema object.

        :param  name            name of the action schema
        :param  parameters      a list of the parameters for this action schema
        :param  preconditions   predicates that must be met before the action
                                can be executed.
        :param  invariants      predicates that should be met at all times during
                                the execution of an action.
        :param  postconditions  predicates that must be met after the action is
                                completed.
        """
        assert(isinstance(name, str) and not name is None)
        assert(len(name) > 0)
        assert(isinstance(parameters, list) and not parameters is None)
        assert(isinstance(preconditions, list) and not preconditions is None)
        assert(isinstance(postconditions, list) and not postconditions is None)
        assert(isinstance(invariants, list) and not invariants is None)

        self.__name           = name
        self.__parameters     = parameters
        self.__preconditions  = preconditions
        self.__invariants     = invariants
        self.__postconditions = postconditions

    def getName(self):
        """
        Returns the name of this schema.
        """
        return self.__name

    def dispatch(self, action):
        """
        Responsible for invoking an action belonging to this schema.

        :param  action  an Action belonging to this schema
        """
        raise UnimplementedError

    def getParameters(self):
        """
        Returns the parameters being hold for the current action schema. This is
        used to generate actions
        """
        return copy.deepcopy(self.__parameters)

    def getPreconditions(self):
        """
        Returns the preconditions being hold for the current action schema. This
        is used to generate and validate actions.
        """
        return copy.deepcopy(self.__preconditions)

    def satisfiedPostConditions(self, systemVariables, parameters):
        """
        Checks that the postconditions are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the postconditions that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is being executed.
        """
        #print 'Doing postconditions. Action: {}'.format(parameters.getKind())
        postconditionsFailed = []
        success               = True
        for postcondition in self.__postconditions:
            if not postcondition.check(systemVariables, parameters.getValues()):
                postconditionsFailed.append(postcondition.getName())
                success = False

        return (success, postconditionsFailed)

    def satisfiedPreconditions(self, systemVariables, parameters):
        """
        Checks that the preconditions are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the preconditions that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is about to be
                                    dispatched.
        """
        #print 'Doing precondition. Action: {}'.format(parameters.getKind())
        preconditionsFailed = []
        success              = True
        for precondition in self.__preconditions:
            if not precondition.check(systemVariables, parameters.getValues()):
                preconditionsFailed.append(precondition.getName())
                success = False
        return (success, preconditionsFailed)

    def satisfiedInvariants(self, systemVariables, parameters):
        """
        Checks that the invariants are met. Returns a tuple, with a boolean
        holding the success or failure of the check, and a list with the name of
        the invariants that were not met (if any).

        :param  systemVariables     the system variables.
        :param  parameters          parameters of the action that is about to be
                                    dispatched or that is currently being executed.
        """
        #print 'Doing invariants. Action: {}'.format(parameters.getKind())
        invariantsFailed    = []
        success             = True
        for invariant in self.__invariants:
            if not invariant.check(systemVariables, parameters.getValues()):
                invariantsFailed.append(invariant.getName())
                success = False
        return (success, invariantsFailed)
<|endoftext|>