diff --git a/distutils/ccompiler.py b/distutils/ccompiler.py index c9eb709b..777fc661 100644 --- a/distutils/ccompiler.py +++ b/distutils/ccompiler.py @@ -392,7 +392,7 @@ def _fix_compile_args(self, output_dir, macros, include_dirs): return output_dir, macros, include_dirs def _prep_compile(self, sources, output_dir, depends=None): - """Decide which souce files must be recompiled. + """Decide which source files must be recompiled. Determine the list of object files corresponding to 'sources', and figure out which ones really need to be recompiled. diff --git a/distutils/command/bdist_msi.py b/distutils/command/bdist_msi.py index 15259532..56c4b988 100644 --- a/distutils/command/bdist_msi.py +++ b/distutils/command/bdist_msi.py @@ -231,11 +231,7 @@ def run(self): if os.path.exists(installer_name): os.unlink(installer_name) metadata = self.distribution.metadata - author = metadata.author - if not author: - author = metadata.maintainer - if not author: - author = "UNKNOWN" + author = metadata.author or metadata.maintainer version = metadata.get_version() # ProductVersion must be strictly numeric # XXX need to deal with prerelease versions diff --git a/distutils/command/bdist_rpm.py b/distutils/command/bdist_rpm.py index 550cbfa1..a2a9e8e5 100644 --- a/distutils/command/bdist_rpm.py +++ b/distutils/command/bdist_rpm.py @@ -399,7 +399,7 @@ def _make_spec_file(self): '%define unmangled_version ' + self.distribution.get_version(), '%define release ' + self.release.replace('-','_'), '', - 'Summary: ' + self.distribution.get_description(), + 'Summary: ' + (self.distribution.get_description() or "UNKNOWN"), ] # Workaround for #14443 which affects some RPM based systems such as @@ -438,7 +438,7 @@ def _make_spec_file(self): spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz') spec_file.extend([ - 'License: ' + self.distribution.get_license(), + 'License: ' + (self.distribution.get_license() or "UNKNOWN"), 'Group: ' + self.group, 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot', 'Prefix: %{_prefix}', ]) @@ -464,7 +464,7 @@ def _make_spec_file(self): spec_file.append('%s: %s' % (field, val)) - if self.distribution.get_url() != 'UNKNOWN': + if self.distribution.get_url(): spec_file.append('Url: ' + self.distribution.get_url()) if self.distribution_name: @@ -483,7 +483,7 @@ def _make_spec_file(self): spec_file.extend([ '', '%description', - self.distribution.get_long_description() + self.distribution.get_long_description() or "", ]) # put locale descriptions into spec file diff --git a/distutils/command/check.py b/distutils/command/check.py index af311ca9..8a02dbca 100644 --- a/distutils/command/check.py +++ b/distutils/command/check.py @@ -82,54 +82,19 @@ def check_metadata(self): """Ensures that all required elements of meta-data are supplied. Required fields: - name, version, URL - - Recommended fields: - (author and author_email) or (maintainer and maintainer_email)) + name, version Warns if any are missing. """ metadata = self.distribution.metadata missing = [] - for attr in ('name', 'version', 'url'): - if not (hasattr(metadata, attr) and getattr(metadata, attr)): + for attr in 'name', 'version': + if not getattr(metadata, attr, None): missing.append(attr) if missing: - self.warn("missing required meta-data: %s" % ', '.join(missing)) - if not ( - self._check_contact("author", metadata) or - self._check_contact("maintainer", metadata) - ): - self.warn("missing meta-data: either (author and author_email) " + - "or (maintainer and maintainer_email) " + - "should be supplied") - - def _check_contact(self, kind, metadata): - """ - Returns True if the contact's name is specified and False otherwise. - This function will warn if the contact's email is not specified. - """ - name = getattr(metadata, kind) or '' - email = getattr(metadata, kind + '_email') or '' - - msg = ("missing meta-data: if '{}' supplied, " + - "'{}' should be supplied too") - - if name and email: - return True - - if name: - self.warn(msg.format(kind, kind + '_email')) - return True - - addresses = [(alias, addr) for alias, addr in getaddresses([email])] - if any(alias and addr for alias, addr in addresses): - # The contact's name can be encoded in the email: `Name ` - return True - - return False + self.warn("missing required meta-data: %s" % ', '.join(missing)) def check_restructuredtext(self): """Checks if the long string fields are reST-compliant.""" diff --git a/distutils/dist.py b/distutils/dist.py index 37db4d6c..45024975 100644 --- a/distutils/dist.py +++ b/distutils/dist.py @@ -1064,9 +1064,8 @@ def read_pkg_file(self, file): def _read_field(name): value = msg[name] - if value == 'UNKNOWN': - return None - return value + if value and value != "UNKNOWN": + return value def _read_list(name): values = msg.get_all(name, None) @@ -1125,23 +1124,24 @@ def write_pkg_file(self, file): self.classifiers or self.download_url): version = '1.1' + # required fields file.write('Metadata-Version: %s\n' % version) file.write('Name: %s\n' % self.get_name()) file.write('Version: %s\n' % self.get_version()) - file.write('Summary: %s\n' % self.get_description()) - file.write('Home-page: %s\n' % self.get_url()) - file.write('Author: %s\n' % self.get_contact()) - file.write('Author-email: %s\n' % self.get_contact_email()) - file.write('License: %s\n' % self.get_license()) - if self.download_url: - file.write('Download-URL: %s\n' % self.download_url) - long_desc = rfc822_escape(self.get_long_description()) - file.write('Description: %s\n' % long_desc) + def maybe_write(header, val): + if val: + file.write("{}: {}\n".format(header, val)) - keywords = ','.join(self.get_keywords()) - if keywords: - file.write('Keywords: %s\n' % keywords) + # optional fields + maybe_write("Summary", self.get_description()) + maybe_write("Home-page", self.get_url()) + maybe_write("Author", self.get_contact()) + maybe_write("Author-email", self.get_contact_email()) + maybe_write("License", self.get_license()) + maybe_write("Download-URL", self.download_url) + maybe_write("Description", rfc822_escape(self.get_long_description() or "")) + maybe_write("Keywords", ",".join(self.get_keywords())) self._write_list(file, 'Platform', self.get_platforms()) self._write_list(file, 'Classifier', self.get_classifiers()) @@ -1152,6 +1152,7 @@ def write_pkg_file(self, file): self._write_list(file, 'Obsoletes', self.get_obsoletes()) def _write_list(self, file, name, values): + values = values or [] for value in values: file.write('%s: %s\n' % (name, value)) @@ -1167,35 +1168,35 @@ def get_fullname(self): return "%s-%s" % (self.get_name(), self.get_version()) def get_author(self): - return self.author or "UNKNOWN" + return self.author def get_author_email(self): - return self.author_email or "UNKNOWN" + return self.author_email def get_maintainer(self): - return self.maintainer or "UNKNOWN" + return self.maintainer def get_maintainer_email(self): - return self.maintainer_email or "UNKNOWN" + return self.maintainer_email def get_contact(self): - return self.maintainer or self.author or "UNKNOWN" + return self.maintainer or self.author def get_contact_email(self): - return self.maintainer_email or self.author_email or "UNKNOWN" + return self.maintainer_email or self.author_email def get_url(self): - return self.url or "UNKNOWN" + return self.url def get_license(self): - return self.license or "UNKNOWN" + return self.license get_licence = get_license def get_description(self): - return self.description or "UNKNOWN" + return self.description def get_long_description(self): - return self.long_description or "UNKNOWN" + return self.long_description def get_keywords(self): return self.keywords or [] @@ -1204,7 +1205,7 @@ def set_keywords(self, value): self.keywords = _ensure_list(value, 'keywords') def get_platforms(self): - return self.platforms or ["UNKNOWN"] + return self.platforms def set_platforms(self, value): self.platforms = _ensure_list(value, 'platforms') @@ -1216,7 +1217,7 @@ def set_classifiers(self, value): self.classifiers = _ensure_list(value, 'classifiers') def get_download_url(self): - return self.download_url or "UNKNOWN" + return self.download_url # PEP 314 def get_requires(self): diff --git a/distutils/tests/test_check.py b/distutils/tests/test_check.py index b41dba3d..2414d6eb 100644 --- a/distutils/tests/test_check.py +++ b/distutils/tests/test_check.py @@ -43,7 +43,7 @@ def test_check_metadata(self): # by default, check is checking the metadata # should have some warnings cmd = self._run() - self.assertEqual(cmd._warnings, 2) + self.assertEqual(cmd._warnings, 1) # now let's add the required fields # and run it again, to make sure we don't get @@ -81,17 +81,16 @@ def test_check_author_maintainer(self): cmd = self._run(metadata) self.assertEqual(cmd._warnings, 0) - # the check should warn if only email is given and it does not - # contain the name + # the check should not warn if only email is given metadata[kind + '_email'] = 'name@email.com' cmd = self._run(metadata) - self.assertEqual(cmd._warnings, 1) + self.assertEqual(cmd._warnings, 0) - # the check should warn if only the name is given + # the check should not warn if only the name is given metadata[kind] = "Name" del metadata[kind + '_email'] cmd = self._run(metadata) - self.assertEqual(cmd._warnings, 1) + self.assertEqual(cmd._warnings, 0) @unittest.skipUnless(HAS_DOCUTILS, "won't test without docutils") def test_check_document(self): diff --git a/distutils/tests/test_dist.py b/distutils/tests/test_dist.py index 36155be1..9132bc04 100644 --- a/distutils/tests/test_dist.py +++ b/distutils/tests/test_dist.py @@ -519,7 +519,7 @@ def test_read_metadata(self): self.assertEqual(metadata.description, "xxx") self.assertEqual(metadata.download_url, 'http://example.com') self.assertEqual(metadata.keywords, ['one', 'two']) - self.assertEqual(metadata.platforms, ['UNKNOWN']) + self.assertEqual(metadata.platforms, None) self.assertEqual(metadata.obsoletes, None) self.assertEqual(metadata.requires, ['foo']) diff --git a/distutils/tests/test_register.py b/distutils/tests/test_register.py index 5770ed58..45567686 100644 --- a/distutils/tests/test_register.py +++ b/distutils/tests/test_register.py @@ -154,8 +154,8 @@ def _no_way(prompt=''): req1 = dict(self.conn.reqs[0].headers) req2 = dict(self.conn.reqs[1].headers) - self.assertEqual(req1['Content-length'], '1374') - self.assertEqual(req2['Content-length'], '1374') + self.assertEqual(req1['Content-length'], '1359') + self.assertEqual(req2['Content-length'], '1359') self.assertIn(b'xxx', self.conn.reqs[1].data) def test_password_not_in_file(self): diff --git a/distutils/tests/test_sdist.py b/distutils/tests/test_sdist.py index 4c51717c..aa04dd05 100644 --- a/distutils/tests/test_sdist.py +++ b/distutils/tests/test_sdist.py @@ -251,7 +251,7 @@ def test_metadata_check_option(self): cmd.run() warnings = [msg for msg in self.get_logs(WARN) if msg.startswith('warning: check:')] - self.assertEqual(len(warnings), 2) + self.assertEqual(len(warnings), 1) # trying with a complete set of metadata self.clear_logs() diff --git a/docs/distutils/examples.rst b/docs/distutils/examples.rst index e492b7f6..28582bab 100644 --- a/docs/distutils/examples.rst +++ b/docs/distutils/examples.rst @@ -253,9 +253,7 @@ Running the ``check`` command will display some warnings: $ python setup.py check running check - warning: check: missing required meta-data: version, url - warning: check: missing meta-data: either (author and author_email) or - (maintainer and maintainer_email) should be supplied + warning: check: missing required meta-data: version If you use the reStructuredText syntax in the ``long_description`` field and diff --git a/docs/distutils/setupscript.rst b/docs/distutils/setupscript.rst index 4386a60b..3c8e1ab1 100644 --- a/docs/distutils/setupscript.rst +++ b/docs/distutils/setupscript.rst @@ -580,7 +580,7 @@ This information includes: | ``maintainer_email`` | email address of the | email address | \(3) | | | package maintainer | | | +----------------------+---------------------------+-----------------+--------+ -| ``url`` | home page for the package | URL | \(1) | +| ``url`` | home page for the package | URL | | +----------------------+---------------------------+-----------------+--------+ | ``description`` | short, summary | short string | | | | description of the | | | @@ -610,8 +610,8 @@ Notes: It is recommended that versions take the form *major.minor[.patch[.sub]]*. (3) - Either the author or the maintainer must be identified. If maintainer is - provided, distutils lists it as the author in :file:`PKG-INFO`. + If maintainer is provided and author is not, distutils lists maintainer as + the author in :file:`PKG-INFO`. (4) The ``long_description`` field is used by PyPI when you publish a package,