Merge lp:~danilo/pygettextpo/msgctxt-support into lp:pygettextpo

Proposed by Данило Шеган
Status: Needs review
Proposed branch: lp:~danilo/pygettextpo/msgctxt-support
Merge into: lp:pygettextpo
Prerequisite: lp:~danilo/pygettextpo/simplify
Diff against target: 303 lines (+96/-93)
2 files modified
gettextpo.c (+82/-92)
test_gettextpo.py (+14/-1)
To merge this branch: bzr merge lp:~danilo/pygettextpo/msgctxt-support
Reviewer Review Type Date Requested Status
Benji York (community) code Approve
Review via email: mp+92726@code.launchpad.net

Description of the change

Provide support for msgctxt field in GNU gettext PO files.

This depends on the 'simplify' branch which simplifies the C code to reduce repeating of the same pattern. A new test is added to ensure this works like the other fields.

http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files

To post a comment you must log in.
Revision history for this message
Benji York (benji) wrote :

Looks good.

review: Approve (code)
Revision history for this message
Colin Watson (cjwatson) wrote :

I've converted pygettextpo to git and merged this branch (though I can't mark this MP as Merged):

  https://git.launchpad.net/pygettextpo/commit/?id=771d6e7853f6149cec3cf93aa0ab58a397ff11c5

Unmerged revisions

29. By Данило Шеган

Re-merge simplify branch.

28. By Данило Шеган

Merge 'simplify' branch, make use of the refactoring for set_msgctxt.

27. By Данило Шеган

Merge pep8-fixes branch.

26. By Данило Шеган

Make msgctxt support conditional.

25. By Данило Шеган

