@@ -3,17 +3,17 @@ defmodule Pythonx.Uv do
33
44 require Logger
55
6- @ uv_version "0.5.21 "
6+ def default_uv_version ( ) , do: "0.8.5 "
77
88 @ doc """
99 Fetches Python and dependencies based on the given configuration.
1010 """
1111 @ spec fetch ( String . t ( ) , boolean ( ) , keyword ( ) ) :: :ok
1212 def fetch ( pyproject_toml , priv? , opts \\ [ ] ) do
13- opts = Keyword . validate! ( opts , force: false )
13+ opts = Keyword . validate! ( opts , force: false , uv_version: default_uv_version ( ) )
1414
15- project_dir = project_dir ( pyproject_toml , priv? )
16- python_install_dir = python_install_dir ( priv? )
15+ project_dir = project_dir ( pyproject_toml , priv? , opts [ :uv_version ] )
16+ python_install_dir = python_install_dir ( priv? , opts [ :uv_version ] )
1717
1818 if opts [ :force ] || priv? do
1919 _ = File . rm_rf ( project_dir )
@@ -30,7 +30,8 @@ defmodule Pythonx.Uv do
3030 # We always use uv-managed Python, so the paths are predictable.
3131 if run! ( [ "sync" , "--python-preference" , "only-managed" ] ,
3232 cd: project_dir ,
33- env: % { "UV_PYTHON_INSTALL_DIR" => python_install_dir }
33+ env: % { "UV_PYTHON_INSTALL_DIR" => python_install_dir } ,
34+ uv_version: opts [ :uv_version ]
3435 ) != 0 do
3536 _ = File . rm_rf ( project_dir )
3637 raise "fetching Python and dependencies failed, see standard output for details"
@@ -40,15 +41,15 @@ defmodule Pythonx.Uv do
4041 :ok
4142 end
4243
43- defp python_install_dir ( priv? ) do
44+ defp python_install_dir ( priv? , uv_version ) do
4445 if priv? do
4546 Path . join ( :code . priv_dir ( :pythonx ) , "uv/python" )
4647 else
47- Path . join ( cache_dir ( ) , "python" )
48+ Path . join ( cache_dir ( uv_version ) , "python" )
4849 end
4950 end
5051
51- defp project_dir ( pyproject_toml , priv? ) do
52+ defp project_dir ( pyproject_toml , priv? , uv_version ) do
5253 if priv? do
5354 Path . join ( :code . priv_dir ( :pythonx ) , "uv/project" )
5455 else
@@ -57,7 +58,7 @@ defmodule Pythonx.Uv do
5758 |> :erlang . md5 ( )
5859 |> Base . encode32 ( case: :lower , padding: false )
5960
60- Path . join ( [ cache_dir ( ) , "projects" , cache_id ] )
61+ Path . join ( [ cache_dir ( uv_version ) , "projects" , cache_id ] )
6162 end
6263 end
6364
@@ -66,8 +67,9 @@ defmodule Pythonx.Uv do
6667 fetched by `fetch/3`.
6768 """
6869 @ spec init ( String . t ( ) , boolean ( ) ) :: :ok
69- def init ( pyproject_toml , priv? ) do
70- project_dir = project_dir ( pyproject_toml , priv? )
70+ def init ( pyproject_toml , priv? , opts \\ [ ] ) do
71+ opts = Keyword . validate! ( opts , uv_version: default_uv_version ( ) )
72+ project_dir = project_dir ( pyproject_toml , priv? , opts [ :uv_version ] )
7173
7274 # Uv stores Python installations in versioned directories in the
7375 # Python install dir. To find the versioned name for this project,
@@ -91,7 +93,7 @@ defmodule Pythonx.Uv do
9193 { :unix , _osname } -> Path . basename ( Path . dirname ( abs_executable_dir ) )
9294 end
9395
94- root_dir = Path . join ( python_install_dir ( priv? ) , versioned_dir_name )
96+ root_dir = Path . join ( python_install_dir ( priv? , opts [ :uv_version ] ) , versioned_dir_name )
9597
9698 case :os . type ( ) do
9799 { :win32 , _osname } ->
@@ -158,10 +160,11 @@ defmodule Pythonx.Uv do
158160 defp make_windows_slashes ( path ) , do: String . replace ( path , "/" , "\\ " )
159161
160162 defp run! ( args , opts ) do
161- path = uv_path ( )
163+ { uv_version , opts } = Keyword . pop ( opts , :uv_version , default_uv_version ( ) )
164+ path = uv_path ( uv_version )
162165
163166 if not File . exists? ( path ) do
164- download! ( )
167+ download! ( uv_version )
165168 end
166169
167170 { _stream , status } =
@@ -170,31 +173,31 @@ defmodule Pythonx.Uv do
170173 status
171174 end
172175
173- defp uv_path ( ) do
174- Path . join ( [ cache_dir ( ) , "bin" , "uv" ] )
176+ defp uv_path ( uv_version ) do
177+ Path . join ( [ cache_dir ( uv_version ) , "bin" , "uv" ] )
175178 end
176179
177180 @ version Mix.Project . config ( ) [ :version ]
178181
179- defp cache_dir ( ) do
182+ defp cache_dir ( uv_version ) do
180183 base_dir =
181184 if dir = System . get_env ( "PYTHONX_CACHE_DIR" ) do
182185 Path . expand ( dir )
183186 else
184187 :filename . basedir ( :user_cache , "pythonx" )
185188 end
186189
187- Path . join ( [ base_dir , @ version , "uv" , @ uv_version ] )
190+ Path . join ( [ base_dir , @ version , "uv" , uv_version ] )
188191 end
189192
190- defp download! ( ) do
193+ defp download! ( uv_version ) do
191194 { archive_type , archive_name } = archive_name ( )
192195
193- url = "https://github.com/astral-sh/uv/releases/download/#{ @ uv_version } /#{ archive_name } "
196+ url = "https://github.com/astral-sh/uv/releases/download/#{ uv_version } /#{ archive_name } "
194197 Logger . debug ( "Downloading uv archive from #{ url } " )
195198 archive_binary = Pythonx.Utils . fetch_body! ( url )
196199
197- path = uv_path ( )
200+ path = uv_path ( uv_version )
198201 { :ok , uv_binary } = extract_executable ( archive_type , archive_binary )
199202 File . mkdir_p! ( Path . dirname ( path ) )
200203 File . write! ( path , uv_binary )
0 commit comments