77from pathlib import Path
88from typing import Callable
99
10+ from pdm .backend ._vendor .packaging .version import Version
1011from pdm .backend .exceptions import ConfigError , PDMWarning , ValidationError
1112from pdm .backend .hooks .base import Context
1213from pdm .backend .hooks .version .scm import SCMVersion as SCMVersion
@@ -55,12 +56,12 @@ def pdm_build_initialize(self, context: Context) -> None:
5556 )
5657 return
5758 options = {k : v for k , v in version_config .items () if k != "source" }
58- metadata ["version" ] = getattr ( self , f"resolve_version_from_ { source } " ) (
59- context , ** options
59+ metadata ["version" ] = str (
60+ getattr ( self , f"resolve_version_from_ { source } " )( context , ** options )
6061 )
6162 metadata ["dynamic" ].remove ("version" )
6263
63- def resolve_version_from_file (self , context : Context , path : str ) -> str :
64+ def resolve_version_from_file (self , context : Context , path : str ) -> Version :
6465 """Resolve version from a file."""
6566 version_source = context .root / path
6667 with open (version_source , encoding = "utf-8" ) as fp :
@@ -72,7 +73,7 @@ def resolve_version_from_file(self, context: Context, path: str) -> str:
7273 f"Couldn't find version in file { version_source !r} , "
7374 "it should appear as `__version__ = 'a.b.c'`." ,
7475 )
75- return match .group (1 )
76+ return Version ( match .group (1 ) )
7677
7778 def resolve_version_from_scm (
7879 self ,
@@ -83,7 +84,7 @@ def resolve_version_from_scm(
8384 tag_filter : str | None = None ,
8485 version_format : str | None = None ,
8586 fallback_version : str | None = None ,
86- ) -> str :
87+ ) -> Version :
8788 if os .environ .get ("PDM_BUILD_SCM_VERSION" ):
8889 version = os .environ ["PDM_BUILD_SCM_VERSION" ]
8990 else :
@@ -114,9 +115,18 @@ def resolve_version_from_scm(
114115 version = version_formatter (scm_version , context ) # type: ignore[call-arg]
115116 else :
116117 version = version_formatter (scm_version ) # type: ignore[call-arg]
117-
118+ try :
119+ parsed_version = Version (version )
120+ except ValueError :
121+ if fallback_version is not None :
122+ return Version (fallback_version )
123+ raise ConfigError (
124+ f"Invalid version { version } , it must comply with PEP 440. \n "
125+ "You can still specify the version via environment variable "
126+ "`PDM_BUILD_SCM_VERSION`, or specify `fallback_version` config."
127+ )
118128 self ._write_version (context , version , write_to , write_template )
119- return version
129+ return parsed_version
120130
121131 def _write_version (
122132 self ,
@@ -146,8 +156,17 @@ def resolve_version_from_call(
146156 getter : str ,
147157 write_to : str | None = None ,
148158 write_template : str = "{}\n " ,
149- ) -> str :
159+ fallback_version : str | None = None ,
160+ ) -> Version :
150161 version_getter , args = evaluate_module_attribute (getter , context .root )
151162 version = version_getter (* args )
163+ if version is None :
164+ if fallback_version is not None :
165+ return Version (fallback_version )
166+ else :
167+ raise ConfigError (
168+ "Cannot get version from the call, you can specify fallback version via `fallback_version` config."
169+ )
170+ parsed_version = Version (version )
152171 self ._write_version (context , version , write_to , write_template )
153- return version
172+ return parsed_version
0 commit comments