<pre style='margin:0'>
Renee Otten (reneeotten) pushed a commit to branch master
in repository upt-macports.

</pre>
<p><a href="https://github.com/macports/upt-macports/commit/0336f4045c39b6c04af22b2e4eb34c157ea1618f">https://github.com/macports/upt-macports/commit/0336f4045c39b6c04af22b2e4eb34c157ea1618f</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 0336f40  Standardize Perl versioning scheme for MacPorts
</span>0336f40 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 0336f4045c39b6c04af22b2e4eb34c157ea1618f
</span>Author: Korusuke <karan.sheth@somaiya.edu>
AuthorDate: Thu Aug 8 23:29:55 2019 +0530

<span style='display:block; white-space:pre;color:#404040;'>    Standardize Perl versioning scheme for MacPorts
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    MacPorts follows the "normalized, dotted-decimal form" versioning
</span><span style='display:block; white-space:pre;color:#404040;'>    scheme, similar to what is obtained from:
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>      perl -Mversion -e 'print version->parse("<VERSION>")->normal'
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    So we need do the same translation before checking if a package needs to
</span><span style='display:block; white-space:pre;color:#404040;'>    be packaged.
</span>---
 setup.cfg                                   |  2 +-
 upt_macports/tests/test_macports_backend.py | 36 +++++++++++++++++++++++++
 upt_macports/upt_macports.py                | 42 +++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 1 deletion(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/setup.cfg b/setup.cfg
</span><span style='display:block; white-space:pre;color:#808080;'>index 87728f2..886b95f 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/setup.cfg
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/setup.cfg
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -21,6 +21,7 @@ install_requires =
</span>     requests
     upt
     jinja2
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    packaging
</span> include_package_data = true
 
 [options.entry_points]
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -30,4 +31,3 @@ upt.backends =
</span> [options.extras_require]
 test =
     requests-mock
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    
</span>\ No newline at end of file
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/upt_macports/tests/test_macports_backend.py b/upt_macports/tests/test_macports_backend.py
</span><span style='display:block; white-space:pre;color:#808080;'>index 7a6b3fa..da7ac14 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/upt_macports/tests/test_macports_backend.py
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/upt_macports/tests/test_macports_backend.py
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -49,5 +49,41 @@ class TestMacPortsPackageExist(unittest.TestCase):
</span>             self.macports_backend.package_versions('foo')
 
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+class TestMacPortsCpanVersion(unittest.TestCase):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    def setUp(self):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        self.macports_backend = MacPortsBackend()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        self.macports_backend.upt_pkg = upt.Package('foo', '42')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        self.macports_backend.frontend = 'cpan'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    def test_version_conversion(self):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        converted = ['1', '1.2.3', '1.200.0', '1.200.0', '1.20.0',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     '1', '1.2.3', '1.200.0', '1.200.0', '1.20.0']
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        upstream = ['1', '1.2.3', '1.2', '1.20', '1.02',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    'v1', 'v1.2.3', 'v1.2', 'v1.20', 'v1.02']
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        for mp_ver, cpan_ver in zip(upstream, converted):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            self.assertEqual(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    self.macports_backend.standardize_CPAN_version(mp_ver),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    cpan_ver)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    @mock.patch('upt.Backend.needs_requirement')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    def test_needs_requirement(self, mock_need_req):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        specifiers = {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '>=42': '>=42',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '<=42': '<=42',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '!=42': '!=42',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '==42': '==42',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '>= 1.2, != 1.5, < 2.0': '>=1.200.0, !=1.500.0, <2.0.0',
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            '>= 1.2, != 2, < 3.0': '>=1.200.0, !=2, <3.0.0'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        for key, value in specifiers.items():
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            req = upt.PackageRequirement('bar', key)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            self.macports_backend.needs_requirement(req, 'fake-phase')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            self.assertCountEqual(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                mock_need_req.call_args[0][0].specifier.split(', '),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                value.split(', ')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> if __name__ == '__main__':
     unittest.main()
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/upt_macports/upt_macports.py b/upt_macports/upt_macports.py
</span><span style='display:block; white-space:pre;color:#808080;'>index 0945c47..eb3b725 100755
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/upt_macports/upt_macports.py
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/upt_macports/upt_macports.py
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -7,6 +7,7 @@ import requests
</span> import os
 import subprocess
 import sys
<span style='display:block; white-space:pre;background:#e0ffe0;'>+from packaging.specifiers import SpecifierSet
</span> 
 
 class MacPortsPackage(object):
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -256,3 +257,44 @@ class MacPortsBackend(upt.Backend):
</span>             sys.exit(f'The command "{cmd}" failed. '
                      'Please make sure you have MacPorts installed '
                      'and/or your PATH is set-up correctly.')
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    @staticmethod
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    def standardize_CPAN_version(version):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        """Parse CPAN version and return a normalized, dotted-decimal form.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        The resulting version is identical to the MacPorts conversion as
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        performed by the perl5 PortGroup.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        It is almost the same as the suggested conversion using:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+          perl -Mversion -e 'print version->parse("<VERSION>")->normal'
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        with the exception of version numbers that do not contain a "dot".
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        """
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        version_strip = version.lstrip('v')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        version_split = version_strip.split('.')
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # no or more than 1 'dots': no conversion required
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if len(version_split) != 2:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return version_strip
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # conversion required
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        std_version = version_split[0]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fractional = version_split[1]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        index = 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        while index < len(fractional) or index < 6:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            sub = fractional[index:index+3]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if len(sub) < 3:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                sub += '0'*(3-len(sub))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            std_version += '.' + str(int(sub))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            index += 3
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return std_version
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    def needs_requirement(self, req, phase):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if self.frontend == 'cpan' and req.specifier:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            s = SpecifierSet(req.specifier)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            req.specifier = ', '.join(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                [dep.operator +
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                 self.standardize_CPAN_version(dep.version) for dep in s])
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return super().needs_requirement(req, phase)
</span></pre><pre style='margin:0'>

</pre>