<commit_before>import sys
import time
import requests
import json
import re

###############################################################################
# The sysdig cloud client
###############################################################################
class SdcClient:
    userinfo = None
    n_connected_agents = None

    def __init__(self, token, sdc_url = 'https://app.sysdigcloud.com'):
        self.token = token
        self.hdrs = {'Authorization': 'Bearer ' + self.token, 'Content-Type': 'application/json'}
        self.url = sdc_url

    def __checkResponse(self, r):
        if r.status_code >= 300:
            self.errorcode = r.status_code

            j = r.json()
            if 'errors' in j:
                if j['errors'][0]['message']:
                    self.lasterr = j['errors'][0]['message']
                else:
                    self.lasterr = j['errors'][0]['reason']
            if 'message' in j:
                    self.lasterr = j['message']
            else:
                self.lasterr = 'status code ' + str(self.errorcode)
            return False
        return True

    def getUserInfo(self):
        if self.userinfo == None:
            r = requests.get(self.url + '/api/user/me', headers=self.hdrs)
            if not self.__checkResponse(r):
                return [False, self.lasterr]
            self.userinfo = r.json()
        return [True, self.userinfo]

    def getNConnectedAgents(self):
        r = requests.get(self.url + '/api/agents/connected', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        data = r.json()
        return [True, data['total']]

    def createAlert(self, name, description, condition, for_each, for_atelast_us, severity):
        #
        # Get the list of alerts from the server
        #
        r = requests.get(self.url + '/api/alerts', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        j = r.json()

        print 'Creating alert %s' % (description)

        #
        # If this alert already exists, don't create it again
        #
        for db in j['alerts']:
            if 'description' in db:
                if db['description'] == description:
                    return [False, 'alert ' + name + ' already exists']

        #
        # Populate the alert information
        #
        alert_json = {
            'alert' : {
                'type' : 'MANUAL',
                'name' : name,
                'description' : description,
                'enabled' : True,
                'severity' : severity,
                'notify' : [ 'EMAIL' ],
                'timespan' : for_atelast_us,
                'condition' : condition
            }
        }

        if for_each != None and for_each != []:
            alert_json['alert']['segmentBy'] = [ for_each ]
            alert_json['alert']['segmentCondition'] = { 'type' : 'ANY' }

        #
        # Create the new alert
        #
        r = requests.post(self.url + '/api/alerts', headers=self.hdrs, data = json.dumps(alert_json))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getNotificationSettings(self):
        r = requests.get(self.url + '/api/settings/notifications', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def setNotificationSettings(self, settings):
        r = requests.put(self.url + '/api/settings/notifications', headers=self.hdrs, data = json.dumps(settings))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def addEmailNotificationRecipient(self, email):
        #
        # Retirieve the user's notification settings
        #
        r = requests.get(self.url + '/api/settings/notifications', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        j = r.json()

        #
        # Enable email notifications
        #
        j['userNotification']['email']['enabled'] = True

        #
        # Add the given recipient
        #
        if not email in j['userNotification']['email']['recipients']:
            j['userNotification']['email']['recipients'].append(email)
        else:
            return [False, 'notification target ' + email + ' already present']

        return self.setNotificationSettings(j)

    def getExploreGroupingHierarchy(self):
        r = requests.get(self.url + '/api/groupConfigurations', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]

        data = r.json()

        if not 'groupConfigurations' in data:
            return [False, 'corrputed groupConfigurations API response']

        gconfs = data['groupConfigurations']

        for gconf in gconfs:
            if gconf['id'] == 'explore':
                res = []
                items = gconf['groups'][0]['groupBy']

                for item in items:
                    res.append(item['metric'])

                return [True, res]

        return [False, 'corrputed groupConfigurations API response, missing "explore" entry']

    def getDataRetentionInfo(self):
        r = requests.get(self.url + '/api/history/timelines/', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getTopologyMap(self, grouping_hierarchy, time_window_s, sampling_time_s):
        #
        # Craft the time interval section
        #
        tlines = self.getDataRetentionInfo()

        for tline in tlines[1]['agents']:
            if tline['sampling'] == sampling_time_s * 1000000:
                timeinfo = tline

        if timeinfo == None:
            return [False, "sampling time " + str(sampling_time_s) + " not supported"]

        timeinfo['from'] = timeinfo['to'] - timeinfo['sampling']

        #
        # Create the grouping hierarchy
        #
        gby = [{'metric': g} for g in grouping_hierarchy]

        #
        # Prepare the json
        #
        req_json = {
            'format': {
                'type': 'map',
                'exportProcess': True
            },
            'time': timeinfo,
            #'filter': {
            #    'filters': [
            #        {
            #            'metric': 'agent.tag.Tag',
            #            'op': '=',
            #            'value': 'production-maintenance',
            #            'filters': None
            #        }
            #    ],
            #    'logic': 'and'
            #},
            'limit': {
                'hostGroups': 20,
                'hosts': 20,
                'containers': 20,
                'processes': 10
            },
            'group': {
                'configuration': {
                    'groups': [
                        {
                            'filters': [],
                            'groupBy': gby
                        }
                    ]
                }
            },
            'nodeMetrics': [
                {
                    'id': 'cpu.used.percent',
                    'aggregation': 'timeAvg',
                    'groupAggregation': 'avg'
                }
            ],
            'linkMetrics': [
                {
                    'id': 'net.bytes.total',
                    'aggregation': 'timeAvg',
                    'groupAggregation': 'sum'
                }
            ]
        }

        #
        # Fire the request
        #
        r = requests.post(self.url + '/api/data?format=map', headers=self.hdrs, data = json.dumps(req_json))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getDashboards(self):
        r = requests.get(self.url + '/ui/dashboards', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getAlerts(self):
        r = requests.get(self.url + '/api/alerts', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def create_dashboard_from_template(self, newdashname, templatename, scope):
        #
        # Create the unique ID for this dashboard
        #
        baseconfid = newdashname
        for sentry in scope:
            baseconfid = baseconfid + sentry.keys()[0]
            baseconfid = baseconfid + sentry.values()[0]

        print baseconfid

        #
        # Get the list of dashboards from the server
        #
        r = requests.get(self.url + '/ui/dashboards', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]

        j = r.json()

        #
        # Find our template dashboard
        #
        dboard = None

        for db in j['dashboards']:
            if db['name'] == templatename:
                dboard = db
                break

        if dboard == None:
            print 'can\'t find dashboard ' + templatename + ' to use as a template'
            sys.exit(0)

        #
        # Create the dashboard name
        #
        if newdashname:
            dname = newdashname
        else:
            dname = dboard['name'] + ' for ' + service

        #
        # If this dashboard already exists, don't create it another time
        #
        for db in j['dashboards']:
            if db['name'] == dname:
                for view in db['items']:
                    if view['groupId'][0:len(baseconfid)] == baseconfid:
                        print 'dashboard ' + dname + ' already exists - ' + baseconfid
                        return

        #
        # Clean up the dashboard we retireved so it's ready to be pushed
        #
        dboard['id'] = None
        dboard['version'] = None
        dboard['name'] = dname
        dboard['isShared'] = False # make sure the dashboard is not shared

        #
        # Assign the filter and the group ID to each view to point to this service
        #
        filters = []
        gby = []
        for sentry in scope:
            filters.append({'metric' : sentry.keys()[0], 'op' : '=', 'value' : sentry.values()[0]   , 'filters' : None})
            gby.append({'metric': sentry.keys()[0]})

        filter = {
            'filters' :
            {
                'logic' : 'and',
                'filters' : filters
            }
        }

        j = 0

        for view in dboard['items']:
            j = j + 1

            #
            # create the grouping configuration
            #
            confid = baseconfid + str(j)

            gconf = { 'id': confid,
                'groups': [
                    {
                        'groupBy': gby
                    }
                ]
            }

            r = requests.post(self.url + '/api/groupConfigurations', headers=self.hdrs, data = json.dumps(gconf))
            if not self.__checkResponse(r):
                return [False, self.lasterr]

            view['filter'] = filter
            view['groupId'] = confid

    #   print json.dumps(dboard, indent=4, separators=(',', ': '))

        ddboard = {'dashboard': dboard}

        #
        # Create the new dashboard
        #
        r = requests.post(self.url + '/ui/dashboards', headers=self.hdrs, data = json.dumps(ddboard))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        else:
            return [True, r.json()]
<commit_msg>alert annotations<commit_after>import sys
import time
import requests
import json
import re

###############################################################################
# The sysdig cloud client
###############################################################################
class SdcClient:
    userinfo = None
    n_connected_agents = None

    def __init__(self, token, sdc_url = 'https://app.sysdigcloud.com'):
        self.token = token
        self.hdrs = {'Authorization': 'Bearer ' + self.token, 'Content-Type': 'application/json'}
        self.url = sdc_url

    def __checkResponse(self, r):
        if r.status_code >= 300:
            self.errorcode = r.status_code

            j = r.json()
            if 'errors' in j:
                if 'message' in j['errors'][0]:
                    self.lasterr = j['errors'][0]['message']
                else:
                    self.lasterr = j['errors'][0]['reason']
            elif 'message' in j:
                    self.lasterr = j['message']
            else:
                self.lasterr = 'status code ' + str(self.errorcode)
            return False
        return True

    def getUserInfo(self):
        if self.userinfo == None:
            r = requests.get(self.url + '/api/user/me', headers=self.hdrs)
            if not self.__checkResponse(r):
                return [False, self.lasterr]
            self.userinfo = r.json()
        return [True, self.userinfo]

    def getNConnectedAgents(self):
        r = requests.get(self.url + '/api/agents/connected', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        data = r.json()
        return [True, data['total']]

    def getAlerts(self):
        r = requests.get(self.url + '/api/alerts', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def createAlert(self, name, description, severity, for_atelast_us, condition, for_each = [], filter = [], annotations={}):
        #
        # Get the list of alerts from the server
        #
        r = requests.get(self.url + '/api/alerts', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        j = r.json()

        #
        # If this alert already exists, don't create it again
        #
        for db in j['alerts']:
            if 'description' in db:
                if db['description'] == description:
                    return [False, 'alert ' + name + ' already exists']

        #
        # Populate the alert information
        #
        alert_json = {
            'alert' : {
                'type' : 'MANUAL',
                'name' : name,
                'description' : description,
                'enabled' : True,
                'severity' : severity,
                'notify' : [ 'EMAIL' ],
                'timespan' : for_atelast_us,
                'condition' : condition,
                'filter': filter
            }
        }

        if for_each != None and for_each != []:
            alert_json['alert']['segmentBy'] = for_each
            alert_json['alert']['segmentCondition'] = { 'type' : 'ANY' }

        if annotations != None and annotations != {}:
            alert_json['alert']['annotations'] = annotations

        print alert_json

        #
        # Create the new alert
        #
        r = requests.post(self.url + '/api/alerts', headers=self.hdrs, data = json.dumps(alert_json))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getNotificationSettings(self):
        r = requests.get(self.url + '/api/settings/notifications', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def setNotificationSettings(self, settings):
        r = requests.put(self.url + '/api/settings/notifications', headers=self.hdrs, data = json.dumps(settings))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def addEmailNotificationRecipient(self, email):
        #
        # Retirieve the user's notification settings
        #
        r = requests.get(self.url + '/api/settings/notifications', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        j = r.json()

        #
        # Enable email notifications
        #
        j['userNotification']['email']['enabled'] = True

        #
        # Add the given recipient
        #
        if not email in j['userNotification']['email']['recipients']:
            j['userNotification']['email']['recipients'].append(email)
        else:
            return [False, 'notification target ' + email + ' already present']

        return self.setNotificationSettings(j)

    def getExploreGroupingHierarchy(self):
        r = requests.get(self.url + '/api/groupConfigurations', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]

        data = r.json()

        if not 'groupConfigurations' in data:
            return [False, 'corrputed groupConfigurations API response']

        gconfs = data['groupConfigurations']

        for gconf in gconfs:
            if gconf['id'] == 'explore':
                res = []
                items = gconf['groups'][0]['groupBy']

                for item in items:
                    res.append(item['metric'])

                return [True, res]

        return [False, 'corrputed groupConfigurations API response, missing "explore" entry']

    def getDataRetentionInfo(self):
        r = requests.get(self.url + '/api/history/timelines/', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getTopologyMap(self, grouping_hierarchy, time_window_s, sampling_time_s):
        #
        # Craft the time interval section
        #
        tlines = self.getDataRetentionInfo()

        for tline in tlines[1]['agents']:
            if tline['sampling'] == sampling_time_s * 1000000:
                timeinfo = tline

        if timeinfo == None:
            return [False, "sampling time " + str(sampling_time_s) + " not supported"]

        timeinfo['from'] = timeinfo['to'] - timeinfo['sampling']

        #
        # Create the grouping hierarchy
        #
        gby = [{'metric': g} for g in grouping_hierarchy]

        #
        # Prepare the json
        #
        req_json = {
            'format': {
                'type': 'map',
                'exportProcess': True
            },
            'time': timeinfo,
            #'filter': {
            #    'filters': [
            #        {
            #            'metric': 'agent.tag.Tag',
            #            'op': '=',
            #            'value': 'production-maintenance',
            #            'filters': None
            #        }
            #    ],
            #    'logic': 'and'
            #},
            'limit': {
                'hostGroups': 20,
                'hosts': 20,
                'containers': 20,
                'processes': 10
            },
            'group': {
                'configuration': {
                    'groups': [
                        {
                            'filters': [],
                            'groupBy': gby
                        }
                    ]
                }
            },
            'nodeMetrics': [
                {
                    'id': 'cpu.used.percent',
                    'aggregation': 'timeAvg',
                    'groupAggregation': 'avg'
                }
            ],
            'linkMetrics': [
                {
                    'id': 'net.bytes.total',
                    'aggregation': 'timeAvg',
                    'groupAggregation': 'sum'
                }
            ]
        }

        #
        # Fire the request
        #
        r = requests.post(self.url + '/api/data?format=map', headers=self.hdrs, data = json.dumps(req_json))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def getDashboards(self):
        r = requests.get(self.url + '/ui/dashboards', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        return [True, r.json()]

    def create_dashboard_from_template(self, newdashname, templatename, scope):
        #
        # Create the unique ID for this dashboard
        #
        baseconfid = newdashname
        for sentry in scope:
            baseconfid = baseconfid + sentry.keys()[0]
            baseconfid = baseconfid + sentry.values()[0]

        print baseconfid

        #
        # Get the list of dashboards from the server
        #
        r = requests.get(self.url + '/ui/dashboards', headers=self.hdrs)
        if not self.__checkResponse(r):
            return [False, self.lasterr]

        j = r.json()

        #
        # Find our template dashboard
        #
        dboard = None

        for db in j['dashboards']:
            if db['name'] == templatename:
                dboard = db
                break

        if dboard == None:
            print 'can\'t find dashboard ' + templatename + ' to use as a template'
            sys.exit(0)

        #
        # Create the dashboard name
        #
        if newdashname:
            dname = newdashname
        else:
            dname = dboard['name'] + ' for ' + service

        #
        # If this dashboard already exists, don't create it another time
        #
        for db in j['dashboards']:
            if db['name'] == dname:
                for view in db['items']:
                    if view['groupId'][0:len(baseconfid)] == baseconfid:
                        print 'dashboard ' + dname + ' already exists - ' + baseconfid
                        return

        #
        # Clean up the dashboard we retireved so it's ready to be pushed
        #
        dboard['id'] = None
        dboard['version'] = None
        dboard['name'] = dname
        dboard['isShared'] = False # make sure the dashboard is not shared

        #
        # Assign the filter and the group ID to each view to point to this service
        #
        filters = []
        gby = []
        for sentry in scope:
            filters.append({'metric' : sentry.keys()[0], 'op' : '=', 'value' : sentry.values()[0]   , 'filters' : None})
            gby.append({'metric': sentry.keys()[0]})

        filter = {
            'filters' :
            {
                'logic' : 'and',
                'filters' : filters
            }
        }

        j = 0

        for view in dboard['items']:
            j = j + 1

            #
            # create the grouping configuration
            #
            confid = baseconfid + str(j)

            gconf = { 'id': confid,
                'groups': [
                    {
                        'groupBy': gby
                    }
                ]
            }

            r = requests.post(self.url + '/api/groupConfigurations', headers=self.hdrs, data = json.dumps(gconf))
            if not self.__checkResponse(r):
                return [False, self.lasterr]

            view['filter'] = filter
            view['groupId'] = confid

    #   print json.dumps(dboard, indent=4, separators=(',', ': '))

        ddboard = {'dashboard': dboard}

        #
        # Create the new dashboard
        #
        r = requests.post(self.url + '/ui/dashboards', headers=self.hdrs, data = json.dumps(ddboard))
        if not self.__checkResponse(r):
            return [False, self.lasterr]
        else:
            return [True, r.json()]
<|endoftext|>


<commit_before>from __future__ import unicode_literals
import json
import pytz

from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.template import loader, Context
from django.conf import settings

from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.sites.models import Site

from django_ical.views import ICalFeed

from account.decorators import login_required

from symposion.schedule.forms import SlotEditForm, ScheduleSectionForm
from symposion.schedule.models import Schedule, Day, Slot, Presentation, Session, SessionRole
from symposion.schedule.timetable import TimeTable
from symposion.conference.models import Conference

def fetch_schedule(slug):
    qs = Schedule.objects.all()

    if slug is None:
        if qs.count() > 1:
            raise Http404()
        schedule = next(iter(qs), None)
        if schedule is None:
            raise Http404()
    else:
        schedule = get_object_or_404(qs, section__slug=slug)

    return schedule

def schedule_conference(request):

    if request.user.is_staff:
        schedules = Schedule.objects.filter(hidden=False)
    else:
        schedules = Schedule.objects.filter(published=True, hidden=False)

    sections = []
    for schedule in schedules:
        days_qs = Day.objects.filter(schedule=schedule)
        days = [TimeTable(day) for day in days_qs]
        sections.append({
            "schedule": schedule,
            "days": days,
        })

    day_switch = request.GET.get('day', None)
    ctx = {
        "sections": sections,
        "day_switch": day_switch
    }
    return render(request, "symposion/schedule/schedule_conference.html", ctx)

def schedule_detail(request, slug=None):

    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    days_qs = Day.objects.filter(schedule=schedule)
    days = [TimeTable(day) for day in days_qs]

    ctx = {
        "schedule": schedule,
        "days": days,
    }
    return render(request, "symposion/schedule/schedule_detail.html", ctx)

def schedule_list(request, slug=None):
    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    presentations = Presentation.objects.filter(section=schedule.section)
    presentations = presentations.exclude(cancelled=True)

    if not request.user.is_staff:
        presentations = presentations.exclude(unpublish=True)

    ctx = {
        "schedule": schedule,
        "presentations": presentations,
    }
    return render(request, "symposion/schedule/schedule_list.html", ctx)

def schedule_list_csv(request, slug=None):
    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    presentations = Presentation.objects.filter(section=schedule.section)
    presentations = presentations.exclude(cancelled=True)
    if not request.user.is_staff:
        presentations = presentations.exclude(unpublish=True)
    presentations = presentations.order_by("id")
    response = HttpResponse(content_type="text/csv")

    if slug:
        file_slug = slug
    else:
        file_slug = "presentations"
    response["Content-Disposition"] = 'attachment; filename="%s.csv"' % file_slug

    response.write(loader.get_template("symposion/schedule/schedule_list.csv").render(Context({
        "presentations": presentations,

    })))
    return response

@login_required
def schedule_edit(request, slug=None):

    if not request.user.is_staff:
        raise Http404()

    schedule = fetch_schedule(slug)

    if request.method == "POST":
        form = ScheduleSectionForm(
            request.POST, request.FILES, schedule=schedule
        )
        if form.is_valid():
            if 'submit' in form.data:
                msg = form.build_schedule()
            elif 'delete' in form.data:
                msg = form.delete_schedule()
            messages.add_message(request, msg[0], msg[1])
    else:
        form = ScheduleSectionForm(schedule=schedule)
    days_qs = Day.objects.filter(schedule=schedule)
    days = [TimeTable(day) for day in days_qs]
    ctx = {
        "schedule": schedule,
        "days": days,
        "form": form
    }
    return render(request, "symposion/schedule/schedule_edit.html", ctx)

@login_required
def schedule_slot_edit(request, slug, slot_pk):

    if not request.user.is_staff:
        raise Http404()

    slot = get_object_or_404(Slot, day__schedule__section__slug=slug, pk=slot_pk)

    if request.method == "POST":
        form = SlotEditForm(request.POST, slot=slot)
        if form.is_valid():
            save = False
            if "content_override" in form.cleaned_data:
                slot.content_override = form.cleaned_data["content_override"]
                save = True
            if "presentation" in form.cleaned_data:
                presentation = form.cleaned_data["presentation"]
                if presentation is None:
                    slot.unassign()
                else:
                    slot.assign(presentation)
            if save:
                slot.save()
        return redirect("schedule_edit", slug)
    else:
        form = SlotEditForm(slot=slot)
        ctx = {
            "slug": slug,
            "form": form,
            "slot": slot,
        }
        return render(request, "symposion/schedule/_slot_edit.html", ctx)

def schedule_presentation_detail(request, pk):

    presentation = get_object_or_404(Presentation, pk=pk)

    if presentation.slot:
        # 1) Schedule from presentation's slot
        schedule = presentation.slot.day.schedule
    else:
        # 2) Fall back to the schedule for this proposal
        schedule = presentation.proposal.kind.section.schedule

    if not request.user.is_staff:
        # 3) Is proposal unpublished?
        if presentation.unpublish or not (schedule and schedule.published):
            raise Http404()

    ctx = {
        "presentation": presentation,
        "schedule": schedule,
    }
    return render(request, "symposion/schedule/presentation_detail.html", ctx)

def schedule_json(request):
    slots = Slot.objects.filter(
        day__schedule__published=True,
        day__schedule__hidden=False
    ).order_by("start")

    protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
    data = []
    for slot in slots:
        slot_data = {
            "room": ", ".join(room["name"] for room in slot.rooms.values()),
            "rooms": [room["name"] for room in slot.rooms.values()],
            "start": slot.start_datetime.isoformat(),
            "end": slot.end_datetime.isoformat(),
            "duration": slot.length_in_minutes,
            "kind": slot.kind.label,
            "section": slot.day.schedule.section.slug,
            "conf_key": slot.pk,
            # TODO: models should be changed.
            # these are model features from other conferences that have forked symposion
            # these have been used almost everywhere and are good candidates for
            # base proposals
            "license": "CC BY",
            "tags": "",
            "released": True,
            "contact": [],
        }
        if hasattr(slot.content, "proposal"):
            if slot.content.unpublish and not request.user.is_staff:
                continue

            slot_data.update({
                "name": slot.content.title,
                "authors": [s.name for s in slot.content.speakers()],
                "contact": [
                    s.email for s in slot.content.speakers()
                ] if request.user.has_perm('symposion_speakers.can_view_contact_details') or request.user.is_staff else ["redacted"],
                "abstract": slot.content.abstract,
                "conf_url": "%s://%s%s" % (
                    protocol,
                    Site.objects.get_current().domain,
                    reverse("schedule_presentation_detail", args=[slot.content.pk])
                ),
                "cancelled": slot.content.cancelled,
            })
            if not slot.content.speaker.twitter_username == '':
                slot_data["twitter_id"] = slot.content.speaker.twitter_username
        else:
            slot_data.update({
                "name": slot.content_override if slot.content_override else "Slot",
            })
        data.append(slot_data)

    return HttpResponse(
        json.dumps({"schedule": data}, indent=2),
        content_type="application/json"
    )

class EventFeed(ICalFeed):

    product_id = '-//linux.conf.au/schedule//EN'
    timezone = settings.TIME_ZONE
    filename = 'conference.ics'
    description = Conference.objects.all().first().title

    def items(self):
        return Slot.objects.filter(
            day__schedule__published=True,
            day__schedule__hidden=False
        ).exclude(
            kind__label='shortbreak'
        ).order_by("start")

    def item_title(self, item):
        if hasattr(item.content, 'proposal'):
            title =  item.content.title
        else:
            title = item.kind if item.kind else "Slot"
        return title

    def item_description(self, item):
        if hasattr(item.content, 'proposal'):
            description = "Speaker: %s\n%s" % (
                item.content.speaker, item.content.abstract)
        else:
            description = item.content_override if item.content_override else "No description"
        return description

    def item_start_datetime(self, item):
        return pytz.timezone(settings.TIME_ZONE).localize(item.start_datetime)

    def item_end_datetime(self, item):
        return pytz.timezone(settings.TIME_ZONE).localize(item.end_datetime)

    def item_location(self, item):
        return ", ".join(room["name"] for room in item.rooms.values())

    def item_link(self, item):
        if hasattr(item.content, 'proposal'):
            return 'http://%s%s' % (
                                    Site.objects.get_current().domain,
                                    reverse('schedule_presentation_detail', args=[item.content.pk])
                                    )
        else:
            return 'http://%s' % Site.objects.get_current().domain

    def item_guid(self, item):
        return '%d@%s' % (item.pk, Site.objects.get_current().domain)

def session_list(request):
    sessions = Session.objects.all().order_by('pk')

    return render(request, "symposion/schedule/session_list.html", {
        "sessions": sessions,
    })

@login_required
def session_staff_email(request):

    if not request.user.is_staff:
        return redirect("schedule_session_list")

    data = "\n".join(user.email for user in User.objects.filter(sessionrole__isnull=False).distinct())

    return HttpResponse(data, content_type="text/plain;charset=UTF-8")

def session_detail(request, session_id):

    session = get_object_or_404(Session, id=session_id)

    chair = None
    chair_denied = False
    chairs = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR).exclude(status=False)
    if chairs:
        chair = chairs[0].user
    else:
        if request.user.is_authenticated():
            # did the current user previously try to apply and got rejected?
            if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_CHAIR, status=False):
                chair_denied = True

    runner = None
    runner_denied = False
    runners = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER).exclude(status=False)
    if runners:
        runner = runners[0].user
    else:
        if request.user.is_authenticated():
            # did the current user previously try to apply and got rejected?
            if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_RUNNER, status=False):
                runner_denied = True

    if request.method == "POST" and request.user.is_authenticated():
        if not hasattr(request.user, "attendee") or not request.user.attendee.completed_registration:
            response = redirect("guided_registration")
            response["Location"] += "?next=%s" % request.path
            return response

        role = request.POST.get("role")
        if role == "chair":
            if chair is None and not chair_denied:
                SessionRole(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user).save()
        elif role == "runner":
            if runner is None and not runner_denied:
                SessionRole(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user).save()
        elif role == "un-chair":
            if chair == request.user:
                session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user)
                if session_role:
                    session_role[0].delete()
        elif role == "un-runner":
            if runner == request.user:
                session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user)
                if session_role:
                    session_role[0].delete()

        return redirect("schedule_session_detail", session_id)

    return render(request, "symposion/schedule/session_detail.html", {
        "session": session,
        "chair": chair,
        "chair_denied": chair_denied,
        "runner": runner,
        "runner_denied": runner_denied,
    })
<commit_msg>Fixed recording release to default false<commit_after>from __future__ import unicode_literals
import json
import pytz

from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.template import loader, Context
from django.conf import settings

from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.sites.models import Site

from django_ical.views import ICalFeed

from account.decorators import login_required

from symposion.schedule.forms import SlotEditForm, ScheduleSectionForm
from symposion.schedule.models import Schedule, Day, Slot, Presentation, Session, SessionRole
from symposion.schedule.timetable import TimeTable
from symposion.conference.models import Conference

def fetch_schedule(slug):
    qs = Schedule.objects.all()

    if slug is None:
        if qs.count() > 1:
            raise Http404()
        schedule = next(iter(qs), None)
        if schedule is None:
            raise Http404()
    else:
        schedule = get_object_or_404(qs, section__slug=slug)

    return schedule

def schedule_conference(request):

    if request.user.is_staff:
        schedules = Schedule.objects.filter(hidden=False)
    else:
        schedules = Schedule.objects.filter(published=True, hidden=False)

    sections = []
    for schedule in schedules:
        days_qs = Day.objects.filter(schedule=schedule)
        days = [TimeTable(day) for day in days_qs]
        sections.append({
            "schedule": schedule,
            "days": days,
        })

    day_switch = request.GET.get('day', None)
    ctx = {
        "sections": sections,
        "day_switch": day_switch
    }
    return render(request, "symposion/schedule/schedule_conference.html", ctx)

def schedule_detail(request, slug=None):

    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    days_qs = Day.objects.filter(schedule=schedule)
    days = [TimeTable(day) for day in days_qs]

    ctx = {
        "schedule": schedule,
        "days": days,
    }
    return render(request, "symposion/schedule/schedule_detail.html", ctx)

def schedule_list(request, slug=None):
    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    presentations = Presentation.objects.filter(section=schedule.section)
    presentations = presentations.exclude(cancelled=True)

    if not request.user.is_staff:
        presentations = presentations.exclude(unpublish=True)

    ctx = {
        "schedule": schedule,
        "presentations": presentations,
    }
    return render(request, "symposion/schedule/schedule_list.html", ctx)

def schedule_list_csv(request, slug=None):
    schedule = fetch_schedule(slug)
    if not schedule.published and not request.user.is_staff:
        raise Http404()

    presentations = Presentation.objects.filter(section=schedule.section)
    presentations = presentations.exclude(cancelled=True)
    if not request.user.is_staff:
        presentations = presentations.exclude(unpublish=True)
    presentations = presentations.order_by("id")
    response = HttpResponse(content_type="text/csv")

    if slug:
        file_slug = slug
    else:
        file_slug = "presentations"
    response["Content-Disposition"] = 'attachment; filename="%s.csv"' % file_slug

    response.write(loader.get_template("symposion/schedule/schedule_list.csv").render(Context({
        "presentations": presentations,

    })))
    return response

@login_required
def schedule_edit(request, slug=None):

    if not request.user.is_staff:
        raise Http404()

    schedule = fetch_schedule(slug)

    if request.method == "POST":
        form = ScheduleSectionForm(
            request.POST, request.FILES, schedule=schedule
        )
        if form.is_valid():
            if 'submit' in form.data:
                msg = form.build_schedule()
            elif 'delete' in form.data:
                msg = form.delete_schedule()
            messages.add_message(request, msg[0], msg[1])
    else:
        form = ScheduleSectionForm(schedule=schedule)
    days_qs = Day.objects.filter(schedule=schedule)
    days = [TimeTable(day) for day in days_qs]
    ctx = {
        "schedule": schedule,
        "days": days,
        "form": form
    }
    return render(request, "symposion/schedule/schedule_edit.html", ctx)

@login_required
def schedule_slot_edit(request, slug, slot_pk):

    if not request.user.is_staff:
        raise Http404()

    slot = get_object_or_404(Slot, day__schedule__section__slug=slug, pk=slot_pk)

    if request.method == "POST":
        form = SlotEditForm(request.POST, slot=slot)
        if form.is_valid():
            save = False
            if "content_override" in form.cleaned_data:
                slot.content_override = form.cleaned_data["content_override"]
                save = True
            if "presentation" in form.cleaned_data:
                presentation = form.cleaned_data["presentation"]
                if presentation is None:
                    slot.unassign()
                else:
                    slot.assign(presentation)
            if save:
                slot.save()
        return redirect("schedule_edit", slug)
    else:
        form = SlotEditForm(slot=slot)
        ctx = {
            "slug": slug,
            "form": form,
            "slot": slot,
        }
        return render(request, "symposion/schedule/_slot_edit.html", ctx)

def schedule_presentation_detail(request, pk):

    presentation = get_object_or_404(Presentation, pk=pk)

    if presentation.slot:
        # 1) Schedule from presentation's slot
        schedule = presentation.slot.day.schedule
    else:
        # 2) Fall back to the schedule for this proposal
        schedule = presentation.proposal.kind.section.schedule

    if not request.user.is_staff:
        # 3) Is proposal unpublished?
        if presentation.unpublish or not (schedule and schedule.published):
            raise Http404()

    ctx = {
        "presentation": presentation,
        "schedule": schedule,
    }
    return render(request, "symposion/schedule/presentation_detail.html", ctx)

def schedule_json(request):
    slots = Slot.objects.filter(
        day__schedule__published=True,
        day__schedule__hidden=False
    ).order_by("start")

    protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
    data = []
    for slot in slots:
        slot_data = {
            "room": ", ".join(room["name"] for room in slot.rooms.values()),
            "rooms": [room["name"] for room in slot.rooms.values()],
            "start": slot.start_datetime.isoformat(),
            "end": slot.end_datetime.isoformat(),
            "duration": slot.length_in_minutes,
            "kind": slot.kind.label,
            "section": slot.day.schedule.section.slug,
            "conf_key": slot.pk,
            # TODO: models should be changed.
            # these are model features from other conferences that have forked symposion
            # these have been used almost everywhere and are good candidates for
            # base proposals
            "license": "CC BY",
            "tags": "",
            "released": False,
            "contact": [],
        }
        if hasattr(slot.content, "proposal"):
            if slot.content.unpublish and not request.user.is_staff:
                continue

            slot_data.update({
                "name": slot.content.title,
                "authors": [s.name for s in slot.content.speakers()],
                "contact": [
                    s.email for s in slot.content.speakers()
                ] if request.user.has_perm('symposion_speakers.can_view_contact_details') or request.user.is_staff else ["redacted"],
                "abstract": slot.content.abstract,
                "conf_url": "%s://%s%s" % (
                    protocol,
                    Site.objects.get_current().domain,
                    reverse("schedule_presentation_detail", args=[slot.content.pk])
                ),
                "cancelled": slot.content.cancelled,
                "released": slot.content.proposal.recording_release
            })
            if not slot.content.speaker.twitter_username == '':
                slot_data["twitter_id"] = slot.content.speaker.twitter_username
        else:
            slot_data.update({
                "name": slot.content_override if slot.content_override else "Slot",
            })
        data.append(slot_data)

    return HttpResponse(
        json.dumps({"schedule": data}, indent=2),
        content_type="application/json"
    )

class EventFeed(ICalFeed):

    product_id = '-//linux.conf.au/schedule//EN'
    timezone = settings.TIME_ZONE
    filename = 'conference.ics'
    description = Conference.objects.all().first().title

    def items(self):
        return Slot.objects.filter(
            day__schedule__published=True,
            day__schedule__hidden=False
        ).exclude(
            kind__label='shortbreak'
        ).order_by("start")

    def item_title(self, item):
        if hasattr(item.content, 'proposal'):
            title =  item.content.title
        else:
            title = item.kind if item.kind else "Slot"
        return title

    def item_description(self, item):
        if hasattr(item.content, 'proposal'):
            description = "Speaker: %s\n%s" % (
                item.content.speaker, item.content.abstract)
        else:
            description = item.content_override if item.content_override else "No description"
        return description

    def item_start_datetime(self, item):
        return pytz.timezone(settings.TIME_ZONE).localize(item.start_datetime)

    def item_end_datetime(self, item):
        return pytz.timezone(settings.TIME_ZONE).localize(item.end_datetime)

    def item_location(self, item):
        return ", ".join(room["name"] for room in item.rooms.values())

    def item_link(self, item):
        if hasattr(item.content, 'proposal'):
            return 'http://%s%s' % (
                                    Site.objects.get_current().domain,
                                    reverse('schedule_presentation_detail', args=[item.content.pk])
                                    )
        else:
            return 'http://%s' % Site.objects.get_current().domain

    def item_guid(self, item):
        return '%d@%s' % (item.pk, Site.objects.get_current().domain)

def session_list(request):
    sessions = Session.objects.all().order_by('pk')

    return render(request, "symposion/schedule/session_list.html", {
        "sessions": sessions,
    })

@login_required
def session_staff_email(request):

    if not request.user.is_staff:
        return redirect("schedule_session_list")

    data = "\n".join(user.email for user in User.objects.filter(sessionrole__isnull=False).distinct())

    return HttpResponse(data, content_type="text/plain;charset=UTF-8")

def session_detail(request, session_id):

    session = get_object_or_404(Session, id=session_id)

    chair = None
    chair_denied = False
    chairs = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR).exclude(status=False)
    if chairs:
        chair = chairs[0].user
    else:
        if request.user.is_authenticated():
            # did the current user previously try to apply and got rejected?
            if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_CHAIR, status=False):
                chair_denied = True

    runner = None
    runner_denied = False
    runners = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER).exclude(status=False)
    if runners:
        runner = runners[0].user
    else:
        if request.user.is_authenticated():
            # did the current user previously try to apply and got rejected?
            if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_RUNNER, status=False):
                runner_denied = True

    if request.method == "POST" and request.user.is_authenticated():
        if not hasattr(request.user, "attendee") or not request.user.attendee.completed_registration:
            response = redirect("guided_registration")
            response["Location"] += "?next=%s" % request.path
            return response

        role = request.POST.get("role")
        if role == "chair":
            if chair is None and not chair_denied:
                SessionRole(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user).save()
        elif role == "runner":
            if runner is None and not runner_denied:
                SessionRole(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user).save()
        elif role == "un-chair":
            if chair == request.user:
                session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user)
                if session_role:
                    session_role[0].delete()
        elif role == "un-runner":
            if runner == request.user:
                session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user)
                if session_role:
                    session_role[0].delete()

        return redirect("schedule_session_detail", session_id)

    return render(request, "symposion/schedule/session_detail.html", {
        "session": session,
        "chair": chair,
        "chair_denied": chair_denied,
        "runner": runner,
        "runner_denied": runner_denied,
    })
<|endoftext|>


<commit_before>import subprocess

from xml.etree import ElementTree

class Varnishstat(object):
    def __init__(self, agentConfig, checksLogger, rawConfig):
        self.agentConfig = agentConfig
        self.checksLogger = checksLogger
        self.rawConfig = rawConfig

    def run(self):
        stats = {}
        varnishstat = subprocess.Popen(
            ['varnishstat','-x'],
            stdout=subprocess.PIPE,
        )
        stats_xml = ElementTree.parse(varnishstat.stdout)

        for stat_node in stats_xml.findall('stat'):
            label = stat_node.findtext('description')
            value = stat_node.findtext('value')
            stats[label] = value

	# Count uptime in days
	uptime = float(stats['Client uptime'])
        stats['Client uptime'] = uptime / 86400

	# Count cache hit and miss ratios
	requests = float(stats['Client requests received'])
        hits = float(stats['Cache hits'])
        misses = float(stats['Cache misses'])
        stats['Hit ratio'] = float(hits / requests) * 100
        stats['Miss ratio'] = float(misses / requests) * 100

        # Convert body and header bytes to MB
        body_bytes = float(stats['Total body bytes'])
	stats['Total body MB'] = float(body_bytes / 1048576)
	header_bytes = float(stats['Total header bytes'])
	stats['Total header MB'] = float(header_bytes / 1048576)

        return stats
<commit_msg>Implemented better actual request, hit, miss, hit ratio and miss ratio counters.<commit_after>import subprocess

from xml.etree import ElementTree

class Varnishstat(object):
    def __init__(self, agentConfig, checksLogger, rawConfig):
        self.agentConfig = agentConfig
        self.checksLogger = checksLogger
        self.rawConfig = rawConfig

    def run(self):
        stats = {}
        varnishstat = subprocess.Popen(
            ['varnishstat','-x'],
            stdout=subprocess.PIPE,
        )
        stats_xml = ElementTree.parse(varnishstat.stdout)

        for stat_node in stats_xml.findall('stat'):
            label = stat_node.findtext('description')
            value = stat_node.findtext('value')
            stats[label] = value

	      # Count uptime in days
	      uptime = float(stats['Client uptime'])
        stats['Client uptime'] = uptime / 86400

	      requests_new = int(stats['Client requests received'])
        hits_new = int(stats['Cache hits'])
        misses_new = int(stats['Cache misses'])
        requests_old = int(0)
        hits_old = int(0)
        misses_old = int(0)

        try:
          with open('/tmp/sdstats', 'r') as sfile:
            requests_old = int(sfile.readline())
            hits_old = int(sfile.readline())
            misses_old = int(sfile.readline())
            sfile.close()
        except IOError as e:
          sfile = open('/tmp/sdstats', 'w')
          req = str(requests_new)
          hit = str(hits_new)
          miss = str(misses_new)
          sfile.write(req + '\n' + hit + '\n' + miss)
          sfile.close()

        sfile = open('/tmp/sdstats', 'w')
        req = str(requests_new)
        hit = str(hits_new)
        miss = str(misses_new)
        sfile.write(req + '\n' + hit + '\n' + miss)
        sfile.close()

        requests = float(requests_new - requests_old)
        hits = float(hits_new - hits_old)
        misses = float(misses_new - misses_old)
        if requests != 0.00:
          stats['Hit ratio'] = float(hits / requests) * 100
          stats['Miss ratio'] = float(misses / requests) * 100
          stats['Client requests received'] = int(requests)
          stats['Cache hits'] = int(hits)
          stats['Cache misses'] = int(misses)
        else:
          stats['Hit ratio'] = 0.00
          stats['Miss ratio'] = 0.00
          stats['Client requests received'] = 0
          stats['Cache hits'] = 0
          stats['Cache misses'] = 0

        # Convert body and header bytes to MB
        body_bytes = float(stats['Total body bytes'])
	      stats['Total body MB'] = float(body_bytes / 1048576)
	      header_bytes = float(stats['Total header bytes'])
	      stats['Total header MB'] = float(header_bytes / 1048576)

        return stats
<|endoftext|>


<commit_before>"""

  fs.wrapfs:  class for wrapping an existing FS object with added functionality

This module provides the class WrapFS, a base class for objects that wrap
another FS object and provide some transformation of its contents.  It could
be very useful for implementing e.g. transparent encryption or compression
services.

As a simple example of how this class could be used, the 'HideDotFiles' class
implements the standard unix shell functionality of hiding dot files in
directory listings.

"""

from fnmatch import fnmatch

from fs.base import FS, threading, synchronize
from fs.errors import *

def rewrite_errors(func):
    @wraps(func)
    def wrapper(self,*args,**kwds):
        try:
            return func(self,*args,**kwds)
        except ResourceError, e:
            try:
                e.path = self._decode(e.path)
            except AttributeError:
                pass
            raise
    return wrapper

class WrapFS(FS):
    """FS that wraps another FS, providing translation etc.

    This class allows simple transforms to be applied to the names
    and/or contents of files in an FS.  It could be used to implement
    e.g. compression or encryption in a relatively painless manner.

    The following methods can be overridden to control how files are
    accessed in the underlying FS object:

        _file_wrap(file,mode):  called for each file that is opened from
                                the underlying FS; may return a modified
                                file-like object.

        _encode(path):  encode a path for access in the underlying FS

        _decode(path):  decode a path from the underlying FS

    If the required path translation proceeds one component at a time,
    it may be simpler to override the _encode_name() and _decode_name()
    methods.
    """

    def __init__(self,fs):
        super(WrapFS,self).__init__()
        try:
            self._lock = fs._lock
        except (AttributeError,FSError):
            self._lock = None
        self.wrapped_fs = fs

    def _file_wrap(self,f,mode):
        """Apply wrapping to an opened file."""
        return f

    def _encode_name(self,name):
        """Encode path component for the underlying FS."""
        return name

    def _decode_name(self,name):
        """Decode path component from the underlying FS."""
        return name

    def _encode(self,path):
        """Encode path for the underlying FS."""
        names = path.split("/")
        e_names = []
        for name in names:
            if name == "":
                e_names.append("")
            else:
                e_names.append(self._encode_name(name))
        return "/".join(e_names)

    def _decode(self,path):
        """Decode path from the underlying FS."""
        names = path.split("/")
        d_names = []
        for name in names:
            if name == "":
                d_names.append("")
            else:
                d_names.append(self._decode_name(name))
        return "/".join(d_names)

    def _adjust_mode(self,mode):
        """Adjust the mode used to open a file in the underlying FS.

        This method takes the mode given when opening a file, and should
        return a two-tuple giving the mode to be used in this FS as first
        item, and the mode to be used in the underlying FS as the second.

        An example of why this is needed is a WrapFS subclass that does
        transparent file compression - in this case files from the wrapped
        FS cannot be opened in append mode.
        """
        return (mode,mode)

    @rewrite_errors
    def getsyspath(self,path,allow_none=False):
        return self.wrapped_fs.getsyspath(self._encode(path),allow_none)

    @rewrite_errors
    def hassyspath(self,path):
        return self.wrapped_fs.hassyspath(self._encode(path))

    @rewrite_errors
    def open(self,path,mode="r"):
        (mode,wmode) = self._adjust_mode(mode)
        f = self.wrapped_fs.open(self._encode(path),wmode)
        return self._file_wrap(f,mode)

    @rewrite_errors
    def exists(self,path):
        return self.wrapped_fs.exists(self._encode(path))

    @rewrite_errors
    def isdir(self,path):
        return self.wrapped_fs.isdir(self._encode(path))

    @rewrite_errors
    def isfile(self,path):
        return self.wrapped_fs.isfile(self._encode(path))

    @rewrite_errors
    def listdir(self,path="",**kwds):
        wildcard = kwds.pop("wildcard","*")
        info = kwds.get("info",False)
        entries = []
        for e in self.wrapped_fs.listdir(self._encode(path),**kwds):
            if info:
                e = e.copy()
                e["name"] = self._decode(e["name"])
                if wildcard is not None and not fnmatch(e["name"],wildcard):
                    continue
            else:
                e = self._decode(e)
                if wildcard is not None and not fnmatch(e,wildcard):
                    continue
            entries.append(e)
        return entries

    @rewrite_errors
    def makedir(self,path,*args,**kwds):
        return self.wrapped_fs.makedir(self._encode(path),*args,**kwds)

    @rewrite_errors
    def remove(self,path):
        return self.wrapped_fs.remove(self._encode(path))

    @rewrite_errors
    def removedir(self,path,*args,**kwds):
        return self.wrapped_fs.removedir(self._encode(path),*args,**kwds)

    @rewrite_errors
    def rename(self,src,dst):
        return self.wrapped_fs.rename(self._encode(src),self._encode(dst))

    @rewrite_errors
    def getinfo(self,path):
        return self.wrapped_fs.getinfo(self._encode(path))

    @rewrite_errors
    def desc(self,path):
        return self.wrapped_fs.desc(self._encode(path))

    @rewrite_errors
    def copy(self,src,dst,overwrite=False,chunk_size=16384):
        return self.wrapped_fs.copy(self._encode(src),self._encode(dst),overwrite,chunk_size)

    @rewrite_errors
    def move(self,src,dst,overwrite=False,chunk_size=16384):
        return self.wrapped_fs.move(self._encode(src),self._encode(dst),overwrite,chunk_size)

    @rewrite_errors
    def movedir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384):
        return self.wrapped_fs.movedir(self._encode(src),self._encode(dst),overwrite,ignore_errors,chunk_size)

    @rewrite_errors
    def copydir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384):
        return self.wrapped_fs.copydir(self._encode(src),self._encode(dst),overwrite,ignore_errors,chunk_size)

    @rewrite_errors
    def getxattr(self,path,name,default=None):
        return self.wrapped_fs.getxattr(self._encode(path),name,default)

    @rewrite_errors
    def setxattr(self,path,name,value):
        return self.wrapped_fs.setxattr(self._encode(path),name,value)

    @rewrite_errors
    def delxattr(self,path,name):
        return self.wrapped_fs.delxattr(self._encode(path),name)

    @rewrite_errors
    def listxattrs(self,path):
        return self.wrapped_fs.listxattrs(self._encode(path))

    def __getattr__(self,attr):
        return getattr(self.wrapped_fs,attr)

    @rewrite_errors
    def close(self):
        if hasattr(self.wrapped_fs,"close"):
            self.wrapped_fs.close()

