Skip to content

fix: tilecpp exported unconditionally despite conditional import - #181

Open
andrewwhitecdw wants to merge 1 commit into
NVIDIA:mainfrom
andrewwhitecdw:bugfix/init-tilecpp-exported-unconditionally
Open

fix: tilecpp exported unconditionally despite conditional import#181
andrewwhitecdw wants to merge 1 commit into
NVIDIA:mainfrom
andrewwhitecdw:bugfix/init-tilecpp-exported-unconditionally

Conversation

@andrewwhitecdw

@andrewwhitecdw andrewwhitecdw commented Aug 13, 2026

Copy link
Copy Markdown

This PR addresses the following issue in src/tilegym/ops/__init__.py: tilecpp exported unconditionally despite conditional import.

Changes

  • src/tilegym/ops/__init__.py: tilecpp exported unconditionally despite conditional import.

Details

--- a/src/tilegym/ops/__init__.py
+++ b/src/tilegym/ops/__init__.py
@@ -1,39 +1,49 @@
-# Import CUDA Tile C++ backend if available
-if is_backend_available("tilecpp"):
-    from . import tilecpp
-
-# Re-export key interfaces
-from .attn_interface import attention_sink_interface
-from .attn_interface import fmha_interface
-from .attn_interface import get_attention_sink_interface
-from .attn_interface import get_fmha_gemma3_interface
-from .attn_interface import get_fmha_interface
-from .attn_interface import mla_decoding_interface
-from .attn_interface import mla_interface
-from .moe_interface import fused_moe
-
-# Import all operation interfaces from the unified ops module
-from .ops import *
-
-__all__ = [
-    # Export all operations from ops module
-    # Backend implementations
-    "tilecpp",
-    # Interface modules
-    "attn_interface",
-    "moe_interface",
-    # Re-exported submodules
-    # Key interfaces
-    "attention_sink_interface",
-    "fmha_interface",
-    "get_attention_sink_interface",
-    "get_fmha_interface",
-    "get_fmha_gemma3_interface",
-    "mla_interface",
-    "mla_decoding_interface",
-    "fused_moe",
-]
-
-# Add cutile to exports only if successfully imported
-if cutile is not None:
-    __all__.append("cutile")
+# Import CUDA Tile C++ backend if available
+tilecpp = None  # type: ignore
+if is_backend_available("tilecpp"):
+    try:
+        from . import tilecpp
+    except (ImportError, RuntimeError):
+        import warnings
+
+        warnings.warn(
+            "tilecpp backend import failed, tilecpp operations will not be available"
+        )
+        tilecpp = None  # type: ignore
+
+# Re-export key interfaces
+from .attn_interface import attention_sink_interface
+from .attn_interface import fmha_interface
+from .attn_interface import get_attention_sink_interface
+from .attn_interface import get_fmha_gemma3_interface
+from .attn_interface import get_fmha_interface
+from .attn_interface import mla_decoding_interface
+from .attn_interface import mla_interface
+from .moe_interface import fused_moe
+
+# Import all operation interfaces from the unified ops module
+from .ops import *
+
+__all__ = [
+    # Export all operations from ops module
+    # Backend implementations
+    # Interface modules
+    "attn_interface",
+    "moe_interface",
+    # Re-exported submodules
+    # Key interfaces
+    "attention_sink_interface",
+    "fmha_interface",
+    "get_attention_sink_interface",
+    "get_fmha_interface",
+    "get_fmha_gemma3_interface",
+    "mla_interface",
+    "mla_decoding_interface",
+    "fused_moe",
+]
+
+# Add backend submodules to exports only if successfully imported
+if cutile is not None:
+    __all__.append("cutile")
+if tilecpp is not None:
+    __all__.append("tilecpp")

Tests

  • tests/test_ops_init.py
--- /dev/null
+++ b/tests/test_ops_init.py
@@ -0,0 +1,11 @@
+"""Tests for the tilegym.ops package init."""
+
+
+def test_tilecpp_not_exported_when_unavailable():
+    """If tilecpp is not imported, it must not appear in __all__."""
+    import tilegym.ops as ops
+
+    if not hasattr(ops, "tilecpp") or ops.tilecpp is None:
+        assert "tilecpp" not in ops.__all__
+
+
+def test_star_import_does_not_raise():
+    """`from tilegym.ops import *` must always succeed."""
+    import tilegym.ops as ops
+
+    # Exercise __all__ by performing a star import in a fresh namespace.
+    namespace = {"__name__": "test_ops_init"}
+    exec("from tilegym.ops import *", namespace)
+    for name in ops.__all__:
+        assert name in namespace

Contributor guidelines

Per this repo's CONTRIBUTING.md:

  • All commits are signed off (Signed-off-by trailer, DCO).

CI Configuration

config:
  build: true
  # valid options are "ops" and "benchmark"
  test: ["ops", "benchmark"]

Signed-off-by: andrewwhitecdw <andrewwhitecdw@users.noreply.github.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@hannahli-nv

Copy link
Copy Markdown
Collaborator

Hi @andrewwhitecdw, thanks for the fix!

Two small asks before we can merge:

  1. Could you please drop tests/test_ops_init.py? The current test layout doesn't really need a dedicated test for this guard.

  2. Since it's your first time to contribute codes, we'll need a signed CLA file. Per first-time-contributors-cla-required, contributions to the skills/ directory only need a DCO sign-off, but changes elsewhere are MIT-licensed and require a signed CLA (LICENSES/CLA.md) emailed to TileGym@nvidia.com. Thanks for understanding!

@hannahli-nv

Copy link
Copy Markdown
Collaborator

/ok to test 633189e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants