← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~alvarocs/pygettextpo:upgrade-python-version into pygettextpo:main

 

Alvaro Crespo Serrano has proposed merging ~alvarocs/pygettextpo:upgrade-python-version into pygettextpo:main.

Commit message:
Upgrade python versions 3.8 to 3.13

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~alvarocs/pygettextpo/+git/pygettextpo/+merge/480200

- Add support for Python versions 3.8 to 3.13.
- Drop support for Python 2.
- Add tox testing support.
- Add pre-commit and linting.
- Add NEWS.rst releases file.

Tox runs successfully on all python versions and for lint.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~alvarocs/pygettextpo:upgrade-python-version into pygettextpo:main.
diff --git a/.gitignore b/.gitignore
index d0f7d29..00ccc83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ gettextpo*.so
 /build
 /dist
 /MANIFEST
+__pycache__
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..f2476ee
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,31 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+-   repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v5.0.0
+    hooks:
+    -   id: check-added-large-files
+    -   id: check-merge-conflict
+    -   id: check-xml
+    -   id: check-yaml
+    -   id: debug-statements
+-   repo: https://github.com/PyCQA/isort
+    rev: 5.13.2
+    hooks:
+    -   id: isort
+-   repo: https://github.com/PyCQA/flake8
+    rev: 7.1.1
+    hooks:
+    -   id: flake8
+-   repo: https://github.com/asottile/pyupgrade
+    rev: v3.19.1
+    hooks:
+    -   id: pyupgrade
+-   repo: https://github.com/mgedmin/check-manifest
+    rev: "0.50"
+    hooks:
+    -   id: check-manifest
+-   repo: https://github.com/psf/black
+    rev: 24.10.0
+    hooks:
+    - id: black
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
index 250e48a..3e2cdb2 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,6 @@
 include Makefile
 include MANIFEST.in
 include README
+include *.yaml
+include tox.ini
+include *.rst
diff --git a/NEWS.rst b/NEWS.rst
new file mode 100644
index 0000000..9c9a42b
--- /dev/null
+++ b/NEWS.rst
@@ -0,0 +1,25 @@
+.. This is your project NEWS file which will contain the release notes.
+.. Example: http://www.python.org/download/releases/2.6/NEWS.txt
+.. The content of this file, along with README.rst, will appear in your
+.. project's PyPI page.
+
+News
+====
+
+0.3
+---
+*Release date: (unreleased)
+
+* Add support for Python versions 3.8 to 3.13.
+* Drop support for Python 2.
+* Add tox testing support.
+* Add pre-commit and linting.
+* Add NEWS.rst releases file.
+
+
+0.2
+---
+
+*Release date: 28-Sep-2022*
+
+* Initial release of pygettextpo.
diff --git a/README b/README.rst
similarity index 100%
rename from README
rename to README.rst
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..edac645
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,21 @@
+[metadata]
+name = pygettextpo
+version = 0.3
+description = A binding for the libgettext-po library
+long_description = file: README.rst
+long_description_content_type = text/x-rst
+url = https://launchpad.net/pygettextpo
+author = Canonical Ltd.
+author_email = lazr-developers@xxxxxxxxxxxxxxxxxxx
+license = GNU Affero General Public License v3
+classifiers =
+    License :: OSI Approved :: GNU Affero General Public License v3
+    Programming Language :: Python
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3.9
+    Programming Language :: Python :: 3.10
+    Programming Language :: Python :: 3.11
+    Programming Language :: Python :: 3.12
+    Programming Language :: Python :: 3.13
+    Topic :: Software Development :: Version Control
diff --git a/setup.py b/setup.py
old mode 100755
new mode 100644
index 6f1a22c..e0158f1
--- a/setup.py
+++ b/setup.py
@@ -1,25 +1,29 @@
-#!/usr/bin/env python
+#! /usr/bin/python3
+
+# Copyright (C) 2022 Canonical Ltd.
+#
+# This program 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.
+#
+# This program 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.
 #