def wrap_fs_methods(decorator,cls=None):
    """Apply the given decorator to all FS methods on the given class.

    This function can be used in two ways.  When called with two arguments it
    applies the given function 'decorator' to each FS method of the given
    class.  When called with just a single argument, it creates and returns
    a class decorator which will do the same thing when applied.  So you can
    use it like this:

        wrap_fs_methods(mydecorator,MyFSClass)

    Or on more recent Python versions, like this:

        @wrap_fs_methods(mydecorator)
        class MyFSClass(FS):
            ...

    """
    methods = ("open","exists","isdir","isfile","listdir","makedir","remove",
               "removedir","rename","getinfo","copy","move","copydir",
               "movedir","close","getxattr","setxattr","delxattr","listxattrs")
    def apply_decorator(cls):
        for method_name in methods:
            method = getattr(cls,method_name,None)
            if method is not None:
                setattr(cls,method_name,decorator(method))
        return cls
    if cls is not None:
        return apply_decorator(cls)
    else:
        return apply_decorator

class HideDotFiles(WrapFS):
    """FS wrapper class that hides dot-files in directory listings.

    The listdir() function takes an extra keyword argument 'hidden'
    indicating whether hidden dotfiles shoud be included in the output.
    It is False by default.
    """

    def is_hidden(self,path):
        """Check whether the given path should be hidden."""
        return path and basename(path)[0] == "."

    def _encode(self,path):
        return path

    def _decode(self,path):
        return path

    def listdir(self,path="",**kwds):
        hidden = kwds.pop("hidden",True)
        entries = self.wrapped_fs.listdir(path,**kwds)
        if not hidden:
            entries = [e for e in entries if not self.is_hidden(e)]
        return entries

    def walk(self, path="/", wildcard=None, dir_wildcard=None, search="breadth",hidden=False):
        if search == "breadth":
            dirs = [path]
            while dirs:
                current_path = dirs.pop()
                paths = []
                for filename in self.listdir(current_path,hidden=hidden):
                    path = pathjoin(current_path, filename)
                    if self.isdir(path):
                        if dir_wildcard is not None:
                            if fnmatch(path, dir_wilcard):
                                dirs.append(path)
                        else:
                            dirs.append(path)
                    else:
                        if wildcard is not None:
                            if fnmatch(path, wildcard):
                                paths.append(filename)
                        else:
                            paths.append(filename)
                yield (current_path, paths)
        elif search == "depth":
            def recurse(recurse_path):
                for path in self.listdir(recurse_path, wildcard=dir_wildcard, full=True, dirs_only=True,hidden=hidden):
                    for p in recurse(path):
                        yield p
                yield (recurse_path, self.listdir(recurse_path, wildcard=wildcard, files_only=True,hidden=hidden))
            for p in recurse(path):
                yield p
        else:
            raise ValueError("Search should be 'breadth' or 'depth'")

    def isdirempty(self, path):
        path = normpath(path)
        iter_dir = iter(self.listdir(path,hidden=True))
        try:
            iter_dir.next()
        except StopIteration:
            return True
        return False

