1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414import logging
15+ import textwrap
1516
17+ import build
1618import pretend
1719import pytest
1820
19- from twine import commands
20- from twine import package as package_file
2121from twine .commands import check
2222
2323
@@ -38,10 +38,8 @@ def test_str_representation(self):
3838 assert str (self .stream ) == "line 2: Warning: Title underline too short."
3939
4040
41- def test_check_no_distributions (monkeypatch , caplog ):
42- monkeypatch .setattr (commands , "_find_dists" , lambda a : [])
43-
44- assert not check .check (["dist/*" ])
41+ def test_fails_no_distributions (caplog ):
42+ assert not check .check ([])
4543 assert caplog .record_tuples == [
4644 (
4745 "twine.commands.check" ,
@@ -51,75 +49,51 @@ def test_check_no_distributions(monkeypatch, caplog):
5149 ]
5250
5351
54- def test_check_passing_distribution (monkeypatch , capsys ):
55- renderer = pretend .stub (render = pretend .call_recorder (lambda * a , ** kw : "valid" ))
56- package = pretend .stub (
57- metadata_dictionary = lambda : {
58- "description" : "blah" ,
59- "description_content_type" : "text/markdown" ,
60- }
61- )
62- warning_stream = ""
63-
64- monkeypatch .setattr (check , "_RENDERERS" , {None : renderer })
65- monkeypatch .setattr (commands , "_find_dists" , lambda a : ["dist/dist.tar.gz" ])
66- monkeypatch .setattr (
67- package_file ,
68- "PackageFile" ,
69- pretend .stub (from_filename = lambda * a , ** kw : package ),
70- )
71- monkeypatch .setattr (check , "_WarningStream" , lambda : warning_stream )
72-
73- assert not check .check (["dist/*" ])
74- assert capsys .readouterr ().out == "Checking dist/dist.tar.gz: PASSED\n "
75- assert renderer .render .calls == [pretend .call ("blah" , stream = warning_stream )]
76-
77-
78- @pytest .mark .parametrize ("content_type" , ["text/plain" , "text/markdown" ])
79- def test_check_passing_distribution_with_none_renderer (
80- content_type ,
81- monkeypatch ,
82- capsys ,
83- ):
84- """Pass when rendering a content type can't fail."""
85- package = pretend .stub (
86- metadata_dictionary = lambda : {
87- "description" : "blah" ,
88- "description_content_type" : content_type ,
89- }
90- )
52+ def build_sdist (src_path , project_files ):
53+ """
54+ Build a source distribution similar to `python3 -m build --sdist`.
9155
92- monkeypatch .setattr (commands , "_find_dists" , lambda a : ["dist/dist.tar.gz" ])
93- monkeypatch .setattr (
94- package_file ,
95- "PackageFile" ,
96- pretend .stub (from_filename = lambda * a , ** kw : package ),
56+ Returns the absolute path of the built distribution.
57+ """
58+ project_files = {
59+ "pyproject.toml" : (
60+ """
61+ [build-system]
62+ requires = ["setuptools"]
63+ build-backend = "setuptools.build_meta"
64+ """
65+ ),
66+ ** project_files ,
67+ }
68+
69+ for filename , content in project_files .items ():
70+ (src_path / filename ).write_text (textwrap .dedent (content ))
71+
72+ builder = build .ProjectBuilder (src_path )
73+ return builder .build ("sdist" , str (src_path / "dist" ))
74+
75+
76+ @pytest .mark .parametrize ("strict" , [False , True ])
77+ def test_warns_missing_description (strict , tmp_path , capsys , caplog ):
78+ sdist = build_sdist (
79+ tmp_path ,
80+ {
81+ "setup.cfg" : (
82+ """
83+ [metadata]
84+ name = test-package
85+ version = 0.0.1
86+ """
87+ ),
88+ },
9789 )
9890
99- assert not check .check (["dist/*" ])
100- assert capsys .readouterr ().out == "Checking dist/dist.tar.gz: PASSED\n "
91+ assert check .check ([sdist ], strict = strict ) is strict
10192
102-
103- def test_check_no_description (monkeypatch , capsys , caplog ):
104- package = pretend .stub (
105- metadata_dictionary = lambda : {
106- "description" : None ,
107- "description_content_type" : None ,
108- }
109- )
110-
111- monkeypatch .setattr (commands , "_find_dists" , lambda a : ["dist/dist.tar.gz" ])
112- monkeypatch .setattr (
113- package_file ,
114- "PackageFile" ,
115- pretend .stub (from_filename = lambda * a , ** kw : package ),
93+ assert capsys .readouterr ().out == f"Checking { sdist } : " + (
94+ "FAILED due to warnings\n " if strict else "PASSED with warnings\n "
11695 )
11796
118- assert not check .check (["dist/*" ])
119-
120- assert capsys .readouterr ().out == (
121- "Checking dist/dist.tar.gz: PASSED with warnings\n "
122- )
12397 assert caplog .record_tuples == [
12498 (
12599 "twine.commands.check" ,
@@ -134,71 +108,167 @@ def test_check_no_description(monkeypatch, capsys, caplog):
134108 ]
135109
136110
137- def test_strict_fails_on_warnings (monkeypatch , capsys , caplog ):
138- package = pretend .stub (
139- metadata_dictionary = lambda : {
140- "description" : None ,
141- "description_content_type" : None ,
142- }
111+ def test_warns_missing_file (tmp_path , capsys , caplog ):
112+ sdist = build_sdist (
113+ tmp_path ,
114+ {
115+ "setup.cfg" : (
116+ """
117+ [metadata]
118+ name = test-package
119+ version = 0.0.1
120+ long_description = file:README.rst
121+ long_description_content_type = text/x-rst
122+ """
123+ ),
124+ },
143125 )
144126
145- monkeypatch .setattr (commands , "_find_dists" , lambda a : ["dist/dist.tar.gz" ])
146- monkeypatch .setattr (
147- package_file ,
148- "PackageFile" ,
149- pretend .stub (from_filename = lambda * a , ** kw : package ),
150- )
127+ assert not check .check ([sdist ])
151128
152- assert check . check ([ "dist/*" ], strict = True )
129+ assert capsys . readouterr (). out == f"Checking { sdist } : PASSED with warnings \n "
153130
154- assert capsys .readouterr ().out == (
155- "Checking dist/dist.tar.gz: FAILED due to warnings\n "
156- )
157131 assert caplog .record_tuples == [
158132 (
159133 "twine.commands.check" ,
160134 logging .WARNING ,
161- "`long_description_content_type ` missing. defaulting to `text/x-rst` ." ,
135+ "`long_description ` missing." ,
162136 ),
137+ ]
138+
139+
140+ def test_fails_rst_syntax_error (tmp_path , capsys , caplog ):
141+ sdist = build_sdist (
142+ tmp_path ,
143+ {
144+ "setup.cfg" : (
145+ """
146+ [metadata]
147+ name = test-package
148+ version = 0.0.1
149+ long_description = file:README.rst
150+ long_description_content_type = text/x-rst
151+ """
152+ ),
153+ "README.rst" : (
154+ """
155+ ============
156+ """
157+ ),
158+ },
159+ )
160+
161+ assert check .check ([sdist ])
162+
163+ assert capsys .readouterr ().out == f"Checking { sdist } : FAILED\n "
164+
165+ assert caplog .record_tuples == [
163166 (
164167 "twine.commands.check" ,
165- logging .WARNING ,
166- "`long_description` missing." ,
168+ logging .ERROR ,
169+ "`long_description` has syntax errors in markup "
170+ "and would not be rendered on PyPI.\n "
171+ "line 2: Error: Document or section may not begin with a transition." ,
167172 ),
168173 ]
169174
170175
171- def test_check_failing_distribution (monkeypatch , capsys , caplog ):
172- renderer = pretend .stub (render = pretend .call_recorder (lambda * a , ** kw : None ))
173- package = pretend .stub (
174- metadata_dictionary = lambda : {
175- "description" : "blah" ,
176- "description_content_type" : "text/markdown" ,
177- }
176+ def test_fails_rst_no_content (tmp_path , capsys , caplog ):
177+ sdist = build_sdist (
178+ tmp_path ,
179+ {
180+ "setup.cfg" : (
181+ """
182+ [metadata]
183+ name = test-package
184+ version = 0.0.1
185+ long_description = file:README.rst
186+ long_description_content_type = text/x-rst
187+ """
188+ ),
189+ "README.rst" : (
190+ """
191+ test-package
192+ ============
193+ """
194+ ),
195+ },
178196 )
179- warning_stream = "Syntax error"
180-
181- monkeypatch .setattr (check , "_RENDERERS" , {None : renderer })
182- monkeypatch .setattr (commands , "_find_dists" , lambda a : ["dist/dist.tar.gz" ])
183- monkeypatch .setattr (
184- package_file ,
185- "PackageFile" ,
186- pretend .stub (from_filename = lambda * a , ** kw : package ),
187- )
188- monkeypatch .setattr (check , "_WarningStream" , lambda : warning_stream )
189197
190- assert check .check (["dist/*" ])
198+ assert check .check ([sdist ])
199+
200+ assert capsys .readouterr ().out == f"Checking { sdist } : FAILED\n "
191201
192- assert capsys .readouterr ().out == "Checking dist/dist.tar.gz: FAILED\n "
193202 assert caplog .record_tuples == [
194203 (
195204 "twine.commands.check" ,
196205 logging .ERROR ,
197- "`long_description` has syntax errors in markup and would not be rendered "
198- "on PyPI.\n Syntax error " ,
206+ "`long_description` has syntax errors in markup "
207+ "and would not be rendered on PyPI.\n " ,
199208 ),
200209 ]
201- assert renderer .render .calls == [pretend .call ("blah" , stream = warning_stream )]
210+
211+
212+ def test_passes_rst_description (tmp_path , capsys , caplog ):
213+ sdist = build_sdist (
214+ tmp_path ,
215+ {
216+ "setup.cfg" : (
217+ """
218+ [metadata]
219+ name = test-package
220+ version = 0.0.1
221+ long_description = file:README.rst
222+ long_description_content_type = text/x-rst
223+ """
224+ ),
225+ "README.rst" : (
226+ """
227+ test-package
228+ ============
229+
230+ A test package.
231+ """
232+ ),
233+ },
234+ )
235+
236+ assert not check .check ([sdist ])
237+
238+ assert capsys .readouterr ().out == f"Checking { sdist } : PASSED\n "
239+
240+ assert not caplog .record_tuples
241+
242+
243+ @pytest .mark .parametrize ("content_type" , ["text/markdown" , "text/plain" ])
244+ def test_passes_markdown_description (content_type , tmp_path , capsys , caplog ):
245+ sdist = build_sdist (
246+ tmp_path ,
247+ {
248+ "setup.cfg" : (
249+ f"""
250+ [metadata]
251+ name = test-package
252+ version = 0.0.1
253+ long_description = file:README.md
254+ long_description_content_type = { content_type }
255+ """
256+ ),
257+ "README.md" : (
258+ """
259+ # test-package
260+
261+ A test package.
262+ """
263+ ),
264+ },
265+ )
266+
267+ assert not check .check ([sdist ])
268+
269+ assert capsys .readouterr ().out == f"Checking { sdist } : PASSED\n "
270+
271+ assert not caplog .record_tuples
202272
203273
204274def test_main (monkeypatch ):
0 commit comments