@@ -61,32 +61,31 @@ def project2licenses(project: dict[str, Any], lfac: 'LicenseFactory', *,
6161 # https://packaging.python.org/en/latest/specifications/core-metadata/#classifier-multiple-use
6262 yield from classifiers2licenses (classifiers , lfac , lack )
6363 if plicense := project .get ('license' ):
64- # https://packaging.python.org/en/latest/specifications/pyproject-toml/#license
65- # https://peps.python.org/pep-0621/#license
66- # https://packaging.python.org/en/latest/specifications/core-metadata/#license
67- if 'file' in plicense and 'text' in plicense :
68- # per spec:
69- # > These keys are mutually exclusive, so a tool MUST raise an error if the metadata specifies both keys.
70- raise ValueError ('`license.file` and `license.text` are mutually exclusive,' )
71- if 'file' in plicense :
72- # per spec:
73- # > [...] a string value that is a relative file path [...].
74- # > Tools MUST assume the file’s encoding is UTF-8.
75- with open (join (dirname (fpath ), plicense ['file' ]), 'rb' ) as plicense_fileh :
76- yield DisjunctiveLicense (name = f"declared license of '{ project ['name' ]} '" ,
77- acknowledgement = lack ,
78- text = AttachedText (encoding = Encoding .BASE_64 ,
79- content = b64encode (plicense_fileh .read ()).decode ()))
80- elif len (plicense_text := plicense .get ('text' , '' )) > 0 :
81- license = lfac .make_from_string (plicense_text ,
82- license_acknowledgement = lack )
83- if isinstance (license , DisjunctiveLicense ) and license .id is None :
84- # per spec, `License` is either a SPDX ID/Expression, or a license text(not name!)
85- yield DisjunctiveLicense (name = f"declared license of '{ project ['name' ]} '" ,
86- acknowledgement = lack ,
87- text = AttachedText (content = plicense_text ))
88- else :
89- yield license
64+ # Handle both PEP 621 (dict) and PEP 639 (str) license formats
65+ if isinstance (plicense , dict ):
66+ if 'file' in plicense and 'text' in plicense :
67+ raise ValueError ('`license.file` and `license.text` are mutually exclusive,' )
68+ if 'file' in plicense :
69+ with open (join (dirname (fpath ), plicense ['file' ]), 'rb' ) as plicense_fileh :
70+ yield DisjunctiveLicense (name = f"declared license of '{ project ['name' ]} '" ,
71+ acknowledgement = lack ,
72+ text = AttachedText (encoding = Encoding .BASE_64 ,
73+ content = b64encode (plicense_fileh .read ()).decode ()))
74+ elif len (plicense_text := plicense .get ('text' , '' )) > 0 :
75+ license = lfac .make_from_string (plicense_text ,
76+ license_acknowledgement = lack )
77+ if isinstance (license , DisjunctiveLicense ) and license .id is None :
78+ yield DisjunctiveLicense (name = f"declared license of '{ project ['name' ]} '" ,
79+ acknowledgement = lack ,
80+ text = AttachedText (content = plicense_text ))
81+ else :
82+ yield license
83+ elif isinstance (plicense , str ):
84+ # PEP 639: license is a string (SPDX expression or license reference)
85+ license = lfac .make_from_string (plicense , license_acknowledgement = lack )
86+ yield license
87+ else :
88+ raise TypeError (f"Unexpected type for 'license': { type (plicense )} " )
9089
9190
9291def project2extrefs (project : dict [str , Any ]) -> Generator ['ExternalReference' , None , None ]:
0 commit comments