class LimitSize(WrapFS):

    def __init__(self,fs,max_size):
        self.max_size = max_size
        super(LimitSize,self).__init__(fs)
        self.cur_size = sum(self.getsize(f) for f in self.walkfiles())

    @synchronize
    def open(self,path,mode="r"):
        try:
            size = self.getsize(path)
        except ResourceNotFoundError:
            size = 0
        f = super(LimitSize,self).open(path,mode)
        if "w" in mode:
            self.cur_size -= size
            size = 0
        return LimitSizeFile(self,f,mode,size)

    def _acquire_space(self,size):
        new_size = self.cur_size + size
        if new_size > self.max_size:
            raise StorageSpaceError("write")
        self.cur_size = new_size

    #  Disable use of system-level paths, so that copy/copydir have to
    #  fall back to manual writes and pass through _acquire_space.
    getsyspath = FS.getsyspath
    copy = FS.copy
    copydir = FS.copydir

    @synchronize
    def remove(self,path):
        size = self.getsize(path)
        super(LimitSize,self).remove(path)
        self.cur_size -= size

    @synchronize
    def removedir(self,path,recursive=False,force=False):
        size = sum(self.getsize(f) for f in self.walkfiles(path))
        super(LimitSize,self).removedir(path,recursive=recursive,force=force)
        self.cur_size -= size

