Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
python-poetry
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
python-poetry
Commits
17a5df2f
Unverified
Commit
17a5df2f
authored
Apr 07, 2019
by
Sébastien Eustace
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix metadata inconsistency between wheels and sdists
parent
e2ca0611
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
144 additions
and
160 deletions
+144
-160
poetry/masonry/builders/builder.py
+56
-0
poetry/masonry/builders/sdist.py
+1
-39
poetry/masonry/builders/wheel.py
+2
-40
tests/masonry/builders/fixtures/simple_version/pyproject.toml
+0
-3
tests/masonry/builders/test_builder.py
+79
-0
tests/masonry/builders/test_sdist.py
+6
-38
tests/masonry/builders/test_wheel.py
+0
-40
No files found.
poetry/masonry/builders/builder.py
View file @
17a5df2f
...
...
@@ -13,6 +13,7 @@ from poetry.utils._compat import Path
from
poetry.utils._compat
import
basestring
from
poetry.utils._compat
import
glob
from
poetry.utils._compat
import
lru_cache
from
poetry.utils._compat
import
to_str
from
poetry.vcs
import
get_vcs
from
..metadata
import
Metadata
...
...
@@ -22,6 +23,13 @@ from ..utils.package_include import PackageInclude
AUTHOR_REGEX
=
re
.
compile
(
r"(?u)^(?P<name>[- .,\w\d'’\"()]+) <(?P<email>.+?)>$"
)
METADATA_BASE
=
"""
\
Metadata-Version: 2.1
Name: {name}
Version: {version}
Summary: {summary}
"""
class
Builder
(
object
):
...
...
@@ -147,6 +155,54 @@ class Builder(object):
return
sorted
(
to_add
)
def
get_metadata_content
(
self
):
# type: () -> bytes
content
=
METADATA_BASE
.
format
(
name
=
self
.
_meta
.
name
,
version
=
self
.
_meta
.
version
,
summary
=
to_str
(
self
.
_meta
.
summary
),
)
# Optional fields
if
self
.
_meta
.
home_page
:
content
+=
"Home-page: {}
\n
"
.
format
(
self
.
_meta
.
home_page
)
if
self
.
_meta
.
license
:
content
+=
"License: {}
\n
"
.
format
(
self
.
_meta
.
license
)
if
self
.
_meta
.
keywords
:
content
+=
"Keywords: {}
\n
"
.
format
(
self
.
_meta
.
keywords
)
if
self
.
_meta
.
author
:
content
+=
"Author: {}
\n
"
.
format
(
to_str
(
self
.
_meta
.
author
))
if
self
.
_meta
.
author_email
:
content
+=
"Author-email: {}
\n
"
.
format
(
to_str
(
self
.
_meta
.
author_email
))
if
self
.
_meta
.
requires_python
:
content
+=
"Requires-Python: {}
\n
"
.
format
(
self
.
_meta
.
requires_python
)
for
classifier
in
self
.
_meta
.
classifiers
:
content
+=
"Classifier: {}
\n
"
.
format
(
classifier
)
for
extra
in
sorted
(
self
.
_meta
.
provides_extra
):
content
+=
"Provides-Extra: {}
\n
"
.
format
(
extra
)
for
dep
in
sorted
(
self
.
_meta
.
requires_dist
):
content
+=
"Requires-Dist: {}
\n
"
.
format
(
dep
)
for
url
in
sorted
(
self
.
_meta
.
project_urls
,
key
=
lambda
u
:
u
[
0
]):
content
+=
"Project-URL: {}
\n
"
.
format
(
to_str
(
url
))
if
self
.
_meta
.
description_content_type
:
content
+=
"Description-Content-Type: {}
\n
"
.
format
(
self
.
_meta
.
description_content_type
)
if
self
.
_meta
.
description
is
not
None
:
content
+=
"
\n
"
+
to_str
(
self
.
_meta
.
description
)
+
"
\n
"
return
content
def
convert_entry_points
(
self
):
# type: () -> dict
result
=
defaultdict
(
list
)
...
...
poetry/masonry/builders/sdist.py
View file @
17a5df2f
...
...
@@ -41,17 +41,6 @@ setup(**setup_kwargs)
"""
PKG_INFO
=
"""
\
Metadata-Version: 2.1
Name: {name}
Version: {version}
Summary: {summary}
Home-page: {home_page}
Author: {author}
Author-email: {author_email}
"""
class
SdistBuilder
(
Builder
):
def
build
(
self
,
target_dir
=
None
):
# type: (Path) -> Path
self
.
_io
.
writeln
(
" - Building <info>sdist</info>"
)
...
...
@@ -195,34 +184,7 @@ class SdistBuilder(Builder):
)
def
build_pkg_info
(
self
):
pkg_info
=
PKG_INFO
.
format
(
name
=
self
.
_meta
.
name
,
version
=
self
.
_meta
.
version
,
summary
=
self
.
_meta
.
summary
,
home_page
=
self
.
_meta
.
home_page
,
author
=
to_str
(
self
.
_meta
.
author
),
author_email
=
to_str
(
self
.
_meta
.
author_email
),
)
if
self
.
_meta
.
keywords
:
pkg_info
+=
"Keywords: {}
\n
"
.
format
(
self
.
_meta
.
keywords
)
if
self
.
_meta
.
requires_python
:
pkg_info
+=
"Requires-Python: {}
\n
"
.
format
(
self
.
_meta
.
requires_python
)
for
classifier
in
self
.
_meta
.
classifiers
:
pkg_info
+=
"Classifier: {}
\n
"
.
format
(
classifier
)
for
extra
in
sorted
(
self
.
_meta
.
provides_extra
):
pkg_info
+=
"Provides-Extra: {}
\n
"
.
format
(
extra
)
for
dep
in
sorted
(
self
.
_meta
.
requires_dist
):
pkg_info
+=
"Requires-Dist: {}
\n
"
.
format
(
dep
)
for
url
in
sorted
(
self
.
_meta
.
project_urls
,
key
=
lambda
u
:
u
[
0
]):
pkg_info
+=
"Project-URL: {}
\n
"
.
format
(
url
)
return
encode
(
pkg_info
)
return
encode
(
self
.
get_metadata_content
())
def
find_packages
(
self
,
include
):
"""
...
...
poetry/masonry/builders/wheel.py
View file @
17a5df2f
...
...
@@ -15,6 +15,7 @@ from typing import Set
from
poetry.__version__
import
__version__
from
poetry.semver
import
parse_constraint
from
poetry.utils._compat
import
decode
from
..utils.helpers
import
normalize_file_permissions
from
..utils.package_include
import
PackageInclude
...
...
@@ -309,43 +310,4 @@ class WheelBuilder(Builder):
"""
Write out metadata in the 2.x format (email like)
"""
fp
.
write
(
"Metadata-Version: 2.1
\n
"
)
fp
.
write
(
"Name: {}
\n
"
.
format
(
self
.
_meta
.
name
))
fp
.
write
(
"Version: {}
\n
"
.
format
(
self
.
_meta
.
version
))
fp
.
write
(
"Summary: {}
\n
"
.
format
(
self
.
_meta
.
summary
))
fp
.
write
(
"Home-page: {}
\n
"
.
format
(
self
.
_meta
.
home_page
or
"UNKNOWN"
))
fp
.
write
(
"License: {}
\n
"
.
format
(
self
.
_meta
.
license
or
"UNKNOWN"
))
# Optional fields
if
self
.
_meta
.
keywords
:
fp
.
write
(
"Keywords: {}
\n
"
.
format
(
self
.
_meta
.
keywords
))
if
self
.
_meta
.
author
:
fp
.
write
(
"Author: {}
\n
"
.
format
(
self
.
_meta
.
author
))
if
self
.
_meta
.
author_email
:
fp
.
write
(
"Author-email: {}
\n
"
.
format
(
self
.
_meta
.
author_email
))
if
self
.
_meta
.
requires_python
:
fp
.
write
(
"Requires-Python: {}
\n
"
.
format
(
self
.
_meta
.
requires_python
))
for
classifier
in
self
.
_meta
.
classifiers
:
fp
.
write
(
"Classifier: {}
\n
"
.
format
(
classifier
))
for
extra
in
sorted
(
self
.
_meta
.
provides_extra
):
fp
.
write
(
"Provides-Extra: {}
\n
"
.
format
(
extra
))
for
dep
in
sorted
(
self
.
_meta
.
requires_dist
):
fp
.
write
(
"Requires-Dist: {}
\n
"
.
format
(
dep
))
for
url
in
sorted
(
self
.
_meta
.
project_urls
,
key
=
lambda
u
:
u
[
0
]):
fp
.
write
(
"Project-URL: {}
\n
"
.
format
(
url
))
if
self
.
_meta
.
description_content_type
:
fp
.
write
(
"Description-Content-Type: "
"{}
\n
"
.
format
(
self
.
_meta
.
description_content_type
)
)
if
self
.
_meta
.
description
is
not
None
:
fp
.
write
(
"
\n
"
+
self
.
_meta
.
description
+
"
\n
"
)
fp
.
write
(
decode
(
self
.
get_metadata_content
()))
tests/masonry/builders/fixtures/simple_version/pyproject.toml
View file @
17a5df2f
...
...
@@ -5,12 +5,9 @@ description = "Some description."
authors
=
[
"Sébastien Eustace <sebastien@eustace.io>"
]
license
=
"MIT"
readme
=
"README.rst"
homepage
=
"https://poetry.eustace.io/"
[tool.poetry.dependencies]
python
=
"3.6"
tests/masonry/builders/test_builder.py
View file @
17a5df2f
# -*- coding: utf-8 -*-
from
email.parser
import
Parser
from
poetry.io
import
NullIO
from
poetry.masonry.builders.builder
import
Builder
from
poetry.poetry
import
Poetry
...
...
@@ -52,3 +55,79 @@ def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
)
assert
{
"my_package/Bar/foo/bar/Foo.py"
}
==
builder
.
find_excluded_files
()
def
test_get_metadata_content
():
builder
=
Builder
(
Poetry
.
create
(
Path
(
__file__
)
.
parent
/
"fixtures"
/
"complete"
),
NullEnv
(),
NullIO
(),
)
metadata
=
builder
.
get_metadata_content
()
p
=
Parser
()
parsed
=
p
.
parsestr
(
metadata
)
assert
parsed
[
"Metadata-Version"
]
==
"2.1"
assert
parsed
[
"Name"
]
==
"my-package"
assert
parsed
[
"Version"
]
==
"1.2.3"
assert
parsed
[
"Summary"
]
==
"Some description."
assert
parsed
[
"Author"
]
==
"Sébastien Eustace"
assert
parsed
[
"Author-email"
]
==
"sebastien@eustace.io"
assert
parsed
[
"Keywords"
]
==
"packaging,dependency,poetry"
assert
parsed
[
"Requires-Python"
]
==
">=3.6,<4.0"
assert
parsed
[
"License"
]
==
"MIT"
assert
parsed
[
"Home-page"
]
==
"https://poetry.eustace.io/"
classifiers
=
parsed
.
get_all
(
"Classifier"
)
assert
classifiers
==
[
"License :: OSI Approved :: MIT License"
,
"Programming Language :: Python :: 3"
,
"Programming Language :: Python :: 3.6"
,
"Programming Language :: Python :: 3.7"
,
"Topic :: Software Development :: Build Tools"
,
"Topic :: Software Development :: Libraries :: Python Modules"
,
]
extras
=
parsed
.
get_all
(
"Provides-Extra"
)
assert
extras
==
[
"time"
]
requires
=
parsed
.
get_all
(
"Requires-Dist"
)
assert
requires
==
[
"cachy[msgpack] (>=0.2.0,<0.3.0)"
,
"cleo (>=0.6,<0.7)"
,
'pendulum (>=1.4,<2.0); extra == "time"'
,
]
urls
=
parsed
.
get_all
(
"Project-URL"
)
assert
urls
==
[
"Documentation, https://poetry.eustace.io/docs"
,
"Repository, https://github.com/sdispater/poetry"
,
]
def
test_metadata_homepage_default
():
builder
=
Builder
(
Poetry
.
create
(
Path
(
__file__
)
.
parent
/
"fixtures"
/
"simple_version"
),
NullEnv
(),
NullIO
(),
)
metadata
=
Parser
()
.
parsestr
(
builder
.
get_metadata_content
())
assert
metadata
[
"Home-page"
]
is
None
def
test_metadata_with_vcs_dependencies
():
builder
=
Builder
(
Poetry
.
create
(
Path
(
__file__
)
.
parent
/
"fixtures"
/
"with_vcs_dependency"
),
NullEnv
(),
NullIO
(),
)
metadata
=
Parser
()
.
parsestr
(
builder
.
get_metadata_content
())
requires_dist
=
metadata
[
"Requires-Dist"
]
assert
"cleo @ git+https://github.com/sdispater/cleo.git@master"
==
requires_dist
tests/masonry/builders/test_sdist.py
View file @
17a5df2f
...
...
@@ -135,48 +135,16 @@ def test_make_setup():
assert
ns
[
"extras_require"
]
==
{
"time"
:
[
"pendulum>=1.4,<2.0"
]}
def
test_make_pkg_info
():
def
test_make_pkg_info
(
mocker
):
get_metadata_content
=
mocker
.
patch
(
"poetry.masonry.builders.builder.Builder.get_metadata_content"
)
poetry
=
Poetry
.
create
(
project
(
"complete"
))
builder
=
SdistBuilder
(
poetry
,
NullEnv
(),
NullIO
())
pkg_info
=
builder
.
build_pkg_info
()
p
=
Parser
()
parsed
=
p
.
parsestr
(
to_str
(
pkg_info
))
assert
parsed
[
"Metadata-Version"
]
==
"2.1"
assert
parsed
[
"Name"
]
==
"my-package"
assert
parsed
[
"Version"
]
==
"1.2.3"
assert
parsed
[
"Summary"
]
==
"Some description."
assert
parsed
[
"Author"
]
==
"Sébastien Eustace"
assert
parsed
[
"Author-email"
]
==
"sebastien@eustace.io"
assert
parsed
[
"Keywords"
]
==
"packaging,dependency,poetry"
assert
parsed
[
"Requires-Python"
]
==
">=3.6,<4.0"
classifiers
=
parsed
.
get_all
(
"Classifier"
)
assert
classifiers
==
[
"License :: OSI Approved :: MIT License"
,
"Programming Language :: Python :: 3"
,
"Programming Language :: Python :: 3.6"
,
"Programming Language :: Python :: 3.7"
,
"Topic :: Software Development :: Build Tools"
,
"Topic :: Software Development :: Libraries :: Python Modules"
,
]
builder
.
build_pkg_info
()
extras
=
parsed
.
get_all
(
"Provides-Extra"
)
assert
extras
==
[
"time"
]
requires
=
parsed
.
get_all
(
"Requires-Dist"
)
assert
requires
==
[
"cachy[msgpack] (>=0.2.0,<0.3.0)"
,
"cleo (>=0.6,<0.7)"
,
'pendulum (>=1.4,<2.0); extra == "time"'
,
]
urls
=
parsed
.
get_all
(
"Project-URL"
)
assert
urls
==
[
"Documentation, https://poetry.eustace.io/docs"
,
"Repository, https://github.com/sdispater/poetry"
,
]
assert
get_metadata_content
.
called
def
test_make_pkg_info_any_python
():
...
...
tests/masonry/builders/test_wheel.py
View file @
17a5df2f
...
...
@@ -128,43 +128,3 @@ def test_package_with_include(mocker):
assert
"my_module.py"
in
names
assert
"notes.txt"
in
names
assert
"package_with_include/__init__.py"
in
names
def
test_write_metadata_file_license_homepage_default
(
mocker
):
# Preparation
mocked_poetry
=
mocker
.
Mock
()
mocked_poetry
.
file
.
parent
=
Path
(
"."
)
mocked_poetry
.
package
=
ProjectPackage
(
"pkg_name"
,
"1.0.0"
)
mocked_file
=
mocker
.
Mock
()
mocked_venv
=
mocker
.
Mock
()
mocked_io
=
mocker
.
Mock
()
# patch Module init inside Builder class
mocker
.
patch
(
"poetry.masonry.builders.builder.Module"
)
w
=
WheelBuilder
(
mocked_poetry
,
mocked_venv
,
mocked_io
)
# Action
w
.
_write_metadata_file
(
mocked_file
)
# Assertion
mocked_file
.
write
.
assert_any_call
(
"Home-page: UNKNOWN
\n
"
)
mocked_file
.
write
.
assert_any_call
(
"License: UNKNOWN
\n
"
)
def
test_metadata_file_with_vcs_dependencies
():
project_path
=
fixtures_dir
/
"with_vcs_dependency"
WheelBuilder
.
make
(
Poetry
.
create
(
str
(
project_path
)),
NullEnv
(),
NullIO
())
whl
=
project_path
/
"dist"
/
"with_vcs_dependency-1.2.3-py3-none-any.whl"
assert
whl
.
exists
()
p
=
Parser
()
with
zipfile
.
ZipFile
(
str
(
whl
))
as
z
:
metadata
=
p
.
parsestr
(
to_str
(
z
.
read
(
"with_vcs_dependency-1.2.3.dist-info/METADATA"
))
)
requires_dist
=
metadata
[
"Requires-Dist"
]
assert
"cleo @ git+https://github.com/sdispater/cleo.git@master"
==
requires_dist
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment