1010# See the License for the specific language governing permissions and
1111# limitations under the License.
1212
13+ import json as _json
14+
1315import pretend
1416
1517from pyramid .httpexceptions import HTTPMovedPermanently , HTTPNotFound
@@ -299,7 +301,7 @@ def test_detail_renders(self, pyramid_config, db_request, db_session):
299301
300302 db_request .route_url = pretend .call_recorder (lambda * args , ** kw : url )
301303
302- result = json .json_release (releases [3 ], db_request )
304+ json .json_release (releases [3 ], db_request )
303305
304306 assert set (db_request .route_url .calls ) == {
305307 pretend .call ("packaging.file" , path = files [0 ].path ),
@@ -315,86 +317,115 @@ def test_detail_renders(self, pyramid_config, db_request, db_session):
315317 _assert_has_cors_headers (db_request .response .headers )
316318 assert db_request .response .headers ["X-PyPI-Last-Serial" ] == str (je .id )
317319
318- assert result == {
319- "info" : {
320- "author" : None ,
321- "author_email" : None ,
322- "bugtrack_url" : None ,
323- "classifiers" : [],
324- "description_content_type" : description_content_type ,
325- "description" : releases [- 1 ].description .raw ,
326- "docs_url" : "/the/fake/url/" ,
327- "download_url" : None ,
328- "downloads" : {"last_day" : - 1 , "last_week" : - 1 , "last_month" : - 1 },
329- "home_page" : None ,
330- "keywords" : None ,
331- "license" : None ,
332- "maintainer" : None ,
333- "maintainer_email" : None ,
334- "name" : project .name ,
335- "package_url" : "/the/fake/url/" ,
336- "platform" : None ,
337- "project_url" : "/the/fake/url/" ,
338- "project_urls" : expected_urls ,
339- "release_url" : "/the/fake/url/" ,
340- "requires_dist" : None ,
341- "requires_python" : None ,
342- "summary" : None ,
343- "yanked" : False ,
344- "yanked_reason" : None ,
345- "version" : "3.0" ,
346- },
347- "releases" : {
348- "0.1" : [],
349- "1.0" : [
350- {
351- "comment_text" : None ,
352- "downloads" : - 1 ,
353- "filename" : files [0 ].filename ,
354- "has_sig" : True ,
355- "md5_digest" : files [0 ].md5_digest ,
356- "digests" : {
357- "md5" : files [0 ].md5_digest ,
358- "sha256" : files [0 ].sha256_digest ,
359- },
360- "packagetype" : None ,
361- "python_version" : "source" ,
362- "size" : 200 ,
363- "upload_time" : files [0 ].upload_time .strftime (
364- "%Y-%m-%dT%H:%M:%S"
365- ),
366- "upload_time_iso_8601" : files [0 ].upload_time .isoformat () + "Z" ,
367- "url" : "/the/fake/url/" ,
368- "requires_python" : None ,
369- "yanked" : False ,
370- "yanked_reason" : None ,
371- }
372- ],
373- "2.0" : [
374- {
375- "comment_text" : None ,
376- "downloads" : - 1 ,
377- "filename" : files [1 ].filename ,
378- "has_sig" : True ,
379- "md5_digest" : files [1 ].md5_digest ,
380- "digests" : {
381- "md5" : files [1 ].md5_digest ,
382- "sha256" : files [1 ].sha256_digest ,
383- },
384- "packagetype" : None ,
385- "python_version" : "source" ,
386- "size" : 200 ,
387- "upload_time" : files [1 ].upload_time .strftime (
388- "%Y-%m-%dT%H:%M:%S"
389- ),
390- "upload_time_iso_8601" : files [1 ].upload_time .isoformat () + "Z" ,
391- "url" : "/the/fake/url/" ,
392- "requires_python" : None ,
393- "yanked" : False ,
394- "yanked_reason" : None ,
395- }
396- ],
397- "3.0" : [
320+ assert db_request .response .body == _json .dumps (
321+ {
322+ "info" : {
323+ "author" : None ,
324+ "author_email" : None ,
325+ "bugtrack_url" : None ,
326+ "classifiers" : [],
327+ "description_content_type" : description_content_type ,
328+ "description" : releases [- 1 ].description .raw ,
329+ "docs_url" : "/the/fake/url/" ,
330+ "download_url" : None ,
331+ "downloads" : {"last_day" : - 1 , "last_week" : - 1 , "last_month" : - 1 },
332+ "home_page" : None ,
333+ "keywords" : None ,
334+ "license" : None ,
335+ "maintainer" : None ,
336+ "maintainer_email" : None ,
337+ "name" : project .name ,
338+ "package_url" : "/the/fake/url/" ,
339+ "platform" : None ,
340+ "project_url" : "/the/fake/url/" ,
341+ "project_urls" : expected_urls ,
342+ "release_url" : "/the/fake/url/" ,
343+ "requires_dist" : None ,
344+ "requires_python" : None ,
345+ "summary" : None ,
346+ "yanked" : False ,
347+ "yanked_reason" : None ,
348+ "version" : "3.0" ,
349+ },
350+ "releases" : {
351+ "0.1" : [],
352+ "1.0" : [
353+ {
354+ "comment_text" : None ,
355+ "downloads" : - 1 ,
356+ "filename" : files [0 ].filename ,
357+ "has_sig" : True ,
358+ "md5_digest" : files [0 ].md5_digest ,
359+ "digests" : {
360+ "md5" : files [0 ].md5_digest ,
361+ "sha256" : files [0 ].sha256_digest ,
362+ },
363+ "packagetype" : None ,
364+ "python_version" : "source" ,
365+ "size" : 200 ,
366+ "upload_time" : files [0 ].upload_time .strftime (
367+ "%Y-%m-%dT%H:%M:%S"
368+ ),
369+ "upload_time_iso_8601" : files [0 ].upload_time .isoformat ()
370+ + "Z" ,
371+ "url" : "/the/fake/url/" ,
372+ "requires_python" : None ,
373+ "yanked" : False ,
374+ "yanked_reason" : None ,
375+ }
376+ ],
377+ "2.0" : [
378+ {
379+ "comment_text" : None ,
380+ "downloads" : - 1 ,
381+ "filename" : files [1 ].filename ,
382+ "has_sig" : True ,
383+ "md5_digest" : files [1 ].md5_digest ,
384+ "digests" : {
385+ "md5" : files [1 ].md5_digest ,
386+ "sha256" : files [1 ].sha256_digest ,
387+ },
388+ "packagetype" : None ,
389+ "python_version" : "source" ,
390+ "size" : 200 ,
391+ "upload_time" : files [1 ].upload_time .strftime (
392+ "%Y-%m-%dT%H:%M:%S"
393+ ),
394+ "upload_time_iso_8601" : files [1 ].upload_time .isoformat ()
395+ + "Z" ,
396+ "url" : "/the/fake/url/" ,
397+ "requires_python" : None ,
398+ "yanked" : False ,
399+ "yanked_reason" : None ,
400+ }
401+ ],
402+ "3.0" : [
403+ {
404+ "comment_text" : None ,
405+ "downloads" : - 1 ,
406+ "filename" : files [2 ].filename ,
407+ "has_sig" : True ,
408+ "md5_digest" : files [2 ].md5_digest ,
409+ "digests" : {
410+ "md5" : files [2 ].md5_digest ,
411+ "sha256" : files [2 ].sha256_digest ,
412+ },
413+ "packagetype" : None ,
414+ "python_version" : "source" ,
415+ "size" : 200 ,
416+ "upload_time" : files [2 ].upload_time .strftime (
417+ "%Y-%m-%dT%H:%M:%S"
418+ ),
419+ "upload_time_iso_8601" : files [2 ].upload_time .isoformat ()
420+ + "Z" ,
421+ "url" : "/the/fake/url/" ,
422+ "requires_python" : None ,
423+ "yanked" : False ,
424+ "yanked_reason" : None ,
425+ }
426+ ],
427+ },
428+ "urls" : [
398429 {
399430 "comment_text" : None ,
400431 "downloads" : - 1 ,
@@ -418,32 +449,11 @@ def test_detail_renders(self, pyramid_config, db_request, db_session):
418449 "yanked_reason" : None ,
419450 }
420451 ],
452+ "last_serial" : je .id ,
453+ "vulnerabilities" : [],
421454 },
422- "urls" : [
423- {
424- "comment_text" : None ,
425- "downloads" : - 1 ,
426- "filename" : files [2 ].filename ,
427- "has_sig" : True ,
428- "md5_digest" : files [2 ].md5_digest ,
429- "digests" : {
430- "md5" : files [2 ].md5_digest ,
431- "sha256" : files [2 ].sha256_digest ,
432- },
433- "packagetype" : None ,
434- "python_version" : "source" ,
435- "size" : 200 ,
436- "upload_time" : files [2 ].upload_time .strftime ("%Y-%m-%dT%H:%M:%S" ),
437- "upload_time_iso_8601" : files [2 ].upload_time .isoformat () + "Z" ,
438- "url" : "/the/fake/url/" ,
439- "requires_python" : None ,
440- "yanked" : False ,
441- "yanked_reason" : None ,
442- }
443- ],
444- "last_serial" : je .id ,
445- "vulnerabilities" : [],
446- }
455+ sort_keys = True ,
456+ ).encode ("utf8" )
447457
448458 def test_minimal_renders (self , pyramid_config , db_request ):
449459 project = ProjectFactory .create (has_docs = False )
@@ -463,7 +473,7 @@ def test_minimal_renders(self, pyramid_config, db_request):
463473 url = "/the/fake/url/"
464474 db_request .route_url = pretend .call_recorder (lambda * args , ** kw : url )
465475
466- result = json .json_release (release , db_request )
476+ json .json_release (release , db_request )
467477
468478 assert set (db_request .route_url .calls ) == {
469479 pretend .call ("packaging.file" , path = file .path ),
@@ -476,37 +486,63 @@ def test_minimal_renders(self, pyramid_config, db_request):
476486 _assert_has_cors_headers (db_request .response .headers )
477487 assert db_request .response .headers ["X-PyPI-Last-Serial" ] == str (je .id )
478488
479- assert result == {
480- "info" : {
481- "author" : None ,
482- "author_email" : None ,
483- "bugtrack_url" : None ,
484- "classifiers" : [],
485- "description_content_type" : release .description .content_type ,
486- "description" : release .description .raw ,
487- "docs_url" : None ,
488- "download_url" : None ,
489- "downloads" : {"last_day" : - 1 , "last_week" : - 1 , "last_month" : - 1 },
490- "home_page" : None ,
491- "keywords" : None ,
492- "license" : None ,
493- "maintainer" : None ,
494- "maintainer_email" : None ,
495- "name" : project .name ,
496- "package_url" : "/the/fake/url/" ,
497- "platform" : None ,
498- "project_url" : "/the/fake/url/" ,
499- "project_urls" : None ,
500- "release_url" : "/the/fake/url/" ,
501- "requires_dist" : None ,
502- "requires_python" : None ,
503- "summary" : None ,
504- "yanked" : False ,
505- "yanked_reason" : None ,
506- "version" : "0.1" ,
507- },
508- "releases" : {
509- "0.1" : [
489+ assert db_request .response .body == _json .dumps (
490+ {
491+ "info" : {
492+ "author" : None ,
493+ "author_email" : None ,
494+ "bugtrack_url" : None ,
495+ "classifiers" : [],
496+ "description_content_type" : release .description .content_type ,
497+ "description" : release .description .raw ,
498+ "docs_url" : None ,
499+ "download_url" : None ,
500+ "downloads" : {"last_day" : - 1 , "last_week" : - 1 , "last_month" : - 1 },
501+ "home_page" : None ,
502+ "keywords" : None ,
503+ "license" : None ,
504+ "maintainer" : None ,
505+ "maintainer_email" : None ,
506+ "name" : project .name ,
507+ "package_url" : "/the/fake/url/" ,
508+ "platform" : None ,
509+ "project_url" : "/the/fake/url/" ,
510+ "project_urls" : None ,
511+ "release_url" : "/the/fake/url/" ,
512+ "requires_dist" : None ,
513+ "requires_python" : None ,
514+ "summary" : None ,
515+ "yanked" : False ,
516+ "yanked_reason" : None ,
517+ "version" : "0.1" ,
518+ },
519+ "releases" : {
520+ "0.1" : [
521+ {
522+ "comment_text" : None ,
523+ "downloads" : - 1 ,
524+ "filename" : file .filename ,
525+ "has_sig" : True ,
526+ "md5_digest" : file .md5_digest ,
527+ "digests" : {
528+ "md5" : file .md5_digest ,
529+ "sha256" : file .sha256_digest ,
530+ },
531+ "packagetype" : None ,
532+ "python_version" : "source" ,
533+ "size" : 200 ,
534+ "upload_time" : file .upload_time .strftime (
535+ "%Y-%m-%dT%H:%M:%S"
536+ ),
537+ "upload_time_iso_8601" : file .upload_time .isoformat () + "Z" ,
538+ "url" : "/the/fake/url/" ,
539+ "requires_python" : None ,
540+ "yanked" : False ,
541+ "yanked_reason" : None ,
542+ }
543+ ]
544+ },
545+ "urls" : [
510546 {
511547 "comment_text" : None ,
512548 "downloads" : - 1 ,
@@ -527,30 +563,12 @@ def test_minimal_renders(self, pyramid_config, db_request):
527563 "yanked" : False ,
528564 "yanked_reason" : None ,
529565 }
530- ]
566+ ],
567+ "last_serial" : je .id ,
568+ "vulnerabilities" : [],
531569 },
532- "urls" : [
533- {
534- "comment_text" : None ,
535- "downloads" : - 1 ,
536- "filename" : file .filename ,
537- "has_sig" : True ,
538- "md5_digest" : file .md5_digest ,
539- "digests" : {"md5" : file .md5_digest , "sha256" : file .sha256_digest },
540- "packagetype" : None ,
541- "python_version" : "source" ,
542- "size" : 200 ,
543- "upload_time" : file .upload_time .strftime ("%Y-%m-%dT%H:%M:%S" ),
544- "upload_time_iso_8601" : file .upload_time .isoformat () + "Z" ,
545- "url" : "/the/fake/url/" ,
546- "requires_python" : None ,
547- "yanked" : False ,
548- "yanked_reason" : None ,
549- }
550- ],
551- "last_serial" : je .id ,
552- "vulnerabilities" : [],
553- }
570+ sort_keys = True ,
571+ ).encode ("utf8" )
554572
555573 def test_vulnerabilities_renders (self , pyramid_config , db_request ):
556574 project = ProjectFactory .create (has_docs = False )
@@ -570,7 +588,7 @@ def test_vulnerabilities_renders(self, pyramid_config, db_request):
570588
571589 result = json .json_release (release , db_request )
572590
573- assert result ["vulnerabilities" ] == [
591+ assert _json . loads ( result . body ) ["vulnerabilities" ] == [
574592 {
575593 "id" : "PYSEC-001" ,
576594 "source" : "the source" ,
0 commit comments