class LimitSizeFile(object):

    def __init__(self,fs,file,mode,size):
        self._lock = fs._lock
        self.fs = fs
        self.file = file
        self.mode = mode
        self.size = size
        self.closed = False

    @synchronize
    def write(self,data):
        pos = self.file.tell()
        if pos > self.size:
            self.size = pos
        diff = pos + len(data) - self.size
        if diff <= 0:
            self.file.write(data)
        else:
            self.fs._acquire_space(diff)
            self.file.write(data)
            self.size += diff

    def writelines(self,lines):
        for line in lines:
            self.write(line)

    @synchronize
    def truncate(self,size=None):
        pos = self.file.tell()
        if size is None:
            size = pos
        self.fs._acquire_space(size - self.size)
        self.file.truncate(size)
        self.size = size

    #  This is lifted straight from the stdlib's tempfile.py
    def __getattr__(self,name):
        file = self.__dict__['file']
        a = getattr(file, name)
        if not issubclass(type(a), type(0)):
            setattr(self, name, a)
        return a

    def __enter__(self):
        self.file.__enter__()
        return self

    def __exit__(self,exc,value,tb):
        self.close()
        return False

    def __iter__(self):
        return iter(self.file)

<commit_msg>fix keyword arguments in WrapFS<commit_after>"""

  fs.wrapfs:  class for wrapping an existing FS object with added functionality

This module provides the class WrapFS, a base class for objects that wrap
another FS object and provide some transformation of its contents.  It could
be very useful for implementing e.g. transparent encryption or compression
services.

As a simple example of how this class could be used, the 'HideDotFiles' class
implements the standard unix shell functionality of hiding dot files in
directory listings.

"""

