Skip to content

Commit 9e1556f

Browse files
committed
refactor
1 parent e7bfc0e commit 9e1556f

File tree

3 files changed

+111
-91
lines changed

3 files changed

+111
-91
lines changed

lib/pythonx.ex

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,23 @@ defmodule Pythonx do
88

99
@moduledoc readme_docs
1010

11+
defstruct [
12+
:python_dl_path,
13+
:python_home_path,
14+
:python_executable_path,
15+
:sys_paths
16+
]
17+
1118
alias Pythonx.Object
1219

1320
@install_env_name "PYTHONX_FLAME_INIT_STATE"
1421

22+
@type init_state :: %__MODULE__{
23+
python_dl_path: String.t(),
24+
python_home_path: String.t(),
25+
python_executable_path: String.t(),
26+
sys_paths: [String.t()]
27+
}
1528
@type encoder :: (term(), encoder() -> Object.t())
1629

1730
@doc ~s'''
@@ -60,25 +73,20 @@ defmodule Pythonx do
6073
opts = Keyword.validate!(opts, force: false, uv_version: Pythonx.Uv.default_uv_version())
6174

6275
Pythonx.Uv.fetch(pyproject_toml, false, opts)
63-
install_paths = Pythonx.Uv.init(pyproject_toml, false, Keyword.take(opts, [:uv_version]))
64-
65-
init_state = %{
66-
type: :uv_init,
67-
pyproject_toml: pyproject_toml,
68-
opts: Keyword.drop(opts, [:force]),
69-
install_paths: install_paths
70-
}
71-
76+
init_state = Pythonx.Uv.init(pyproject_toml, false, Keyword.take(opts, [:uv_version]))
7277
:persistent_term.put(:pythonx_init_state, init_state)
7378
end
7479

75-
@spec init_state() :: map()
80+
@spec init_state() :: init_state()
7681
defp init_state() do
7782
:persistent_term.get(:pythonx_init_state)
7883
end
7984

85+
@doc ~s'''
86+
Fetches the pythonx init state from the system environment variable.
87+
'''
8088
@spec init_state_from_env() :: String.t() | nil
81-
defp init_state_from_env(), do: System.get_env(@install_env_name)
89+
def init_state_from_env(), do: System.get_env(@install_env_name)
8290

8391
@doc ~s'''
8492
Returns a map containing the environment variables required to initialize Pythonx.
@@ -90,7 +98,7 @@ defmodule Pythonx do
9098
|> :erlang.term_to_binary()
9199
|> Base.encode64()
92100

93-
%{@install_env_name => init_state}
101+
%{name: @install_env_name, value: init_state}
94102
end
95103

96104
@doc ~s'''
@@ -100,29 +108,12 @@ defmodule Pythonx do
100108
def install_paths() do
101109
init_state = init_state()
102110

103-
init_state.install_paths
104-
|> Enum.map(fn path -> Path.wildcard("#{path}/**", match_dot: true) end)
105-
|> List.flatten()
106-
end
107-
108-
@doc false
109-
def maybe_uv_init_from_env() do
110-
case init_state_from_env() do
111-
nil ->
112-
:noop
113-
114-
init_state_env_value ->
115-
%{
116-
type: :uv_init,
117-
pyproject_toml: pyproject_toml,
118-
opts: opts
119-
} =
120-
init_state_env_value
121-
|> Base.decode64!()
122-
|> :erlang.binary_to_term()
123-
124-
uv_init(pyproject_toml, opts)
125-
end
111+
[
112+
init_state.python_dl_path,
113+
init_state.python_executable_path
114+
] ++
115+
init_state.sys_paths ++
116+
Path.wildcard(Path.join(init_state.python_home_path, "**"), match_dot: true)
126117
end
127118

128119
# Initializes the Python interpreter.
@@ -175,6 +166,16 @@ defmodule Pythonx do
175166
Pythonx.NIF.init(python_dl_path, python_home_path, python_executable_path, opts[:sys_paths])
176167
end
177168

169+
@spec init(init_state()) :: :ok
170+
def init(%__MODULE__{
171+
python_dl_path: python_dl_path,
172+
python_home_path: python_home_path,
173+
python_executable_path: python_executable_path,
174+
sys_paths: sys_paths
175+
}) do
176+
init(python_dl_path, python_home_path, python_executable_path, sys_paths: sys_paths)
177+
end
178+
178179
@doc ~S'''
179180
Evaluates the Python `code`.
180181

lib/pythonx/application.ex

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,18 @@ defmodule Pythonx.Application do
3131
Pythonx.Uv.fetch(pyproject_toml, true, opts)
3232
defp maybe_uv_init(), do: Pythonx.Uv.init(unquote(pyproject_toml), true, unquote(opts))
3333
else
34-
defp maybe_uv_init(), do: Pythonx.maybe_uv_init_from_env()
34+
defp maybe_uv_init() do
35+
case Pythonx.init_state_from_env() do
36+
nil ->
37+
:noop
38+
39+
init_state_env_value ->
40+
init_state_env_value
41+
|> Base.decode64!()
42+
|> :erlang.binary_to_term()
43+
|> Pythonx.init()
44+
end
45+
end
3546
end
3647

