[Checkins] SVN: vanguardistas.pydebdep/trunk/ * Add a vanguardistas.pydebdep.translator.egg_to_deb function that converts egg

Brian Sutherland jinty at web.de
Sun Apr 13 12:54:13 EDT 2008


Log message for revision 85333:
  * Add a vanguardistas.pydebdep.translator.egg_to_deb function that converts egg
    versions to debian versions maintaining their sort order.
  * Hook above function into the deb/egg version compare function.
  * Produce dependeny lines that contain dpkg-ized version rather than egg versions.
  
  NOTE: The tests of the above changes fail with the setuptools 0.6c3, but pass with 0.6c8.
        This is because of the way that "dev" sorts specially in later setuptools versions.
  
  

Changed:
  U   vanguardistas.pydebdep/trunk/CHANGES.txt
  U   vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/pydebdep.py
  U   vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/tests/dummy.foo.egg-info/requires.txt
  U   vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/translator.py

-=-
Modified: vanguardistas.pydebdep/trunk/CHANGES.txt
===================================================================
--- vanguardistas.pydebdep/trunk/CHANGES.txt	2008-04-13 15:19:50 UTC (rev 85332)
+++ vanguardistas.pydebdep/trunk/CHANGES.txt	2008-04-13 16:54:12 UTC (rev 85333)
@@ -1,6 +1,14 @@
-0.1.0 (unreleased)
+0.1.0 (13-04-2008)
 ------------------
 
+* Add a venguardistas.pydebdep.translator.egg_to_deb function that converts egg
+  versions to debian versions maintaining their sort order.
+* Hook above function into the deb/egg version compare function.
+* Produce dependeny lines that contain dpkg-ized version rather than egg versions.
+
+NOTE: The tests of the above changes fail with the setuptools 0.6c3, but pass with 0.6c8.
+      This is because of the way that "dev" sorts specially in later setuptools versions.
+
 0.0.3 (10-04-2008)
 ------------------
 

Modified: vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/pydebdep.py
===================================================================
--- vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/pydebdep.py	2008-04-13 15:19:50 UTC (rev 85332)
+++ vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/pydebdep.py	2008-04-13 16:54:12 UTC (rev 85333)
@@ -24,7 +24,7 @@
                                '<': '<<',
                                '==': '=',
                                '!=': None, # != not supported by debian, use conflicts in future for this
-                               '<=': '<='} 
+                               '<=': '<='}
 
 def parse_args(argv):
     """Parse the command line arguments"""
@@ -40,7 +40,7 @@
     assert options.depends ^ options.conflicts
     assert os.path.exists(options.egginfo), options.egginfo
     return options
-    
+
 def get_debian_dependencies(file):
     """Returns a list of the format of the dpkg dependency info."""
     pydeps = []
@@ -57,7 +57,8 @@
                 op = setuptools_debian_operators[op]
                 if op is None:
                     continue
-                pydeps.append('%s (%s %s)' % (bin_pkg, op, version))
+                dpkg_version = translator.egg_to_deb(version)
+                pydeps.append('%s (%s %s)' % (bin_pkg, op, dpkg_version))
         else:
             pydeps.append(bin_pkg)
     # Let's depend on the namespace pacakges as well.