from fnmatch import fnmatch

from fs.base import FS, threading, synchronize
from fs.errors import *

def rewrite_errors(func):
    @wraps(func)
    def wrapper(self,*args,**kwds):
        try:
            return func(self,*args,**kwds)
        except ResourceError, e:
            try:
                e.path = self._decode(e.path)
            except AttributeError:
                pass
            raise
    return wrapper

class WrapFS(FS):
    """FS that wraps another FS, providing translation etc.

    This class allows simple transforms to be applied to the names
    and/or contents of files in an FS.  It could be used to implement
    e.g. compression or encryption in a relatively painless manner.

    The following methods can be overridden to control how files are
    accessed in the underlying FS object:

        _file_wrap(file,mode):  called for each file that is opened from
                                the underlying FS; may return a modified
                                file-like object.

        _encode(path):  encode a path for access in the underlying FS

        _decode(path):  decode a path from the underlying FS

    If the required path translation proceeds one component at a time,
    it may be simpler to override the _encode_name() and _decode_name()
    methods.
    """

    def __init__(self,fs):
        super(WrapFS,self).__init__()
        try:
            self._lock = fs._lock
        except (AttributeError,FSError):
            self._lock = None
        self.wrapped_fs = fs

    def _file_wrap(self,f,mode):
        """Apply wrapping to an opened file."""
        return f

    def _encode_name(self,name):
        """Encode path component for the underlying FS."""
        return name

    def _decode_name(self,name):
        """Decode path component from the underlying FS."""
        return name

    def _encode(self,path):
        """Encode path for the underlying FS."""
        names = path.split("/")
        e_names = []
        for name in names:
            if name == "":
                e_names.append("")
            else:
                e_names.append(self._encode_name(name))
        return "/".join(e_names)

    def _decode(self,path):
        """Decode path from the underlying FS."""
        names = path.split("/")
        d_names = []
        for name in names:
            if name == "":
                d_names.append("")
            else:
                d_names.append(self._decode_name(name))
        return "/".join(d_names)

    def _adjust_mode(self,mode):
        """Adjust the mode used to open a file in the underlying FS.

        This method takes the mode given when opening a file, and should
        return a two-tuple giving the mode to be used in this FS as first
        item, and the mode to be used in the underlying FS as the second.

        An example of why this is needed is a WrapFS subclass that does
        transparent file compression - in this case files from the wrapped
        FS cannot be opened in append mode.
        """
        return (mode,mode)

    @rewrite_errors
    def getsyspath(self,path,allow_none=False):
        return self.wrapped_fs.getsyspath(self._encode(path),allow_none)

    @rewrite_errors
    def hassyspath(self,path):
        return self.wrapped_fs.hassyspath(self._encode(path))

    @rewrite_errors
    def open(self,path,mode="r"):
        (mode,wmode) = self._adjust_mode(mode)
        f = self.wrapped_fs.open(self._encode(path),wmode)
        return self._file_wrap(f,mode)

    @rewrite_errors
    def exists(self,path):
        return self.wrapped_fs.exists(self._encode(path))

    @rewrite_errors
    def isdir(self,path):
        return self.wrapped_fs.isdir(self._encode(path))

    @rewrite_errors
    def isfile(self,path):
        return self.wrapped_fs.isfile(self._encode(path))

    @rewrite_errors
    def listdir(self,path="",**kwds):
        wildcard = kwds.pop("wildcard","*")
        info = kwds.get("info",False)
        entries = []
        for e in self.wrapped_fs.listdir(self._encode(path),**kwds):
            if info:
                e = e.copy()
                e["name"] = self._decode(e["name"])
                if wildcard is not None and not fnmatch(e["name"],wildcard):
                    continue
            else:
                e = self._decode(e)
                if wildcard is not None and not fnmatch(e,wildcard):
                    continue
            entries.append(e)
        return entries

    @rewrite_errors
    def makedir(self,path,*args,**kwds):
        return self.wrapped_fs.makedir(self._encode(path),*args,**kwds)

    @rewrite_errors
    def remove(self,path):
        return self.wrapped_fs.remove(self._encode(path))

    @rewrite_errors
    def removedir(self,path,*args,**kwds):
        return self.wrapped_fs.removedir(self._encode(path),*args,**kwds)

    @rewrite_errors
    def rename(self,src,dst):
        return self.wrapped_fs.rename(self._encode(src),self._encode(dst))

    @rewrite_errors
    def getinfo(self,path):
        return self.wrapped_fs.getinfo(self._encode(path))

    @rewrite_errors
    def desc(self,path):
        return self.wrapped_fs.desc(self._encode(path))

    @rewrite_errors
    def copy(self,src,dst,**kwds):
        return self.wrapped_fs.copy(self._encode(src),self._encode(dst),**kwds)

    @rewrite_errors
    def move(self,src,dst,**kwds):
        return self.wrapped_fs.move(self._encode(src),self._encode(dst),**kwds)

    @rewrite_errors
    def movedir(self,src,dst,**kwds):
        return self.wrapped_fs.movedir(self._encode(src),self._encode(dst),**kwds)

    @rewrite_errors
    def copydir(self,src,dst,**kwds):
        return self.wrapped_fs.copydir(self._encode(src),self._encode(dst),**kwds)

    @rewrite_errors
    def getxattr(self,path,name,default=None):
        return self.wrapped_fs.getxattr(self._encode(path),name,default)

    @rewrite_errors
    def setxattr(self,path,name,value):
        return self.wrapped_fs.setxattr(self._encode(path),name,value)

    @rewrite_errors
    def delxattr(self,path,name):
        return self.wrapped_fs.delxattr(self._encode(path),name)

    @rewrite_errors
    def listxattrs(self,path):
        return self.wrapped_fs.listxattrs(self._encode(path))

    def __getattr__(self,attr):
        return getattr(self.wrapped_fs,attr)

    @rewrite_errors
    def close(self):
        if hasattr(self.wrapped_fs,"close"):
            self.wrapped_fs.close()