-# Copyright Canonical Ltd.  This software is licensed under the GNU
-# Affero General Public License version 3 (see the file LICENSE).
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-from setuptools import setup, Extension
+from setuptools import Extension, setup
 
 gettextpo = Extension(
-    'gettextpo', ['gettextpo.c'],
-    libraries=['gettextpo'])
+    "gettextpo",
+    sources=["gettextpo.c"],
+    libraries=["gettextpo"],
+)
 
 setup(
-    name='pygettextpo',
-    version='0.2',
-    author='Canonical Ltd.',
-    author_email='lazr-developers@xxxxxxxxxxxxxxxxxxx',
-    description='A binding for the libgettext-po library',
-    url='https://launchpad.net/pygettextpo',
-    classifiers=[
-        "License :: OSI Approved :: GNU Affero General Public License v3",
-        "Programming Language :: Python",
-        "Programming Language :: Python :: 2",
-        "Programming Language :: Python :: 3",
-        ],
-    ext_modules=[gettextpo])
+    ext_modules=[gettextpo],
+)
diff --git a/test_gettextpo.py b/tests/test_gettextpo.py
similarity index 59%
rename from test_gettextpo.py
rename to tests/test_gettextpo.py
index 7dbee20..a79fcbf 100644
--- a/test_gettextpo.py
+++ b/tests/test_gettextpo.py
@@ -2,6 +2,7 @@
 # Affero General Public License version 3 (see the file LICENSE).
 
 import unittest
+
 import gettextpo
 
 
@@ -16,7 +17,7 @@ class PoFileTestCase(unittest.TestCase):
         # Test that we can add messages to a new pofile object
         pofile = gettextpo.PoFile()
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Hello')
+        msg.set_msgid(b"Hello")
         poiter = iter(pofile)
         poiter.insert(msg)
 
@@ -27,7 +28,7 @@ class PoFileTestCase(unittest.TestCase):
         pofile1 = gettextpo.PoFile()
         pofile2 = gettextpo.PoFile()
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Hello')
+        msg.set_msgid(b"Hello")
 
         poiter = iter(pofile1)
         poiter.insert(msg)
@@ -41,38 +42,39 @@ class PoMessageTestCase(unittest.TestCase):
     def testCreateMessage(self):
         # Test that messages can be created.
         msg = gettextpo.PoMessage()
+        self.assertEqual(msg.msgid, None)
 
     def testSetMsgId(self):
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Hello')
-        self.assertEqual(msg.msgid, b'Hello')
-        msg.set_msgid_plural(b'Hellos')
-        self.assertEqual(msg.msgid_plural, b'Hellos')
+        msg.set_msgid(b"Hello")
+        self.assertEqual(msg.msgid, b"Hello")
+        msg.set_msgid_plural(b"Hellos")
+        self.assertEqual(msg.msgid_plural, b"Hellos")
 
     def testSetMsgCtxt(self):
         msg = gettextpo.PoMessage()
-        msg.set_msgctxt(b'Hello')
-        self.assertEqual(msg.msgctxt, b'Hello')
+        msg.set_msgctxt(b"Hello")
+        self.assertEqual(msg.msgctxt, b"Hello")
 
     def testSetMsgStr(self):
         msg = gettextpo.PoMessage()
-        msg.set_msgstr(b'Hello World')
-        self.assertEqual(msg.msgstr, b'Hello World')
+        msg.set_msgstr(b"Hello World")
+        self.assertEqual(msg.msgstr, b"Hello World")
 
     def testSetMsgStrPlural(self):
         # Test handling of plural msgstrs.  The PoMessage object can
         # not hold plural msgstrs if the msgid does not have a plural.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Something')
-        self.assertRaises(ValueError, msg.set_msgstr_plural, 0, b'Zero')
+        msg.set_msgid(b"Something")
+        self.assertRaises(ValueError, msg.set_msgstr_plural, 0, b"Zero")
         self.assertEqual(msg.msgstr_plural, [])
 
         # need to set the plural msgid first, then add the plural msgstrs
-        msg.set_msgid_plural(b'Somethings')
-        msg.set_msgstr_plural(0, b'Zero')
-        msg.set_msgstr_plural(1, b'One')
-        msg.set_msgstr_plural(2, b'Two')
-        self.assertEqual(msg.msgstr_plural, [b'Zero', b'One', b'Two'])
+        msg.set_msgid_plural(b"Somethings")
+        msg.set_msgstr_plural(0, b"Zero")
+        msg.set_msgstr_plural(1, b"One")
+        msg.set_msgstr_plural(2, b"Two")
+        self.assertEqual(msg.msgstr_plural, [b"Zero", b"One", b"Two"])
 
 
 class CheckFormatTestCase(unittest.TestCase):
@@ -83,7 +85,8 @@ class CheckFormatTestCase(unittest.TestCase):
         self.assertEqual(expected_errors, raised.exception.error_list)
         self.assertEqual(
             "\n".join(message for _, _, message in expected_errors),
-            str(raised.exception))
+            str(raised.exception),
+        )
 
     def testGoodFormat(self):
         # Check that no exception is raised on a good translation.
@@ -93,9 +96,9 @@ class CheckFormatTestCase(unittest.TestCase):
         # format a floating point value, so no error should be raised on
         # that kind of change.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Hello %s %d %g')
-        msg.set_format('c-format', True)
-        msg.set_msgstr(b'Bye %s %.2d %f')
+        msg.set_msgid(b"Hello %s %d %g")
+        msg.set_format("c-format", True)
+        msg.set_msgstr(b"Bye %s %.2d %f")
 
         # this should run without an exception
         msg.check_format()
@@ -103,39 +106,48 @@ class CheckFormatTestCase(unittest.TestCase):
     def testAddFormatSpec(self):
         # Test that an exception is raised when a format string is added.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'No format specifiers')
-        msg.set_format('c-format', True)
-        msg.set_msgstr(b'One format specifier: %20s')
+        msg.set_msgid(b"No format specifiers")
+        msg.set_format("c-format", True)
+        msg.set_msgstr(b"One format specifier: %20s")
         expected_errors = [
-            ("error", 0,
-             "number of format specifications in 'msgid' and 'msgstr' does "
-             "not match"),
-            ]
+            (
+                "error",
+                0,
+                "number of format specifications in 'msgid' and 'msgstr' does "
+                "not match",
+            ),
+        ]
         self.assertGettextPoError(expected_errors, msg)
 
     def testSwapFormatSpecs(self):
         # Test that an exception is raised when format strings are transposed.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Spec 1: %s, Spec 2: %d')
-        msg.set_format('c-format', True)
-        msg.set_msgstr(b'Spec 1: %d, Spec 2: %s')
+        msg.set_msgid(b"Spec 1: %s, Spec 2: %d")
+        msg.set_format("c-format", True)
+        msg.set_msgstr(b"Spec 1: %d, Spec 2: %s")
         expected_errors = [
-            ("error", 0,
-             "format specifications in 'msgid' and 'msgstr' for argument 1 "
-             "are not the same"),
-            ("error", 0,
-             "format specifications in 'msgid' and 'msgstr' for argument 2 "
-             "are not the same"),
-            ]
+            (
+                "error",
+                0,
+                "format specifications in 'msgid' and 'msgstr' for argument 1 "
+                "are not the same",
+            ),
+            (
+                "error",
+                0,
+                "format specifications in 'msgid' and 'msgstr' for argument 2 "
+                "are not the same",
+            ),
+        ]
         self.assertGettextPoError(expected_errors, msg)
 
     def testNonFormatString(self):
         # Test that no exception is raised if the message is not marked as
         # a format string.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Spec 1: %s, Spec 2: %d')
-        msg.set_format('c-format', False)
-        msg.set_msgstr(b'Spec 1: %d, Spec 2: %s')
+        msg.set_msgid(b"Spec 1: %s, Spec 2: %d")
+        msg.set_format("c-format", False)
+        msg.set_msgstr(b"Spec 1: %d, Spec 2: %s")
 
         # this should run without an exception
         msg.check_format()
@@ -143,8 +155,8 @@ class CheckFormatTestCase(unittest.TestCase):
     def testEmptyMsgStr(self):
         # Test that empty translations do not trigger a failure.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'Hello %s')
-        msg.set_format('c-format', True)
+        msg.set_msgid(b"Hello %s")
+        msg.set_format("c-format", True)
         msg.set_msgstr(None)
 
         # this should run without an exception
@@ -153,12 +165,12 @@ class CheckFormatTestCase(unittest.TestCase):
     def testGoodPlural(self):
         # Test that a good plural message passes without error.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'%d apple')
-        msg.set_msgid_plural(b'%d apples')
-        msg.set_format('c-format', True)
-        msg.set_msgstr_plural(0, b'%d orange')
-        msg.set_msgstr_plural(1, b'%d oranges')
-        msg.set_msgstr_plural(2, b'%d oranges_')
+        msg.set_msgid(b"%d apple")
+        msg.set_msgid_plural(b"%d apples")
+        msg.set_format("c-format", True)
+        msg.set_msgstr_plural(0, b"%d orange")
+        msg.set_msgstr_plural(1, b"%d oranges")
+        msg.set_msgstr_plural(2, b"%d oranges_")
 
         # this should run without an exception
         msg.check_format()
@@ -166,28 +178,32 @@ class CheckFormatTestCase(unittest.TestCase):
     def testBadPlural(self):
         # Test that bad plural translations raise an error error.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(b'%d apple')
-        msg.set_msgid_plural(b'%d apples')
-        msg.set_format('c-format', True)
-        msg.set_msgstr_plural(0, b'%d orange')
-        msg.set_msgstr_plural(1, b'%d oranges')
-        msg.set_msgstr_plural(2, b'%g oranges_')
+        msg.set_msgid(b"%d apple")
+        msg.set_msgid_plural(b"%d apples")
+        msg.set_format("c-format", True)
+        msg.set_msgstr_plural(0, b"%d orange")
+        msg.set_msgstr_plural(1, b"%d oranges")
+        msg.set_msgstr_plural(2, b"%g oranges_")
         expected_errors = [
-            ("error", 0,
-             "format specifications in 'msgid_plural' and 'msgstr[2]' for "
-             "argument 1 are not the same"),
-            ]
+            (
+                "error",
+                0,
+                "format specifications in 'msgid_plural' and 'msgstr[2]' for "
+                "argument 1 are not the same",
+            ),
+        ]
         self.assertGettextPoError(expected_errors, msg)
 
     def testUnicodeString(self):
         # Test that a translation with unicode chars is working.
         msg = gettextpo.PoMessage()
-        msg.set_msgid(u'Carlos Perell\xf3 Mar\xedn')
-        msg.set_msgstr(u'Carlos Perell\xf3 Mar\xedn')
-        self.assertEqual(msg.msgid, b'Carlos Perell\xc3\xb3 Mar\xc3\xadn')
-        self.assertEqual(msg.msgstr, b'Carlos Perell\xc3\xb3 Mar\xc3\xadn')
+        msg.set_msgid("Carlos Perell\xf3 Mar\xedn")
+        msg.set_msgstr("Carlos Perell\xf3 Mar\xedn")
+        self.assertEqual(msg.msgid, b"Carlos Perell\xc3\xb3 Mar\xc3\xadn")
+        self.assertEqual(msg.msgstr, b"Carlos Perell\xc3\xb3 Mar\xc3\xadn")
+
 
-## XXXX - gettext doesn't seem to check for this one
+#  XXXX - gettext doesn't seem to check for this one
 #
 #    def testBadPluralMsgId(self):
 #        # Test that conflicting plural msgids raise errors on their own.
@@ -198,5 +214,5 @@ class CheckFormatTestCase(unittest.TestCase):
 #        self.assertRaises(gettextpo.error, msg.check_format)
 #
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..28accfb
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,41 @@
+[tox]
+envlist =
+    py38,py39,py310,py311,py312,py313,lint
+
+[testenv]
+commands =
+    pytest tests {posargs} 
+deps =
+    pytest
+    testtools
+
+[testenv:lint]
+basepython =
+    python3.12
+deps =
+    pre-commit
+commands =
+    pre-commit run --all-files
+
+[testenv:coverage]
+basepython =
+    python3.12
+deps =
+    .[testing,test]
+commands =
+    coverage erase
+    coverage run -m pytest tests {posargs}
+    coverage combine
+    coverage html
+    coverage report -m --fail-under=91
+
+[flake8]
+ignore =
+    # Incompatible with Black.
+    E203,
+    W503
+
+[isort]
+known_first_party = pygettextpo
+line_length = 79
+profile = black
\ No newline at end of file