Commits

Daniel Holth committed f61d3f4

improved unicode handling; updated schema

Comments (0)

Files changed (3)

wheel/metadata.py

 import os
 import textwrap
 import pkg_resources
+import email.header
+import json
 
 METADATA_VERSION = "2.0"
 
     metadata = {}
     pkg_info = read_pkg_info(path)
     
+    description = {}
+    
     if pkg_info['Description']:
-        metadata['description'] = dedent_description(pkg_info)
+        description['text'] = dedent_description(pkg_info)
         del pkg_info['Description']
     else:
         payload = pkg_info.get_payload()
         if payload:
-            metadata['description'] = payload
-    
+            description['text'] = payload
+            
+    if pkg_info['Summary']:
+        summary = pkginfo_unicode(pkg_info, 'Summary')
+        description['summary'] = summary
+        del pkg_info['Summary']
+        
+    if description:
+        pkg_info['description'] = description
+
     for key in unique(k.lower() for k in pkg_info.keys()):
         low_key = key.replace('-', '_')
 
                         extra_requirements[extra_name].append(requirement)
                 else:
                     requirements.append(requirement)
-            metadata['requires'] = requirements
+            metadata['run_requires'] = requirements
             if extra_requirements:
-                metadata['may_require'] = [{'extra':key, 'dependencies':value} 
+                metadata['run_may_require'] = [{'extra':key, 'dependencies':value} 
                         for key, value in sorted(extra_requirements.items())]
                 if not 'extras' in metadata:
                     metadata['extras'] = []
 
     return pkg_info
 
+            
+def pkginfo_unicode(pkg_info, field):
+    """Hack to coax Unicode out of an email Message()"""
+    text = pkg_info[field]
+    field = field.lower()
+    if not isinstance(text, str):
+        for item in pkg_info.raw_items():
+            if item[0].lower() == field:
+                text = item[1].encode('ascii', 'surrogateescape')\
+                                      .decode('utf-8')
+                break
+
+    return text
+
 
 def dedent_description(pkg_info):
     """
     surrogates = False
     if not isinstance(description, str):
         surrogates = True
-        for item in pkg_info.raw_items():
-            if item[0].lower() == 'description':
-                description = item[1].encode('ascii', 'surrogateescape')\
-                                             .decode('utf-8')
-                break
+        description = pkginfo_unicode(pkg_info, 'Description')
 
     description_lines = description.splitlines()
     description_dedent = '\n'.join(

wheel/test/complex-dist/setup.py

 try:
     unicode
     def u8(s):
-        return s.decode('unicode-escape').encode('utf-8')
+        return s.decode('unicode-escape')
 except NameError:
     def u8(s):
-        return s.encode('utf-8')
+        return s
 
-setup(name='complex-dist',
-      version='0.1',
-      description=u8('Another testing distribution \N{SNOWMAN}'),
-      author="Illustrious Author",
-      author_email="illustrious@example.org",
-      url="http://example.org/exemplary",
-      packages=['complexdist'],
-      setup_requires=["wheel", "setuptools"],
-      install_requires=["quux", "splort"],
-      extras_require={'simple':['simple.dist']},
-      tests_require=["foo", "bar"],
-      entry_points={'console_scripts':['complex-dist=complexdist:main']}
-      )
+if __name__ == "__main__":
+    setup(name='complex-dist',
+          version='0.1',
+          description=u8('Another testing distribution \N{SNOWMAN}'),
+          author="Illustrious Author",
+          author_email="illustrious@example.org",
+          url="http://example.org/exemplary",
+          packages=['complexdist'],
+          setup_requires=["wheel", "setuptools"],
+          install_requires=["quux", "splort"],
+          extras_require={'simple':['simple.dist']},
+          tests_require=["foo", "bar"],
+          entry_points={'console_scripts':['complex-dist=complexdist:main']}
+          )
 

wheel/test/pymeta-schema.json

   "properties": {
     "metadata_version": {
       "description": "Version of the file format",
-      "type": "string"
+      "type": "string",
+      "pattern": "^(\\d+(\\.\\d+)*)$"
     },
     "name": {
       "description": "The name of the distribution.",
       "type": "string",
-      "pattern": "^[0-9A-Za-z_.-]+$"
+      "pattern": "^[0-9A-Za-z]([0-9A-Za-z_.-]*[0-9A-Za-z])?$"
     },
     "version": {
       "description": "The distribution's public version identifier",
-      "type": "string"
+      "type": "string",
+      "pattern": "^(\\d+(\\.\\d+)*)((a|b|c|rc)(\\d+))?(\\.(post)(\\d+))?(\\.(dev)(\\d+))?$"
     },
     "source_label": {
       "description": "A constrained identifying text string",
-      "type": "string"
+      "type": "string",
+      "pattern": "^[0-9a-z_.-+]+$"
     },
     "source_url": {
       "description": "A string containing a full URL where the source for this specific version of the distribution can be downloaded.",
-      "type": "string"
+      "type": "string",
+      "format": "uri"
     },
     "summary": {
       "description": "A one-line summary of what the distribution does.",
     },
     "description": {
       "description": "The distribution metadata should include a longer description of the distribution that may run to several paragraphs.",
-      "type": "string"
-    },
-    "description_format": {
-      "description": "A field indicating the intended format of the text in the description field.",
-      "type": "string"
+      "$ref": "#/definitions/document"
     },
     "keywords": {
-      "description": "A array of additional keywords to be used to assist searching for the distribution in a larger catalog.",
-      "type": "array"
+      "description": "A list of additional keywords to be used to assist searching for the distribution in a larger catalog.",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
     },
     "license": {
       "description": "A string indicating the license covering the distribution.",
     },
     "license_url": {
       "description": "A specific URL referencing the full licence text for this version of the distribution.",
-      "type": "string"
+      "type": "string",
+      "format": "uri"
     },
     "classifiers": {
-      "description": "A array of strings, with each giving a single classification value for the distribution.",
-      "type": "array"
+      "description": "A list of strings, with each giving a single classification value for the distribution.",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
     },
     "contacts": {
-      "description": "A array of contributor entries giving the recommended contact points for getting more information about the project.",
+      "description": "A list of contributor entries giving the recommended contact points for getting more information about the project.",
       "type": "array",
       "items": {
         "type": "object",
       }
     },
     "contributors": {
-      "description": "A array of contributor entries for other contributors not already listed as current project points of contact.",
-      "type": "array"
+      "description": "A list of contributor entries for other contributors not already listed as current project points of contact.",
+      "type": "array",
+      "items": {
+        "type": "object",
+        "$ref": "#/definitions/contact"
+      }
     },
     "project_urls": {
       "description": "A mapping of arbitrary text labels to additional URLs relevant to the project.",
       "type": "object"
     },
-    "requires": {
-      "description": "A array of other distributions needed when this distribution is deployed.",
-      "type": "array"
+    "extras": {
+      "description": "A list of optional sets of dependencies that may be used to define conditional dependencies in \"may_require\" and similar fields.",
+      "type": "array",
+      "items": {
+        "type": "string",
+        "$ref": "#/definitions/extra_name"
+      }
     },
-    "extras": {
-      "description": "A array of optional sets of dependencies that may be used to define conditional dependencies in \"may_require\" and similar fields.",
-      "type": "array"
+    "distributes": {
+      "description": "A list of subdistributions made available through this metadistribution.",
+      "type": "array",
+      "$ref": "#/definitions/dependencies"
     },
-    "may_require": {
-      "description": "A array of other distributions that may be needed when this distribution is deployed, based on the extras requested and the target deployment environment.",
-      "$ref": "#/definitions/may_requires"
+    "may_distribute": {
+      "description": "A list of subdistributions that may be made available through this metadistribution, based on the extras requested and the target deployment environment.",
+      "$ref": "#/definitions/conditional_dependencies"
+    },
+    "run_requires": {
+      "description": "A list of other distributions needed when to run this distribution.",
+      "type": "array",
+      "$ref": "#/definitions/dependencies"
+    },
+    "run_may_require": {
+      "description": "A list of other distributions that may be needed when this distribution is deployed, based on the extras requested and the target deployment environment.",
+      "$ref": "#/definitions/conditional_dependencies"
     },
     "test_requires": {
-      "description": "A array of other distributions needed when this distribution is tested.",
-      "type": "array"
+      "description": "A list of other distributions needed when this distribution is tested.",
+      "type": "array",
+      "$ref": "#/definitions/dependencies"
     },
     "test_may_require": {
-      "description": "A array of other distributions that may be needed when this distribution is tested, based on the extras requested and the target deployment environment.",
+      "description": "A list of other distributions that may be needed when this distribution is tested, based on the extras requested and the target deployment environment.",
       "type": "array",
-      "$ref": "#/definitions/may_requires"
+      "$ref": "#/definitions/conditional_dependencies"
     },
     "build_requires": {
-      "description": "A array of other distributions needed when this distribution is built.",
-      "type": "array"
+      "description": "A list of other distributions needed when this distribution is built.",
+      "type": "array",
+      "$ref": "#/definitions/dependencies"
     },
     "build_may_require": {
-      "description": "A array of other distributions that may be needed when this distribution is built, based on the extras requested and the target deployment environment.",
+      "description": "A list of other distributions that may be needed when this distribution is built, based on the extras requested and the target deployment environment.",
       "type": "array",
-      "$ref": "#/definitions/may_requires"
+      "$ref": "#/definitions/conditional_dependencies"
     },
     "dev_requires": {
-      "description": "A array of other distributions needed when this distribution is developed.",
-      "type": "array"
+      "description": "A list of other distributions needed when this distribution is developed.",
+      "type": "array",
+      "$ref": "#/definitions/dependencies"
     },
     "dev_may_require": {
-      "description": "A array of other distributions that may be needed when this distribution is developed, based on the extras requested and the target deployment environment.",
+      "description": "A list of other distributions that may be needed when this distribution is developed, based on the extras requested and the target deployment environment.",
       "type": "array",
-      "$ref": "#/definitions/may_requires"
+      "$ref": "#/definitions/conditional_dependencies"
     },
     "provides": {
-      "description": "A array of strings naming additional dependency requirements that are satisfied by installing this distribution. These strings must be of the form Name or Name (Version), as for the requires field.",
-      "type": "array"
+      "description": "A list of strings naming additional dependency requirements that are satisfied by installing this distribution. These strings must be of the form Name or Name (Version), as for the requires field.",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
     },
     "obsoleted_by": {
       "description": "A string that indicates that this project is no longer being developed. The named project provides a substitute or replacement.",
-      "type": "string"
+      "type": "string",
+      "$ref": "#/definitions/version_specifier"
     },
     "supports_environments": {
-      "description": "A array of strings specifying the environments that the distribution explicitly supports.",
+      "description": "A list of strings specifying the environments that the distribution explicitly supports.",
       "type": "array",
       "items": {
-        "type": "string"
+        "type": "string",
+        "$ref": "#/definitions/environment_marker"
       }
     },
     "metabuild_hooks": {
           "type": "string"
         }
       },
+      "required": ["name"],
       "additionalProperties": false
     },
-    "may_requires": {
+    "dependencies": {
+      "type": "array",
+      "items": {
+        "type": "string",
+        "$ref": "#/definitions/version_specifier"
+      }
+    },
+    "document": {
+      "type": "object",
+      "properties": {
+        "summary": {
+          "type": "string"
+        },
+        "embedded": {
+          "type": "string"
+        }
+      }
+    },
+    "conditional_dependencies": {
       "type": "array",
       "items": {
         "type": "object",
         "properties": {
           "extra": {
-            "type": "string"
+            "type": "string",
+            "$ref": "#/definitions/extra_name"
           },
           "environment": {
-            "type": "string"
+            "type": "string",
+            "$ref": "#/definitions/environment_marker"
           },
           "dependencies": {
             "type": "array",
-            "items": {
-              "type": "string"
-            }
+            "$ref": "#/definitions/dependencies"
           }
         },
         "required": ["dependencies"],
         "additionalProperties": false
       }
+    },
+    "version_specifier": {
+        "type": "string"
+    },
+    "extra_name": {
+        "type": "string"
+    },
+    "environment_marker": {
+        "type": "string"
     }
   }
 }