3748
defp enable_sigchld() do

lib/pythonx/uv.ex

Lines changed: 63 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ defmodule Pythonx.Uv do
6666
Initializes the interpreter using Python and dependencies previously
6767
fetched by `fetch/3`.
6868
"""
69-
@spec init(String.t(), boolean()) :: list(String.t())
69+
@spec init(String.t(), boolean()) :: Pythonx.init_state()
7070
def init(pyproject_toml, priv?, opts \\ []) do
7171
opts = Keyword.validate!(opts, uv_version: default_uv_version())
7272
project_dir = project_dir(pyproject_toml, priv?, opts[:uv_version])
@@ -95,61 +95,69 @@ defmodule Pythonx.Uv do
9595

9696
root_dir = Path.join(python_install_dir(priv?, opts[:uv_version]), versioned_dir_name)
9797

98-
case :os.type() do
99-
{:win32, _osname} ->
100-
# Note that we want the version-specific DLL, rather than the
101-
# "forwarder DLL" python3.dll, otherwise symbols cannot be
102-
# found directly.
103-
python_dl_path =
104-
root_dir
105-
|> Path.join("python3?*.dll")
106-
|> wildcard_one!()
107-
|> make_windows_slashes()
108-
109-
python_home_path = make_windows_slashes(root_dir)
110-
111-
python_executable_path =
112-
project_dir
113-
|> Path.join(".venv/Scripts/python.exe")
114-
|> make_windows_slashes()
115-
116-
venv_packages_path =
117-
project_dir
118-
|> Path.join(".venv/Lib/site-packages")
119-
|> make_windows_slashes()
120-
121-
Pythonx.init(python_dl_path, python_home_path, python_executable_path,
122-
sys_paths: [venv_packages_path]
123-
)
124-
125-
{:unix, osname} ->
126-
dl_extension =
127-
case osname do
128-
:darwin -> ".dylib"
129-
:linux -> ".so"
130-
end
131-
132-
python_dl_path =
133-
root_dir
134-
|> Path.join("lib/libpython3.*" <> dl_extension)
135-
|> wildcard_one!()
136-
|> Path.expand()
137-
138-
python_home_path = root_dir
139-
140-
python_executable_path = Path.join(project_dir, ".venv/bin/python")
141-
142-
venv_packages_path =
143-
project_dir
144-
|> Path.join(".venv/lib/python3*/site-packages")
145-
|> wildcard_one!()
146-
147-
Pythonx.init(python_dl_path, python_home_path, python_executable_path,
148-
sys_paths: [venv_packages_path]
149-
)
150-
end
98+
init_state =
99+
case :os.type() do
100+
{:win32, _osname} ->
101+
# Note that we want the version-specific DLL, rather than the
102+
# "forwarder DLL" python3.dll, otherwise symbols cannot be
103+
# found directly.
104+
python_dl_path =
105+
root_dir
106+
|> Path.join("python3?*.dll")
107+
|> wildcard_one!()
108+
|> make_windows_slashes()
109+
110+
python_home_path = make_windows_slashes(root_dir)
111+
112+
python_executable_path =
113+
project_dir
114+
|> Path.join(".venv/Scripts/python.exe")
115+
|> make_windows_slashes()
116+
117+
venv_packages_path =
118+
project_dir
119+
|> Path.join(".venv/Lib/site-packages")
120+
|> make_windows_slashes()
121+
122+
%Pythonx{
123+
python_dl_path: python_dl_path,
124+
python_home_path: python_home_path,
125+
python_executable_path: python_executable_path,
126+
sys_paths: [venv_packages_path]
127+
}
128+
129+
{:unix, osname} ->
130+
dl_extension =
131+
case osname do
132+
:darwin -> ".dylib"
133+
:linux -> ".so"
134+
end
135+
136+
python_dl_path =
137+
root_dir
138+
|> Path.join("lib/libpython3.*" <> dl_extension)
139+
|> wildcard_one!()
140+
|> Path.expand()
141+
142+
python_home_path = root_dir
143+
144+
python_executable_path = Path.join(project_dir, ".venv/bin/python")
145+
146+
venv_packages_path =
147+
project_dir
148+
|> Path.join(".venv/lib/python3*/site-packages")
149+
|> wildcard_one!()
150+
151+
%Pythonx{
152+
python_dl_path: python_dl_path,
153+
python_home_path: python_home_path,
154+
python_executable_path: python_executable_path,
155+
sys_paths: [venv_packages_path]
156+
}
157+
end
151158

152-
[root_dir, project_dir]
159+
Pythonx.init(init_state)
160+
init_state
153161
end
154162

155163
defp wildcard_one!(path) do

0 commit comments

Comments
 (0)