Skip to content

Commit da0f840

Browse files
committed
Eliminate local imports where feasible
In the case of appose.__version__, this necessitated moving the version string into a separate _version.py, to eliminate a circular dependency: appose.util (lowest - utilities) ↓ appose.tool (uses utilities) ↓ appose.builder (uses tools) ↓ appose/__init__.py (highest - imports everything) The problem was util/download.py importing __version__ from the top-level package, violating this hierarchy. Solution: Moved __version__ to a foundational module like appose/_version.py or appose/version.py. Now: - appose/__init__.py imports and re-exports it - util/download.py imports it from the foundational module - No circular dependency
1 parent c1c52c6 commit da0f840

9 files changed

Lines changed: 45 additions & 21 deletions

File tree

src/appose/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,7 @@ def task_listener(event):
231231
from .environment import Environment
232232
from .service import TaskException # noqa: F401
233233
from .shm import NDArray, SharedMemory # noqa: F401
234-
235-
__version__ = "0.7.3.dev0"
234+
from ._version import __version__ # noqa: F401
236235

237236

238237
def pixi(source: str | Path | None = None) -> PixiBuilder:

src/appose/_version.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
###
2+
# #%L
3+
# Appose: multi-language interprocess cooperation with shared memory.
4+
# %%
5+
# Copyright (C) 2023 - 2025 Appose developers.
6+
# %%
7+
# Redistribution and use in source and binary forms, with or without
8+
# modification, are permitted provided that the following conditions are met:
9+
#
10+
# 1. Redistributions of source code must retain the above copyright notice,
11+
# this list of conditions and the following disclaimer.
12+
# 2. Redistributions in binary form must reproduce the above copyright notice,
13+
# and/or other materials provided with the distribution.
14+
#
15+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
19+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25+
# POSSIBILITY OF SUCH DAMAGE.
26+
# #L%
27+
###
28+
29+
"""Version information for Appose."""
30+
31+
__version__ = "0.7.3.dev0"

src/appose/builder/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@
4545
from typing import Callable
4646
from urllib.request import urlopen
4747

48+
from .. import scheme
4849
from ..environment import Environment
4950
from ..scheme import Scheme
50-
from .. import scheme
51+
from ..util.filepath import appose_envs_dir
5152

5253

5354
# Type alias for progress callback
@@ -554,8 +555,6 @@ def _env_dir(self) -> Path:
554555
if self.env_dir:
555556
return self.env_dir
556557
# Fall back to Appose-managed environments directory
557-
from ..util.filepath import appose_envs_dir
558-
559558
return Path(appose_envs_dir()) / self._env_name()
560559

561560
def _scheme(self) -> Scheme:

src/appose/builder/mamba.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
from . import BaseBuilder, BuildException, Builder, BuilderFactory
3939
from ..environment import Environment
40+
from ..tool.mamba import Mamba
4041

4142

4243
class MambaBuilder(BaseBuilder):
@@ -78,8 +79,6 @@ def build(self) -> Environment:
7879
Raises:
7980
BuildException: If the build fails
8081
"""
81-
from ..tool.mamba import Mamba
82-
8382
env_dir = self._env_dir()
8483

8584
# Check for incompatible existing environments
@@ -192,7 +191,7 @@ def wrap(self, env_dir: str | Path) -> Environment:
192191
self.base(env_path)
193192
return self.build()
194193

195-
def _create_environment(self, env_dir: Path, mamba) -> Environment:
194+
def _create_environment(self, env_dir: Path, mamba: Mamba) -> Environment:
196195
"""
197196
Creates an Environment for the given Mamba/conda directory.
198197

src/appose/builder/pixi.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
from . import BaseBuilder, BuildException, Builder, BuilderFactory
3838
from ..environment import Environment
39+
from ..tool.pixi import Pixi
3940

4041

4142
class PixiBuilder(BaseBuilder):
@@ -105,8 +106,6 @@ def build(self) -> Environment:
105106
Raises:
106107
BuildException: If the build fails
107108
"""
108-
from ..tool.pixi import Pixi
109-
110109
env_dir = self._env_dir()
111110

112111
# Check for incompatible existing environments
@@ -285,7 +284,7 @@ def wrap(self, env_dir: str | Path) -> Environment:
285284
self.base(env_path)
286285
return self.build()
287286

288-
def _create_environment(self, env_dir: Path, pixi) -> Environment:
287+
def _create_environment(self, env_dir: Path, pixi: Pixi) -> Environment:
289288
"""
290289
Creates an Environment for the given Pixi directory.
291290

src/appose/builder/uv.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737

3838
from . import BaseBuilder, BuildException, Builder, BuilderFactory
3939
from ..environment import Environment
40+
from ..tool.uv import Uv
41+
from ..util.platform import is_windows
4042

4143

4244
class UvBuilder(BaseBuilder):
@@ -108,8 +110,6 @@ def build(self) -> Environment:
108110
Raises:
109111
BuildException: If the build fails
110112
"""
111-
from ..tool.uv import Uv
112-
113113
env_dir = self._env_dir()
114114

115115
# Check for incompatible existing environments
@@ -262,8 +262,6 @@ def _create_environment(self, env_dir: Path) -> Environment:
262262
Returns:
263263
Environment configured for this uv/venv installation
264264
"""
265-
from ..util.platform import is_windows
266-
267265
# Convert to absolute path for consistency
268266
env_dir_abs = env_dir.absolute()
269267
base = str(env_dir_abs)

src/appose/tool/mamba.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,7 @@ class Mamba(Tool):
106106

107107
# URL from where Micromamba is downloaded to be installed
108108
DOWNLOAD_URL: str | None = (
109-
f"https://micro.mamba.pm/api/micromamba/{PLATFORM}/latest"
110-
if PLATFORM
111-
else None
109+
f"https://micro.mamba.pm/api/micromamba/{PLATFORM}/latest" if PLATFORM else None
112110
)
113111

114112
def __init__(self, rootdir: str | None = None):

src/appose/util/download.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
from typing import Callable
2020
from urllib.error import HTTPError
2121

22-
from .. import __version__
22+
from .._version import __version__
23+
from .filepath import file_type
2324

2425

2526
def download(
@@ -41,7 +42,6 @@ def download(
4142
Raises:
4243
IOError: If download fails.
4344
"""
44-
from .filepath import file_type
4545

4646
# Resolve redirects and get final URL
4747
final_url = redirected_url(url_path)

src/appose/util/proxy.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757

5858
from typing import TYPE_CHECKING, Any
5959

60+
from .. import syntax
61+
6062
if TYPE_CHECKING:
6163
from ..service import Service
6264

@@ -99,7 +101,6 @@ def create(service: Service, var: str, queue: str | None = None) -> Any:
99101
Raises:
100102
RuntimeError: If a proxied method call fails in the worker process.
101103
"""
102-
from .. import syntax
103104

104105
class ProxyHandler:
105106
def __init__(self, service: Service, var: str, queue: str | None):

0 commit comments

Comments
 (0)