def wrap_fs_methods(decorator,cls=None):
    """Apply the given decorator to all FS methods on the given class.

    This function can be used in two ways.  When called with two arguments it
    applies the given function 'decorator' to each FS method of the given
    class.  When called with just a single argument, it creates and returns
    a class decorator which will do the same thing when applied.  So you can
    use it like this:

        wrap_fs_methods(mydecorator,MyFSClass)

    Or on more recent Python versions, like this:

        @wrap_fs_methods(mydecorator)
        class MyFSClass(FS):
            ...

    """
    methods = ("open","exists","isdir","isfile","listdir","makedir","remove",
               "removedir","rename","getinfo","copy","move","copydir",
               "movedir","close","getxattr","setxattr","delxattr","listxattrs")
    def apply_decorator(cls):
        for method_name in methods:
            method = getattr(cls,method_name,None)
            if method is not None:
                setattr(cls,method_name,decorator(method))
        return cls
    if cls is not None:
        return apply_decorator(cls)
    else:
        return apply_decorator

class HideDotFiles(WrapFS):
    """FS wrapper class that hides dot-files in directory listings.

    The listdir() function takes an extra keyword argument 'hidden'
    indicating whether hidden dotfiles shoud be included in the output.
    It is False by default.
    """

    def is_hidden(self,path):
        """Check whether the given path should be hidden."""
        return path and basename(path)[0] == "."

    def _encode(self,path):
        return path

    def _decode(self,path):
        return path

    def listdir(self,path="",**kwds):
        hidden = kwds.pop("hidden",True)
        entries = self.wrapped_fs.listdir(path,**kwds)
        if not hidden:
            entries = [e for e in entries if not self.is_hidden(e)]
        return entries

    def walk(self, path="/", wildcard=None, dir_wildcard=None, search="breadth",hidden=False):
        if search == "breadth":
            dirs = [path]
            while dirs:
                current_path = dirs.pop()
                paths = []
                for filename in self.listdir(current_path,hidden=hidden):
                    path = pathjoin(current_path, filename)
                    if self.isdir(path):
                        if dir_wildcard is not None:
                            if fnmatch(path, dir_wilcard):
                                dirs.append(path)
                        else:
                            dirs.append(path)
                    else:
                        if wildcard is not None:
                            if fnmatch(path, wildcard):
                                paths.append(filename)
                        else:
                            paths.append(filename)
                yield (current_path, paths)
        elif search == "depth":
            def recurse(recurse_path):
                for path in self.listdir(recurse_path, wildcard=dir_wildcard, full=True, dirs_only=True,hidden=hidden):
                    for p in recurse(path):
                        yield p
                yield (recurse_path, self.listdir(recurse_path, wildcard=wildcard, files_only=True,hidden=hidden))
            for p in recurse(path):
                yield p
        else:
            raise ValueError("Search should be 'breadth' or 'depth'")

    def isdirempty(self, path):
        path = normpath(path)
        iter_dir = iter(self.listdir(path,hidden=True))
        try:
            iter_dir.next()
        except StopIteration:
            return True
        return False

