damned-lies r1251 - in trunk: . stats vertimus vertimus/tests



Author: claudep
Date: Mon Dec 29 17:33:16 2008
New Revision: 1251
URL: http://svn.gnome.org/viewvc/damned-lies?rev=1251&view=rev

Log:
2008-12-29  Claude Paroz  <claude 2xlibre net>

	* stats/utils.py: Allow raw data as input for run_shell_command, piped
	through stdin. Useful for data in memory and not saved in the file system.
	* vertimus/tests/__init__.py: Add test with valid and not valid po file
	submission.
	* vertimus/tests/valid_po.po: Valid po file for tests.
	* vertimus/views.py:
	* vertimus/forms.py: ActionForm moved from view to forms. Add clean_file
	to check validity of po file submitted through the form. 

Added:
   trunk/vertimus/forms.py
   trunk/vertimus/tests/valid_po.po
Modified:
   trunk/ChangeLog
   trunk/stats/utils.py
   trunk/vertimus/tests/__init__.py
   trunk/vertimus/views.py

Modified: trunk/stats/utils.py
==============================================================================
--- trunk/stats/utils.py	(original)
+++ trunk/stats/utils.py	Mon Dec 29 17:33:16 2008
@@ -24,6 +24,7 @@
 
 from django.utils.translation import ugettext as _, ugettext_noop
 from django.core.mail import send_mail
+from django.core.files.base import File
 from stats.conf import settings
 
 STATUS_OK = 0
@@ -42,10 +43,15 @@
     replacements = {"<ul>": "\n", "</ul>": "\n", "<li>": " * ", "\n</li>": "", "</li>": ""}
     return multiple_replace(replacements, string)
 
-def run_shell_command(cmd, env=None):
+def run_shell_command(cmd, env=None, input_data=None):
     if settings.DEBUG: print >>sys.stderr, cmd
     
-    pipe = Popen(cmd, shell=True, env=env, stdout=PIPE, stderr=STDOUT)
+    stdin = None
+    if input_data:
+        stdin = PIPE
+    pipe = Popen(cmd, shell=True, env=env, stdin=stdin, stdout=PIPE, stderr=STDOUT)
+    if input_data:
+        pipe.stdin.write(input_data)
     (output, errout) = pipe.communicate()
     status = pipe.returncode
     
@@ -164,26 +170,37 @@
         'untranslated' : 0,
         'errors' : [],
         }
+    c_env = {"LC_ALL": "C", "LANG": "C", "LANGUAGE": "C"}
 
-    if not os.access(pofile, os.R_OK):
-        res['errors'].append(("error", ugettext_noop("PO file '%s' does not exist or cannot be read.") % pofile))
-        return res
+    if isinstance(pofile, basestring):
+        # pofile is a filesystem path
+        filename = os.path.basename(pofile)
+        if not os.access(pofile, os.R_OK):
+            res['errors'].append(("error", ugettext_noop("PO file '%s' does not exist or cannot be read.") % pofile))
+            return res
+        input_data = None
+        input_file = pofile
+    elif isinstance(pofile, File):
+        filename = pofile.name
+        input_data = pofile.read()
+        input_file = "-"
+    else:
+        raise ValueError("pofile type not recognized")
     
-    c_env = {"LC_ALL": "C", "LANG": "C", "LANGUAGE": "C"}
     if msgfmt_checks:
-        command = "msgfmt -cv -o /dev/null %s" % pofile
+        command = "msgfmt -cv -o /dev/null %s" % input_file
     else:
-        command = "msgfmt --statistics -o /dev/null %s" % pofile
+        command = "msgfmt --statistics -o /dev/null %s" % input_file
 
-    (status, output) = run_shell_command(command, env=c_env)
+    (status, output) = run_shell_command(command, env=c_env, input_data=input_data)
 
     if status != STATUS_OK:
         if msgfmt_checks:
-            res['errors'].append(("error", ugettext_noop("PO file '%s' doesn't pass msgfmt check: not updating.") % (os.path.basename(pofile))))
+            res['errors'].append(("error", ugettext_noop("PO file '%s' doesn't pass msgfmt check: not updating.") % (filename)))
         else:
             res['errors'].append(("error", ugettext_noop("Can't get statistics for POT file '%s'.") % (pofile)))
 
-    if msgfmt_checks and os.access(pofile, os.X_OK):
+    if msgfmt_checks and input_file != "-" and os.access(pofile, os.X_OK):
         res['errors'].append(("warn", ugettext_noop("This PO file has an executable bit set.")))
 
     r_tr = re.search(r"([0-9]+) translated", output)
@@ -199,13 +216,20 @@
 
     if msgfmt_checks:
         # Check if PO file is in UTF-8
