Пример #1
0
    def voiceslots_match(self, slot, request):
        vs = self.voiceslots().filter(
            verbiage=slot.verbiage,
            bravo_checksum=slot.bravo_checksum).exclude(pk=slot.pk).exclude(
                status=VoiceSlot.MISSING)
        for s in vs:
            s.status = slot.status
            if s.status == VoiceSlot.PASS:
                a = Action.objects.filter(
                    scope__voiceslot=slot,
                    type=Action.TESTER_PASS_SLOT).order_by('-time')[0]
                Action.log(a.actor, Action.AUTO_PASS_SLOT,
                           'Slot passed as identical to {0}'.format(slot.name),
                           s)

            elif s.status == VoiceSlot.FAIL:
                a = Action.objects.filter(
                    scope__voiceslot=slot,
                    type=Action.TESTER_FAIL_SLOT).order_by('-time')[0]
                Action.log(
                    a.actor, Action.AUTO_FAIL_SLOT,
                    u'{0} (duplicate of {1})'.format(a.description,
                                                     a.scope.voiceslot.name),
                    s)
            s.save()
        return vs.count()
Пример #2
0
def failed(request, pid):
    if request.method == 'GET':
        if request.GET.get('export', False) == 'csv':
            return contexts.failed_csv(get_object_or_404(Project, pk=pid),
                                       HttpResponse(content_type='text/csv'))

        #Defective
        defective = []
        project = get_object_or_404(Project, pk=pid)
        failing_slots = project.voiceslots().filter(status=VoiceSlot.FAIL)
        for slot in failing_slots:
            action = Action.objects.filter(
                scope__voiceslot=slot,
                type__in=[Action.TESTER_FAIL_SLOT,
                          Action.AUTO_FAIL_SLOT]).latest('time')
            temp = {
                'name': slot.name,
                'language': slot.language.name,
                'path': slot.filepath(),
                'test_time': action.time,
                'fail_note': action.description
            }
            defective.append(temp)

        context = RequestContext(request, {
            'project': project,
            'project_defective': defective
        })

        Action.log(request.user, Action.REPORT_GENERATION,
                   'Viewed failed report dashboard', project)

        return render(request, "reports/failed.html", context)
    return HttpResponseNotFound()
Пример #3
0
 def test_voiceslot_action_success(self):
     user = User.objects.first()
     Action.log(user, Action.TESTER_PASS_SLOT, u"'sup?",
                VoiceSlot.objects.first())
     a = Action.objects.get(description=u"'sup?")
     self.assertEqual(a.scope.voiceslot, VoiceSlot.objects.first())
     self.assertEqual(a.scope.language, Language.objects.first())
     self.assertEqual(a.scope.project, Project.objects.first())
Пример #4
0
    def test_project_voiceslots_fail(self):
        Action.log(self.user,
                   Action.TESTER_FAIL_SLOT,
                   self.description,
                   self.voiceslot_fail)
        response = self.client.get(reverse('reports:failed',
                                           args=[self.project.id, ]), )

        self.assertContains(response, self.voiceslot_fail.name)
        self.assertContains(response, self.description)
Пример #5
0
    def test_project_progress_voiceslots_auto_fail(self):
        Action.log(self.user,
                   Action.AUTO_FAIL_SLOT,
                   self.description,
                   self.voiceslot)
        self.action = Action.objects.get(actor=self.user)

        response = self.client.get(reverse('reports:report_project',
                                           args=[self.project.id, ]),
                                   follow=True)
        self.assertEqual(response.status_code, 200)
Пример #6
0
def join_project(request, pid):
    if request.method == 'GET':
        p = get_object_or_404(Project, pk=pid)
        page = request.GET.get('page', '')
        p.users.add(request.user)
        p.save()
        Action.log(request.user, Action.TESTER_JOIN_PROJECT, u'Joined project',
                   p)
        messages.info(request, "You joined the project!")
        if page == "home":
            return redirect("core:home")
        elif page == "projects":
            return redirect("projects:projects")
        return redirect("projects:project", pid=pid)
    return HttpResponseNotFound()