class LimitSize(WrapFS):

    def __init__(self,fs,max_size):
        self.max_size = max_size
        super(LimitSize,self).__init__(fs)
        self.cur_size = sum(self.getsize(f) for f in self.walkfiles())

    @synchronize
    def open(self,path,mode="r"):
        try:
            size = self.getsize(path)
        except ResourceNotFoundError:
            size = 0
        f = super(LimitSize,self).open(path,mode)
        if "w" in mode:
            self.cur_size -= size
            size = 0
        return LimitSizeFile(self,f,mode,size)

    def _acquire_space(self,size):
        new_size = self.cur_size + size
        if new_size > self.max_size:
            raise StorageSpaceError("write")
        self.cur_size = new_size

    #  Disable use of system-level paths, so that copy/copydir have to
    #  fall back to manual writes and pass through _acquire_space.
    getsyspath = FS.getsyspath
    copy = FS.copy
    copydir = FS.copydir

    @synchronize
    def remove(self,path):
        size = self.getsize(path)
        super(LimitSize,self).remove(path)
        self.cur_size -= size

    @synchronize
    def removedir(self,path,recursive=False,force=False):
        size = sum(self.getsize(f) for f in self.walkfiles(path))
        super(LimitSize,self).removedir(path,recursive=recursive,force=force)
        self.cur_size -= size