@@ -74,15 +75,15 @@
 
 def deps(argv=sys.argv):
     """Run the dependency calculation program.
-    
+
         >>> import os
         >>> here = os.path.dirname(__file__)
         >>> ex1 = os.path.join(here, 'tests', 'dummy.foo.egg-info')
         >>> exitcode = deps(['bin', '--egg_info', ex1, '--depends'])
-        python-foo (>> 0.1), python-foobar, python-bar (<< 0.3), python-dummy
+        python-foo (>> 0.1), python-foobar, python-bar (<< 0.3~c~pre1), python-dummy
         >>> exitcode
         0
-        
+
         >>> exitcode = deps(['bin', '--egg_info', ex1, '--conflicts'])
         <BLANKLINE>
         >>> exitcode

Modified: vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/tests/dummy.foo.egg-info/requires.txt
===================================================================
--- vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/tests/dummy.foo.egg-info/requires.txt	2008-04-13 15:19:50 UTC (rev 85332)
+++ vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/tests/dummy.foo.egg-info/requires.txt	2008-04-13 16:54:12 UTC (rev 85333)
@@ -1,4 +1,4 @@
 foo > 0.1
 foobar
 bar != 0.2
-bar < 0.3
\ No newline at end of file
+bar < 0.3pre1

Modified: vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/translator.py
===================================================================
--- vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/translator.py	2008-04-13 15:19:50 UTC (rev 85332)
+++ vanguardistas.pydebdep/trunk/src/vanguardistas/pydebdep/translator.py	2008-04-13 16:54:12 UTC (rev 85333)
@@ -15,6 +15,8 @@
 import logging
 from subprocess import call
 
+from pkg_resources import component_re # Is this a public interface?
+
 _marker = object()
 _here = os.path.dirname(__file__)
 
@@ -33,7 +35,7 @@
         'python-imaging'
         >>> trans.source_to_egg('python-imaging')
         'PIL'
-    
+
     A global translation where the binary and source translations are different:
 
         >>> trans.egg_to_source('vanguardistas.builder')
@@ -45,7 +47,7 @@
 
         >>> trans.source_to_egg('somesource')
         'someegg'
-    
+
     A debiam package name can only be lowercase, so the default package translation should guess only lowercase names
     (http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Package)
 
@@ -106,11 +108,169 @@
         return 'python-%s' % egg_name.lower()
 
 
+def egg_to_deb(version):
+    """Converts an egg version to debian format to preserve sorting rules.
+
+    We try to convert egg versions to debian versions here in a way that
+    preserves sorting rules and takes into account egg ideosynchracies. We also
+    try to maintain readability of the version numbers and so do not aim for
+    perfection (It's highly doubtful we could attain it anyway).
+
+    Setup a testing function:
+
+        >>> from pkg_resources import parse_version
+        >>> def test_gt(v1, v2):
+        ...     st_gt = parse_version(v1) > parse_version(v2)
+        ...     v1_c, v2_c = egg_to_deb(v1), egg_to_deb(v2)
+        ...     dpkg_gt = _dpkg_is_gt(v1_c, v2_c)
+        ...     print "Dpkgized versions:", v1_c, v2_c
+        ...     if st_gt == dpkg_gt:
+        ...         if st_gt:
+        ...             print "Greater Than"
+        ...         else:
+        ...             print "Not Greater Than"
+        ...     else:
+        ...         print "ERROR: setuptools and dpkg do not agree."
+        ...     if _dpkg_is_gt(v1, v2) == st_gt:
+        ...         print "Dpkg understands setuptools version"
+        ...     else:
+        ...         print "Dpkg would have got this comparison wrong using only setuptools versions."
+
+    These are the cases we want to fix:
+
+        >>> test_gt('2.8.0', '2.8.0dev1')
+        Dpkgized versions: 2.8.0 2.8.0~~dev1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0pre1', '2.8.0a1')
+        Dpkgized versions: 2.8.0~c~pre1 2.8.0~a1
+        Greater Than
+        Dpkg understands setuptools version
+
+        >>> test_gt('2.8.0d1', '2.8.0pre1')
+        Dpkgized versions: 2.8.0~d1 2.8.0~c~pre1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0a1', '2.8.0dev1')
+        Dpkgized versions: 2.8.0~a1 2.8.0~~dev1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0-1', '2.8.0rc1')
+        Dpkgized versions: 2.8.0-1 2.8.0~c~rc1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+
+        >>> test_gt('2.8.1', '2.8.0-1')
+        Dpkgized versions: 2.8.1 2.8.0-1
+        Greater Than
+        Dpkg understands setuptools version
+
+        >>> test_gt('2.8.0', '2.8.0a1')
+        Dpkgized versions: 2.8.0 2.8.0~a1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0', '2.8.0pre1')
+        Dpkgized versions: 2.8.0 2.8.0~c~pre1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0preview1', '2.8.0a1')
+        Dpkgized versions: 2.8.0~c~preview1 2.8.0~a1
+        Greater Than
+        Dpkg understands setuptools version
+
+        >>> test_gt('2.8.0', '2.8.0rc1')
+        Dpkgized versions: 2.8.0 2.8.0~c~rc1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0', '2.8.0RC1')
+        Dpkgized versions: 2.8.0 2.8.0~c~rc1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0possible', '2.8.0rc1') # even duplicate the bugs...
+        Dpkgized versions: 2.8.0~possible 2.8.0~c~rc1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0rc1', '2.8.0RC1')
+        Dpkgized versions: 2.8.0~c~rc1 2.8.0~c~rc1
+        Not Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+        >>> test_gt('2.8.0cat', '2.8.0rc1')
+        Dpkgized versions: 2.8.0~cat 2.8.0~c~rc1
+        Greater Than
+        Dpkg would have got this comparison wrong using only setuptools versions.
+
+    """
+    version = version.lower()
+    result = []
+    for part in component_re.split(version):
+        if not part or part.isdigit() or part == '.' or part == '-':
+            result.append(part)
+            continue
+        result.append('~')
+        if part in ['pre', 'preview', 'rc']:
+            # ok. so because of the way setuptools does this, we can't manage to preserve the original
+            # version number and maintain sort order
+            result.append('c~')
+        if part == 'dev':
+            result.append('~')
+        result.append(part)
+    return ''.join(result)
+
+
 def version_compare(egg, source):
-    if _dpkg_is_gt(egg.version, source.version):
-        logging.debug("%s is greater than %s" % (egg.version, source.version))
+    """Compare an egg and deb version.
+
+    Returns None if the comparison is meaningless.
+
+        >>> class VersionStub:
+        ...     pass
+
+        >>> source = VersionStub()
+        >>> egg =VersionStub()
+
+    A normal comparison returning >:
+
+        >>> egg.version = '2'
+        >>> source.version = '1'
+        >>> version_compare(egg, source)
+        '>'
+
+    We don't yet know how to decide on less than (Changing this is a TODO):
+
+        >>> egg.version = '1'
+        >>> source.version = '2'
+        >>> version_compare(egg, source) is None
+        True
+
+    But we can do some complex compares correctly:
+
+        >>> egg.version = '1.0a1'
+        >>> source.version = '1.0~~dev1'
+        >>> version_compare(egg, source)
+        '>'
+
+        >>> egg.version = '1.0b1'
+        >>> source.version = '1.0~a1'
+        >>> version_compare(egg, source)
+        '>'
+
+
+    """
+    dpkgized = egg_to_deb(egg.version)
+    if _dpkg_is_gt(dpkgized, source.version):
+        logging.debug("%s (dpkgized: %s) is greater than %s" % (egg.version, dpkgized, source.version))
         return '>'
-    logging.debug("%s is NOT greater than %s" % (egg.version, source.version))
+    logging.debug("%s (dpkgized: %s) is NOT greater than %s" % (egg.version, dpkgized, source.version))
     return None # Dunno!!!
 
 def _dpkg_is_gt(v1, v2):



More information about the Checkins mailing list