Add msgctxt support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'gettextpo.c'
--- gettextpo.c 2009-06-02 15:31:25 +0000
+++ gettextpo.c 2012-02-13 10:08:18 +0000
@@ -11,6 +11,7 @@
11#include <gettext-po.h>11#include <gettext-po.h>
1212
13#define MIN_REQUIRED_GETTEXTPO_VERSION 0x000E0213#define MIN_REQUIRED_GETTEXTPO_VERSION 0x000E02
14#define MIN_MSGCTXT_GETTEXTPO_VERSION 0x000F00
1415
15#if LIBGETTEXTPO_VERSION < MIN_REQUIRED_GETTEXTPO_VERSION16#if LIBGETTEXTPO_VERSION < MIN_REQUIRED_GETTEXTPO_VERSION
16# error "this module requires gettext >= 0.14.2"17# error "this module requires gettext >= 0.14.2"
@@ -533,35 +534,60 @@
533 return res;534 return res;
534}535}
535536
537typedef void (po_value_setter_t)(po_message_t, const char *);
538
539static PyObject *
540_message_set_field(PyPoMessage *self, PyObject *args, const char *field,
541 po_value_setter_t * setter)
542{
543 const char *value;
544 PyObject *object;
545 PyObject *string;
546
547 if (!PyArg_ParseTuple(args, field, &object))
548 return NULL;
549
550 if (object == Py_None) {
551 (*setter)(self->msg, NULL);
552 } else {
553 string = get_pystring_from_pyobject(object);
554
555 if (string == NULL)
556 /* Got an exception */
557 return NULL;
558 else {
559 value = PyString_AsString(string);
560 (*setter)(self->msg, value);
561 Py_DECREF(string);
562 }
563 }
564
565 Py_RETURN_NONE;
566}
567
568/* msgctxt support was added in 0.15. */
569#if LIBGETTEXTPO_VERSION >= MIN_MSGCTXT_GETTEXTPO_VERSION
570
571PyDoc_STRVAR(doc_pypo_message_set_msgctxt,
572"M.set_msgctxt(msgctxt) -> None. Set the msgctxt for this PoMessage");
573
574static PyObject *
575pypo_message_set_msgctxt(PyPoMessage *self, PyObject *args)
576{
577 return _message_set_field(self, args, "O:set_msgctxt",
578 &po_message_set_msgctxt);
579}
580#endif
581
582
536PyDoc_STRVAR(doc_pypo_message_set_msgid,583PyDoc_STRVAR(doc_pypo_message_set_msgid,
537"M.set_msgid(msgid) -> None. Set the msgid for this PoMessage");584"M.set_msgid(msgid) -> None. Set the msgid for this PoMessage");
538585
539static PyObject *586static PyObject *
540pypo_message_set_msgid(PyPoMessage *self, PyObject *args)587pypo_message_set_msgid(PyPoMessage *self, PyObject *args)
541{588{
542 const char *msgid;589 return _message_set_field(self, args, "O:set_msgid",
543 PyObject *object;590 &po_message_set_msgid);
544 PyObject *string;
545
546 if (!PyArg_ParseTuple(args, "O:set_msgid", &object))
547 return NULL;
548
549 if (object == Py_None) {
550 po_message_set_msgid(self->msg, NULL);
551 } else {
552 string = get_pystring_from_pyobject(object);
553
554 if (string == NULL)
555 /* Got an exception */
556 return NULL;
557 else {
558 msgid = PyString_AsString(string);
559 po_message_set_msgid(self->msg, msgid);
560 Py_DECREF(string);
561 }
562 }
563
564 Py_RETURN_NONE;
565}591}
566592
567PyDoc_STRVAR(doc_pypo_message_set_msgid_plural,593PyDoc_STRVAR(doc_pypo_message_set_msgid_plural,
@@ -571,29 +597,8 @@
571static PyObject *597static PyObject *
572pypo_message_set_msgid_plural(PyPoMessage *self, PyObject *args)598pypo_message_set_msgid_plural(PyPoMessage *self, PyObject *args)
573{599{
574 const char *msgid;600 return _message_set_field(self, args, "O:set_msgid_plural",
575 PyObject *object;601 &po_message_set_msgid_plural);
576 PyObject *string;
577
578 if (!PyArg_ParseTuple(args, "O:set_msgid_plural", &object))
579 return NULL;
580
581 if (object == Py_None) {
582 po_message_set_msgid_plural(self->msg, NULL);
583 } else {
584 string = get_pystring_from_pyobject(object);
585
586 if (string == NULL)
587 /* Got an exception */
588 return NULL;
589 else {
590 msgid = PyString_AsString(string);
591 po_message_set_msgid_plural(self->msg, msgid);
592 Py_DECREF(string);
593 }
594 }
595
596 Py_RETURN_NONE;
597}602}
598603
599PyDoc_STRVAR(doc_pypo_message_set_msgstr,604PyDoc_STRVAR(doc_pypo_message_set_msgstr,
@@ -602,29 +607,8 @@
602static PyObject *607static PyObject *
603pypo_message_set_msgstr(PyPoMessage *self, PyObject *args)608pypo_message_set_msgstr(PyPoMessage *self, PyObject *args)
604{609{
605 const char *msgstr;610 return _message_set_field(self, args, "O:set_msgstr",
606 PyObject *object;611 &po_message_set_msgstr);
607 PyObject *string;
608
609 if (!PyArg_ParseTuple(args, "O:set_msgstr", &object))
610 return NULL;
611
612 if (object == Py_None) {
613 po_message_set_msgstr(self->msg, NULL);
614 } else {
615 string = get_pystring_from_pyobject(object);
616
617 if (string == NULL)
618 /* Got an exception */
619 return NULL;
620 else {
621 msgstr = PyString_AsString(string);
622 po_message_set_msgstr(self->msg, msgstr);
623 Py_DECREF(string);
624 }
625 }
626
627 Py_RETURN_NONE;
628}612}
629613
630PyDoc_STRVAR(doc_pypo_message_set_msgstr_plural,614PyDoc_STRVAR(doc_pypo_message_set_msgstr_plural,
@@ -675,29 +659,8 @@
675static PyObject *659static PyObject *
676pypo_message_set_comments(PyPoMessage *self, PyObject *args)660pypo_message_set_comments(PyPoMessage *self, PyObject *args)
677{661{
678 const char *comments;662 return _message_set_field(self, args, "O:set_comments",
679 PyObject *object;663 &po_message_set_comments);
680 PyObject *string;
681
682 if (!PyArg_ParseTuple(args, "O:set_comments", &object))
683 return NULL;
684
685 if (object == Py_None) {
686 po_message_set_comments(self->msg, NULL);
687 } else {
688 string = get_pystring_from_pyobject(object);
689
690 if (string == NULL)
691 /* Got an exception */
692 return NULL;
693 else {
694 comments = PyString_AsString(string);
695 po_message_set_comments(self->msg, comments);
696 Py_DECREF(string);
697 }
698 }
699
700 Py_RETURN_NONE;
701}664}
702665
703PyDoc_STRVAR(doc_pypo_message_set_format,666PyDoc_STRVAR(doc_pypo_message_set_format,
@@ -779,6 +742,11 @@
779}742}
780743
781static PyMethodDef pypo_message_methods[] = {744static PyMethodDef pypo_message_methods[] = {
745/* msgctxt support was added in 0.15. */
746#if LIBGETTEXTPO_VERSION >= MIN_MSGCTXT_GETTEXTPO_VERSION
747 { "set_msgctxt", (PyCFunction)pypo_message_set_msgctxt, METH_VARARGS,
748 doc_pypo_message_set_msgctxt },
749#endif
782 { "set_msgid", (PyCFunction)pypo_message_set_msgid, METH_VARARGS,750 { "set_msgid", (PyCFunction)pypo_message_set_msgid, METH_VARARGS,
783 doc_pypo_message_set_msgid },751 doc_pypo_message_set_msgid },
784 { "set_msgid_plural", (PyCFunction)pypo_message_set_msgid_plural, METH_VARARGS,752 { "set_msgid_plural", (PyCFunction)pypo_message_set_msgid_plural, METH_VARARGS,
@@ -796,6 +764,23 @@
796 { NULL, 0, 0 }764 { NULL, 0, 0 }
797};765};
798766
767/* msgctxt support was added in 0.15. */
768#if LIBGETTEXTPO_VERSION >= MIN_MSGCTXT_GETTEXTPO_VERSION
769PyDoc_STRVAR(doc_pypo_message_msgctxt,
770"M.msgctxt -> the msgctxt for this PoMessage.");
771
772static PyObject *
773pypo_message_get_msgctxt(PyPoMessage *self, void *closure)
774{
775 const char *msgctxt;
776
777 msgctxt = po_message_msgctxt(self->msg);
778 if (msgctxt)
779 return PyString_FromString(msgctxt);
780 Py_RETURN_NONE;
781}
782#endif
783
799PyDoc_STRVAR(doc_pypo_message_msgid,784PyDoc_STRVAR(doc_pypo_message_msgid,
800"M.msgid -> the msgid for this PoMessage.");785"M.msgid -> the msgid for this PoMessage.");
801786
@@ -878,6 +863,11 @@
878863
879864
880static PyGetSetDef pypo_message_getsets[] = {865static PyGetSetDef pypo_message_getsets[] = {
866/* msgctxt support was added in 0.15. */
867#if LIBGETTEXTPO_VERSION >= MIN_MSGCTXT_GETTEXTPO_VERSION
868 { "msgctxt", (getter)pypo_message_get_msgctxt, (setter)0,
869 doc_pypo_message_msgctxt },
870#endif
881 { "msgid", (getter)pypo_message_get_msgid, (setter)0,871 { "msgid", (getter)pypo_message_get_msgid, (setter)0,
882 doc_pypo_message_msgid },872 doc_pypo_message_msgid },
883 { "msgid_plural", (getter)pypo_message_get_msgid_plural, (setter)0,873 { "msgid_plural", (getter)pypo_message_get_msgid_plural, (setter)0,
884874
=== modified file 'test_gettextpo.py'
--- test_gettextpo.py 2009-06-02 15:31:25 +0000
+++ test_gettextpo.py 2012-02-13 10:08:18 +0000
@@ -4,11 +4,14 @@
4import unittest4import unittest
5import gettextpo5import gettextpo
66
7
7class PoFileTestCase(unittest.TestCase):8class PoFileTestCase(unittest.TestCase):
9
8 def testCreateEmpty(self):10 def testCreateEmpty(self):
9 # Test that we can create an empty pofile object11 # Test that we can create an empty pofile object
10 pofile = gettextpo.PoFile()12 pofile = gettextpo.PoFile()
11 self.assertEquals(list(iter(pofile)), [])13 self.assertEquals(list(iter(pofile)), [])
14
12 def testAddMessage(self):15 def testAddMessage(self):
13 # Test that we can add messages to a new pofile object16 # Test that we can add messages to a new pofile object
14 pofile = gettextpo.PoFile()17 pofile = gettextpo.PoFile()
@@ -18,6 +21,7 @@
18 poiter.insert(msg)21 poiter.insert(msg)
1922
20 self.assertEquals(list(iter(pofile)), [msg])23 self.assertEquals(list(iter(pofile)), [msg])
24
21 def testAddMessageTwice(self):25 def testAddMessageTwice(self):
22 # A message object can only be added to one pofile object26 # A message object can only be added to one pofile object
23 pofile1 = gettextpo.PoFile()27 pofile1 = gettextpo.PoFile()
@@ -31,7 +35,9 @@
31 poiter = iter(pofile2)35 poiter = iter(pofile2)
32 self.assertRaises(ValueError, poiter.insert, msg)36 self.assertRaises(ValueError, poiter.insert, msg)
3337
38
34class PoMessageTestCase(unittest.TestCase):39class PoMessageTestCase(unittest.TestCase):
40
35 def testCreateMessage(self):41 def testCreateMessage(self):
36 # Test that messages can be created.42 # Test that messages can be created.
37 msg = gettextpo.PoMessage()43 msg = gettextpo.PoMessage()
@@ -43,11 +49,16 @@
43 msg.set_msgid_plural('Hellos')49 msg.set_msgid_plural('Hellos')
44 self.assertEquals(msg.msgid_plural, 'Hellos')50 self.assertEquals(msg.msgid_plural, 'Hellos')
4551
52 def testSetMsgCtxt(self):
53 msg = gettextpo.PoMessage()
54 msg.set_msgctxt('Hello')
55 self.assertEquals(msg.msgctxt, 'Hello')
56
46 def testSetMsgStr(self):57 def testSetMsgStr(self):
47 msg = gettextpo.PoMessage()58 msg = gettextpo.PoMessage()
48 msg.set_msgstr('Hello World')59 msg.set_msgstr('Hello World')
49 self.assertEquals(msg.msgstr, 'Hello World')60 self.assertEquals(msg.msgstr, 'Hello World')
50 61
51 def testSetMsgStrPlural(self):62 def testSetMsgStrPlural(self):
52 # Test handling of plural msgstrs. The PoMessage object can63 # Test handling of plural msgstrs. The PoMessage object can
53 # not hold plural msgstrs if the msgid does not have a plural.64 # not hold plural msgstrs if the msgid does not have a plural.
@@ -63,7 +74,9 @@
63 msg.set_msgstr_plural(2, 'Two')74 msg.set_msgstr_plural(2, 'Two')
64 self.assertEquals(msg.msgstr_plural, ['Zero', 'One', 'Two'])75 self.assertEquals(msg.msgstr_plural, ['Zero', 'One', 'Two'])
6576
77
66class CheckFormatTestCase(unittest.TestCase):78class CheckFormatTestCase(unittest.TestCase):
79
67 def testGoodFormat(self):80 def testGoodFormat(self):
68 # Check that no exception is raised on a good translation.81 # Check that no exception is raised on a good translation.
6982

Subscribers

People subscribed via source and target branches