class LimitSizeFile(object):

    def __init__(self,fs,file,mode,size):
        self._lock = fs._lock
        self.fs = fs
        self.file = file
        self.mode = mode
        self.size = size
        self.closed = False

    @synchronize
    def write(self,data):
        pos = self.file.tell()
        if pos > self.size:
            self.size = pos
        diff = pos + len(data) - self.size
        if diff <= 0:
            self.file.write(data)
        else:
            self.fs._acquire_space(diff)
            self.file.write(data)
            self.size += diff

    def writelines(self,lines):
        for line in lines:
            self.write(line)

    @synchronize
    def truncate(self,size=None):
        pos = self.file.tell()
        if size is None:
            size = pos
        self.fs._acquire_space(size - self.size)
        self.file.truncate(size)
        self.size = size

    #  This is lifted straight from the stdlib's tempfile.py
    def __getattr__(self,name):
        file = self.__dict__['file']
        a = getattr(file, name)
        if not issubclass(type(a), type(0)):
            setattr(self, name, a)
        return a

    def __enter__(self):
        self.file.__enter__()
        return self

    def __exit__(self,exc,value,tb):
        self.close()
        return False

    def __iter__(self):
        return iter(self.file)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import numpy as np

def is_multiclass_classifier(clf):
    """
    Return True if a classifier is multiclass or False if it is binary.
    """
    return clf.coef_.shape[0] > 1

def is_multitarget_regressor(clf):
    """
    Return True if a regressor is multitarget
    or False if it predicts a single target.
    """
    return len(clf.coef_.shape) > 1 and clf.coef_.shape[0] > 1

def is_probabilistic_classifier(clf):
    """ Return True if a classifier can return probabilities """
    return hasattr(clf, 'predict_proba')

def has_intercept(clf):
    """ Return True if classifier has intercept fit. """
    return getattr(clf, 'fit_intercept', False)

def get_feature_names(clf, vec=None, bias_name='<BIAS>', feature_names=None):
    """
    Return a vector of feature names, including bias feature.
    If vec is None or doesn't have get_feature_names() method,
    features are named x1, x2, etc.
    """
    if feature_names is None:
        if vec and hasattr(vec, 'get_feature_names'):
            feature_names = list(vec.get_feature_names())
        else:
            num_features = get_num_features(clf)
            feature_names = ["x%d" % i for i in range(num_features)]
    else:
        feature_names = list(feature_names)
        num_features = clf.coef_.shape[-1]
        if len(feature_names) != num_features:
            raise ValueError("feature_names has a wrong length: "
                             "expected=%d, got=%d" % (num_features,
                                                      len(feature_names)))
    if bias_name is not None and has_intercept(clf):
        feature_names += [bias_name]
    return np.array(feature_names)

def get_target_names(clf):
    """
    Return a vector of target names: y if the is only one target,
    and y0, ... if there are multiple targets.
    """
    if len(clf.coef_.shape) == 1:
        target_names = ['y']
    else:
        num_targets, _ = clf.coef_.shape
        target_names = ['y%d' % i for i in range(num_targets)]
    return np.array(target_names)

def get_coef(clf, label_id):
    """
    Return a vector of coefficients for a given label,
    including bias feature.
    """
    if len(clf.coef_.shape) == 2:
        # Most classifiers (even in binary case) and regressors
        coef = clf.coef_[label_id]
    elif len(clf.coef_.shape) == 1:
        # SGDRegressor stores coefficients in a 1D array
        if label_id != 0:
            raise ValueError(
                'Unexpected label_id %s for 1D coefficient' % label_id)
        coef = clf.coef_
    else:
        raise ValueError('Unexpected clf.coef_ shape: %s' % clf.coef_.shape)
    if not has_intercept(clf):
        return coef
    if label_id == 0 and not isinstance(clf.intercept_, np.ndarray):
        bias = clf.intercept_
    else:
        bias = clf.intercept_[label_id]
    return np.hstack([coef, bias])

def rename_label(label_id, label, target_names):
    """ Rename label according to target_names """
    if target_names is None:
        return label
    if isinstance(target_names, dict):
        return target_names[label]
    return target_names[label_id]

def get_num_features(clf):
    """ Return size of a feature vector classifier expects as an input. """
    if hasattr(clf, 'coef_'):
        return clf.coef_.shape[-1]
    elif hasattr(clf, 'feature_importances_'):
        return clf.feature_importances_.shape[-1]
    elif hasattr(clf, 'feature_count_'):
        return clf.feature_count_.shape[-1]
    elif hasattr(clf, 'theta_'):
        return clf.theta_.shape[-1]
    else:
        raise ValueError("Can't figure out feature vector size for %s" % clf)
<commit_msg>fixed get_feature_names for classifiers without coef_ when feature_names is passed<commit_after># -*- coding: utf-8 -*-
import numpy as np

def is_multiclass_classifier(clf):
    """
    Return True if a classifier is multiclass or False if it is binary.
    """
    return clf.coef_.shape[0] > 1

def is_multitarget_regressor(clf):
    """
    Return True if a regressor is multitarget
    or False if it predicts a single target.
    """
    return len(clf.coef_.shape) > 1 and clf.coef_.shape[0] > 1

def is_probabilistic_classifier(clf):
    """ Return True if a classifier can return probabilities """
    return hasattr(clf, 'predict_proba')

def has_intercept(clf):
    """ Return True if classifier has intercept fit. """
    return getattr(clf, 'fit_intercept', False)

def get_feature_names(clf, vec=None, bias_name='<BIAS>', feature_names=None):
    """
    Return a vector of feature names, including bias feature.
    If vec is None or doesn't have get_feature_names() method,
    features are named x1, x2, etc.
    """
    if feature_names is None:
        if vec and hasattr(vec, 'get_feature_names'):
            feature_names = list(vec.get_feature_names())
        else:
            num_features = get_num_features(clf)
            feature_names = ["x%d" % i for i in range(num_features)]
    else:
        feature_names = list(feature_names)
        num_features = get_num_features(clf)
        if len(feature_names) != num_features:
            raise ValueError("feature_names has a wrong length: "
                             "expected=%d, got=%d" % (num_features,
                                                      len(feature_names)))
    if bias_name is not None and has_intercept(clf):
        feature_names += [bias_name]
    return np.array(feature_names)

def get_target_names(clf):
    """
    Return a vector of target names: y if the is only one target,
    and y0, ... if there are multiple targets.
    """
    if len(clf.coef_.shape) == 1:
        target_names = ['y']
    else:
        num_targets, _ = clf.coef_.shape
        target_names = ['y%d' % i for i in range(num_targets)]
    return np.array(target_names)

def get_coef(clf, label_id):
    """
    Return a vector of coefficients for a given label,
    including bias feature.
    """
    if len(clf.coef_.shape) == 2:
        # Most classifiers (even in binary case) and regressors
        coef = clf.coef_[label_id]
    elif len(clf.coef_.shape) == 1:
        # SGDRegressor stores coefficients in a 1D array
        if label_id != 0:
            raise ValueError(
                'Unexpected label_id %s for 1D coefficient' % label_id)
        coef = clf.coef_
    else:
        raise ValueError('Unexpected clf.coef_ shape: %s' % clf.coef_.shape)
    if not has_intercept(clf):
        return coef
    if label_id == 0 and not isinstance(clf.intercept_, np.ndarray):
        bias = clf.intercept_
    else:
        bias = clf.intercept_[label_id]
    return np.hstack([coef, bias])

def rename_label(label_id, label, target_names):
    """ Rename label according to target_names """
    if target_names is None:
        return label
    if isinstance(target_names, dict):
        return target_names[label]
    return target_names[label_id]

def get_num_features(clf):
    """ Return size of a feature vector classifier expects as an input. """
    if hasattr(clf, 'coef_'):
        return clf.coef_.shape[-1]
    elif hasattr(clf, 'feature_importances_'):
        return clf.feature_importances_.shape[-1]
    elif hasattr(clf, 'feature_count_'):
        return clf.feature_count_.shape[-1]
    elif hasattr(clf, 'theta_'):
        return clf.theta_.shape[-1]
    else:
        raise ValueError("Can't figure out feature vector size for %s" % clf)
<|endoftext|>