-        command = ("msgconv -t UTF-8 %s | diff -i -u %s - >/dev/null") % (pofile,
-                                                                          pofile)
-        (status, output) = run_shell_command(command, env=c_env)
+        if input_file == "-":
+            try:
+                input_data.decode('UTF-8')
+                status = STATUS_OK
+            except:
+                status = STATUS_OK+1
+        else:
+            command = ("msgconv -t UTF-8 %s | diff -i -u %s - >/dev/null") % (pofile,
+                                                                              pofile)
+            (status, output) = run_shell_command(command, env=c_env)
         if status != STATUS_OK:
-            myfile = os.path.basename(pofile)
             res['errors'].append(("warn",
-                                  ugettext_noop("PO file '%s' is not UTF-8 encoded.") % (myfile)))
+                              ugettext_noop("PO file '%s' is not UTF-8 encoded.") % (filename)))
+
     return res
 
 

Added: trunk/vertimus/forms.py
==============================================================================
--- (empty file)
+++ trunk/vertimus/forms.py	Mon Dec 29 17:33:16 2008
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 StÃphane Raimbault <stephane raimbault gmail com>
+# Copyright (c) 2008 Claude Paroz <claude 2xlibre net>.
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Damned Lies is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import os
+
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+
+from stats.utils import po_file_stats
+
+class ActionForm(forms.Form):
+    action = forms.ChoiceField(label=_("Action"),
+#        help_text="Choose an action you want to apply",
+        choices=())
+    comment = forms.CharField(label=_("Comment"),
+#        help_text="Leave a comment to explain your action",
+        max_length=1000,
+        required=False,
+        widget=forms.Textarea)
+    file = forms.FileField(label=_("File"), required=False)
+
+    def __init__(self, available_actions, *args, **kwargs):
+        super(ActionForm, self).__init__(*args, **kwargs)
+        self.fields['action'].choices = available_actions
+
+    def clean_file(self):
+        data = self.cleaned_data['file']
+        ext = os.path.splitext(data.name)[1]
+        # If this is a .po file, check validity (msgfmt)
+        if ext == ".po":
+            res = po_file_stats(data)
+            if res['errors']:
+                raise forms.ValidationError(".po file does not pass 'msgfmt -vc'. Please correct the file and try again.")
+

Modified: trunk/vertimus/tests/__init__.py
==============================================================================
--- trunk/vertimus/tests/__init__.py	(original)
+++ trunk/vertimus/tests/__init__.py	Mon Dec 29 17:33:16 2008
@@ -21,7 +21,10 @@
 import os
 
 from django.test import TestCase
-from django.core.files.base import ContentFile
+from django.core.files.base import File, ContentFile
+from django.core.files.uploadedfile import SimpleUploadedFile
+from django.http import QueryDict
+from django.utils.datastructures import MultiValueDict
 from django.conf import settings
 
 from people.models import Person
@@ -29,6 +32,7 @@
 from languages.models import Language
 from stats.models import Module, Branch, Release, Category, Domain
 from vertimus.models import *
+from vertimus.forms import ActionForm
 
 class VertimusTests(TestCase):
 
@@ -386,5 +390,18 @@
 
         self.assertEqual(state.name, 'Translated')
         
-
+    def test_uploaded_file_validation(self):
+        # Test a non valid po file
+        post_content = QueryDict('action=WC&comment=Test1')
+        post_file = MultiValueDict({'file': [SimpleUploadedFile('filename.po', 'Not valid po file content')]})
+        form = ActionForm([('WC', u'Write a comment')], post_content, post_file)
         
+        self.assert_('file' in form.errors)
+
+        # Test a valid po file
+        f = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "valid_po.po"), 'r')
+        post_file = MultiValueDict({'file': [File(f)]})
+        form = ActionForm([('WC', u'Write a comment')], post_content, post_file)
+
+        self.assert_(form.is_valid())
+

Modified: trunk/vertimus/views.py
==============================================================================
--- trunk/vertimus/views.py	(original)
+++ trunk/vertimus/views.py	Mon Dec 29 17:33:16 2008
@@ -22,29 +22,13 @@
 from django.shortcuts import render_to_response, get_object_or_404
 from django.http import HttpResponseRedirect, Http404
 from django.template import RequestContext
-from django.utils.translation import ugettext_lazy as _
-from django import forms
 from django.core import urlresolvers
 from django.conf import settings
 
 from people.models import Person
 from stats.models import Statistics, Module, Branch, Domain, Language
 from vertimus.models import StateDb, ActionDb, ActionAbstract
-
-class ActionForm(forms.Form):
-    action = forms.ChoiceField(label=_("Action"),
-#        help_text="Choose an action you want to apply",
-        choices=())
-    comment = forms.CharField(label=_("Comment"),
-#        help_text="Leave a comment to explain your action",
-        max_length=1000,
-        required=False,
-        widget=forms.Textarea)
-    file = forms.FileField(label=_("File"), required=False)
-
-    def __init__(self, available_actions, *args, **kwargs):
-        super(ActionForm, self).__init__(*args, **kwargs)
-        self.fields['action'].choices = available_actions
+from vertimus.forms import ActionForm
 
 def vertimus_by_stats_id(request, stats_id):
     """Access to Vertimus view by a Statistics ID"""



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]