Пример #7
0
def archive_project(request, pid):
    if request.method == 'GET':
        p = get_object_or_404(Project, pk=pid)
        action = Action.ARCHIVE_PROJECT
        note = 'Archive Project.'
        if p.status == Project.TESTING:
            p.status = Project.CLOSED
        elif p.status == Project.CLOSED:
            p.status = Project.TESTING
            action = Action.UN_ARCHIVE_PROJECT
            note = 'Un Archive Project.'
        p.save()
        Action.log(request.user, action, note, p)

    return redirect("projects:project", pid)
Пример #8
0
def leave_project(request, pid):
    if request.method == 'GET':
        p = get_object_or_404(Project, pk=pid)
        page = request.GET.get('page', '')
        p.users.remove(request.user)
        p.save()
        Action.log(request.user, Action.TESTER_LEAVE_PROJECT, u'Left project',
                   p)
        messages.info(request, "You left the project")
        if page == "home":
            return redirect("core:home")
        elif page == "projects":
            return redirect("projects:projects")
        return redirect("projects:project", pid=pid)
    return HttpResponseNotFound()
Пример #9
0
def fetch(request, pid):
    if request.method == 'GET':
        p = get_object_or_404(Project, pk=pid)
        if p.bravo_server:
            try:
                with pysftp.Connection(
                        p.bravo_server.address,
                        username=p.bravo_server.account,
                        private_key=settings.PRIVATE_KEY) as sftp:
                    result = helpers.fetch_slots_from_server(
                        p, sftp, request.user)
                    if result['valid']:
                        messages.success(request, result["message"])
                        Action.log(request.user, Action.UPDATE_FILE_STATUSES,
                                   'File status update ran', p)

                    else:
                        messages.danger(request, result['message'])
                return redirect("projects:project", pid)
            except pysftp.ConnectionException:
                messages.danger(
                    request, "Connection error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.CredentialException:
                messages.danger(
                    request, "Credentials error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.AuthenticationException:
                messages.danger(
                    request, "Authentication error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.SSHException:
                messages.danger(
                    request,
                    "SSH error to server \"{0}\"".format(p.bravo_server.name))
                return redirect("projects:project", pid)
        messages.danger(request, "No server associated with project")
        return redirect("projects:project", pid)
    return HttpResponseNotFound()
Пример #10
0
def able_update_file_status(request, p):
    try:
        with pysftp.Connection(p.bravo_server.address,
                               username=p.bravo_server.account,
                               private_key=settings.PRIVATE_KEY) as sftp:
            result = helpers.fetch_slots_from_server(p, sftp, request.user)
            if result['valid']:
                messages.success(request, result["message"])
                Action.log(request.user, Action.UPDATE_FILE_STATUSES,
                           'File status update ran', p)
                return True
            else:
                messages.danger(request, result['message'])
                return False
    except (pysftp.ConnectionException, pysftp.CredentialException,
            pysftp.AuthenticationException, pysftp.SSHException):
        messages.danger(
            request,
            "Connection error to server \"{0}\"".format(p.bravo_server.name))
        return False
Пример #11
0
def verify_file_transfer(request, pid):
    """View to identify potential problems with file transfer from Bravo to Preprod"""
    p = get_object_or_404(Project, pk=pid)
    if request.method == 'GET':
        # Send list of Producer applications on GET request.
        apps = p.get_applications()
        json_data = json.dumps({'apps': apps})
        return HttpResponse(json_data, content_type="application/json")
    elif request.method == 'POST':
        status = ElpisStatus.objects.get_or_create(project=p)[0]
        if status.running:
            return HttpResponse(json.dumps({
                'success': False,
                'message': 'Task already running'
            }),
                                content_type="application/json")
        apps = request.POST.getlist('applications')
        query_item = verify_file_transfer_task.delay(project_id=pid, apps=apps)
        status.query_id = query_item
        status.running = True
        status.save()
        Action.log(request.user, Action.ELPIS_RUN, 'Elpis run initiated', p)
        return HttpResponse(json.dumps({'success': True}),
                            content_type="application/json")
Пример #12
0
def initiate_status_update(request, pid):
    """
    Kicks off the request from "Update File Statuses"
    """
    if not request.method == "POST":
        raise Http404
    project = Project.objects.get(pk=pid)
    status = UpdateStatus.objects.get_or_create(project=project)[0]
    if status.running:
        return HttpResponse(json.dumps({
            'success': False,
            'message': 'Task already running'
        }),
                            content_type="application/json")
    query_item = update_file_statuses.delay(project_id=pid,
                                            user_id=request.user.pk)
    status.query_id = query_item
    status.running = True
    status.save()
    Action.log(request.user, Action.UPDATE_FILE_STATUSES,
               'Updated file statuses', Project.objects.get(pk=pid))

    return HttpResponse(json.dumps({'success': True}),
                        content_type="application/json")
Пример #13
0
def missing(request, pid):
    if request.method == 'GET':
        if request.GET.get('export', False) == 'csv':
            return contexts.missing_csv(get_object_or_404(Project, pk=pid),
                                        HttpResponse(content_type='text/csv'))

        # Missing
        missing = []
        project = get_object_or_404(Project, pk=pid)
        missing_slots = project.voiceslots_missing().order_by('path', 'name')
        for item in missing_slots:
            temp = {'filepath': item.filepath, 'language': item.language.name}
            missing.append(temp)

        context = RequestContext(request, {
            'project': project,
            'missing_slots': missing
        })

        Action.log(request.user, Action.REPORT_GENERATION,
                   'Viewed missing report dashboard', project)

        return render(request, "reports/missing.html", context)
    return HttpResponseNotFound()
Пример #14
0
def queue(request, pid):
    if request.method == 'GET':
        # check if voice slot already listened
        finish_listen = request.GET.get('listened', 'notyet')
        fail_select = request.GET.get('fail_select', False)
        p = get_object_or_404(Project, pk=pid)
        # check if update file status from bravo server
        if not p.voiceslots().filter(status=VoiceSlot.READY).exists():
            messages.danger(request, 'No files are pending test.')
            return redirect('projects:project', pid=pid)
        lang = get_object_or_404(Language,
                                 project=p,
                                 name=request.GET.get('language',
                                                      '__malformed').lower())
        slots_out = request.user.voiceslot_set.all()
        # TODO check this block
        if slots_out.count() > 0:
            slot = slots_out.order_by('?').first()
            if slot.language.pk == lang.pk:
                try:
                    slot_file = slot.download()
                except IOError:
                    slot.status = VoiceSlot.MISSING
                    slot.save()
                    return queue(request, pid)
                return render(
                    request, "projects/testslot.html",
                    contexts.context_testslot(request.user_agent.browser, p,
                                              slot, slot_file, finish_listen,
                                              fail_select))
            else:
                for slot in slots_out:
                    slot.check_in(request.user)
        slot = lang.voiceslot_set.filter(
            status=VoiceSlot.READY, checked_out=False).order_by('?').first()
        # check if all voice slots have been tested
        if not slot:
            messages.warning(request,
                             'No new voice slots available to be tested')
            return redirect('projects:project', pid=pid)
        # check if project has default bravo server
        if not p.bravo_server:
            messages.warning(request, 'Please set default bravo server')
            return redirect('projects:project', pid=pid)

        try:
            slot_file = slot.download()
        except IOError:
            slot.status = VoiceSlot.MISSING
            slot.save()
            return queue(request, pid)
        return render(
            request, "projects/testslot.html",
            contexts.context_testslot(request.user_agent.browser, p, slot,
                                      slot_file, finish_listen, fail_select))
    elif request.method == 'POST':
        p = get_object_or_404(Project, pk=pid)
        lang = get_object_or_404(Language,
                                 project=p,
                                 name=request.GET.get('language',
                                                      '__malformed').lower())
        tested_slot = get_object_or_404(VoiceSlot,
                                        pk=request.POST.get('slot-id', -1))
        if "cancel_test" in request.POST:
            tested_slot.check_in(request.user)
            return redirect("projects:project", pid=pid)
        elif "submit_test" in request.POST:
            test_result = request.POST.get('slot_status', False)
            finish_listen_post = request.POST.get('finish_listen', 'notyet')
            already_listen_post = request.GET.get('listened', 'notyet')
            fail_select = request.GET.get('fail_select', False)

            # finish_listen to check if finish listened without Pass/Fail selection
            if not test_result and (finish_listen_post == 'heard'
                                    or already_listen_post
                                    == 'heard') and fail_select != 'selected':

                messages.danger(request, "Please enter a pass or fail")
                return HttpResponseRedirect(
                    reverse("projects:queue", args=(p.pk, )) + "?language=" +
                    lang.name + '&listened=heard')
            elif test_result == 'pass':
                tested_slot.status = VoiceSlot.PASS
                tested_slot.check_in(request.user)
                tested_slot.save()
                Action.log(
                    request.user, Action.TESTER_PASS_SLOT,
                    '{0} passed in queue testing'.format(tested_slot.name),
                    tested_slot)
                # do updates to files here and get count for p pass
                count = p.voiceslots_match(tested_slot, request)
            else:
                if not request.POST.get('notes', False):
                    messages.danger(request,
                                    "Please provide notes on test failure")
                    return HttpResponseRedirect(
                        reverse("projects:queue", args=(p.pk, )) +
                        "?language=" + lang.name +
                        '&listened=heard&fail_select=selected')
                tested_slot.status = VoiceSlot.FAIL
                tested_slot.check_in(request.user)
                tested_slot.save()
                Action.log(request.user, Action.TESTER_FAIL_SLOT,
                           request.POST['notes'], tested_slot)
                # do updates to files here and get count for p failure
                count = p.voiceslots_match(tested_slot, request)
                p.failure_count += 1
            p.tests_run += 1
            p.save()
            if count > 0:
                messages.success(request,
                                 "{0} matching slots updated".format(count))

            slot_filter = lang.voiceslot_set.filter(status=VoiceSlot.READY,
                                                    checked_out=False)
            if slot_filter.count() > 0:
                slot = slot_filter.order_by('?').first()
            else:
                ten_minutes_ago = datetime.now() - timedelta(minutes=10)
                slot_filter = lang.voiceslot_set.filter(
                    status=VoiceSlot.READY,
                    checked_out=True,
                    checked_out_time__lte=ten_minutes_ago)
                if slot_filter.count() > 0:
                    slot = slot_filter.order_by('?').first()
                else:
                    messages.success(
                        request,
                        "All slots in this language are tested or recently checked out for testing."
                    )
                    return redirect("projects:project", pid=pid)
            slot_file = slot.download()

            # reset if finish listen to not yet
            #finish_listen = 'notyet'
            #fail_select = False

            #return render(request, "projects/testslot.html", contexts.context_testslot(request.user_agent.browser, p, slot, slot_file, finish_listen, fail_select))
            return HttpResponseRedirect(
                reverse("projects:queue", args=(p.pk, )) + "?language=" +
                lang.name)
        else:
            return HttpResponseNotFound()
Пример #15
0
def report_project(request, pid):
    if request.method == 'GET':
        project = get_object_or_404(Project, pk=pid)

        if not project.root_path:
            messages.danger(request, 'Please set project root path')
            return redirect('reports:reports')

        vuids = project.vuid_set.all()
        if vuids.count() == 0:
            messages.danger(request, 'Please upload prompt list file')
            return redirect('reports:reports')

        if not project.voiceslots().filter(status__in=[
                VoiceSlot.READY, VoiceSlot.PASS, VoiceSlot.FAIL,
                VoiceSlot.MISSING
        ]).exists():
            messages.danger(request,
                            'Please update file statuses from bravo server')
            return redirect('reports:reports')

        # Get VUID upload_date
        vuid_upload_date = None
        if vuids.count() == 1:
            vuid_upload_date = project.vuid_set.all()[0].upload_date
        elif vuids.count() > 1:
            # find least vuid upload date
            vuid_upload_date = project.vuid_set.all()[0].upload_date
            for vuid in project.vuid_set.all():
                if vuid.upload_date < vuid_upload_date:
                    vuid_upload_date = vuid.upload_date

        # Progress of project
        # First check vuid upload_date
        if vuid_upload_date:
            # Second check Actions type

            outputs = {
                'date': [],
                'fail': [],
                'pass': [],
                'new': [],
                'missing': []
            }

            try:
                end = date.fromtimestamp(float(
                    request.GET.get('end'))) + timedelta(days=1)
            except (TypeError, ValueError):
                end = datetime.now().date() + timedelta(days=1)

            try:
                start = date.fromtimestamp(float(
                    request.GET.get('start'))) + timedelta(days=1)
            except (TypeError, ValueError):
                start = end - timedelta(days=10)

            start_original = start

            while start <= end:
                statuses = project.status_as_of(
                    time.mktime(start.timetuple()) - 1)
                #print start, end, statuses
                if start == start_original:
                    start += timedelta(days=1)
                    continue
                outputs['date'].append(
                    (start - timedelta(days=1)).strftime("%Y-%m-%d"))
                outputs['fail'].append(
                    int(statuses[Action.TESTER_FAIL_SLOT] +
                        statuses[Action.AUTO_FAIL_SLOT]))
                outputs['pass'].append(
                    int(statuses[Action.TESTER_PASS_SLOT] +
                        statuses[Action.AUTO_PASS_SLOT]))
                outputs['new'].append(int(statuses[Action.AUTO_NEW_SLOT]))
                outputs['missing'].append(
                    int(statuses[Action.AUTO_MISSING_SLOT]))
                start += timedelta(days=1)

        else:
            outputs = None

        context = RequestContext(
            request, {
                'project':
                project,
                'project_progress':
                outputs,
                'start':
                float(
                    request.GET.get('start',
                                    time.mktime(start_original.timetuple()))),
                'end':
                time.mktime(end.timetuple()) - 3601,
                'feed':
                Action.objects.filter(
                    scope__project=project).order_by('-time')[0:10]
            })
        Action.log(request.user, Action.REPORT_GENERATION,
                   'Viewed progress report dashboard', project)
        return render(request, "reports/report_project.html", context)
Пример #16
0
def testslot(request, pid, vsid):
    if request.method == 'GET':
        finish_listen = request.GET.get('listened', 'notyet')
        fail_select = request.GET.get('fail_select', False)
        p = get_object_or_404(Project, pk=pid)
        slot = get_object_or_404(VoiceSlot, pk=vsid)
        if p.bravo_server:
            try:
                with pysftp.Connection(
                        p.bravo_server.address,
                        username=p.bravo_server.account,
                        private_key=settings.PRIVATE_KEY) as conn:
                    remote_path = slot.filepath()
                    filename = "{0}.wav".format(str(uuid.uuid4()))
                    filenamezip = filename + ".gz"
                    local_path = os.path.join(settings.MEDIA_ROOT, filename)
                    local_path_zip = os.path.join(settings.MEDIA_ROOT,
                                                  filenamezip)
                    if conn.exists(remote_path):
                        conn.get(remote_path, local_path)
                    else:
                        conn.get(remote_path + ".gz", local_path_zip)
                        with gzip.open(local_path_zip, 'rb') as in_file:
                            out_file = open(local_path, 'wb')
                            s = in_file.read()
                        with open(local_path, 'w') as f:
                            f.write(s)
                    filepath = settings.MEDIA_URL + filename
                    slot.check_out(request.user)
            except IOError as e:
                messages.danger(
                    request, "File missing on server \"{0}\"".format(
                        p.bravo_server.name))
                slot.status = VoiceSlot.MISSING
                slot.save()
                Action.log(request.user, Action.AUTO_MISSING_SLOT,
                           'Slot found missing by individual slot test', slot)
                return redirect("projects:project", pid)
            except pysftp.ConnectionException:
                messages.danger(
                    request, "Connection error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.CredentialException:
                messages.danger(
                    request, "Credentials error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.AuthenticationException:
                messages.danger(
                    request, "Authentication error to server \"{0}\"".format(
                        p.bravo_server.name))
                return redirect("projects:project", pid)
            except pysftp.SSHException:
                messages.danger(
                    request,
                    "SSH error to server \"{0}\"".format(p.bravo_server.name))
                return redirect("projects:project", pid)
            return render(
                request, "projects/testslot.html",
                contexts.context_testslot(request.user_agent.browser, p, slot,
                                          filepath, finish_listen,
                                          fail_select))
        messages.danger(request, "No server associated with project")
        return redirect("projects:project", pid)
    return submitslot(request, vsid)
Пример #17
0
def project(request, pid):
    if request.method == 'GET':
        p = get_object_or_404(Project, pk=pid)
        # status = UpdateStatus.objects.get_or_create(project=p)[0]
        # if status.running:
        #     status.running = False
        #     status.save()
        return render(
            request, "projects/project.html",
            contexts.context_project(
                p,
                server_form=ServerForm(
                    initial={'server': p.current_server_pk()})))
    elif request.method == 'POST':
        messages.danger(request, '1')
        if "update_server" in request.POST:
            form = ServerForm(request.POST)
            p = get_object_or_404(Project, pk=pid)
            if form.is_valid():
                server = form.cleaned_data['server']
                if server is None:
                    if p.bravo_server is None:
                        return redirect("projects:project", pid=pid)
                    p.bravo_server = None
                    p.save()
                else:
                    if p.bravo_server is not None:
                        if server == p.bravo_server.name:
                            return redirect("projects:project", pid=pid)

                    # force update file status from bravo server
                    old_bravo_server = p.bravo_server
                    p.bravo_server = Server.objects.get(name=server)
                    p.save()
                    if not able_update_file_status(request, p):
                        p.bravo_server = old_bravo_server
                        p.save()
                        messages.warning(
                            request,
                            'Cannot update file status, set Bravo Server back')
                        return redirect("projects:project", pid=pid)

                Action.log(request.user, Action.UPDATE_BRAVO_SERVER,
                           u'Bravo server updated to ' + unicode(server), p)
                messages.success(request, "Updated server successfully")
                return redirect("projects:project", pid=pid)
            messages.danger(request, "Unable to update server")
            return render(request, "projects/project.html",
                          contexts.context_project(p, server_form=form))
        elif "upload_file" in request.POST:
            messages.danger(request, '2')
            form = UploadForm(request.POST, request.FILES)
            p = get_object_or_404(Project, pk=pid)
            if form.is_valid():
                messages.danger(request, '3')
                # if user not member in CS, PM, Superuser cannot upload
                if not (request.user.usersettings.creative_services
                        or request.user.usersettings.project_manager
                        or request.user.is_superuser):
                    messages.danger(request,
                                    'You have no authority to upload.')
                elif 'file' in request.FILES and request.FILES[
                        'file'].name.endswith('.xlsx'):
                    result = helpers.upload_vuid(form.cleaned_data['file'],
                                                 request.user, p)
                    if result['valid']:
                        messages.success(request, result["message"])
                    else:
                        messages.danger(request, result['message'])
                elif 'file' in request.FILES:
                    messages.danger(
                        request,
                        "Invalid file type, unable to upload (must be .xlsx)")
                return redirect("projects:project", pid=pid)
            messages.danger(request, "Unable to upload file")
            return render(
                request, "projects/project.html",
                contexts.context_project(
                    p,
                    upload_form=form,
                    server_form=ServerForm(
                        initial={'server': p.current_server_pk()})))
        elif "update_root_path" in request.POST:
            messages.danger(request, '4')
            form = ProjectRootPathForm(request.POST)
            p = get_object_or_404(Project, pk=pid)
            if form.is_valid():
                root_path = form.cleaned_data['root_path']

                if not os.path.isabs(root_path):
                    messages.danger(request,
                                    'Bravo Server Root Path Format Incorrect')
                    return redirect('projects:project', pid=pid)

                #remove last slash of root path
                while root_path and root_path[-1] == '/':
                    root_path = root_path[:-1]

                if p.root_path and not helpers.verify_update_root_path(
                        p, root_path):
                    messages.danger(request, 'New root path not allowed')
                    return redirect('projects:project', pid=pid)

                p.root_path = root_path
                p.save()
                Action.log(
                    request.user, Action.UPDATE_ROOT_PATH,
                    u'Bravo server root path updated to ' + unicode(root_path),
                    p)
                messages.success(request,
                                 'Updated Bravo Server Path Successfully')
                return redirect('projects:project', pid=pid)
        messages.danger(request, '5')
        messages.danger(
            request, 'valid? ' + str(UploadForm(request.POST, request.FILES)))
        return redirect("projects:project", pid=pid)
    return HttpResponseNotFound()
Пример #18
0
def new(request):
    if request.method == 'GET':
        return render(request, "projects/new.html", contexts.context_new())
    elif request.method == 'POST':
        if "create_project" in request.POST:
            form = ProjectForm(request.POST, request.FILES)
            if form.is_valid():
                # Check if default Bravo Server exist
                try:
                    bravo_server = Server.objects.get(active=True)
                except Server.DoesNotExist:
                    messages.danger(request,
                                    "Please set default Bravo Server first.")
                    return render(request, "projects/new.html",
                                  contexts.context_new(form))

                n = form.cleaned_data['name']
                root_path = form.cleaned_data['root_path']
                if root_path and not os.path.isabs(root_path):
                    messages.danger(request,
                                    'Bravo Server Root Path Format Incorrect')
                    return render(request, 'projects/new.html',
                                  contexts.context_new(form))

                # remove last slash of root path
                while root_path and root_path[-1] == '/':
                    root_path = root_path[:-1]

                p = Project(name=n)
                try:
                    p.full_clean()
                    p.save()
                    p.users.add(request.user)
                    p.bravo_server = bravo_server  # set default bravo server
                    p.root_path = root_path
                    p.save()
                    messages.success(request, "Created project")
                    if 'file' in request.FILES and request.FILES[
                            'file'].name.endswith('.xlsx'):
                        result = helpers.upload_vuid(form.cleaned_data['file'],
                                                     request.user, p)
                        if result['valid']:
                            messages.success(request, result["message"])
                        else:
                            messages.danger(request, result['message'])
                    elif 'file' in request.FILES:
                        messages.danger(
                            request,
                            "Invalid file type, unable to upload (must be .xlsx)"
                        )
                    Action.log(request.user, Action.CREATE_PROJECT,
                               '{0} created'.format(p.name), p)
                    return redirect("projects:project", pid=p.pk)
                except ValidationError as e:
                    if 'name' in e.message_dict:
                        messages.danger(request, e.message_dict.get('name')[0])
                    return render(request, "projects/new.html",
                                  contexts.context_new(form))
            messages.danger(request, "Unable to create project")
            return render(request, "projects/new.html",
                          contexts.context_new(form))
    return HttpResponseNotFound()
Пример #19
0
def update_file_statuses(project_id, user_id):
    """Background process to update file statuses from Bravo server"""
    try:
        sleep(1.25)  # Stupid fix for a stupid race condition
        project = Project.objects.get(pk=int(project_id))
        status = UpdateStatus.objects.get_or_create(project__pk=project_id)[0]
        user = User.objects.get(pk=int(user_id))
        # Connect to Bravo server and get filenames and md5sums
        with pysftp.Connection(project.bravo_server.address,
                               username=project.bravo_server.account,
                               private_key=settings.PRIVATE_KEY) as sftp:
            result = sftp.execute(
                'find {0}/ -name "*.wav"'.format(project.root_path) +
                ' -exec md5sum {} \; -exec stat -c"%Y" {} \;')

        FileStatus = namedtuple('FileStatus', 'md5 path modified')
        file_statuses = []
        try:
            for i in range(0, len(result), 2):
                md5 = result[i].split()[0]
                filename = ' '.join(result[i].split()[1:])
                modified = result[i + 1].strip()
                file_statuses.append(FileStatus(md5, filename, modified))
        except IndexError:
            print "Update IndexError Result:"
            print repr(result)

        # Find and update matching voiceslots
        slots = project.voiceslots()
        for fs in file_statuses:
            if slots.filter(name=fs.path.split('/')[-1][:-4]).exists():
                slot_candidates = slots.filter(
                    name=fs.path.split('/')[-1][:-4])
                for slot in slot_candidates:
                    if fs.path == slot.filepath():
                        if slot.status in (VoiceSlot.NEW, VoiceSlot.MISSING,
                                           VoiceSlot.READY):
                            slot.bravo_checksum = fs.md5
                            slot.bravo_time = datetime.utcfromtimestamp(
                                float(fs.modified)).replace(tzinfo=pytz.utc)
                            slot.status = VoiceSlot.READY
                            slot.save()
                            Action.log(user, Action.AUTO_NEW_SLOT,
                                       "Slot ready for testing", slot)
                            break
                        elif slot.status in (VoiceSlot.PASS, VoiceSlot.FAIL):
                            if fs.md5 != slot.bravo_checksum:
                                slot.bravo_checksum = fs.md5
                                slot.bravo_time = datetime.fromtimestamp(
                                    float(
                                        fs.modified)).replace(tzinfo=pytz.utc)
                                slot.status = VoiceSlot.READY
                                slot.save()
                                Action.log(user, Action.AUTO_NEW_SLOT,
                                           "Slot changed and needs retesting",
                                           slot)
                                break

        # Find and mark missing voiceslots
        vuid_set = set(slots.values_list('name', flat=True))
        found_set = set([fs.path.split('/')[-1][:-4] for fs in file_statuses])
        missing_set = vuid_set - found_set
        missing_slots = slots.filter(name__in=list(missing_set))
        missing_slots.update(status=VoiceSlot.MISSING)

        # Hack for files found in the wrong language. No es bueno
        stragglers = slots.filter(status=VoiceSlot.NEW)
        stragglers.update(status=VoiceSlot.MISSING)
        for slot in stragglers:
            Action.log(user, Action.AUTO_MISSING_SLOT,
                       "Slot not found in update",
                       slot)  # Missing period to distinguish

        for slot in missing_slots:
            Action.log(user, Action.AUTO_MISSING_SLOT,
                       "Slot not found in update.", slot)
        status.running = False
        status.save()
    except Exception as e:
        logger = get_task_logger(__name__)
        logger.error("Celery task failed")
        logger.error(e)
        logger.error("Project id: {0}".format(project_id))
        sleep(3)
        try:
            project = Project.objects.get(pk=int(project_id))
            logger.error("Waiting would have fixed this.")
        except Exception as e:
            logger.error("Waiting didn't fix it")
Пример #20
0
def submitslot(request, vsid):
    if request.method == 'POST':
        if "submit_test" in request.POST:
            slot = get_object_or_404(VoiceSlot, pk=vsid)
            p = slot.language.project
            slot_status = request.POST.get('slot_status', False)

            finish_listen_post = request.POST.get('finish_listen', 'notyet')
            already_listen_post = request.GET.get('listened', 'notyet')
            fail_select = request.GET.get('fail_select', False)

            if not slot_status and (finish_listen_post == 'heard'
                                    or already_listen_post
                                    == 'heard') and fail_select != 'selected':
                messages.danger(request, "Please enter a pass or fail")
                # return redirect("projects:testslot", pid=p.pk, vsid=vsid)
                response = redirect("projects:testslot", pid=p.pk, vsid=vsid)
                response['Location'] += '?listened=heard'
                return response
            if slot_status == 'pass':
                slot.status = VoiceSlot.PASS
                slot.check_in(request.user)
                slot.save()
                helpers.update_checksum(pid=p.pk, vsid=vsid, user=request.user)
                Action.log(request.user, Action.TESTER_PASS_SLOT,
                           '{0} passed by manual testing'.format(slot.name),
                           slot)

                # do updates to files here and get count for p pass
                count = p.voiceslots_match(slot, request)
            else:
                if not request.POST.get('notes', False):
                    messages.danger(request,
                                    "Please provide notes on test failure")
                    response = redirect("projects:testslot",
                                        pid=p.pk,
                                        vsid=vsid)
                    response[
                        'Location'] += '?listened=heard&fail_select=selected'
                    return response
                slot.status = VoiceSlot.FAIL
                slot.check_in(request.user)
                slot.save()
                helpers.update_checksum(pid=p.pk, vsid=vsid, user=request.user)
                Action.log(request.user, Action.TESTER_FAIL_SLOT,
                           request.POST['notes'], slot)

                # do updates to files here and get count for p failure
                count = p.voiceslots_match(slot, request)
                p.failure_count += 1
            p.tests_run += 1
            p.save()
            messages.success(
                request,
                u"Tested voice slot \"{0}\", {1} matching slots updated".
                format(slot.name, count))
            return redirect("projects:project", pid=p.pk)
        elif "cancel_test" in request.POST:
            slot = get_object_or_404(VoiceSlot, pk=vsid)
            slot.check_in(request.user)
            return redirect("projects:project", pid=slot.language.project.pk)
    return HttpResponseNotFound()